{"version":3,"sources":["webpack:///firebase-firestore.js","webpack:///./src/firestore/util/log.ts","webpack:///./src/firestore/util/assert.ts","webpack:///./src/firestore/platform/platform.ts","webpack:///./src/firestore/util/api.ts","webpack:///./src/firestore/util/obj.ts","webpack:///./src/firestore/util/input_validation.ts","webpack:///./src/firestore/util/misc.ts","webpack:///./src/firestore/api/blob.ts","webpack:///./src/firestore/model/field_value.ts","webpack:///./src/firestore/util/types.ts","webpack:///./src/firestore/core/query.ts","webpack:///./src/firestore/remote/rpc_error.ts","webpack:///./src/firestore/model/collections.ts","webpack:///./src/firestore/remote/watch_change.ts","webpack:///./src/firestore/remote/serializer.ts","webpack:///./src/firestore/api/field_path.ts","webpack:///./src/firestore/core/view.ts","webpack:///./src/firestore/local/encoded_resource_path.ts","webpack:///./src/firestore/local/indexeddb_schema.ts","webpack:///./src/firestore/local/simple_db.ts","webpack:///./src/firestore/local/indexeddb_mutation_queue.ts","webpack:///./src/firestore/local/indexeddb_query_cache.ts","webpack:///./src/firestore/local/indexeddb_remote_document_cache.ts","webpack:///./src/firestore/local/local_serializer.ts","webpack:///./src/firestore/api/credentials.ts","webpack:///./src/firestore/api/observer.ts","webpack:///./src/firestore/api/user_data_converter.ts","webpack:///./src/firestore/api/database.ts","webpack:///./src/firestore/platform/config.ts","webpack:///./src/firestore.ts","webpack:///./src/firestore/core/version.ts","webpack:///./src/firestore/util/error.ts","webpack:///./src/firestore/api/geo_point.ts","webpack:///./src/firestore/core/database_info.ts","webpack:///./src/firestore/model/path.ts","webpack:///./src/firestore/model/document_key.ts","webpack:///./src/firestore/model/document.ts","webpack:///./src/firestore/util/sorted_map.ts","webpack:///./src/firestore/local/query_data.ts","webpack:///./src/firestore/core/timestamp.ts","webpack:///./src/firestore/core/snapshot_version.ts","webpack:///./src/firestore/model/mutation.ts","webpack:///./src/firestore/remote/existence_filter.ts","webpack:///./src/firestore/util/sorted_set.ts","webpack:///./src/firestore/remote/remote_event.ts","webpack:///./src/firestore/remote/stream_bridge.ts","webpack:///./src/firestore/platform_browser/webchannel_connection.ts","webpack:///./src/firestore/platform_browser/browser_platform.ts","webpack:///./src/firestore/platform_browser/browser_init.ts","webpack:///./src/firestore/core/types.ts","webpack:///./src/firestore/core/view_snapshot.ts","webpack:///./src/firestore/core/target_id_generator.ts","webpack:///./src/firestore/model/document_set.ts","webpack:///./src/firestore/util/obj_map.ts","webpack:///./src/firestore/core/event_manager.ts","webpack:///./src/firestore/local/persistence_promise.ts","webpack:///./src/firestore/local/eager_garbage_collector.ts","webpack:///./src/firestore/local/local_view_changes.ts","webpack:///./src/firestore/local/reference_set.ts","webpack:///./src/firestore/remote/persistent_stream.ts","webpack:///./src/firestore/core/sync_engine.ts","webpack:///./src/firestore/model/mutation_batch.ts","webpack:///./src/firestore/local/indexeddb_persistence.ts","webpack:///./src/firestore/local/local_documents_view.ts","webpack:///./src/firestore/local/remote_document_change_buffer.ts","webpack:///./src/firestore/local/local_store.ts","webpack:///./src/firestore/local/memory_mutation_queue.ts","webpack:///./src/firestore/local/memory_query_cache.ts","webpack:///./src/firestore/local/memory_remote_document_cache.ts","webpack:///./src/firestore/local/memory_persistence.ts","webpack:///./src/firestore/local/no_op_garbage_collector.ts","webpack:///./src/firestore/util/promise.ts","webpack:///./src/firestore/remote/backoff.ts","webpack:///./src/firestore/remote/datastore.ts","webpack:///./src/firestore/core/transaction.ts","webpack:///./src/firestore/remote/remote_store.ts","webpack:///./src/firestore/core/firestore_client.ts","webpack:///./src/firestore/util/async_observer.ts","webpack:///./src/firestore/util/async_queue.ts","webpack:///./src/firestore/auth/user.ts","webpack:///./src/firestore/api/field_value.ts","webpack:///./node_modules/@firebase/webchannel-wrapper/dist/index.js"],"names":["webpackJsonpFirebase","66","module","__webpack_exports__","__webpack_require__","getLogLevel","logLevel","setLogLevel","newLevel","debug","tag","msg","obj","_i","arguments","length","LogLevel","DEBUG","time","Date","toISOString","args","map","argToString","console","log","apply","SDK_VERSION","concat","log_error","ERROR","error","JSON","stringify","e","fail","failure","message","Error","assert","assertion","emptyByteString","platform_PlatformSupport","getPlatform","makeConstructorPrivate","cls","optionalMessage","PublicConstructor","FirestoreError","Code","INVALID_ARGUMENT","prototype","staticProperty","hasOwnProperty","contains","key","Object","call","defaulted","value","defaultValue","undefined","forEachNumber","fn","num","parseInt","isNaN","forEach","isEmpty","_typeof","shallowCopy","result","validateExactNumberOfArgs","functionName","numberOfArgs","formatPlural","validateAtLeastNumberOfArgs","minNumberOfArgs","validateBetweenNumberOfArgs","maxNumberOfArgs","validateNamedArrayAtLeastNumberOfElements","name","minNumberOfElements","Array","validateArgType","type","position","argument","validateType","ordinal","validateOptionalArgType","validateNamedType","optionName","validateNamedOptionalType","inputName","input","input_validation__typeof","isPlainObject","description","valueDescription","getPrototypeOf","substring","customObjectName","tryGetCustomObjectType","constructor","funcNameRegex","results","exec","validateDefined","validateOptionNames","options","optionNames","_","indexOf","join","invalidClassError","str","primitiveComparator","left","right","equals","arrayEquals","i","immediatePredecessor","s","lastIndex","charAt","String","fromCharCode","charCodeAt","immediateSuccessor","assertUint8ArrayAvailable","Uint8Array","UNIMPLEMENTED","assertBase64Available","base64Available","numericComparator","numericEquals","isNullOrUndefined","isSafeInteger","isInteger","MAX_SAFE_INTEGER","MIN_SAFE_INTEGER","fieldFilter","field","op","NullValue","INSTANCE","query_RelationOp","EQUAL","NullFilter","DoubleValue","NAN","NanFilter","query_RelationFilter","isPermanentError","code","OK","CANCELLED","UNKNOWN","DEADLINE_EXCEEDED","RESOURCE_EXHAUSTED","INTERNAL","UNAVAILABLE","UNAUTHENTICATED","NOT_FOUND","ALREADY_EXISTS","PERMISSION_DENIED","FAILED_PRECONDITION","ABORTED","OUT_OF_RANGE","DATA_LOSS","mapCodeFromRpcStatus","status","RpcCode","mapCodeFromRpcCode","mapRpcCodeFromCode","mapCodeFromHttpStatus","maybeDocumentMap","EMPTY_MAYBE_DOCUMENT_MAP","documentMap","EMPTY_DOCUMENT_MAP","documentVersionMap","EMPTY_DOCUMENT_VERSION_MAP","documentKeySet","EMPTY_DOCUMENT_KEY_SET","applyResumeToken","change","resumeToken","assertPresent","parseInt64","hasTag","fromDotSeparatedString","path","search","RESERVED","field_path_FieldPath","bind","split","compareChangeType","c1","c2","order","ChangeType","Added","Modified","Metadata","Removed","encode","encodeSeparator","encodeSegment","get","segment","resultBuf","c","escapeChar","encodedNul","encodedEscape","encodedSeparatorChar","decode","path_ResourcePath","EMPTY_PATH","lastReasonableEscapeIndex","segments","segmentBuilder","start","end","currentPiece","push","createOrUpgradeDb","db","oldVersion","createObjectStore","DbMutationQueue","store","keyPath","DbMutationBatch","DbTargetDocument","createIndex","documentTargetsIndex","documentTargetsKeyPath","unique","DbTarget","queryTargetsIndexName","queryTargetsKeyPath","indexeddb_schema_DbDocumentMutation","DbRemoteDocument","DbOwner","DbTargetGlobal","wrapRequest","request","persistence_promise_PersistencePromise","resolve","reject","onsuccess","event","target","onerror","validateStreamToken","token","mutationsStore","txn","getStore","documentMutationsStore","mutationQueuesStore","simple_db_SimpleDbTransaction","targetsStore","indexeddb_query_cache_getStore","globalTargetStore","documentTargetStore","remoteDocumentsStore","dbKey","docKey","toArray","isDocumentQuery","dbQuery","documents","makeCredentialsProvider","credentials","credentials_EmptyCredentialsProvider","credentials_GoogleCredentialsProvider","client","credentials_FirstPartyCredentialsProvider","sessionIndex","isPartialObserver","implementsAnyMethods","methods","observer__typeof","object","methods_1","method","looksLikeJsonObject","user_data_converter__typeof","geo_point_GeoPoint","blob_Blob","DocumentKeyReference","FieldValueImpl","validatePlainObject","context","createError","fieldPathFromArgument","methodName","_internalPath","fieldPathFromDotSeparatedString","errorMessage","validateSetOptions","merge","validateReference","documentRef","firestore","database_DocumentReference","changesFromSnapshot","snapshot","oldDocs","lastDoc_1","index_1","docChanges","doc","database_DocumentSnapshot","fromCache","query","docComparator","oldIndex","newIndex","indexTracker_1","delete","add","resultChangeType","configureForFirebase","firebase","registerService","app","database_Firestore","firestoreNamespace","registerFirestore","instance","defineProperty","src_app","PlatformSupport","setPlatform","platform","__extends","this","extendStatics","setPrototypeOf","__proto__","d","b","p","__","create","_super","_this","toString","Symbol","iterator","misc_AutoId","AutoId","newId","chars","autoId","Math","floor","random","Blob","binaryString","_binaryString","fromBase64String","base64","atob","fromUint8Array","array","char","toBase64","btoa","toUint8Array","buffer","_equals","other","_compareTo","PublicBlob","GeoPoint","latitude","longitude","isFinite","_lat","_long","enumerable","configurable","DatabaseInfo","databaseId","persistenceKey","host","ssl","DEFAULT_DATABASE_NAME","database_info_DatabaseId","DatabaseId","projectId","database","compareTo","path___extends","path_Path","Path","offset","init","len","construct","comparator","child","nameOrPath","slice","limit","popFirst","size","popLast","firstSegment","lastSegment","index","isPrefixOf","p1","p2","min","ResourcePath","canonicalString","fromString","filter","identifierRegExp","path_FieldPath","FieldPath","isValidIdentifier","test","replace","isKeyField","keyField","fromServerFormat","current","addCurrentSegment","inBackticks","next","document_key_DocumentKey","DocumentKey","isDocumentKey","k1","k2","fromSegments","fromPathString","EMPTY","document_Document","Document","version","data","hasLocalMutations","fieldValue","compareByKey","d1","d2","compareByField","v1","v2","document_NoDocument","NoDocument","sorted_map_SortedMap","SortedMap","root","sorted_map_LLRBNode","insert","copy","BLACK","remove","node","cmp","getPredecessorKey","rightParent","prunedNodes","minKey","maxKey","inorderTraversal","action","k","v","reverseTraversal","getIterator","resultGenerator","sorted_map_SortedMapIterator","getIteratorFrom","getReverseIterator","getReverseIteratorFrom","SortedMapIterator","startKey","isReverse","nodeStack","getNext","pop","hasNext","peek","LLRBNode","color","RED","n","fixUp","removeMin","isRed","moveRedLeft","smallest","rotateRight","moveRedRight","rotateLeft","colorFlip","nl","nr","checkMaxDepth","blackDepth","check","pow","LLRBEmptyNode","TypeOrder","field_value___extends","QueryPurpose","field_value_FieldValue","FieldValue","val","defaultCompareTo","typeOrder","internalValue","field_value_BooleanValue","BooleanValue","of","TRUE","FALSE","NumberValue","IntegerValue","NaN","POSITIVE_INFINITY","Infinity","NEGATIVE_INFINITY","field_value_StringValue","StringValue","TimestampValue","toDate","ServerTimestampValue","localWriteTime","BlobValue","field_value_RefValue","RefValue","GeoPointValue","field_value_ObjectValue","ObjectValue","it1","it2","next1","next2","set","to","setChild","newChild","pathSegment","childName","field_value_ArrayValue","ArrayValue","minLength","NumberAsAny","Number","query_Query","Query","explicitOrderBy","filters","startAt","endAt","memoizedCanonicalId","memoizedOrderBy","assertValidBound","atPath","inequalityField","getInequalityFilterField","firstOrderByField","getFirstOrderByField","KEY_ORDERING_ASC","query_OrderBy","foundKeyOrdering","_a","orderBy","lastDirection","dir","Direction","ASCENDING","KEY_ORDERING_DESC","addFilter","isInequality","newFilters","addOrderBy","newOrderBy","withLimit","withStartAt","bound","withEndAt","canonicalId","_b","_c","comparedOnKeyField","comp","compare","matches","matchesAncestor","matchesOrderBy","matchesFilters","matchesBounds","hasLimit","docPath","sortsBeforeDocument","RelationOp","LESS_THAN","LESS_THAN_OR_EQUAL","GREATER_THAN_OR_EQUAL","GREATER_THAN","RelationFilter","refValue","comparison","matchesComparison","matchesValue","DESCENDING","query_Bound","Bound","before","component","orderByComponent","docValue","thisPosition","otherPosition","OrderBy","isKeyOrderBy","isoRegExp","RegExp","timestamp_Timestamp","Timestamp","seconds","nanos","now","fromEpochMilliseconds","fromDate","date","getTime","milliseconds","fromISOString","utc","fraction","nanoStr","substr","toEpochMilliseconds","snapshot_version_SnapshotVersion","SnapshotVersion","timestamp","fromMicroseconds","fromTimestamp","forDeletedDoc","MIN","toMicroseconds","toTimestamp","MutationType","query_data_QueryData","QueryData","targetId","purpose","snapshotVersion","update","updated","mutation___extends","mutation_FieldMask","FieldMask","fields","ServerTimestampTransform","FieldTransform","transform","MutationResult","transformResults","mutation_Precondition","Precondition","updateTime","exists","isValidFor","maybeDoc","isNone","NONE","mutation_Mutation","Mutation","verifyKeyMatches","getPostMutationVersion","mutation_SetMutation","SetMutation","precondition","Set","applyToRemoteDocument","mutationResult","applyToLocalView","mutation_PatchMutation","PatchMutation","fieldMask","Patch","newData","patchDocument","patchObject","fieldPath","newValue","mutation_TransformMutation","TransformMutation","fieldTransforms","Transform","requireDocument","transformObject","localTransformResults","fieldTransform","mutation_DeleteMutation","DeleteMutation","Delete","ExistenceFilter","count","CurrentStatusUpdate","sorted_set_SortedSet","SortedSet","fromMapKeys","keys","has","elem","first","last","cb","forEachInRange","range","iter","forEachWhile","firstAfterOrEqual","unionWith","thisIt","otherIt","thisElem","otherElem","remote_event_RemoteEvent","RemoteEvent","targetChanges","documentUpdates","addDocumentUpdate","handleExistenceFilterMismatch","mapping","ResetMapping","currentStatusUpdate","MarkNotCurrent","WatchTargetChangeState","EMPTY_KEY_SET","docs","UpdateMapping","addedDocuments","removedDocuments","applyToKeySet","DocumentWatchChange","updatedTargetIds","removedTargetIds","newDoc","ExistenceFilterChange","existenceFilter","watch_change_WatchTargetChange","WatchTargetChange","state","targetIds","cause","watch_change_WatchChangeAggregator","WatchChangeAggregator","listenTargets","pendingTargetResponses","existenceFilters","frozen","watchChange","addDocumentChange","addTargetChange","addExistenceFilterChange","addChanges","watchChanges","createRemoteEvent","isActiveTarget","ensureTargetChange","None","docChange","relevant","targetChange","NoChange","recordTargetResponse","Current","MarkCurrent","Reset","newCount","DIRECTIONS","dirs","OPERATORS","ops","serializer_JsonProtoSerializer","JsonProtoSerializer","useProto3Json","unsafeCastProtoByteString","byteString","fromRpcStatus","toBytes","bytes","fromBlob","blob","toVersion","fromVersion","toResourceName","fullyQualifiedPrefixPath","fromResourceName","resource","isValidResourceName","toName","fromName","extractLocalPathFromResourceName","toQueryPath","encodedDatabaseId","fromQueryPath","resourceName","toValue","nullValue","booleanValue","integerValue","doubleValue","stringValue","mapValue","toMapValue","arrayValue","toArrayValue","timestampValue","geoPointValue","bytesValue","referenceValue","fromValue","fromFields","values","dbId","toMutationDocument","toFields","toDocument","document","fromDocument","fromFound","found","fromMissing","missing","readTime","fromMaybeDocument","toWatchTargetChangeState","toTestWatchChange","documentChange","documentDelete","documentRemove","targetChangeType","fromWatchChange","fromWatchTargetChangeState","causeProto","entityChange","docDelete","docRemove","versionFromListenResponse","toMutation","mutation","updateMask","toDocumentMask","toFieldTransform","currentDocument","toPrecondition","fromMutation","proto","fromPrecondition","fromDocumentMask","fromFieldTransform","fromWriteResult","fromWriteResults","protos","setToServerValue","toDocumentsTarget","fromDocumentsTarget","documentsTarget","toQueryTarget","structuredQuery","parent","from","collectionId","where","toFilter","toOrder","toLimit","toCursor","fromQueryTarget","fromCount","filterBy","fromFilter","fromOrder","fromCursor","toListenRequestLabels","queryData","toLabel","goog-listen-tags","Listen","ExistenceFilterMismatch","LimboResolution","toTarget","toRelationFilter","toUnaryFilter","compositeFilter","unaryFilter","fromUnaryFilter","fromRelationFilter","f","reduce","accum","orderBys","toPropertyOrder","fromPropertyOrder","cursor","toDirection","fromDirection","toOperatorName","fromOperatorName","toFieldPathReference","fromFieldPathReference","fieldReference","direction","nanField","nullField","fieldPaths","paths","utils_promise","dist","stream_bridge_StreamBridge","StreamBridge","wrappedOnOpen","wrappedOnClose","wrappedOnMessage","sendFn","closeFn","onOpen","callback","onClose","onMessage","close","send","callOnOpen","callOnClose","err","callOnMessage","LOG_TAG","X_GOOG_API_CLIENT_VALUE","webchannel_connection_WebChannelConnection","WebChannelConnection","info","pool","baseUrl","modifyHeadersForRequest","headers","header","authHeaders","invoke","rpcName","url","makeUrl","getObject","xhr","listenOnce","COMPLETE","getLastErrorCode","NO_ERROR","json","getResponseJson","TIMEOUT","HTTP_ERROR","status_1","getStatus","getResponseText","getStatusText","getLastError","releaseObject","requestString","Content-Type","openStream","rpcService","RPC_STREAM_SERVICE_MAPPING","rpcUrlName","RPC_STREAM_NAME_MAPPING","urlParts","webchannelTransport","backgroundChannelTest","httpSessionIdParam","initMessageHeaders","sendRawJson","supportsCrossDomainXhr","channel","createWebChannel","opened","closed","streamBridge","open","unguardedEventListen","listen","param","setTimeout","EventType","OPEN","CLOSE","MESSAGE","msgData","status_2","Write","browser_platform_BrowserPlatform","BrowserPlatform","loadConnection","databaseInfo","newSerializer","encoded","raw","OnlineState","fieldNames","documentId","_DOCUMENT_ID","SyncState","GeneratorIds","view_snapshot_DocumentChangeSet","DocumentChangeSet","changeMap","track","oldChange","getChanges","changes","document_set_DocumentSet","DocumentSet","keyedMap","sortedSet","emptySet","oldSet","prevDoc","thisDoc","otherDoc","docStrings","newSet","obj_map_ObjectMap","ObjectMap","mapKeyFn","inner","id","matches_1","otherKey","splice","entries","entries_1","QueryListenersInfo","listeners","event_manager_EventManager","EventManager","syncEngine","queries","q","onlineState","Unknown","subscribe","onChange","onError","listener","firstListen","queryInfo","onOnlineStateChanged","viewSnap","onViewSnapshot","then","unlisten","lastListen","viewSnaps","viewSnaps_1","event_manager_QueryListener","QueryListener","queryObserver","raisedInitialEvent","snap","syncStateChanged","includeDocumentMetadataChanges","hasPendingWrites","shouldRaiseEvent","shouldRaiseInitialEvent","raiseInitialEvent","maybeOnline","Failed","waitForSyncWhenOnline","hasPendingWritesChanged","includeQueryMetadataChanges","getInitialViewChanges","PersistencePromise","nextCallback","catchCallback","isDone","callbackAttached","catch","nextFn","catchFn","wrapFailure","wrapSuccess","toPromise","wrapUserFunction","waitFor","all","promise","nextPromise","idx","initial","eager_garbage_collector_EagerGarbageCollector","EagerGarbageCollector","isEager","sources","potentialGarbage","addGarbageSource","garbageSource","setGarbageCollector","removeGarbageSource","addPotentialGarbageKey","collectGarbage","promises","garbageKeys","hasRefsPromise","documentHasAnyReferences","hasRefs","source","containsKey","local_view_changes_LocalViewChanges","LocalViewChanges","addedKeys","removedKeys","fromSnapshot","viewSnapshot","reference_set_ReferenceSet","ReferenceSet","refsByKey","reference_set_DocReference","refsByTarget","compareByTargetId","garbageCollector","addReference","ref","addReferences","removeReference","removeRef","removeReferences","removeReferencesForId","emptyKey","startRef","endRef","removeAllReferences","referencesForId","firstRef","DocReference","targetOrBatchId","RESERVED_BITS","PersistentStreamState","TargetIdGenerator","generatorId","initAfter","afterWithoutGenerator","afterGenerator","previousId","forLocalStore","LocalStore","forSyncEngine","SyncEngine","AddedLimboDocument","RemovedLimboDocument","view_View","View","syncedDocuments","syncState","limboDocuments","mutatedKeys","documentSet","computeDocChanges","previousChanges","changeSet","oldDocumentSet","newMutatedKeys","newDocumentSet","needsRefill","lastDocInLimit","newMaybeDoc","oldDoc","docsEqual","applyChanges","sort","limboChanges","applyTargetChange","synced","newSyncState","Synced","Local","shouldBeInLimbo","targetMapping","oldLimboDocuments","QueryView","view","sync_engine_SyncEngine","localStore","remoteStore","currentUser","viewHandler","errorHandler","queryViewsByQuery","queryViewsByTarget","limboTargetsByKey","limboKeysByTarget","limboDocumentRefs","limboCollector","mutationUserCallbacks","targetIdGenerator","assertSubscribed","allocateQuery","executeQuery","remoteDocumentKeys","remoteKeys","viewDocChanges","viewChange","queryView","releaseQuery","removeAndCleanupQuery","write","batch","userCallback","localWrite","addMutationCallback","batchId","emitNewSnapsAndNotifyLocalStore","fillWritePipeline","wrapUpdateFunctionError","runTransaction","updateFunction","retries","transaction","createTransaction","userPromise","commit","applyRemoteEvent","remoteEvent","limboKey","rejectListen","docMap","event_1","queryView_1","applySuccessfulWrite","mutationBatchResult","processUserCallback","acknowledgeBatch","rejectFailedWrite","rejectBatch","newCallbacks","toKey","gcLimboDocuments","updateTrackedLimbos","limboChanges_1","limboChange","trackLimboChange","limboTargetId","currentLimboDocs","newSnaps","docChangesInAllViews","queriesProcessed","notifyLocalViewChanges","fnName","handleUserChange","user","BATCHID_UNKNOWN","mutation_batch_MutationBatch","MutationBatch","mutations","batchResult","mutationResults","keySet","isTombstone","toTombstone","mutation_batch_MutationBatchResult","MutationBatchResult","commitVersion","streamToken","docVersions","versionMap","DbTimestamp","ownerId","leaseTimestampMs","userId","lastAcknowledgedBatchId","lastStreamToken","localWriteTimeMs","DbDocumentMutation","prefixForUser","prefixForPath","PLACEHOLDER","DbNoDocument","noDocument","lastListenSequenceNumber","highestTargetId","highestListenSequenceNumber","lastRemoteSnapshotVersion","ALL_STORES","simple_db_SimpleDb","SimpleDb","openOrCreate","runUpgrade","isAvailable","window","indexedDB","onupgradeneeded","deleteDatabase","ua","navigator","userAgent","mode","objectStores","transactionFn","transactionFnResult","abort","completionPromise","IterationController","dbCursor","shouldStop","nextKey","done","skip","SimpleDbTransaction","objectStoresNames","aborted","onabort","oncomplete","storeName","objectStore","simple_db_SimpleDbStore","SimpleDbStore","put","keyOrValue","loadAll","indexOrRange","iterateCursor","deleteAll","keysOnly","control","iterate","optionsOrCallback","cursorRequest","controller","userResult","primaryKey","skipToKey","continue","indexName","reverse","openKeyCursor","openCursor","indexeddb_mutation_queue_IndexedDbMutationQueue","IndexedDbMutationQueue","serializer","forUser","uid","isUnauthenticated","loadNextBatchIdFromDb","nextBatchId","metadata","checkEmpty","empty","maxBatchId","nextUser","IDBKeyRange","keyForBatchId","getNextBatchId","getHighestAcknowledgedBatchId","getLastStreamToken","setLastStreamToken","addMutationBatch","dbBatch","toDbMutationBatch","mutations_1","indexKey","lookupMutationBatch","fromDbMutationBatch","getNextMutationBatchAfterBatchId","lowerBound","foundBatch","getAllMutationBatches","dbBatches","getAllMutationBatchesThroughBatchId","getAllMutationBatchesAffectingDocumentKey","documentKey","indexPrefix","indexStart","userID","encodedPath","batchID","mutationKey","getAllMutationBatchesAffectingQuery","queryPath","immediateChildrenLength","uniqueBatchIDs","removeMutationBatches","batches","indexTxn","this_1","batches_1","only","numDeleted","removePromise","performConsistencyCheck","startRange","danglingMutationReferences","gc","indexeddb_query_cache_IndexedDbQueryCache","IndexedDbQueryCache","lastSavedVersion","getHighestTargetId","getLastRemoteSnapshotVersion","setLastRemoteSnapshotVersion","addQueryData","addedQueryPromise","toDbTarget","removeQueryData","removeMatchingKeysForTargetId","getQueryData","fromDbTarget","addMatchingKeys","removeMatchingKeys","notifyGCForRemovedKeys","getMatchingKeysForTargetId","indexeddb_remote_document_cache_IndexedDbRemoteDocumentCache","IndexedDbRemoteDocumentCache","addEntry","maybeDocument","toDbRemoteDocument","removeEntry","getEntry","dbRemoteDoc","fromDbRemoteDocument","getDocumentsMatchingQuery","local_serializer_LocalSerializer","LocalSerializer","remoteSerializer","remoteDoc","serializedMutations","m","dbTarget","queryProto","dbTimestamp","EXISTING_OWNER_ERROR_MSG","indexeddb_persistence_IndexedDbPersistence","IndexedDbPersistence","prefix","generateOwnerId","dbName","MAIN_DATABASE","localStoragePrefix","started","simpleDb","tryAcquireOwnerLease","scheduleOwnerLeaseRefreshes","attachWindowUnloadHook","persistenceError","shutdown","detachWindowUnloadHook","stopOwnerLeaseRefreshes","releaseOwnerLease","getMutationQueue","getQueryCache","getRemoteDocumentCache","operation","ensureOwnerLease","buildStoragePrefix","isDefaultDatabase","dbOwner","validOwner","newDbOwner","minAcceptable","maxAcceptable","getZombiedOwnerId","ownerLeaseRefreshHandle","setInterval","reason","clearInterval","windowUnloadHandler","setZombiedOwnerId","addEventListener","removeEventListener","zombiedOwnerId","localStorage","getItem","zombiedOwnerLocalStorageKey","zombieOwnerId","removeItem","setItem","local_documents_view_LocalDocumentsView","LocalDocumentsView","remoteDocumentCache","mutationQueue","getDocument","computeLocalDocument","getDocuments","getDocumentsMatchingDocumentQuery","getDocumentsMatchingCollectionQuery","queryResults","computeLocalDocuments","promisedResults","matchingMutationBatches","matchingKeys","matchingMutationBatches_1","mutatedDoc","remote_document_change_buffer_RemoteDocumentChangeBuffer","RemoteDocumentChangeBuffer","assertChanges","bufferedEntry","local_store_LocalStore","persistence","initialUser","localViewReferences","heldBatchResults","remoteDocuments","queryCache","localDocuments","startMutationQueue","startQueryCache","oldBatches","promisedOldBatches","newBatches","changedKeys","_d","highestAck","ackedBatches","promisedBatch","changedDocuments","affected","shouldHoldBatchResult","documentBuffer_1","releaseBatchResults","promisedAffectedKeys","toReject","affectedKeys","promisedToReject","lastAcked","removeMutationBatch","documentBuffer","changedDocKeys","existingDoc","lastRemoteVersion","remoteVersion","releasedWriteKeys","releaseHeldBatchResults","promisedReleasedWriteKeys","viewChanges","viewChanges_1","nextMutationBatch","afterBatchId","readDocument","cached","documentBuffer_2","garbage","toRelease","isRemoteUpToVersion","batchResults","promiseChain","batchResults_1","applyWriteToRemoteDocuments","affectedDocs","batches_2","docKeys","ackVersion","memory_mutation_queue_MemoryMutationQueue","MemoryMutationQueue","highestAcknowledgedBatchId","batchesByDocumentKey","batchIndex","indexOfExistingBatchId","findMutationBatch","max","rawIndex","indexOfBatchId","getAllLiveMutationBatchesBeforeIndex","endIndex","immediateChildrenPathLength","startPath","rowKeyPath","batchCount","firstBatchId","queueCount","startIndex","queueIndex","length_1","references","memory_query_cache_MemoryQueryCache","MemoryQueryCache","memory_remote_document_cache_MemoryRemoteDocumentCache","MemoryRemoteDocumentCache","memory_persistence_MemoryPersistence","MemoryPersistence","mutationQueues","queue","MemoryPersistenceTransaction","no_op_garbage_collector_NoOpGarbageCollector","NoOpGarbageCollector","promise_Deferred","Deferred","backoff_ExponentialBackoff","ExponentialBackoff","initialDelayMs","backoffFactor","maxDelayMs","reset","currentBaseMs","resetToMax","backoffAndWait","def","delayWithJitterMs","jitterDelayMs","persistent_stream___extends","UserDataSource","BACKOFF_INITIAL_DELAY_MS","BACKOFF_MAX_DELAY_MS","BACKOFF_FACTOR","persistent_stream_PersistentStream","PersistentStream","connection","credentialsProvider","initialBackoffDelay","stream","backoff","Initial","isStarted","Backoff","Auth","Open","isOpen","performBackoff","auth","stop","Stopped","inhibitBackoff","getToken","startStream","schedule","rpcError","handleStreamClose","dispatchIfNotStopped","startRpc","PersistentListenStream","watchChangeProto","onWatchChange","watch","addTarget","labels","unwatch","removeTarget","persistent_stream_PersistentWriteStream","PersistentWriteStream","handshakeComplete_","responseProto","writeResults","commitTime","onMutationResult","onHandshakeComplete","writeHandshake","writeMutations","writes","datastore_Datastore","Datastore","newPersistentWriteStream","newPersistentWatchStream","params","invokeRPC","response","lookup","transaction_Transaction","Transaction","datastore","readVersions","committed","recordVersion","docVersion","existingVersion","preconditionForUpdate","toMutations","unwritten","remote_store_RemoteStore","RemoteStore","asyncQueue","onlineStateHandler","pendingWrites","lastBatchSeen","accumulatedWatchChanges","watchStreamOnlineState","watchStreamFailures","setupStreams","setOnlineStateToHealthy","updateAndBroadcastOnlineState","Healthy","setOnlineStateToUnknown","updateOnlineStateAfterFailure","didChange","watchStream","onWatchStreamOpen","onWatchStreamClose","onWatchStreamChange","writeStream","onWriteStreamOpen","onWriteStreamClose","onWriteHandshakeComplete","cleanupWatchStreamState","sendWatchRequest","startWatchStream","sendUnwatchRequest","recordPendingTargetRequest","shouldStartWatchStream","handleTargetError","handleWatchChangeBatch","aggregator","deletedDoc","trackedRemote","newQueryData","requestQueryData","canWriteMutations","outstandingWrites","handshakeComplete","startWriteStream","shift","success","errorHandling","handleWriteError","handleHandshakeError","firestore_client_FirestoreClient","FirestoreClient","usePersistence","initializationDone","persistenceResult","initialized","setUserChangeListener","initializePersistence","initializeRest","startIndexedDbPersistence","canFallback","warn","startMemoryPersistence","storagePrefix","onlineStateChangedHandler","eventMgr","verifyOperationInProgress","removeUserChangeListener","observer","deferred","AsyncObserver","muted","scheduleEvent","mute","eventHandler","async_queue_AsyncQueue","AsyncQueue","tail","delayedOpCount","operationInProgress","delay","deferred_1","scheduleInternal","stack","drain","User","otherUser","GOOGLE_CREDENTIALS","FIRST_PARTY","OAuthToken","Authorization","EmptyCredentialsProvider","userListener","forceRefresh","credentials_FirebaseCredentialsProvider","FirebaseCredentialsProvider","tokenListener","userCounter","newUser","getUser","addAuthTokenListener","initialUserCounter","tokenData","accessToken","removeAuthTokenListener","getUid","currentUid","GoogleCredentialsProvider","authClient","tokenLiteral","credentials_FirstPartyToken","FirstPartyToken","gapi","X-Goog-AuthUser","FirstPartyCredentialsProvider","api_field_value___extends","DeleteFieldValueImpl","serverTimestamp","ServerTimestampFieldValueImpl","PublicFieldValue","RESERVED_FIELD_REGEX","user_data_converter_ParsedSetData","ParsedSetData","user_data_converter_ParsedUpdateData","ParsedUpdateData","user_data_converter_ParseContext","ParseContext","dataSource","validatePath","childContext","childPath","validatePathSegment","fieldDescription","isWrite","Update","user_data_converter_UserDataConverter","UserDataConverter","preConverter","parseSetData","updateData","runPreConverter","parsedValue","parseData","parseUpdateData","fieldMaskPaths","mask","parseUpdateVarargs","moreFieldsAndValues","value_1","parseQueryValue","QueryValue","parsed","parseArray","parseObject","parseScalarValue","entryIndex","array_1","entry","parsedEntry","database__typeof","database___extends","DEFAULT_HOST","DEFAULT_SSL","database_FirestoreSettings","FirestoreSettings","settings","FirestoreConfig","Firestore","databaseIdOrApp","_firestoreClient","config","firebaseApp","databaseIdFromApp","external_1","_config","settingsLiteral","newSettings","enablePersistence","configureClient","ensureClientConfigured","thisDb","otherDb","_key","_dataConverter","collection","pathString","database_CollectionReference","forPath","database_Transaction","database_WriteBatch","SILENT","level","_firestore","_transaction","fieldOrUpdateData","WriteBatch","_mutations","_committed","verifyNotCommitted","DocumentReference","onSnapshot","includeMetadataChanges","currArg","internalOptions","complete","onSnapshotInternal","errHandler","asyncObserver","internalListener","DocumentSnapshot","_document","_fromCache","convertObject","convertValue","convertArray","database_Query","_query","opStr","_databaseId","validateNewFilter","directionStr","validateNewOrderBy","docOrField","boundFromDocOrFields","startAfter","endBefore","boundFromDocument","allFields","boundFromFields","components","rawValue","wrapped","database_QuerySnapshot","firestoreClient","existingField","validateOrderByAndInequalityMatch","inequality","QuerySnapshot","_originalQuery","_snapshot","_cachedChanges","thisArg","convertToDocumentImpl","CollectionReference","parentPath","docRef","PublicFirestore","PublicTransaction","PublicWriteBatch","PublicDocumentReference","PublicDocumentSnapshot","PublicQuery","PublicQuerySnapshot","PublicCollectionReference","67","exports","l","a","aa","ba","propertyIsEnumerable","ca","da","fa","ha","unshift","r","Function","ia","u","L","Bb","ja","captureStackTrace","ka","ma","na","oa","w","qa","ra","ea","va","wa","xa","ya","y","x","Ba","Ca","Da","Ea","Ga","Fa","Ha","Ia","Ja","Oa","documentMode","Ua","la","Pa","h","A","Qa","ab","relatedTarget","button","screenY","screenX","clientY","clientX","metaKey","shiftKey","altKey","ctrlKey","pointerId","pointerType","changedTouches","srcElement","Ma","nodeName","fromElement","toElement","pageX","pageY","bb","defaultPrevented","fb","src","capture","eb","X","gb","hb","ib","jb","kb","sa","lb","pb","once","qb","rb","$","sb","tb","mb","ub","$a","attachEvent","vb","ob","wb","Ya","xb","yb","detachEvent","nb","zb","Ab","keyCode","returnValue","parentNode","handleEvent","B","P","J","Cb","Db","Eb","eval","Fb","Gb","Hb","Boolean","Ib","valueOf","Lb","Jb","Mb","g","Ob","Pb","Nb","Qb","Sb","MessageChannel","postMessage","createElement","style","display","documentElement","appendChild","contentWindow","location","protocol","origin","port1","onmessage","port2","onreadystatechange","removeChild","Ub","Promise","Tb","Vb","setImmediate","Window","Rb","C","Wb","Xb","t","Yb","Z","K","clearTimeout","Zb","$b","ac","W","D","cc","dc","fc","E","lc","F","G","hc","oc","nc","mc","jc","lastIndexOf","pc","ic","H","kc","qc","rc","parse","Ra","Kb","Pe","I","sc","tc","uc","dispatchEvent","vc","wc","xc","Ac","Bc","Cc","Ec","Fc","ActiveXObject","XMLHttpRequest","S","M","Gc","Hc","T","o","j","N","Ic","Lc","Mc","Nc","Oc","Pc","Qc","ta","Sc","Wc","Kc","Jc","Tc","Uc","Vc","Xc","Rc","Ka","Y","Na","Yc","Zc","O","ad","bd","$c","dd","decodeURIComponent","Q","ed","fd","gd","hd","match","cd","jd","kd","qd","ld","rd","R","sd","abs","td","ud","decodeURI","encodeURI","vd","wd","xd","yd","toLowerCase","zd","Bd","Ad","Cd","Dd","Fd","Gd","Hd","Id","Jd","Kd","Md","Nd","Od","Pd","pa","La","Qd","Rd","Sd","Td","Ud","Vd","Wd","Xd","encodeURIComponent","Yd","Image","onload","Zd","ontimeout","U","$d","ee","z","timeout","ce","fe","ge","he","goog","V","self","ae","de","readyState","ie","je","ke","za","Va","Aa","ga","concurrentRequestLimit","fastHandshake","le","me","ne","sendBeacon","oe","cancel","pe","qe","re","te","se","round","Wa","ue","ve","we","xe","Ld","ye","hostname","port","ze","Ae","Be","testUrl","messageUrlParams","messageHeaders","clientProtocolHeaderRequired","X-Client-Protocol","httpHeadersOverwriteParam","Ce","De","Ee","Ge","He","Ie","Je","Ke","Le","Me","Ne","Oe","trim","Sa","Ta","parseFloat","compatMode","Xa","freeze","Za","2","3","4","preventDefault","\"","\\","/","\b","\f","\n","\r","\t","\u000b","bc","ec","timeStamp","msWriteProfilerMark","yc","zc","Dc","md","nd","od","pd","Ed","getResponseHeader","be","toUpperCase","FormData","setRequestHeader","responseType","withCredentials","statusText","responseText","__data__","Fe","createWebChannelTransport","ErrorCode","WebChannel","XhrIoPool"],"mappings":"AAAA,IACUA,sBAAsB,IAE1BC,GACA,SAAUC,EAAQC,EAAqBC,GAE7C,YCwBM,SAAAC,KACE,MACRC,IACM,QAAAC,GAAwCC,GACpCF,GACVE,EAEM,QAAAC,GAA2BC,EAAaC,GD4B1C,IC5B4C,GAAAC,MAAAC,EAAe,EAAfA,EAAAC,UAAeC,OAAAF,IAAfD,EAAAC,EAAA,GAAAC,UAAeD,EAC1D,IAASP,IAAYU,GAAOC,MAAE,CAC/B,GAAUC,IAAG,GAAUC,OAAeC,cAC5BC,EAAMT,EAAIU,IAAcC,EAC3BC,SAAIC,IAAAC,MAAJF,SAAK,cAAyBG,GAAA,KAAST,EAAA,KAAQR,EAAA,MAAWC,GAAAiB,OACnEP,KAGI,QAAAQ,GAA2BlB,GD+B7B,IC/B+B,GAAAC,MAAAC,EAAe,EAAfA,EAAAC,UAAeC,OAAAF,IAAfD,EAAAC,EAAA,GAAAC,UAAeD,EAC7C,IAASP,IAAYU,GAAOc,MAAE,CAC/B,GAAUZ,IAAG,GAAUC,OAAeC,cAC5BC,EAAMT,EAAIU,IAAcC,EAC3BC,SAAMO,MAAAL,MAANF,SAAO,cAAyBG,GAAA,KAAST,EAAA,KAAUP,GAAAiB,OAC5DP,KAMF,QAAAE,GAA+BX,GAC1B,GAAyB,gBAAdA,GACN,MACRA,EACE,KACQ,MAAKoB,MAAUC,UACvBrB,GAAQ,MAAGsB,GAEH,MACRtB,ICtCE,QAAAuB,GAA8BC,GAGlC,GAAaC,GACX,cAAyBV,GAA+B,gCAAWS,CAMrE,MALKP,GAAUQ,GAKAC,MACjBD,GAMM,QAAAE,GAAmCC,EAAiBH,GACzCG,GACTL,EACNE,GCuBI,QAAAI,KACE,MAAgBC,IAAcC,cACtCF,gBCxCM,QAAAG,GAA0CC,EAA0BC,GACxE,QAAAC,KACE,GAAShB,GAAkC,8BAK3C,MAJoBe,KACbf,GAAQ,IACRA,GACPe,GACM,GAAkBE,IAAKC,GAAiBC,iBAChDnB,GAIiBgB,EAAUI,UAAeN,EAAWM,SAGjD,KAAC,GAAoBC,KAAQP,GACxBA,EAAeQ,eAAiBD,KACXL,EAAgBK,GAAeP,EAC3DO,GAGI,OACRL,GC/BM,QAAAO,GAAkC1C,EAAsB2C,GACtD,MAAOC,QAAUL,UAAeE,eAAKI,KAAI7C,EACjD2C,GAiBM,QAAAG,GAA2CC,EAAiBC,GAC1D,WAAoBC,KAAdF,EAAsBA,EACpCC,EAEM,QAAAE,GACQlD,EACqBmD,GAE7B,IAAC,GAASR,KAAQ3C,GACjB,GAAO4C,OAAUL,UAAeE,eAAKI,KAAI7C,EAAO2C,GAAE,CACnD,GAASS,GAAWC,SAAIV,EAAM,GACpBW,OAAMF,IACZD,EAAIC,EAAKpD,EACb2C,KAKA,QAAAY,GACQvD,EACqBmD,GAE7B,IAAC,GAASR,KAAQ3C,GACV4C,OAAUL,UAAeE,eAAKI,KAAI7C,EAAO2C,IAC/CQ,EAAIR,EAAK3C,EACb2C,IAeE,QAAAa,GAAiCxD,GAC/B2B,EACO,MAAR3B,GAAmC,gBAAb,KAAAA,EAAA,YAAAyD,GAAAzD,IAEzB,sCACE,KAAC,GAAS2C,KAAQ3C,GACjB,GAAO4C,OAAUL,UAAeE,eAAKI,KAAI7C,EAAO2C,GAC3C,OACR,CAEI,QACR,EAEM,QAAAe,GAAqC1D,GACnC2B,EACD3B,GAA2B,gBAAb,KAAAA,EAAA,YAAAyD,GAAAzD,IAEjB,0CACF,IAAY2D,KACR,KAAC,GAAShB,KAAQ3C,GACV4C,OAAUL,UAAeE,eAAKI,KAAI7C,EAAO2C,KAC3CgB,EAAKhB,GAAM3C,EACnB2C,GAEI,OACRgB,GC/EM,QAAAC,GACgBC,EACJpD,EACIqD,GAEjB,GAAKrD,EAAON,SAAkB2D,EAC/B,KAAM,IAAkB1B,IAClBC,GAAiBC,iBACrB,YAAwBuB,EAAc,eACxBE,EAAaD,EAAa,YACd,yBACZC,EAAKtD,EAAON,OAAa,YAG3C,KAWI,QAAA6D,GACgBH,EACJpD,EACOwD,GAEpB,GAAKxD,EAAON,OAAmB8D,EAChC,KAAM,IAAkB7B,IAClBC,GAAiBC,iBACrB,YAAwBuB,EAAuB,wBACjCE,EAAgBE,EAAa,YACjB,yBACZF,EAAKtD,EAAON,OAAa,YAG3C,KAWI,QAAA+D,GACgBL,EACJpD,EACOwD,EACAE,GAEpB,GAAK1D,EAAON,OAAkB8D,GAAQxD,EAAON,OAAmBgE,EACjE,KAAM,IAAkB/B,IAClBC,GAAiBC,iBACrB,YAAwBuB,EAAA,uBAAsCI,EAAO,QACjDE,EAAkC,mCACxCJ,EAAKtD,EAAON,OAAa,YAG3C,KAOI,QAAAiE,GACgBP,EACVd,EACEsB,EACeC,GAExB,KAAQvB,YAAkBwB,SAASxB,EAAO5C,OAAuBmE,EAClE,KAAM,IAAkBlC,IAClBC,GAAiBC,iBACrB,YAAwBuB,EAAA,mBAAuBQ,EAAqB,0CAEnDN,EAAoBO,EAAY,WAErD,KAOI,QAAAE,GACgBX,EACRY,EACIC,EACDC,GAEHC,EAAaf,EAAMY,EAAYI,EAAUH,GAAW,YAClEC,GAMM,QAAAG,GACgBjB,EACRY,EACIC,EACDC,OAEY1B,KAAf0B,GACKH,EAAaX,EAAMY,EAAUC,EAC9CC,GAOI,QAAAI,GACgBlB,EACRY,EACMO,EACHL,GAEHC,EAAaf,EAAMY,EAAeO,EAAS,UACzDL,GAMM,QAAAM,GACgBpB,EACRY,EACMO,EACHL,OAEY1B,KAAf0B,GACOI,EAAalB,EAAMY,EAAYO,EAClDL,GAIF,QAAAC,GACsBf,EACRY,EACKS,EACLC,GAET,QAAa,KAAAA,EAAA,YAAAC,GAAAD,MAAaV,GAAkB,WAAbA,IAA+BY,EAASF,GAAE,CAC1E,GAAiBG,GAAmBC,EAAQJ,EAC5C,MAAM,IAAkB/C,IAClBC,GAAiBC,iBACrB,YAAwBuB,EAAA,mBAA4BqB,EAAG,kBAChCT,EAAA,iBAE3Ba,IAOI,QAAAD,GAAoCF,GACjC,MACoB,gBAAb,KAAAA,EAAA,YAAAC,GAAAD,KACE,OAATA,GACCvC,OAAe4C,eAAOL,KAAWvC,OAE3CL,UAGM,QAAAgD,GAAuCJ,GACxC,OAAqBlC,KAAfkC,EACD,MACR,WAAM,IAAoB,OAAVA,EACR,MACR,MAFU,IAE2B,gBAAdA,GAIf,MAHGA,GAAOhF,OAAM,KACfgF,EAAWA,EAAUM,UAAE,EAAK,IACnC,OACWrE,KAAUC,UACvB8D,EALU,IAK0B,gBAAbA,IAA4C,iBAAfA,GAC5C,MAAG,GACXA,CAFU,IAE2B,gBAAd,KAAAA,EAAA,YAAAC,GAAAD,IAAgB,CAClC,GAAMA,YAAkBZ,OACnB,MACR,UACE,IAAsBmB,GAAyBC,EAAQR,EACpD,OAAkBO,GACZ,YAA4BA,EACrC,UAEA,YATM,MAW6B,kBAAhBP,GAEvB,aACa5D,EAA0B,4BACvC,KAAA4D,EAAA,YAAAC,GAAAD,KAII,QAAAQ,GAA8CR,GAC/C,GAAMA,EAAaS,YAAE,CACtB,GAAmBC,GAA+B,4BACrCC,EAAgBD,EAAKE,KAAMZ,KAAYS,YACjD,IAAQE,GAAWA,EAAO3F,OAAK,EAC1B,MAAQ2F,GAChB,GAEI,MACR,MAGM,QAAAE,GACgBnC,EACJa,EACDC,GAEZ,OAAwB1B,KAAf0B,EACV,KAAM,IAAkBvC,IAClBC,GAAiBC,iBACrB,YAAwBuB,EAAA,uBAA8BgB,EAAUH,GAAG,oCAUnE,QAAAuB,GACgBpC,EACLqC,EACMC,GAElB5C,EAAmC2C,EAAE,SAAIvD,EAAGyD,GAC1C,GAAYD,EAAQE,QAAK1D,GAAK,EAC/B,KAAM,IAAkBP,IAClBC,GAAiBC,iBACrB,mBAAsBK,EAAA,wBAAoCkB,EAAM,0BAEnDsC,EAAKG,KAEtB,SAQE,QAAAC,GACgB1C,EACRY,EACIC,EACDC,GAEf,GAAiBW,GAAmBC,EAAWZ,EACzC,OAAC,IAAkBvC,IACnBC,GAAiBC,iBACrB,YAAwBuB,EAAA,mBAA0BgB,EAAUH,GAAG,qBACrCD,EAAA,iBAE9Ba,GAGA,QAAAT,GAA4BzB,GACnB,OAAOA,GACZ,IAAM,GACE,MAAS,OACjB,KAAM,GACE,MAAU,QAClB,KAAM,GACE,MAAS,OACjB,SACQ,MAAIA,GAEhB,MAKA,QAAAW,GAAiCX,EAAaoD,GACtC,MAAOpD,GAAA,IAAYoD,GAAU,IAANpD,EAAW,GAC1C,KC5QM,QAAAqD,GAAwCC,EAAUC,GACnD,MAAKD,GAASC,GAAW,EACpBD,EAASC,EAAU,EAE7B,EAQM,QAAAC,GACiCF,EACVC,GAExB,MAAc,QAATD,OAAgCzD,KAAfyD,KACRC,IAAQD,EAAOE,OAChCD,IAGmCD,IACnCC,EAII,QAAAE,GAAkDH,EAAYC,GAC/D,GAAKD,EAAOvG,SAAUwG,EAAQxG,OACzB,OACR,CAEI,KAAC,GAAK2G,GAAI,EAAGA,EAAOJ,EAAOvG,OAAK2G,IAC/B,IAAMJ,EAAGI,GAAOF,OAAMD,EAAKG,IACtB,OACR,CAGI,QACR,EAWM,QAAAC,GAAwCC,GAI5C,GAAeC,GAAID,EAAO7G,OAAK,CAC5B,OAAgB,KAAd6G,EAAO7G,OAGZ,GAAwC,OAA5B6G,EAAOE,OAAWD,GACpBD,EAAUvB,UAAE,EACtBwB,GAEKD,EAAUvB,UAAE,EAAYwB,GACnBE,OAAaC,aAAEJ,EAAWK,WAAWJ,GAE/C,GAOI,QAAAK,GAAsCN,GAEpC,MAAEA,GACV,KC/FA,QAAAO,KACK,GAAmC,mBAAjBC,YACnB,KAAM,IAAkBpF,IAClBC,GAAcoF,cAGtB,sDAIF,QAAAC,KACK,IAAiB5F,GAAcC,cAAiB4F,gBACjD,KAAM,IAAkBvF,IAClBC,GAAcoF,cAGtB,2DC6IF,QAAAG,GAAuClB,EAAeC,GACjD,MAAKD,GAASC,GAEjB,EAAeD,EAASC,EAExB,EAAeD,IAAWC,EAE1B,EAEWrD,MAAOoD,GACFpD,MAAOqD,GAAI,GACzB,EAEA,EAQJ,QAAAkB,GAAmCnB,EAAeC,GAG7C,MAAKD,KAAWC,EAEA,IAAND,GAAW,EAAOA,GAAM,EACrCC,EAEaD,IAASA,GAASC,IAC/BA,EClKI,QAAAmB,GAAwC/E,GACtC,MAAe,QAATA,OACdE,KADgCF,EAO1B,QAAAgF,GAAoChF,GACjC,MACIiF,IAAOjF,IACCA,GAAoBkF,IACpBlF,GAErBmF,GC4eM,QAAAC,GACYC,EACFC,EACGtF,GAEd,GAAMA,EAAO6D,OAAU0B,GAAWC,UAAE,CAClC,GAAGF,IAAeG,GAAOC,MAC1B,KAAM,IAAkBrG,IAClBC,GAAiBC,iBACwB,kEAG3C,OAAC,IAAcoG,IACvBN,GAAM,GAAUrF,EAAO6D,OAAY+B,GAAMC,KAAE,CACtC,GAAGP,IAAeG,GAAOC,MAC1B,KAAM,IAAkBrG,IAClBC,GAAiBC,iBACwB,iEAG3C,OAAC,IAAauG,IACtBT,GACQ,MAAC,IAAkBU,IAAMV,EAAIC,EACrCtF,GCphBI,QAAAgG,GAAqCC,GAClC,OAAQA,GACb,IAAS3G,IAAG4G,GACJ,MAAK1H,GAA+B,6BAC5C,KAASc,IAAW6G,UACpB,IAAS7G,IAAS8G,QAClB,IAAS9G,IAAmB+G,kBAC5B,IAAS/G,IAAoBgH,mBAC7B,IAAShH,IAAUiH,SACnB,IAASjH,IAAakH,YAItB,IAASlH,IAAgBmH,gBACjB,OAAO,CACf,KAASnH,IAAkBC,iBAC3B,IAASD,IAAWoH,UACpB,IAASpH,IAAgBqH,eACzB,IAASrH,IAAmBsH,kBAC5B,IAAStH,IAAqBuH,oBAI9B,IAASvH,IAASwH,QAClB,IAASxH,IAAcyH,aACvB,IAASzH,IAAeoF,cACxB,IAASpF,IAAU0H,UACX,OAAM,CACd,SACQ,MAAKxI,GAAwB,wBAEzCyH,IAQM,QAAAgB,GAA6CC,GAEjD,GAAUjB,GAAmBkB,GAAuBD,EACjD,QAAoBhH,KAAf+F,EAIF,MAAmBmB,GAC3BnB,GASM,QAAAmB,GAAyCnB,GACtC,OAAQA,GACb,IAAYkB,IAAGjB,GACP,MAAK5G,IAAI4G,EACjB,KAAYiB,IAAUhB,UACd,MAAK7G,IAAW6G,SACxB,KAAYgB,IAAQf,QACZ,MAAK9G,IAAS8G,OACtB,KAAYe,IAAkBd,kBACtB,MAAK/G,IAAmB+G,iBAChC,KAAYc,IAAmBb,mBACvB,MAAKhH,IAAoBgH,kBACjC,KAAYa,IAASZ,SACb,MAAKjH,IAAUiH,QACvB,KAAYY,IAAYX,YAChB,MAAKlH,IAAakH,WAC1B,KAAYW,IAAgBV,gBACpB,MAAKnH,IAAiBmH,eAC9B,KAAYU,IAAiB5H,iBACrB,MAAKD,IAAkBC,gBAC/B,KAAY4H,IAAUT,UACd,MAAKpH,IAAWoH,SACxB,KAAYS,IAAeR,eACnB,MAAKrH,IAAgBqH,cAC7B,KAAYQ,IAAkBP,kBACtB,MAAKtH,IAAmBsH,iBAChC,KAAYO,IAAoBN,oBACxB,MAAKvH,IAAqBuH,mBAClC,KAAYM,IAAQL,QACZ,MAAKxH,IAASwH,OACtB,KAAYK,IAAaJ,aACjB,MAAKzH,IAAcyH,YAC3B,KAAYI,IAAczC,cAClB,MAAKpF,IAAeoF,aAC5B,KAAYyC,IAAUH,UACd,MAAK1H,IAAW0H,SACxB,SACQ,MAAKxI,GAAwB,wBAEzCyH,IAMM,QAAAoB,GAAmDpB,GACpD,OAAoB/F,KAAf+F,EACA,MAAQkB,IAChBjB,EAEO,QAAQD,GACb,IAAS3G,IAAG4G,GACJ,MAAQiB,IAAIjB,EACpB,KAAS5G,IAAU6G,UACX,MAAQgB,IAAWhB,SAC3B,KAAS7G,IAAQ8G,QACT,MAAQe,IAASf,OACzB,KAAS9G,IAAkB+G,kBACnB,MAAQc,IAAmBd,iBACnC,KAAS/G,IAAmBgH,mBACpB,MAAQa,IAAoBb,kBACpC,KAAShH,IAASiH,SACV,MAAQY,IAAUZ,QAC1B,KAASjH,IAAYkH,YACb,MAAQW,IAAaX,WAC7B,KAASlH,IAAgBmH,gBACjB,MAAQU,IAAiBV,eACjC,KAASnH,IAAiBC,iBAClB,MAAQ4H,IAAkB5H,gBAClC,KAASD,IAAUoH,UACX,MAAQS,IAAWT,SAC3B,KAASpH,IAAeqH,eAChB,MAAQQ,IAAgBR,cAChC,KAASrH,IAAkBsH,kBACnB,MAAQO,IAAmBP,iBACnC,KAAStH,IAAoBuH,oBACrB,MAAQM,IAAqBN,mBACrC,KAASvH,IAAQwH,QACT,MAAQK,IAASL,OACzB,KAASxH,IAAayH,aACd,MAAQI,IAAcJ,YAC9B,KAASzH,IAAcoF,cACf,MAAQyC,IAAezC,aAC/B,KAASpF,IAAU0H,UACX,MAAQG,IAAWH,SAC3B,SACQ,MAAKxI,GAAwB,wBAEzCyH,IASM,QAAAqB,GAA8CJ,GAO3C,OAAUA,GACf,IAAQ,KACA,MAAK5H,IAAI4G,EAEjB,KAAQ,KACA,MAAK5G,IAAkBC,gBAK/B,KAAQ,KACA,MAAKD,IAAiBmH,eAE9B,KAAQ,KACA,MAAKnH,IAAmBsH,iBAEhC,KAAQ,KACA,MAAKtH,IAAWoH,SAExB,KAAQ,KACA,MAAKpH,IAASwH,OAItB,KAAQ,KACA,MAAKxH,IAAcyH,YAE3B,KAAQ,KACA,MAAKzH,IAAoBgH,kBAEjC,KAAQ,KACA,MAAKhH,IAAW6G,SAExB,KAAQ,KACA,MAAK7G,IAAS8G,OAKtB,KAAQ,KACA,MAAK9G,IAAeoF,aAE5B,KAAQ,KACA,MAAKpF,IAAakH,WAE1B,KAAQ,KACA,MAAKlH,IAAmB+G,iBAEhC,SACK,MAAOa,IAAO,KAAUA,EAAO,IAAY5H,GAAI4G,GACxCgB,GAAO,KAAUA,EAAO,IAAY5H,GAAqBuH,oBACzDK,GAAO,KAAUA,EAAO,IAAY5H,GAAUiH,SAC7CjH,GAEjB8G,SC1OM,QAAAmB,KACE,MACRC,IAMM,QAAAC,KACE,MACRC,IAMM,QAAAC,MACE,MACRC,IAIM,QAAAC,MACE,MACRC,ICiQA,QAAAC,IACsBC,EACQC,GAEbA,EAAO7K,OAAK,IACnB4K,EAAYC,YACpBA,GCvOF,QAAAC,IAAmClI,EAAqBuC,GAChD3D,GAAWmG,EAAyB/E,GAAauC,EACzD,eAEA,QAAA4F,IAA0CnI,GAErC,MAA2B,gBAAdA,GAEhBA,EAAqC,gBAAdA,GACNM,SAAMN,EACvB,IACaxB,EAAe,eAC5BwB,GAknCF,QAAAoI,IAAuBnL,EAAcyE,EAAa3E,GAC1C,MAAK2E,KAAY3E,IAAM2E,GAAO3E,IACtCE,GC3nCM,QAAAoL,IAA6CC,GAE9C,GADeA,EAAOC,OAAWC,KACrB,EACb,KAAM,IAAkBnJ,IAClBC,GAAiBC,iBACrB,uBAA2B+I,EAA4B,uDAI3D,KACQ,WAAcG,GAAAC,KAAA3K,MAAA0K,QAAA,IAAAxK,OAAQqK,EAAMK,MACpC,QAAQ,MAAGpK,GACT,KAAM,IAAkBc,IAClBC,GAAiBC,iBACrB,uBAA2B+I,EAA8B,8EC2P/D,QAAAM,IAAyCC,EAAgBC,GACvD,GAAWC,GAAG,SAAmBf,GACxB,OAAUA,GACf,IAAegB,IAAMC,MACb,MAAG,EACX,KAAeD,IAASE,SAExB,IAAeF,IAASG,SAIhB,MAAG,EACX,KAAeH,IAAQI,QACf,MAAG,EACX,SACQ,MAAK5K,GAAuB,uBAExCwJ,IAEM,OAAMe,GAAIF,GAAQE,EAC1BD,GC9SM,QAAAO,IAAmCf,GAEnC,IAAC,GADK1H,GAAM,GACNmD,EAAI,EAAGA,EAAOuE,EAAOlL,OAAK2G,IACxBnD,EAAOxD,OAAK,IACdwD,EAAkB0I,GAC1B1I,IACMA,EAAgB2I,GAAKjB,EAAIkB,IAAGzF,GACpCnD,EACM,OAAgB0I,IACxB1I,GAGA,QAAA2I,IAAsCE,EAAmBC,GAGnD,IAAC,GAFK9I,GAAa8I,EACXtM,EAAUqM,EAAQrM,OACpB2G,EAAI,EAAGA,EAAS3G,EAAK2G,IAAG,CAChC,GAAO4F,GAAUF,EAAOtF,OAAIJ,EACrB,QAAK4F,GACV,IAAS,KACD/I,GAAcgJ,GAAcC,EAC5B,MACR,KAAeD,IACPhJ,GAAcgJ,GAAiBE,EAC/B,MACR,SACQlJ,GAEZ+I,GACM,MACR/I,GAGA,QAAA0I,IAAuC1I,GAC/B,MAAOA,GAAagJ,GAC5BG,GAQM,QAAAC,IAA0C1B,GAG9C,GAAYlL,GAAOkL,EAAQlL,MAExB,IADGwB,EAAOxB,GAAK,EAAiB,gBAASkL,GAC3B,IAAPlL,EAKF,MAJAwB,GACA0J,EAAOnE,OAAG,KAAeyF,IAAQtB,EAAOnE,OAAG,KAAyB4F,GACvD,kBAAOzB,EACxB,iBACiB2B,GACrBC,UASI,KAAC,GAL0BC,GAAS/M,EAAK,EAE/BgN,KACIC,EAAM,GAEVC,EAAI,EAAOA,EAASlN,GAAK,CAGrC,GAASmN,GAAOjC,EAAQhF,QAAWsG,GAASU,EAMrC,SALAC,EAAI,GAAOA,EAA6BJ,IACzC3L,EAAmC,mCAAO8J,EAChD,KAEiBA,EAAOnE,OAAIoG,EAAM,IAEhC,IAAyBR,IACvB,GAAkBS,GAAOlC,EAAU5F,UAAM4H,EAAOC,GACrCd,MAAA,EACqB,KAAdY,EAAOjN,OAGhBqM,EACTe,GACgBH,GAAiBG,EACxBf,EAAkBY,EACXA,EAChB,IACQD,EAAKK,KAAUhB,EACjB,MACR,KAAeI,IACCQ,GAAQ/B,EAAU5F,UAAM4H,EAAOC,GAC/BF,GAAS,IACjB,MACR,KAAkBP,IAEFO,GAAQ/B,EAAU5F,UAAM4H,EAAKC,EAAM,EAC3C,MACR,SACM/L,EAAmC,mCAAO8J,EACjD,KAEIgC,EAAMC,EACb,EAEM,MAAC,IAAgBN,IACzBG,GCpJM,QAAAM,IAA2CC,EAAoBC,GAC7DhM,EAAiB,IAANgM,EAA0C,mCAAeA,GAExED,EAAkBE,kBAAgBC,GAAMC,OACjCC,QAAiBF,GACvBE,UAIDL,EAAkBE,kBAEHI,GAAMF,OACZC,QAAiBC,GAC1BD,UAEwBL,EAAuBE,kBAE/BK,GAAMH,OACbC,QAAkBE,GAC3BF,UAC8BG,YACdD,GAAqBE,qBACrBF,GAAuBG,wBAC/BC,QACR,IAEeX,EAAuBE,kBAASU,GAAMR,OAC9CC,QAAUO,GAChBP,UAEoBG,YACbI,GAAsBC,sBACtBD,GAAoBE,qBACpBH,QACR,IAIAX,EAAkBE,kBAAmBa,GAAQX,OAC7CJ,EAAkBE,kBAAiBc,GAAQZ,OAC3CJ,EAAkBE,kBAAQe,GAAQb,OAClCJ,EAAkBE,kBAAegB,GACrCd,OC4aA,QAAAe,IAA2CC,GACnC,UAAuBC,IAAI,SAAQC,EAAQC,GACxCH,EAAUI,UAAG,SAAaC,GAC/B,GAAYxL,GAASwL,EAAsBC,OAAQzL,MAC5CqL,GACTrL,IAEOmL,EAAQO,QAAG,SAAaF,GACvBF,EAAOE,EAAsBC,OACrCjO,UCgCJ,QAAAmO,IAAmDC,GAK3C,MAJA5N,GACqB,gBAAb4N,GAEZ,qDAEJA,EAKA,QAAAC,IAC6BC,GAErB,MAASC,IACVD,EACYzB,GAEnBF,OAKA,QAAA6B,IAC6BF,GAErB,MAASC,IACVD,EACehB,GAEtBX,OAKA,QAAA8B,IAC6BH,GAErB,MAASC,IACVD,EACY5B,GAEnBC,OAKA,QAAA4B,IAC6BD,EACd3B,GAEV,MAAI2B,aAAgCI,IAC3BJ,EAAM3B,MAClBA,GACavM,EACb,wCCvSF,QAAAuO,IAC6BL,GAErB,MAASM,IAA2BN,EAAUnB,GACtDR,OAKA,QAAAkC,IAC6BP,GAErB,MAASM,IAAuCN,EAAgBb,GACxEd,OAKA,QAAAmC,IAC6BR,GAErB,MAASM,IACVN,EACaxB,GAEpBH,OAKA,QAAAiC,IAC6BN,EACd3B,GAEV,MAAI2B,aAAgCI,IAC3BJ,EAAM3B,MAClBA,GACavM,EACb,wCCxPF,QAAA2O,IAC6BT,GAExB,MAAIA,aAAgCI,IAC3BJ,EAAM3B,MACEY,GAEpBZ,OACavM,EACb,wCAGF,QAAA4O,IAAkCC,GAC1B,MAAOA,GAAK/E,KACpBgF,UC+CA,QAAAC,IAAyCC,GACjC,WACRtN,KADyCsN,EAAUC,UCkM7C,QAAAC,IAAmEC,GACpE,IAAcA,EACT,MAAC,IACTC,GAEO,QAAYD,EAAQjM,MACzB,IAAkB,cACV,MAAC,IAA6BmM,IAAYF,EAASG,OAE3D,KAAW,OACH,MAAC,IAAiCC,IAC3BJ,EAAOG,OACPH,EAAaK,cACxB,IAEJ,KAAe,WACP,MAAYL,GAAQG,MAE5B,SACE,KAAM,IAAkBzO,IAClBC,GAAiBC,iBAI7B,kEC3UM,QAAA0O,IAAsChR,GACpC,MAAqBiR,IAAIjR,GAAS,OAAS,QACnD,aAMA,QAAAiR,IAAwCjR,EAAmBkR,GACtD,GAAwB,gBAAb,KAAAlR,EAAA,YAAAmR,GAAAnR,KAA8B,OAAVA,EAC1B,OACR,CAGI,KAAiB,GADToR,GAA4BpR,EACnBC,EAAO,EAAPoR,EAAOH,EAAPjR,EAAAoR,EAAOlR,OAAAF,IAAA,CAAvB,GAAYqR,GAAAD,EAAApR,EACZ,IAAOqR,IAAUF,IAAyC,kBAAxBA,GAAQE,GACrC,OACR,EAEI,OACR,ECgfA,QAAAC,IAAyCpM,GAChC,QACoB,gBAAb,KAAAA,EAAA,YAAAqM,GAAArM,KACE,OAATA,GACEA,YAAkBZ,QAClBY,YAAiB5E,OACjB4E,YAAqBsM,KACrBtM,YAAiBuM,KACjBvM,YAAiCwM,KACjCxM,YAEXyM,KAEA,QAAAC,IACiBpQ,EACMqQ,EACT3M,GAET,IAAqBoM,GAAOpM,KAAkBE,EAAQF,GAAE,CACzD,GAAiBG,GAAmBC,EAAQJ,EACzC,MAA6B,cAAjBG,EAEAwM,EAAYC,YAAQtQ,EACnC,oBACeqQ,EAAYC,YAAQtQ,EAAM,IACzC6D,IAOE,QAAA0M,IACcC,EACc5G,GAE7B,GAAKA,YAA8BG,IAC9B,MAAKH,GACb6G,CAAM,IAA8B,gBAAd7G,GACd,MAAgC8G,IAAWF,EACnD5G,EAEE,MAAM,IAAkBjJ,IAClBC,GAAiBC,iBACrB,YAAsB2P,EAAA,0FAY5B,QAAAE,IACoBF,EACN5G,GAEZ,IACQ,MAAuBD,IAAMC,GACrC6G,EAAQ,MAAG5Q,GACT,GAAaG,GAAe2Q,GAAI9Q,EAChC,MAAM,IAAkBc,IAClBC,GAAiBC,iBACrB,YAAsB2P,EAAA,gCAE1BxQ,IAOF,QAAA2Q,IAA2CjR,GACnC,MAAMA,aAAiBO,OAAQP,EAAQM,QAAQN,KC6gCvD,QAAAkR,IACoBJ,EACuB/L,GAEtC,WAAuBjD,KAAfiD,GAEFoM,OAET,IAEmBrM,EAAWgM,EAAS/L,GAAa,UAC3BjB,EAAWgN,EAAW,UAAS,QAAS/L,EAAQoM,OAE3EpM,GAEA,QAAAqM,IACoBN,EACsBO,EACpBC,GAEjB,GAAcD,YAA+BE,IAE1C,IAAgBF,EAAUC,YAAeA,EAC7C,KAAM,IAAkBrQ,IAClBC,GAAiBC,iBAGzB,sEACQ,OACRkQ,GARE,KAAuBjM,GAAW0L,EAAqB,oBAAG,EAC5DO,GAeI,QAAAG,IACgBF,EACEG,GAEnB,GAASA,EAAQC,QAAWrP,UAAE,CAG/B,GAAsBsP,GACbC,EAAK,CACR,OAAAH,GAAoBI,WAAItS,IAAC,SAAMqK,GACnC,GAASkI,GAAG,GAAoBC,IACrBT,EACH1H,EAAIkI,IAAItQ,IACRoI,EAAIkI,IACFL,EACRO,UAUI,OATAxR,GACEoJ,EAAKtG,OAAesH,GAAMC,MAEhC,yCACIrK,GACImR,GAAYF,EAAMQ,MAAcC,cAAQP,EAAQ/H,EAAKkI,KAAI,EAEjE,mCACKH,EAAS/H,EAAKkI,KAEfxO,KAAyC,QAC1CwO,MACKK,UAAI,EACJC,SAEZR,OAIA,GAAgBS,GAAWZ,EAASC,OAC9B,OAAAD,GAAoBI,WAAItS,IAAC,SAAMqK,GACnC,GAASkI,GAAG,GAAoBC,IACrBT,EACH1H,EAAIkI,IAAItQ,IACRoI,EAAIkI,IACFL,EACRO,WACUG,GAAM,EACNC,GAAM,CAUZ,OATIxI,GAAKtG,OAAesH,GAAOC,QAC3BsH,EAAeE,EAAQnN,QAAO0E,EAAIkI,IAAMtQ,KAC1ChB,EAAS2R,GAAK,EAAkC,gCAC1CE,EAAeA,EAAOC,OAAO1I,EAAIkI,IAC/CtQ,MACUoI,EAAKtG,OAAesH,GAASI,UACzBqH,EAAeA,EAAIE,IAAO3I,EAAMkI,KACpCM,EAAeC,EAAQnN,QAAO0E,EAAIkI,IAC5CtQ,OACa8B,KAAkBkP,GAAO5I,EAAMtG,MAAKwO,MAAUK,WAAUC,SACvEA,KAIJ,QAAAI,IAA0ClP,GACjC,OAAQA,GACb,IAAesH,IAAMC,MACb,MAAS,OACjB,KAAeD,IAAUE,SACzB,IAAeF,IAASG,SAChB,MAAY,UACpB,KAAeH,IAAQI,QACf,MAAW,SACnB,SACQ,MAAK5K,GAAwB,wBAEzCkD,ICxrDM,QAAAmP,IAA0DC,GACtDA,EAASvK,SAAgBwK,gBACpB,YACX,SAAsBC,GAAK,UAAaC,IAAKD,IAClCrQ,EAEfuQ,KCvCM,QAAAC,IAAoCC,GACpBP,GACtBO,G9BhBAvR,OAAOwR,eAAe7U,EAAqB,cAAgBwD,OAAO,GAGlE,ICeC3C,IDfGiU,GAAU7U,EAAoB,G+BSVuB,GAAWsT,GAAA,QAAatT,a9BEhD,SAAoBX,GAClBA,IAAA,SAAK,QACLA,IAAA,SAAK,QACLA,IAAA,UACF,UAJoBA,YAMpB,IAAYV,IAAWU,GAAOc,MEsB9BY,GAAA,mBAAAwS,MAeA,MAbSA,GAAWC,YAAlB,SAAqCC,GAChBF,EAAUE,UACvBjT,EACN,4BACe+S,EAASE,SAC1BA,GAEOF,EAAWvS,YAAlB,WAIQ,MAHcuS,GAAUE,UACxBjT,EACN,oBACsB+S,EACxBE,UACDF,KH8IGG,GAAYC,MAAQA,KAAKD,WAAa,WACxC,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC9FD,EAAED,UAAYE,IACX,SAAUD,EAAGC,GAChB,IAAK,GAAIC,KAAKD,GACRA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAGtC,OAAO,UAAUF,EAAGC,GAElB,QAASE,KACPP,KAAK9O,YAAckP,EAFrBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,QgCjMlE5S,IAIb4G,GAAc,KAGPC,UAAqB,YAGvBC,QAAmB,UAQV7G,iBAA4B,mBAS3B8G,kBAA6B,oBAGrCK,UAAqB,YAMhBC,eAA0B,iBASvBC,kBAA6B,oBAM/BH,gBAA2B,kBAMxBH,mBAA8B,qBAsB7BO,oBAA+B,sBAS3CC,QAAmB,UAiBdC,aAAwB,eAGvBrC,cAAyB,gBAM9B6B,SAAoB,WASjBC,YAAuB,cAGzBQ,UACT,aAQF3H,GAAA,SAAA+S,GAIE,QAAA/S,GAA+B4G,EAA0BvH,GAAzD,GAAA2T,GACED,EAAAtS,KAAA6R,KAAcjT,IAMfiT,IhCuLC,OgC9LmBU,GAAIpM,KAAMA,EAAWoM,EAAO3T,QAAQA,EAHzD2T,EAAI/Q,KAAmB,gBASjB+Q,EAASC,SAAG,WAAM,MAAOD,GAAK/Q,KAAA,WAAe+Q,EAAKpM,KAAA,MAAUoM,EAAU3T,SAC5E2T,EACF,MAZoCX,IAAArS,EAAK+S,GAYxC/S,GAAAV,OhC8OG+B,GAA4B,kBAAX6R,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUvV,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXsV,SAAyBtV,EAAI4F,cAAgB0P,QAAUtV,IAAQsV,OAAO/S,UAAY,eAAkBvC,IAgFlQoF,GAA6C,kBAAXkQ,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUvV,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXsV,SAAyBtV,EAAI4F,cAAgB0P,QAAUtV,IAAQsV,OAAO/S,UAAY,eAAkBvC,IOzcvRwV,GAAA,mBAAAC,MAYA,MAXSA,GAAKC,MAAZ,WAKM,IAAC,GAHMC,GACwD,iEACzDC,EAAM,GACN9O,EAAI,EAAGA,EAAK,GAAKA,IACnB8O,GAASD,EAAOzO,OAAK2O,KAAMC,MAAKD,KAASE,SAAQJ,EACzDxV,QAEM,OADAwB,GAAqB,KAAdiU,EAAOzV,OAA4B,oBAAWyV,GAE7DA,GACDH,KCOD/D,GAAA,WAOE,QAAAsE,GAAwCC,GACdvO,IACpBgN,KAAcwB,EACpBD,EAqEF,MAnESD,GAAgBG,iBAAvB,SAAsCC,GACXxS,EAAwB,wBAAW1D,UAAK,GAClDsE,EAAwB,wBAAU,SAAG,EAAU4R,GACtC1O,GACxB,KAEQ,MAAC,IAAQsO,GADqBlU,GAAcC,cAAKsU,KAASD,IAE1D,MAAG9U,GACT,KAAM,IAAkBc,IAClBC,GAAiBC,iBAC0B,gDAEnDhB,KAGK0U,EAAcM,eAArB,SAAuCC,GAGlC,GAFsB3S,EAAsB,sBAAW1D,UAAK,GACnCqH,MACjBgP,YAAwB/O,aACjC,KAAuBjB,GAAsB,sBAAc,aAAG,EAChEgQ,EASM,OAAC,IAAQP,GALGzR,MAAkBhC,UAAI7B,IACjCmC,KAAM0T,EAAE,SAAaC,GAClB,MAAOrP,QAAaC,aAC5BoP,KACKlQ,KAAK,MAIP0P,EAAAzT,UAAQkU,SAAf,WAGQ,MAFmB7S,GAAgB,gBAAW1D,UAAK,GACjCwH,IACF5F,GAAcC,cAAK2U,KAAKhC,KAChDwB,IAEOF,EAAAzT,UAAYoU,aAAnB,WAC2B/S,EAAoB,oBAAW1D,UAAK,GACjCqH,GAExB,KAAC,GADOqP,GAAG,GAAcpP,YAAKkN,KAAcwB,EAAS/V,QAC/C2G,EAAI,EAAGA,EAAO4N,KAAcwB,EAAO/V,OAAK2G,IAC1C8P,EAAG9P,GAAO4N,KAAcwB,EAAW7O,WAC3CP,EACM,OACR8P,IAEOZ,EAAAzT,UAAQ8S,SAAf,WACQ,MAAgB,gBAAOX,KAAW+B,WAC1C,KAMOT,EAAAzT,UAAOsU,EAAd,SAA0BC,GAClB,MAAKpC,MAAcwB,IAAUY,EACrCZ,GAMOF,EAAAzT,UAAUwU,EAAjB,SAA6BD,GACrB,MAAoBrQ,GAAKiO,KAAcwB,EAAOY,EACtDZ,IACDF,KAUoBgB,GAAyBhV,EACxC0P,GAEJ,iEyBtHFD,GAAA,WAME,QAAAwF,GAA4BC,EAAmBC,GAI1C,GAHsBvT,EAAW,WAAW1D,UAAK,GACrCsE,EAAW,WAAU,SAAG,EAAY0S,GACpC1S,EAAW,WAAU,SAAG,EAAa2S,IACvCC,SAAUF,IAAYA,GAAM,IAAYA,EAAM,GACzD,KAAM,IAAkB9U,IAClBC,GAAiBC,iBACoC,0DAE7D4U,EACG,KAAUE,SAAWD,IAAaA,GAAO,KAAaA,EAAO,IAC9D,KAAM,IAAkB/U,IAClBC,GAAiBC,iBACuC,6DAEhE6U,EAEIzC,MAAK2C,EAAYH,EACjBxC,KAAM4C,EACZH,EAkCF,MA7BEvU,QAAAwR,eAAI6C,EAAA1U,UAAQ,YjC62BNgK,IiC72BN,WACQ,MAAKmI,MACb2C,GjC82BME,YAAY,EACZC,ciC/2BL,IAKD5U,OAAAwR,eAAI6C,EAAA1U,UAAS,ajCg3BPgK,IiCh3BN,WACQ,MAAKmI,MACb4C,GjCi3BMC,YAAY,EACZC,ciCl3BL,IAMMP,EAAA1U,UAAOsU,EAAd,SAA8BC,GACtB,MAAKpC,MAAK2C,IAAUP,EAAKO,GAAQ3C,KAAM4C,IAAUR,EACzDQ,GAMOL,EAAA1U,UAAUwU,EAAjB,SAAiCD,GACxB,MACcrQ,GAAKiO,KAAK2C,EAAOP,EAAMO,IACvB5Q,EAAKiO,KAAM4C,EAAOR,EAEzCQ,IACDL,KCpEDQ,GAAA,WAWE,QAAAA,GACiCC,EACAC,EACVC,EACAC,GAHZnD,KAAUgD,WAAYA,EACtBhD,KAAciD,eAAQA,EACtBjD,KAAIkD,KAAQA,EACZlD,KAAGmD,IACXA,EACL,MAACJ,MAG0BK,GAAe,YAG1CC,GAAA,WAEE,QAAAC,GAAsCC,EAAmBC,GAApCxD,KAASuD,UAAQA,EAChCvD,KAASwD,SAAWA,GAC1BJ,GAoBF,MAlBElV,QAAAwR,eAAI4D,EAAAzV,UAAiB,qBlCs8BfgK,IkCt8BN,WACQ,MAAKmI,MAASwD,WACtBJ,IlCu8BMP,YAAY,EACZC,ckCx8BL,IAEDQ,EAAAzV,UAAMqE,OAAN,SAAgBkQ,GACP,MACAA,aAAsBkB,IACtBlB,EAAUmB,YAASvD,KAAUuD,WAC7BnB,EAASoB,WAASxD,KAE3BwD,UAEAF,EAAAzV,UAAS4V,UAAT,SAA2BrB,GAClB,MACcrQ,GAAKiO,KAAUuD,UAAOnB,EAAWmB,YACjCxR,EAAKiO,KAASwD,SAAOpB,EAE5CoB,WACDF,KlCm9BGI,GAAiB1D,MAAQA,KAAKD,WAAa,WAC3C,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC5FD,EAAED,UAAYE,IACb,SAAUD,EAAGC,GACd,IAAK,GAAIC,KAAKD,GACNA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAG1C,OAAO,UAAUF,EAAGC,GAEhB,QAASE,KACLP,KAAK9O,YAAckP,EAFvBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,QmCzgCvFoD,GAAA,WAKE,QAAAC,GAAqCnL,EAAiBoL,EAAiBpY,GACjEuU,KAAK8D,KAASrL,EAAQoL,EAC5BpY,GAwIF,MAjIUmY,GAAA/V,UAAIiW,KAAZ,SAA+BrL,EAAiBoL,EAAiBpY,OACtC8C,KAAfsV,EACFA,EACR,EAAiBA,EAAWpL,EAAQhN,QAC9BoB,EAAU,UAASgX,EAAmB,iBAAWpL,EACvDhN,YAEyB8C,KAAf9C,EACFA,EAAWgN,EAAOhN,OAC1BoY,EAAiBpY,EAAWgN,EAAOhN,OAAUoY,GACvChX,EAAU,UAASpB,EAAsB,kBAASgN,EAAOhN,OAC/DoY,IACI7D,KAASvH,SAAYA,EACrBuH,KAAO6D,OAAUA,EACjB7D,KAAI+D,IACVtY,GAOQmY,EAAA/V,UAASmW,UAAjB,SACoBvL,EACHoL,EACApY,GAEf,GAAUkL,GAAezI,OAAOsS,OAAOtS,OAAe4C,eAAQkP,MAExD,OADFrJ,GAAKmN,KAASrL,EAAQoL,EAAUpY,GAEtCkL,GAEAzI,OAAAwR,eAAIkE,EAAA/V,UAAM,UnCugCJgK,ImCvgCN,WACQ,MAAKmI,MACb+D,KnCwgCMlB,YAAY,EACZC,cmCzgCL,IAEDc,EAAA/V,UAAMqE,OAAN,SAAkBkQ,GACV,MACR,KADawB,EAAWK,WAAKjE,KAAQoC,IAGrCwB,EAAA/V,UAAKqW,MAAL,SAA+BC,GAC7B,GAAc1L,GAAOuH,KAASvH,SAAM2L,MAAKpE,KAAO6D,OAAM7D,KAAUqE,QAU1D,OATQF,aAAiBP,GACnBO,EAAQtV,QAAC,SAAOiJ,GAChBW,EAAKK,KACfhB,KACwC,gBAAdqM,GAClB1L,EAAKK,KACfqL,GACMtX,EAA4C,4CAClDsX,GACWnE,KAAUgE,UACvBvL,IAGQmL,EAAA/V,UAAKwW,MAAb,WACQ,MAAKrE,MAAO6D,OAAO7D,KAC3BvU,QAEAmY,EAAA/V,UAAQyW,SAAR,SAAsBC,GAGd,MAFFA,OAAqBhW,KAAdgW,EAAkB,EAAQA,EAC/BtX,EAAK+S,KAAOvU,QAAQ8Y,EAA8C,4CAC7DvE,KAAUgE,UACfhE,KAASvH,SACTuH,KAAO6D,OAAOU,EACdvE,KAAOvU,OAEf8Y,IAEAX,EAAA/V,UAAO2W,QAAP,WAEQ,MADAvX,IAAM+S,KAAUlR,UAAwC,sCACnDkR,KAAUgE,UAAKhE,KAASvH,SAAMuH,KAAO6D,OAAM7D,KAAOvU,OAC/D,IAEAmY,EAAA/V,UAAY4W,aAAZ,WAEQ,MADAxX,IAAM+S,KAAUlR,UAA6C,2CACxDkR,KAASvH,SAAKuH,KAC3B6D,SAEAD,EAAA/V,UAAW6W,YAAX,WAEQ,MADAzX,IAAM+S,KAAUlR,UAA4C,0CACvDkR,KAASvH,SAAKuH,KAAQqE,QACnC,IAEAT,EAAA/V,UAAGgK,IAAH,SAAiB8M,GAET,MADA1X,GAAM0X,EAAO3E,KAAOvU,OAAwB,sBACvCuU,KAASvH,SAAKuH,KAAO6D,OAClCc,IAEAf,EAAA/V,UAAOiB,QAAP,WACQ,MACR,KADakR,KAAOvU,QAGpBmY,EAAA/V,UAAU+W,WAAV,SAAsBxC,GACjB,GAAMA,EAAO3W,OAAOuU,KAAQvU,OACvB,OACR,CAEI,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAOvU,OAAK2G,IAC/B,GAAK4N,KAAInI,IAAGzF,KAAUgQ,EAAIvK,IAAIzF,GACzB,OACR,CAGI,QACR,GAEAwR,EAAA/V,UAAOgB,QAAP,SAAqCJ,GAC/B,IAAC,GAAK2D,GAAO4N,KAAO6D,OAAKjL,EAAOoH,KAAQqE,QAAGjS,EAAMwG,EAAKxG,IACtD3D,EAAKuR,KAASvH,SAClBrG,KAGFwR,EAAA/V,UAAO8N,QAAP,WACQ,MAAKqE,MAASvH,SAAM2L,MAAKpE,KAAO6D,OAAM7D,KAC9CqE,UAEOT,EAAUK,WAAjB,SAA0BY,EAAUC,GAE9B,IAAC,GADIf,GAAO5C,KAAI4D,IAAGF,EAAOpZ,OAAIqZ,EAASrZ,QACjC2G,EAAI,EAAGA,EAAM2R,EAAK3R,IAAG,CAC7B,GAAUJ,GAAK6S,EAAIhN,IAAIzF,GACZH,EAAK6S,EAAIjN,IAAIzF,EACrB,IAAKJ,EAASC,EAAO,OAAI,CACzB,IAAKD,EAASC,EAAO,MAC1B,GACG,MAAG4S,GAAOpZ,OAAKqZ,EAAQrZ,QAAW,EAC/BoZ,EAAOpZ,OAAKqZ,EAAQrZ,OAAU,EAEtC,GACDmY,KAMDtL,GAAA,SAAAmI,GAAA,QAAAuE,KnC2/BQ,MAAkB,QAAXvE,GAAmBA,EAAOrU,MAAM4T,KAAMxU,YmCv9BrDwU,KAAA,MApCkC0D,IAAAsB,EAAIvE,GACpCuE,EAAAnX,UAAeoX,gBAAf,WAKQ,MAAKjF,MAAUrE,UAAK/J,KAC5B,MAEAoT,EAAAnX,UAAQ8S,SAAR,WACQ,MAAKX,MACbiF,mBAKOD,EAAUE,WAAjB,SAA8BvO,GAKzB,GAAKA,EAAQhF,QAAM,OAAM,EAC1B,KAAM,IAAkBjE,IAClBC,GAAiBC,iBACrB,iBAAqB+I,EAEzB,wCAMM,OAAC,IAAgBqO,GAFTrO,EAAaK,MAAK,KAAOmO,OAAC,SAAOrN,GAAI,MAAOA,GAAOrM,OAAI,MAKhEuZ,EAAUzM,WAAG,GAAgByM,OACrCA,GAAArB,IAEqByB,GAA8B,2BAGpDC,GAAA,SAAA5E,GAAA,QAAA6E,KnCu/BQ,MAAkB,QAAX7E,GAAmBA,EAAOrU,MAAM4T,KAAMxU,YmCz4BrDwU,KAAA,MA9G+B0D,IAAA4B,EAAI7E,GAKlB6E,EAAiBC,kBAAhC,SAAgDzN,GACxC,MAAiBsN,IAAKI,KAC9B1N,IAEAwN,EAAAzX,UAAeoX,gBAAf,WACQ,MAAAjF,MAAerE,UACf3P,IAAC,SAAG8F,GAKA,MAJHA,GAAMA,EAAQ2T,QAAK,KAAS,QAAQA,QAAI,IAAS,OACtCH,EAAkBC,kBAAMzT,KACjCA,EAAM,IAAMA,EACjB,KAEFA,IACKF,KACT,MAEA0T,EAAAzX,UAAQ8S,SAAR,WACQ,MAAKX,MACbiF,mBAKAK,EAAAzX,UAAU6X,WAAV,WACQ,MAAkB,KAAb1F,KAAOvU,QAhOsB,aAgORuU,KAAInI,IAAG,IAMlCyN,EAAQK,SAAf,WACQ,MAAC,IAAaL,IAvOoB,cAoPnCA,EAAgBM,iBAAvB,SAAoCjP,GAmBlC,IAlBA,GAAc8B,MACHoN,EAAM,GACZzT,EAAK,EAEa0T,EAAG,WACrB,GAAsB,IAAdD,EAAOpa,OAChB,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACrB,uBAA2B+I,EAAoC,4EAI3D8B,GAAKK,KAAU+M,GAChBA,EACT,IAEeE,GAAS,EAEhB3T,EAAOuE,EAAOlL,QAAG,CACvB,GAAOuM,GAAOrB,EAAIvE,EACf,IAAY,OAAV4F,EAAY,CACZ,GAAE5F,EAAI,IAASuE,EAAQlL,OACxB,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACiB,uCAE1C+I,EACA,IAAUqP,GAAOrP,EAAEvE,EAAM,EACtB,IAAgB,OAAT4T,GAAyB,MAARA,GAA0B,MAAVA,EACzC,KAAM,IAAkBtY,IAClBC,GAAiBC,iBACe,qCAExC+I,EACOkP,IAASG,EACf5T,GACH,MAAqB,MAAT4F,GACC+N,GAAgBA,EAE7B3T,KAAoB,MAAR4F,GAAyB+N,GAI5BF,GAAM7N,EAEf5F,MALsB0T,IAEtB1T,KAOC,GAFiB0T,IAEJC,EACd,KAAM,IAAkBrY,IAClBC,GAAiBC,iBACK,2BAE9B+I,EAEM,OAAC,IAAa2O,GACtB7M,IAEO6M,EAAU/M,WAAG,GAAa+M,OAClCA,GAAA3B,IChTDsC,GAAA,WACE,QAAAC,GAAuCvP,GAAlBqJ,KAAIrJ,KAAcA,EAC/B1J,EACOiZ,EAAcC,cAAMxP,GACuB,uDAChDA,EAAUgF,UAAK/J,KAEzB,MA0CF,MAxCEsU,GAAArY,UAAMqE,OAAN,SAAgCkQ,GACvB,MACS,QAATA,GAET,IAFkC9J,GAAW2L,WAAKjE,KAAKrJ,KAAOyL,EAAMzL,OAIpEuP,EAAArY,UAAQ8S,SAAR,WACQ,MAAKX,QAAKrJ,MAKXuP,EAAUjC,WAAjB,SAAiCmC,EAAiBC,GAC1C,MAAa/N,IAAW2L,WAAGmC,EAAKzP,KAAI0P,EAC5C1P,OAEOuP,EAAaC,cAApB,SAAuCxP,GAC/B,MAAKA,GAAOlL,OAAI,GACxB,GAQOya,EAAYI,aAAnB,SAAsC7N,GAC9B,MAAC,IAAeyN,GAAC,GAAgB5N,IAASG,EAClD2L,WASO8B,EAAcK,eAArB,SAAkC5P,GAC1B,MAAC,IAAeuP,GAAa5N,GAAW4M,WAChDvO,KA7BOuP,EAAKM,MAAG,GAAeN,GAAC,GAAgB5N,SA8BhD4N,KCzCDO,GAAA,WAGE,QAAAC,GAC2BzY,EACQ0Y,EACPC,EACFpV,GAHfwO,KAAG/R,IAAaA,EAChB+R,KAAO2G,QAAiBA,EACxB3G,KAAI4G,KAAaA,EAGtB5G,KAAkB6G,kBAAUrV,EAClCqV,kBA6CF,MA3CEH,GAAA7Y,UAAK6F,MAAL,SAAqBiD,GACb,MAAKqJ,MAAK4G,KAAMlT,MACxBiD,IAEA+P,EAAA7Y,UAAUiZ,WAAV,SAA0BnQ,GACxB,GAAWjD,GAAOsM,KAAMtM,MAAOiD,EACzB,OAAMjD,GAAQA,EAAQrF,YAC9BE,IAEAmY,EAAA7Y,UAAKQ,MAAL,WACQ,MAAK2R,MAAK4G,KAClBvY,SAEAqY,EAAA7Y,UAAMqE,OAAN,SAAyCkQ,GAChC,MACAA,aAAoBsE,IACrB1G,KAAI/R,IAAOiE,OAAMkQ,EAAKnU,MACtB+R,KAAQ2G,QAAOzU,OAAMkQ,EAASuE,UAC9B3G,KAAK4G,KAAO1U,OAAMkQ,EAAMwE,OACxB5G,KAAkB6G,oBAAUzE,EAEpCyE,mBAEAH,EAAA7Y,UAAQ8S,SAAR,WACS,MACL,YAAgBX,KAAI/R,IAAA,KAAS+R,KAAQ2G,QAAA,KAAS3G,KAAK4G,KAAe,yBACvC5G,KAAkB6G,kBAEjD,MAEOH,EAAYK,aAAnB,SAAqCC,EAAmBC,GAChD,MAAYhB,IAAWhC,WAAG+C,EAAI/Y,IAAIgZ,EAC1ChZ,MAEOyY,EAAcQ,eAArB,SAAsCxT,EAAcsT,EAAcC,GAChE,GAAQE,GAAKH,EAAMtT,MAAQA,GACnB0T,EAAKH,EAAMvT,MAAQA,EACxB,YAAiBnF,KAAd4Y,OAAmC5Y,KAAf6Y,EACfD,EAAU1D,UACrB2D,GACava,EACb,2DAEH6Z,KAODW,GAAA,WACE,QAAAC,GAAqCrZ,EAAmC0Y,GAAnD3G,KAAG/R,IAAaA,EAAW+R,KAAO2G,QAAoBA,EAe7E,MAbEW,GAAAzZ,UAAQ8S,SAAR,WACQ,MAAC,cAAkBX,KAAI/R,IAAA,KAAS+R,KAAQ2G,QAChD,KAEOW,EAAAzZ,UAAMqE,OAAb,SAA+BkQ,GACtB,MACAA,IAASA,EAAQuE,QAAOzU,OAAK8N,KAAS2G,UAASvE,EAAInU,IAAOiE,OAAK8N,KAExE/R,MAEOqZ,EAAYP,aAAnB,SAAqCC,EAAmBC,GAChD,MAAYhB,IAAWhC,WAAG+C,EAAI/Y,IAAIgZ,EAC1ChZ,MACDqZ,KChEDC,GAAA,WAIE,QAAAC,GAA4CvD,EAAuBwD,GAAhDzH,KAAUiE,WAAeA,EACtCjE,KAAKyH,KAAOA,GAAkBC,GACpClB,MA0MF,MAvMEgB,GAAA3Z,UAAM8Z,OAAN,SAAa1Z,EAAUI,GACf,MAAC,IAAamZ,GACdxH,KAAWiE,WACXjE,KAAKyH,KACAE,OAAI1Z,EAAOI,EAAM2R,KAAYiE,YAC/B2D,KAAK,KAAM,KAAUF,GAAMG,MAAM,KAE5C,QAGAL,EAAA3Z,UAAMia,OAAN,SAAa7Z,GACL,MAAC,IAAauZ,GACdxH,KAAWiE,WACXjE,KAAKyH,KACAK,OAAI7Z,EAAM+R,KAAYiE,YACxB2D,KAAK,KAAM,KAAUF,GAAMG,MAAM,KAE5C,QAGAL,EAAA3Z,UAAGgK,IAAH,SAAU5J,GAER,IADA,GAAQ8Z,GAAO/H,KAAMyH,MACTM,EAAUjZ,WAAG,CACvB,GAASkZ,GAAOhI,KAAWiE,WAAIhW,EAAM8Z,EAAM9Z,IACxC,IAAW,IAAP+Z,EACC,MAAKD,GACb1Z,KAAc2Z,GAAK,EACbD,EAAOA,EACb/V,KAAcgW,EAAK,IACbD,EAAOA,EACb9V,OAEI,MACR,OAIAuV,EAAA3Z,UAAiBoa,kBAAjB,SAAwBha,GAGtB,IAFA,GAAQ8Z,GAAO/H,KAAMyH,KACNS,EAAqD,MACxDH,EAAUjZ,WAAG,CACvB,GAASkZ,GAAOhI,KAAWiE,WAAIhW,EAAM8Z,EAAM9Z,IACxC,IAAW,IAAP+Z,EAAS,CACX,GAAMD,EAAK/V,KAAWlD,UAInB,MAAiBoZ,GACHA,EACpBja,IACc,IALZ,KADI8Z,EAAOA,EAAM/V,MACL+V,EAAM9V,MAAUnD,WAAMiZ,EAAOA,EAAO9V,KAC1C,OAAK8V,GACb9Z,IAKY+Z,EAAK,EACbD,EAAOA,EACb/V,KAAcgW,EAAK,IACNE,EAAQH,EACfA,EAAOA,EACb9V,OAGF,KAAUpF,GACkD,0EAO9D2a,EAAA3Z,UAAO8D,QAAP,SAAc1D,GAIZ,IAFA,GAAeka,GAAK,EACZJ,EAAO/H,KAAMyH,MACTM,EAAUjZ,WAAG,CACvB,GAASkZ,GAAOhI,KAAWiE,WAAIhW,EAAM8Z,EAAM9Z,IACxC,IAAW,IAAP+Z,EACC,MAAYG,GAAOJ,EAAK/V,KAChCuS,IAAcyD,GAAK,EACbD,EAAOA,EACb/V,MAEamW,GAAQJ,EAAK/V,KAAKuS,KAAK,EAC9BwD,EAAOA,EACb9V,OAGI,OACR,GAEAuV,EAAA3Z,UAAOiB,QAAP,WACQ,MAAKkR,MAAKyH,KAClB3Y,WAGAZ,OAAAwR,eAAI8H,EAAA3Z,UAAI,QtCi4CFgK,IsCj4CN,WACQ,MAAKmI,MAAKyH,KAClBlD,MtCk4CM1B,YAAY,EACZC,csCn4CL,IAGD0E,EAAA3Z,UAAMua,OAAN,WACQ,MAAKpI,MAAKyH,KAClBW,UAGAZ,EAAA3Z,UAAMwa,OAAN,WACQ,MAAKrI,MAAKyH,KAClBY,UAMAb,EAAA3Z,UAAgBya,iBAAhB,SAA6CC,GACrC,MAAMvI,MAAwByH,KAAiBa,iBACvDC,IAEAf,EAAA3Z,UAAOgB,QAAP,SAAgCJ,GAC1BuR,KAAiBsI,iBAAC,SAAEE,EAAGC,GAEnB,MADJha,GAAE+Z,EAAKC,IAEX,KAQFjB,EAAA3Z,UAAgB6a,iBAAhB,SAA6CH,GACrC,MAAMvI,MAAwByH,KAAiBiB,iBACvDH,IAOAf,EAAA3Z,UAAW8a,YAAX,SACqCC,GAE7B,MAAC,IAAqBC,IACtB7I,KAAKyH,KACL,KACAzH,KAAWiE,YACV,EAGT2E,IAOApB,EAAA3Z,UAAeib,gBAAf,SACQ7a,EAC6B2a,GAE7B,MAAC,IAAqBC,IACtB7I,KAAKyH,KACNxZ,EACC+R,KAAWiE,YACV,EAGT2E,IAMApB,EAAA3Z,UAAkBkb,mBAAlB,SACqCH,GAE7B,MAAC,IAAqBC,IACtB7I,KAAKyH,KACL,KACAzH,KAAWiE,YACX,EAGR2E,IAOApB,EAAA3Z,UAAsBmb,uBAAtB,SACQ/a,EAC6B2a,GAE7B,MAAC,IAAqBC,IACtB7I,KAAKyH,KACNxZ,EACC+R,KAAWiE,YACX,EAGR2E,IACDpB,KAGDqB,GAAA,WAKE,QAAAI,GAC4ClB,EACxBmB,EACOjF,EACPkF,EACiBP,GAE/B5I,KAAgB4I,gBAAkBA,GAAS,KAC3C5I,KAAUmJ,UAAaA,EACvBnJ,KAAUoJ,YAGd,KADA,GAAOpB,GAAK,GACAD,EAAUjZ,WAKjB,GAJAkZ,EAAWkB,EAAajF,EAAK8D,EAAI9Z,IAAWib,GAAK,EAEtCC,IAAInB,IAAO,GAElBA,EAAK,EAGJD,EADE/H,KAAWmJ,UACNpB,EACb/V,KACa+V,EACb9V,UACI,IAAe,IAAP+V,EAAS,CAGjBhI,KAAUoJ,UAAKtQ,KAAOiP,EAE5B,OAGM/H,KAAUoJ,UAAKtQ,KAAOiP,GAEpBA,EADE/H,KAAWmJ,UACNpB,EACb9V,MACa8V,EACb/V,MAgDR,MA3CEiX,GAAApb,UAAOwb,QAAP,WACQpc,EACA+S,KAAUoJ,UAAO3d,OAAI,EAEzB,wDAEF,IACgBwD,GADR8Y,EAAO/H,KAAUoJ,UAAQE,KAM9B,IAHKra,EADA+Q,KAAiB4I,gBACV5I,KAAgB4I,gBAAKb,EAAI9Z,IAAM8Z,EAC1C1Z,QAAeJ,IAAM8Z,EAAI9Z,IAAOI,MAAM0Z,EAAS1Z,OAE3C2R,KAAWmJ,UAEjB,IADIpB,EAAOA,EAAM/V,MACL+V,EAAUjZ,WAChBkR,KAAUoJ,UAAKtQ,KAAOiP,GACtBA,EAAOA,EACb9V,UAGA,KADI8V,EAAOA,EAAO9V,OACN8V,EAAUjZ,WAChBkR,KAAUoJ,UAAKtQ,KAAOiP,GACtBA,EAAOA,EACb/V,IAGI,OACR/C,IAEAga,EAAApb,UAAO0b,QAAP,WACQ,MAAKvJ,MAAUoJ,UAAO3d,OAC9B,GAEAwd,EAAApb,UAAI2b,KAAJ,WACK,GAA6B,IAAxBxJ,KAAUoJ,UAAO3d,OAAc,MAAM,KAE7C,IAAUsc,GAAO/H,KAAUoJ,UAAKpJ,KAAUoJ,UAAO3d,OAAM,EACpD,OAAKuU,MAAiB4I,gBACZ5I,KAAgB4I,gBAAKb,EAAI9Z,IAAM8Z,EAC5C1Z,QACcJ,IAAM8Z,EAAI9Z,IAAOI,MAAM0Z,EACrC1Z,QAEH4a,KAGDvB,GAAA,WAWE,QAAA+B,GACexb,EACEI,EACAqb,EAC4B1X,EACCC,GAJrC+N,KAAG/R,IAAGA,EACN+R,KAAK3R,MAAGA,EAKX2R,KAAM0J,MAAgB,MAARA,EAAgBA,EAAWD,EAAKE,IAC9C3J,KAAKhO,KAAe,MAARA,EAAeA,EAAWyX,EAAOjD,MAC7CxG,KAAM/N,MAAgB,MAARA,EAAgBA,EAAWwX,EAAOjD,MAChDxG,KAAKuE,KAAOvE,KAAKhO,KAAKuS,KAAI,EAAOvE,KAAM/N,MAC7CsS,KAwNF,MArNEkF,GAAA5b,UAAI+Z,KAAJ,SACe3Z,EACEI,EACMqb,EAC4B1X,EACCC,GAE5C,MAAC,IAAYwX,GACN,MAARxb,EAAcA,EAAO+R,KAAI/R,IACf,MAARI,EAAgBA,EAAO2R,KAAM3R,MACrB,MAARqb,EAAgBA,EAAO1J,KAAM0J,MACtB,MAAR1X,EAAeA,EAAOgO,KAAKhO,KAClB,MAARC,EAAgBA,EAAO+N,KAEhC/N,QAEAwX,EAAA5b,UAAOiB,QAAP,WACQ,OACR,GAMA2a,EAAA5b,UAAgBya,iBAAhB,SAA6CC,GACpC,MACAvI,MAAwBhO,KAAiBsW,iBAAQC,IAChDA,EAAKvI,KAAI/R,IAAM+R,KAAO3R,QACvB2R,KAAyB/N,MAAiBqW,iBAEnDC,IAMAkB,EAAA5b,UAAgB6a,iBAAhB,SAA6CH,GACpC,MACAvI,MAAyB/N,MAAiByW,iBAAQH,IACjDA,EAAKvI,KAAI/R,IAAM+R,KAAO3R,QACvB2R,KAAwBhO,KAAiB0W,iBAElDH,IAGQkB,EAAA5b,UAAGkX,IAAX,WACK,MAAK/E,MAAKhO,KAAWlD,UAExBkR,KACcA,KAAwBhO,KACtC+S,OAIF0E,EAAA5b,UAAMua,OAAN,WACQ,MAAKpI,MAAM+E,MACnB9W,KAGAwb,EAAA5b,UAAMwa,OAAN,WACK,MAAKrI,MAAM/N,MAAWnD,UACZkR,KACb/R,IACa+R,KAAM/N,MACnBoW,UAIFoB,EAAA5b,UAAM8Z,OAAN,SAAa1Z,EAAUI,EAA2B4V,GAChD,GAAK2F,GAAQ5J,KACJgI,EAAa/D,EAAIhW,EAAG2b,EAAM3b,IAc7B,OAZH2b,GADI5B,EAAK,EACL4B,EAAKhC,KAAK,KAAM,KAAM,KAAGgC,EAAK5X,KAAO2V,OAAI1Z,EAAOI,EAAa4V,GACpE,MAAqB,IAAP+D,EACP4B,EAAKhC,KAAK,KAAOvZ,EAAM,KAAM,KACpC,MACOub,EAAKhC,KACJ,KACA,KACA,KACA,KACHgC,EAAM3X,MAAO0V,OAAI1Z,EAAOI,EAE7B4V,IACQ2F,EACVC,SAEQJ,EAAA5b,UAASic,UAAjB,WACK,GAAK9J,KAAKhO,KAAWlD,UAChB,MAAS2a,GACjBjD,KACA,IAAKoD,GAAwB5J,IAGvB,OAFA4J,GAAK5X,KAAQ+X,SAAMH,EAAK5X,KAAKA,KAAS+X,UAAEH,EAAIA,EAAeI,eAChEJ,EAAIA,EAAKhC,KAAK,KAAM,KAAM,KAAIgC,EAAwB5X,KAAY8X,YAAQ,MACnEF,EACVC,SAGAJ,EAAA5b,UAAMia,OAAN,SACQ7Z,EACmBgW,GAEzB,GAA6BgG,GACxBL,EAAwB5J,IAC1B,IAAWiE,EAAIhW,EAAG2b,EAAK3b,KAAK,EACvB2b,EAAK5X,KAAUlD,WAAM8a,EAAK5X,KAAQ+X,SAAMH,EAAK5X,KAAKA,KAAS+X,UAC9DH,EAAIA,EACPI,eACCJ,EAAIA,EAAKhC,KAAK,KAAM,KAAM,KAAGgC,EAAK5X,KAAO8V,OAAI7Z,EAAagW,GAC7D,UAAQ,CAKH,GAJE2F,EAAK5X,KAAS+X,UAAEH,EAAIA,EAAeM,eAClCN,EAAM3X,MAAUnD,WAAM8a,EAAM3X,MAAQ8X,SAAMH,EAAM3X,MAAKD,KAAS+X,UACjEH,EAAIA,EACPO,gBACiC,IAAnBlG,EAAIhW,EAAG2b,EAAK3b,KAAS,CAC9B,GAAE2b,EAAM3X,MAAWnD,UACd,MAAS2a,GACjBjD,KACUyD,GAAKL,EAAyB3X,MAAO8S,MAC5C6E,EAAIA,EAAKhC,KACAqC,EAAIhc,IACJgc,EAAM5b,MACV,KACA,KACFub,EAAyB3X,MAE/B6X,aAEDF,EAAIA,EAAKhC,KAAK,KAAM,KAAM,KAAM,KAAGgC,EAAM3X,MAAO6V,OAAI7Z,EACvDgW,IACM,MAAE2F,GACVC,SAEAJ,EAAA5b,UAAKkc,MAAL,WACQ,MAAK/J,MACb0J,OAGQD,EAAA5b,UAAKgc,MAAb,WACE,GAAKD,GAAwB5J,IAIvB,OAHD4J,GAAM3X,MAAQ8X,UAAMH,EAAK5X,KAAS+X,UAAEH,EAAIA,EAAcQ,cACtDR,EAAK5X,KAAQ+X,SAAKH,EAAK5X,KAAKA,KAAS+X,UAAEH,EAAIA,EAAeM,eAC1DN,EAAK5X,KAAQ+X,SAAKH,EAAM3X,MAAS8X,UAAEH,EAAIA,EAAaS,aAE3DT,GAEQH,EAAA5b,UAAWmc,YAAnB,WACE,GAAKJ,GAAO5J,KAAaqK,WAYnB,OAXDT,GAAM3X,MAAKD,KAAS+X,UACtBH,EAAIA,EAAKhC,KACJ,KACA,KACA,KACA,KACFgC,EAAyB3X,MAC3BiY,eACDN,EAAIA,EAAcQ,aAClBR,EAAIA,EACPS,aAEFT,GAEQH,EAAA5b,UAAYsc,aAApB,WACE,GAAKP,GAAO5J,KAAaqK,WAKnB,OAJDT,GAAK5X,KAAKA,KAAS+X,UACrBH,EAAIA,EAAeM,cACnBN,EAAIA,EACPS,aAEFT,GAEQH,EAAA5b,UAAUuc,WAAlB,WACE,GAAQE,GAAOtK,KAAK4H,KAAK,KAAM,KAAU6B,EAAIE,IAAM,KAAM3J,KAAM/N,MAAOD,KAChE,OAAKgO,MAAM/N,MAAK2V,KAAK,KAAM,KAAM5H,KAAM0J,MAAIY,EACnD,OAEQb,EAAA5b,UAAWqc,YAAnB,WACE,GAAQK,GAAOvK,KAAK4H,KAAK,KAAM,KAAU6B,EAAIE,IAAM3J,KAAKhO,KAAMC,MAAQ,KAChE,OAAK+N,MAAKhO,KAAK4V,KAAK,KAAM,KAAM5H,KAAM0J,MAAM,KACpDa,IAEQd,EAAA5b,UAASwc,UAAjB,WACE,GAAUrY,GAAOgO,KAAKhO,KAAK4V,KAAK,KAAM,MAAO5H,KAAKhO,KAAM0X,MAAM,KAAQ,MAC3DzX,EAAO+N,KAAM/N,MAAK2V,KAAK,KAAM,MAAO5H,KAAM/N,MAAMyX,MAAM,KAAQ,KACnE,OAAK1J,MAAK4H,KAAK,KAAM,MAAO5H,KAAM0J,MAAM1X,EAChDC,IAGAwX,EAAA5b,UAAa2c,cAAb,WACE,GAAgBC,GAAOzK,KAAS0K,OAC7B,OAAKvJ,MAAIwJ,IAAI,EAAaF,IAAQzK,KAAKuE,KAAK,GASzCkF,EAAA5b,UAAK6c,MAAb,WACK,GAAK1K,KAAQ+J,SAAQ/J,KAAKhO,KAAS+X,QACpC,KAAUld,GAA0B,0BAAOmT,KAAI/R,IAAM,IAAO+R,KAAM3R,MACpE,IACG,IAAK2R,KAAM/N,MAAS8X,QACrB,KAAUld,GAAmB,mBAAOmT,KAAI/R,IAAM,IAAO+R,KAAM3R,MAC7D,WACA,IAAgBoc,GAAQzK,KAAwBhO,KAAS0Y,OACtD,IAAWD,IAAUzK,KAAyB/N,MAASyY,QACxD,KAAU7d,GACZ,sBACQ,OAAc4d,IAAKzK,KAAQ+J,QAAI,EACvC,IAtOKN,EAAKjD,MAAwC,KAE7CiD,EAAGE,KAAQ,EACXF,EAAK5B,OAAS,EAqOtB4B,KAGDmB,GAAA,WAQE,QAAAA,KAFA5K,KAAIuE,KAEW,EAuDjB,MApDEqG,GAAA/c,UAAI+Z,KAAJ,SACe3Z,EACEI,EACMqb,EAC4B1X,EACCC,GAE5C,MACR+N,OAGA4K,EAAA/c,UAAM8Z,OAAN,SAAa1Z,EAAUI,EAA2B4V,GAC1C,MAAC,IAAYyD,IAAUzZ,EAC/BI,IAGAuc,EAAA/c,UAAMia,OAAN,SAAa7Z,EAA2BgW,GAChC,MACRjE,OAEA4K,EAAA/c,UAAOiB,QAAP,WACQ,OACR,GAEA8b,EAAA/c,UAAgBya,iBAAhB,SAAgDC,GACxC,OACR,GAEAqC,EAAA/c,UAAgB6a,iBAAhB,SAAgDH,GACxC,OACR,GAEAqC,EAAA/c,UAAMua,OAAN,WACQ,MACR,OAEAwC,EAAA/c,UAAMwa,OAAN,WACQ,MACR,OAEAuC,EAAA/c,UAAKkc,MAAL,WACQ,OACR,GAGAa,EAAA/c,UAAa2c,cAAb,WACQ,OACR,GAEQI,EAAA/c,UAAK6c,MAAb,WACQ,MACR,IACDE,IAEOlD,IAAMlB,MAAG,GAAkCoE,GtCsuCnD,ISrzDCC,ITqzDGC,GAAwB9K,MAAQA,KAAKD,WAAa,WAClD,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC5FD,EAAED,UAAYE,IACb,SAAUD,EAAGC,GACd,IAAK,GAAIC,KAAKD,GACNA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAG1C,OAAO,UAAUF,EAAGC,GAEhB,QAASE,KACLP,KAAK9O,YAAckP,EAFvBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,SS90DvF,SAAqBsK,GAEnBA,IAAA,aAAa,YACbA,IAAA,gBAAgB,eAChBA,IAAA,eAAe,cACfA,IAAA,kBAAkB,iBAClBA,IAAA,eAAe,cACfA,IAAA,aAAa,YACbA,IAAA,YAAY,WACZA,IAAA,iBAAiB,gBACjBA,IAAA,cAAc,aACdA,IAAA,eACF,eAZqBA,YA8BrB,I8B9CCE,I9B8CDC,GAAA,mBAAAC,MAoBA,MAbEA,GAAApd,UAAQ8S,SAAR,WACE,GAASuK,GAAOlL,KAAS3R,OACnB,OAAa,QAAT6c,EAAkB,OAAMA,MAGpCD,EAAApd,UAAgBsd,iBAAhB,SAAkC/I,GAM1B,MALAnV,GACA+S,KAAUoL,YAAUhJ,EAAUgJ,UAElC,iEAC6BrZ,EAAKiO,KAAUoL,UAAOhJ,EAAYgJ,YAGpEH,KAEDrX,GAAA,SAAA6M,GAOE,QAAA7M,KAAA,GAAA8M,GACED,EAAAtS,KAAO6R,OACRA,IT+zDK,OSv0DNU,GAAS0K,UAAYP,GAAWjX,UAIvB8M,EAAa2K,cAAQ,KAI9B3K,EAkBF,MA3B+BoK,IAAAlX,EAAU6M,GAWvC7M,EAAA/F,UAAKQ,MAAL,WACQ,MACR,OAEAuF,EAAA/F,UAAMqE,OAAN,SAAwBkQ,GAChB,MAAMA,aACdxO,IAEAA,EAAA/F,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAAsBxO,GAE/B,EACWoM,KAAiBmL,iBAC9B/I,IAEOxO,EAAQC,SAAG,GAAgBD,GACnCA,GAAAoX,IAEDM,GAAA,SAAA7K,GAGE,QAAA8K,GAAmDF,GAAnD,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,IT8zDK,OSh0DuBU,GAAa2K,cAASA,EAFnD3K,EAAS0K,UAAYP,GAAcU,aAInC7K,EA0BF,MA/BkCoK,IAAAS,EAAU9K,GAO1C8K,EAAA1d,UAAKQ,MAAL,WACQ,MAAK2R,MACbqL,eAEAE,EAAA1d,UAAMqE,OAAN,SAAwBkQ,GACf,MACAA,aAAwBmJ,IACzBvL,KAAcqL,gBAAUjJ,EAEhCiJ,eAEAE,EAAA1d,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAAyBmJ,GACNxZ,EAAKiO,KACjCoC,GACWpC,KAAiBmL,iBAC9B/I,IAEOmJ,EAAEC,GAAT,SAAwBnd,GAChB,MAAMA,GAAekd,EAAKE,KAAeF,EACjDG,OAEOH,EAAIE,KAAG,GAAgBF,IAAO,GAC9BA,EAAKG,MAAG,GAAgBH,IAAQ,GACxCA,GAAAP,IAGDW,GAAA,SAAAlL,GAGE,QAAAkL,GAA0CN,GAA1C,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,ITyzDK,OS3zDeU,GAAa2K,cAAQA,EAF1C3K,EAAS0K,UAAYP,GAAac,YAIlCjL,EAYF,MAjB0CoK,IAAAa,EAAUlL,GAOlDkL,EAAA9d,UAAKQ,MAAL,WACQ,MAAK2R,MACbqL,eAEAM,EAAA9d,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAAwBuJ,GACPzY,EAAK8M,KAAcqL,cAAOjJ,EACpDiJ,eACWrL,KAAiBmL,iBAC9B/I,IACDuJ,GAAAX,IAoCDY,GAAA,SAAAnL,GACE,QAAAmL,GAAiCP,GTyzD3B,MSxzDJ5K,GAAAtS,KAAA6R,KAAoBqL,IACtBrL,KAaF,MAhBkC8K,IAAAc,EAAWnL,GAK3CmL,EAAA/d,UAAMqE,OAAN,SAAwBkQ,GAGnB,MAAMA,aAAyBwJ,IACZzY,EAAK6M,KAAcqL,cAAOjJ,EAChDiJ,gBAMHO,GAAAD,IAED1X,GAAA,SAAAwM,GACE,QAAAxM,GAA0CoX,GAA1C,GAAA3K,GACED,EAAAtS,KAAA6R,KAAoBqL,IACrBrL,ITwzDK,OS1zDeU,GAAa2K,cAAQA,EAE1C3K,EAiBF,MApBiCoK,IAAA7W,EAAWwM,GAS1CxM,EAAApG,UAAMqE,OAAN,SAAwBkQ,GAGnB,MAAMA,aAAwBnO,IACXd,EAAK6M,KAAcqL,cAAOjJ,EAChDiJ,gBATKpX,EAAGC,IAAG,GAAeD,GAAM4X,KAC3B5X,EAAiB6X,kBAAG,GAAe7X,GAAW8X,KAC9C9X,EAAiB+X,kBAAG,GAAe/X,IAAC,KAa5CA,GAAA0X,IAGDM,GAAA,SAAAxL,GAGE,QAAAyL,GAA0Cb,GAA1C,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,ITuzDK,OSzzDeU,GAAa2K,cAAQA,EAF1C3K,EAAS0K,UAAYP,GAAaqB,YAIlCxL,EAkBF,MAvBiCoK,IAAAoB,EAAUzL,GAOzCyL,EAAAre,UAAKQ,MAAL,WACQ,MAAK2R,MACbqL,eAEAa,EAAAre,UAAMqE,OAAN,SAAwBkQ,GACf,MACAA,aAAuB8J,IAAQlM,KAAcqL,gBAAUjJ,EAEhEiJ,eAEAa,EAAAre,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAAwB8J,GACLna,EAAKiO,KAAcqL,cAAOjJ,EACtDiJ,eACWrL,KAAiBmL,iBAC9B/I,IACD8J,GAAAlB,IAEDmB,GAAA,SAAA1L,GAGE,QAAA0L,GAA6Cd,GAA7C,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,ITqzDK,OSvzDeU,GAAa2K,cAAWA,EAF7C3K,EAAS0K,UAAYP,GAAgBsB,eAIrCzL,EAuBF,MA5BoCoK,IAAAqB,EAAU1L,GAO5C0L,EAAAte,UAAKQ,MAAL,WACQ,MAAK2R,MAAcqL,cAC3Be,UAEAD,EAAAte,UAAMqE,OAAN,SAAwBkQ,GACf,MACAA,aAA0B+J,IAC3BnM,KAAcqL,cAAOnZ,OAAMkQ,EAEnCiJ,gBAEAc,EAAAte,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAA2B+J,GACvBnM,KAAcqL,cAAU5H,UAAMrB,EAC3CiJ,eAAgBjJ,YAAiCiK,KAGjD,EACarM,KAAiBmL,iBAC9B/I,IAEH+J,GAAAnB,IAcDqB,GAAA,SAAA5L,GAGE,QAAA4L,GAA8CC,GAA9C,GAAA5L,GACED,EAAAtS,KAAO6R,OACRA,ITkzDK,OSpzDeU,GAAc4L,eAAWA,EAF9C5L,EAAS0K,UAAYP,GAAgBsB,eAIrCzL,EA2BF,MAhC0CoK,IAAAuB,EAAU5L,GAOlD4L,EAAAxe,UAAKQ,MAAL,WACQ,MACR,OAEAge,EAAAxe,UAAMqE,OAAN,SAAwBkQ,GACf,MACAA,aAAgCiK,IACjCrM,KAAesM,eAAOpa,OAAMkQ,EAEpCkK,iBAEAD,EAAAxe,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAAiCiK,GAC7BrM,KAAesM,eAAU7I,UAAMrB,EAC5CkK,gBAAgBlK,YAA2B+J,IAG3C,EACanM,KAAiBmL,iBAC9B/I,IAGFiK,EAAAxe,UAAQ8S,SAAR,WACQ,MAA8B,8BAAOX,KAAesM,eAC5D,KACDD,GAAArB,IAEDuB,GAAA,SAAA9L,GAGE,QAAA8L,GAAwClB,GAAxC,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,IT8yDK,OShzDeU,GAAa2K,cAAMA,EAFxC3K,EAAS0K,UAAYP,GAAW0B,UAIhC7L,EAmBF,MAxB+BoK,IAAAyB,EAAU9L,GAOvC8L,EAAA1e,UAAKQ,MAAL,WACQ,MAAK2R,MACbqL,eAEAkB,EAAA1e,UAAMqE,OAAN,SAAwBkQ,GACf,MACAA,aAAqBmK,IACtBvM,KAAcqL,cAAQlJ,EAAMC,EAEpCiJ,gBAEAkB,EAAA1e,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAAsBmK,GAClBvM,KAAcqL,cAAWhJ,EAAMD,EAC5CiJ,eACWrL,KAAiBmL,iBAC9B/I,IACDmK,GAAAvB,IAEDwB,GAAA,SAAA/L,GAGE,QAAAgM,GAA2CzJ,EAA2B/U,GAAtE,GAAAyS,GACED,EAAAtS,KAAO6R,OACRA,IT4yDK,OS9yDeU,GAAUsC,WAAYA,EAAWtC,EAAGzS,IAAaA,EAFtEyS,EAAS0K,UAAYP,GAAU4B,SAI/B/L,EAuBF,MA5B8BoK,IAAA2B,EAAUhM,GAOtCgM,EAAA5e,UAAKQ,MAAL,WACQ,MAAK2R,MACb/R,KAEAwe,EAAA5e,UAAMqE,OAAN,SAAwBkQ,GACnB,MAAMA,aAAqBqK,IAEtBzM,KAAI/R,IAAOiE,OAAMkQ,EAAKnU,MAAQ+R,KAAWgD,WAAO9Q,OAAMkQ,EAE9DY,aAKFyJ,EAAA5e,UAAS4V,UAAT,SAA2BrB,GACtB,GAAMA,YAAqBqK,GAAE,CAC9B,GAASzE,GAAOhI,KAAWgD,WAAUS,UAAMrB,EAAaY,WAClD,OAAU,KAANgF,EAAYA,EAAc/B,GAAWhC,WAAKjE,KAAI/R,IAAOmU,EACjEnU,KACM,MAAK+R,MAAiBmL,iBAC9B/I,IACDqK,GAAAzB,IAED0B,GAAA,SAAAjM,GAGE,QAAAiM,GAA4CrB,GAA5C,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,IT0yDK,OS5yDeU,GAAa2K,cAAUA,EAF5C3K,EAAS0K,UAAYP,GAAe6B,cAIpChM,EAmBF,MAxBmCoK,IAAA4B,EAAUjM,GAO3CiM,EAAA7e,UAAKQ,MAAL,WACQ,MAAK2R,MACbqL,eAEAqB,EAAA7e,UAAMqE,OAAN,SAAwBkQ,GACf,MACAA,aAAyBsK,IAC1B1M,KAAcqL,cAAQlJ,EAAMC,EAEpCiJ,gBAEAqB,EAAA7e,UAAS4V,UAAT,SAA2BrB,GACtB,MAAMA,aAA0BsK,GACtB1M,KAAcqL,cAAWhJ,EAAMD,EAC5CiJ,eACWrL,KAAiBmL,iBAC9B/I,IACDsK,GAAA1B,IAED2B,GAAA,SAAAlM,GAGE,QAAAmM,GAAiEvB,GAAjE,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,ITuyDK,OSzyDeU,GAAa2K,cAA+BA,EAFjE3K,EAAS0K,UAAYP,GAAa+B,YAIlClM,EA0HF,MA/HiCoK,IAAA8B,EAAUnM,GAOzCmM,EAAA/e,UAAKQ,MAAL,WACE,GAAYY,KAIN,OAHF+Q,MAAcqL,cAAiB/C,iBAAC,SAAIra,EAAKid,GACrCjc,EAAKhB,GAAMid,EACnB7c,UAEFY,GAEA2d,EAAA/e,UAAOgB,QAAP,SAAwD0Z,GAClDvI,KAAcqL,cAAiB/C,iBACrCC,IAEAqE,EAAA/e,UAAMqE,OAAN,SAAwBkQ,GACnB,GAAMA,YAAwBwK,GAAE,CAGjC,IAFA,GAASC,GAAO7M,KAAcqL,cAAe1C,cACpCmE,EAAQ1K,EAAciJ,cAAe1C,cACpCkE,EAAUtD,WAAOuD,EAAUvD,WAAG,CACtC,GAAWwD,GAA0CF,EAAWxD,UACrD2D,EAA0CF,EAAWzD,SAC7D,IAAM0D,EAAI9e,MAAU+e,EAAI/e,MAAU8e,EAAM1e,MAAO6D,OAAM8a,EAAQ3e,OACxD,OACR,EAGI,OAAKwe,EAAUtD,YAAQuD,EAC/BvD,UAEM,OACR,GAEAqD,EAAA/e,UAAS4V,UAAT,SAA2BrB,GACtB,GAAMA,YAAwBwK,GAAE,CAGjC,IAFA,GAASC,GAAO7M,KAAcqL,cAAe1C,cACpCmE,EAAQ1K,EAAciJ,cAAe1C,cACpCkE,EAAUtD,WAAOuD,EAAUvD,WAAG,CACtC,GAAWwD,GAA0CF,EAAWxD,UACrD2D,EAA0CF,EAAWzD,UACvDrB,EACYjW,EAAMgb,EAAI9e,IAAO+e,EAAK/e,MACpC8e,EAAM1e,MAAUoV,UAAMuJ,EAAQ3e,MAClC,IAAK2Z,EACA,MACRA,GAII,MAAoBjW,GAAI8a,EAAUtD,UAAKuD,EAC/CvD,WACQ,MAAKvJ,MAAiBmL,iBAC9B/I,IAGFwK,EAAA/e,UAAGof,IAAH,SAAmBtW,EAAgBuW,GAE9B,GADGjgB,GAAM0J,EAAU7H,UAAoD,kDACpD,IAAd6H,EAAOlL,OACP,MAAKuU,MAASmN,SAAKxW,EAAe8N,eAC1CyI,EACE,IAAShJ,GAAOlE,KAAMkE,MAAKvN,EAAiB8N,eACjCP,aAAyB0I,KAC7B1I,EAAc0I,EACrBpG,MACA,IAAc4G,GAAyBlJ,EAAI+I,IAAKtW,EAAW2N,WAAM4I,EAC3D,OAAKlN,MAASmN,SAAKxW,EAAe8N,eAC1C2I,IAGFR,EAAA/e,UAAMkR,OAAN,SAAsBpI,GAKjB,GAJG1J,GACC0J,EAAU7H,UAEf,qDACoB,IAAd6H,EAAOlL,OACP,MAAC,IAAemhB,GAAK5M,KAAcqL,cAAOvD,OAAKnR,EACvD8N,gBAEE,IAAWP,GAAOlE,KAAMkE,MAAKvN,EAAiB8N,eAC3C,IAAMP,YAAwB0I,GAAE,CACjC,GAAcQ,GAAQlJ,EAAOnF,OAAKpI,EAAa2N,WACzC,OAAC,IAAesI,GAChB5M,KAAcqL,cAAO1D,OAAKhR,EAAe8N,eAEjD2I,IAEQ,MACRpN,OAIJ4M,EAAA/e,UAAQG,SAAR,SAAwB2I,GAChB,WACRpI,KADayR,KAAMtM,MAAMiD,IAGzBiW,EAAA/e,UAAK6F,MAAL,SAAqBiD,GACb1J,GAAM0J,EAAU7H,UAAmC,gCACzD,IAAS4E,GAAgCsM,IAQnC,OAPFrJ,GAAQ9H,QAAC,SAAoBwe,GAExB3Z,EADEA,YAAwBkZ,GAClBlZ,EAAc2X,cAAIxT,IAAawV,QAC9C9e,OAEAA,KAGJmF,GAEAkZ,EAAA/e,UAAQ8S,SAAR,WACQ,MAAKjU,MAAUC,UAAKqT,KAC5B3R,UAEQue,EAAA/e,UAAKqW,MAAb,SAA+BoJ,GACvB,MAAKtN,MAAcqL,cAAIxT,IAAWyV,QAC1C/e,IAEQqe,EAAA/e,UAAQsf,SAAhB,SAAkCG,EAAmBjf,GAC7C,MAAC,IAAeue,GAAK5M,KAAcqL,cAAO1D,OAAU2F,EAC5Djf,KAEOue,EAAKpG,MAAG,GAAeoG,GAC5B,GAAarF,IACbxV,IACH6a,GAAA5B,IAEDuC,GAAA,SAAA9M,GAGE,QAAA+M,GAAgDnC,GAAhD,GAAA3K,GACED,EAAAtS,KAAO6R,OACRA,ITkxDK,OSpxDeU,GAAa2K,cAAcA,EAFhD3K,EAAS0K,UAAYP,GAAY2C,WAIjC9M,EAuDF,MA5DgCoK,IAAA0C,EAAU/M,GAOxC+M,EAAA3f,UAAKQ,MAAL,WACQ,MAAA2R,MAAmBqL,cAAIrf,IAAC,SAACyc,GAAI,MAACA,GAAQpa,WAG9Cmf,EAAA3f,UAAOgB,QAAP,SAA2C0Z,GACrCvI,KAAcqL,cAAQxc,QAC5B0Z,IAEAiF,EAAA3f,UAAMqE,OAAN,SAAwBkQ,GACnB,GAAMA,YAAuBoL,GAAE,CAC7B,GAAKxN,KAAcqL,cAAO5f,SAAU2W,EAAciJ,cAAQ5f,OACrD,OACR,CAEI,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAcqL,cAAO5f,OAAK2G,IAC7C,IAAM4N,KAAcqL,cAAGjZ,GAAOF,OAAMkQ,EAAciJ,cAAKjZ,IAClD,OACR,CAGI,QACR,EAEM,OACR,GAEAob,EAAA3f,UAAS4V,UAAT,SAA2BrB,GACtB,GAAMA,YAAuBoL,GAAE,CAM5B,IAAC,GALUC,GAAOtM,KAAI4D,IACpB/E,KAAcqL,cAAO5f,OACpB2W,EAAciJ,cACnB5f,QAEQ2G,EAAI,EAAGA,EAAYqb,EAAKrb,IAAG,CACnC,GAAS4V,GAAOhI,KAAcqL,cAAGjZ,GAAUqR,UAAMrB,EAAciJ,cAAKjZ,GAEjE,IAAK4V,EACA,MACRA,GAGI,MAAoBjW,GACpBiO,KAAcqL,cAAO5f,OACpB2W,EAAciJ,cAEvB5f,QACQ,MAAKuU,MAAiBmL,iBAC9B/I,IAGFoL,EAAA3f,UAAQ8S,SAAR,WACQ,MAAKjU,MAAUC,UAAKqT,KAC5B3R,UACDmf,GAAAxC,IClmBgB0C,GAAiBC,OAMPna,GACdka,GAAiBla,oBAAU2N,KAAIwJ,IAAE,EAAK,IAAM,GAM9BpX,GACdma,GAAiBna,kBAAQ4N,KAAIwJ,IAAE,EAAK,IAAK,EAQlCrX,GACPoa,GACXpa,WAAC,SAAKjF,GACJ,MAAyB,gBAAbA,IACJqU,SAAOrU,IACX8S,KAAMC,MAAO/S,KAAUA,GClB/Buf,GAAA,WAQE,QAAAC,GAC6BlX,EACamX,EACTC,EACK1J,EACC2J,EACFC,OAJ1B,KAAAH,cACA,KAAAC,cACA,KAAA1J,MAA2B,UAC3B,KAAA2J,MAA4B,UAC5B,KAAAC,MAA0B,MAL1BjO,KAAIrJ,KAAcA,EAClBqJ,KAAe8N,gBAAgBA,EAC/B9N,KAAO+N,QAAeA,EACtB/N,KAAKqE,MAAsBA,EAC3BrE,KAAOgO,QAAqBA,EAC5BhO,KAAKiO,MAAqBA,EAT7BjO,KAAmBkO,oBAAuB,KAC1ClO,KAAemO,gBAA0B,KAUvCnO,KAASgO,SACXhO,KAAiBoO,iBAAKpO,KAC5BgO,SACQhO,KAAOiO,OACTjO,KAAiBoO,iBAAKpO,KAC5BiO,OAyUJ,MA7VSJ,GAAMQ,OAAb,SAAgC1X,GACxB,MAAC,IAASkX,GAClBlX,IAqBAzI,OAAAwR,eAAImO,EAAAhgB,UAAO,WXg8ELgK,IWh8EN,WACK,GAA+B,OAA1BmI,KAAgBmO,gBAAY,CAClC,GAAqBG,GAAOtO,KAA4BuO,2BACjCC,EAAOxO,KAAwByO,sBACnD,IAAyB,OAATH,GAAwC,OAAVE,EAI5BF,EAAc5I,aAC3B1F,KAAgBmO,iBACtBO,IACM1O,KAAgBmO,iBAClB,GAAWQ,IAAiBL,GAGhCI,QACM,CACAzhB,EAEF,OADaqhB,GACc,OAATE,GACDF,EAAOpc,OAAoBsc,GAE9C,gDACExO,KAAgBmO,kBAEhB,KAAkB,GADFS,IAAS,EACPrjB,EAAoB,EAApBsjB,EAAI7O,KAAgB8N,gBAApBviB,EAAAsjB,EAAoBpjB,OAAAF,IAAA,CAArC,GAAaujB,GAAAD,EAAAtjB,EACZyU,MAAgBmO,gBAAKrV,KAAUgW,GACxBA,EAAMpb,MAAcgS,eACbkJ,GAClB,GAEC,IAAmBA,EAAE,CAGtB,GAAmBG,GACb/O,KAAgB8N,gBAAOriB,OAAI,EACvBuU,KAAgB8N,gBAAK9N,KAAgB8N,gBAAOriB,OAAK,GAAIujB,IAChDC,GAAWC,SACtBlP,MAAgBmO,gBAAKrV,KACViW,IAAcE,GAAUC,UACjBR,GAGxBS,MAGE,MAAKnP,MACbmO,iBXm7EMtL,YAAY,EACZC,cWp7EL,IAED+K,EAAAhgB,UAASuhB,UAAT,SAAwBjK,GAChBlY,EACmC,MAAnC+S,KAA2BuO,8BACrBpJ,YAA2B/Q,OAC5B+Q,EAAekK,gBAChBlK,EAAMzR,MAAOxB,OAAK8N,KAA6BuO,4BAEvD,8CAEIthB,GACQgZ,GAAcE,cAAKnG,KAAMrJ,MAErC,0CACF,IAAgB2Y,GAAOtP,KAAQ+N,QAAOzhB,QAAW6Y,GAC3C,OAAC,IAAS0I,GACV7N,KAAKrJ,KACLqJ,KAAgB8N,gBAAQ1J,QAClBkL,EACNtP,KAAMqE,MACNrE,KAAQgO,QACRhO,KAERiO,QAEAJ,EAAAhgB,UAAU0hB,WAAV,SAA2BT,GACnB7hB,GACQgZ,GAAcE,cAAKnG,KAAMrJ,MAErC,0CACI1J,GAAM+S,KAAQgO,UAAShO,KAAMiO,MAAsC,mCAEzE,IAAgBuB,GAAOxP,KAAgB8N,gBAAOxhB,QAAYwiB,GACpD,OAAC,IAASjB,GACV7N,KAAKrJ,KACC6Y,EACNxP,KAAQ+N,QAAQ3J,QAChBpE,KAAMqE,MACNrE,KAAQgO,QACRhO,KAERiO,QAEAJ,EAAAhgB,UAAS4hB,UAAT,SAA8BpL,GACtB,MAAC,IAASwJ,GACV7N,KAAKrJ,KACLqJ,KAAgB8N,gBAAQ1J,QACxBpE,KAAQ+N,QAAQ3J,QACfC,EACDrE,KAAQgO,QACRhO,KAERiO,QAEAJ,EAAAhgB,UAAW6hB,YAAX,SAAwBC,GAChB,MAAC,IAAS9B,GACV7N,KAAKrJ,KACLqJ,KAAgB8N,gBAAQ1J,QACxBpE,KAAQ+N,QAAQ3J,QAChBpE,KAAMqE,MACLsL,EACD3P,KAERiO,QAEAJ,EAAAhgB,UAAS+hB,UAAT,SAAsBD,GACd,MAAC,IAAS9B,GACV7N,KAAKrJ,KACLqJ,KAAgB8N,gBAAQ1J,QACxBpE,KAAQ+N,QAAQ3J,QAChBpE,KAAMqE,MACNrE,KAAQgO,QAGhB2B,IAKA9B,EAAAhgB,UAAWgiB,YAAX,WACK,GAAmC,OAA9B7P,KAAoBkO,oBAAY,CACtC,GAAe2B,GAAO7P,KAAKrJ,KAAmBsO,iBACnC4K,IAAU,KACjB,KAAiB,GAAAtkB,GAAY,EAAZsjB,EAAI7O,KAAQ+N,QAAZxiB,EAAAsjB,EAAYpjB,OAAAF,IACpBskB,GADIhB,EAAAtjB,GACqBskB,cACzBA,GAAQ,GAEVA,IAAW,MAElB,KAAkB,GAAAC,GAAY,EAAZC,EAAI/P,KAAQ8O,QAAZgB,EAAAC,EAAYtkB,OAAAqkB,IACrBD,GADKE,EAAAD,GACqBD,cAC1BA,GAAQ,GAECzc,GAAK4M,KAAQqE,SACtBwL,GAAU,MACVA,GAAQ7P,KACrBqE,OACQrE,KAASgO,UACJ6B,GAAW,OACXA,GAAQ7P,KAAQgO,QAC7B6B,eACQ7P,KAAOiO,QACF4B,GAAW,OACXA,GAAQ7P,KAAMiO,MAC3B4B,eACI7P,KAAoBkO,oBAC1B2B,EACM,MAAK7P,MACbkO,qBAEAL,EAAAhgB,UAAQ8S,SAAR,WACE,GAAO7O,GAAW,SAAOkO,KAAKrJ,KAAmBsO,iBAiB3C,OAhBEjF,MAAQ+N,QAAOtiB,OAAK,IACvBqG,GAAI,eAAmBkO,KAAQ+N,QAAKnc,KAAM,MAC/C,KACsBwB,EAAK4M,KAAQqE,SAC9BvS,GAAe,YAAOkO,KAC3BqE,OACQrE,KAAgB8N,gBAAOriB,OAAK,IAC/BqG,GAAI,eAAmBkO,KAAgB8N,gBAAKlc,KAAM,MACvD,KACQoO,KAASgO,UACZlc,GAAiB,cAAOkO,KAAQgO,QACrC6B,eACQ7P,KAAOiO,QACVnc,GAAe,YAAOkO,KAAMiO,MACjC4B,eAEU/d,EACZ,KAEA+b,EAAAhgB,UAAMqE,OAAN,SAAmBkQ,GACd,GAAKpC,KAAMqE,QAAUjC,EAAOiC,MACvB,OACR,CAEG,IAAKrE,KAAQ8O,QAAOrjB,SAAU2W,EAAQ0M,QAAQrjB,OACzC,OACR,CAEI,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAQ8O,QAAOrjB,OAAK2G,IACvC,IAAM4N,KAAQ8O,QAAG1c,GAAOF,OAAMkQ,EAAQ0M,QAAK1c,IACtC,OACR,CAGC,IAAK4N,KAAQ+N,QAAOtiB,SAAU2W,EAAQ2L,QAAQtiB,OACzC,OACR,CAEI,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAQ+N,QAAOtiB,OAAK2G,IACvC,IAAM4N,KAAQ+N,QAAG3b,GAAOF,OAAMkQ,EAAQ2L,QAAK3b,IACtC,OACR,CAGC,SAAM4N,KAAKrJ,KAAOzE,OAAMkQ,EAAOzL,SAKX,OAAjBqJ,KAAQgO,SACHhO,KAAQgO,QAAO9b,OAAMkQ,EAAS4L,SAExC,OADU5L,EAAQ4L,WAKO,OAAfhO,KAAMiO,MACTjO,KAAMiO,MAAO/b,OAAMkQ,EAAO6L,OAEpC,OADW7L,EAAM6L,QAGjBJ,EAAAhgB,UAAa8Q,cAAb,SAA0BqI,EAAcC,GAElC,IAAkB,GADA+I,IAAS,EACTzkB,EAAY,EAAZsjB,EAAI7O,KAAQ8O,QAAZvjB,EAAAsjB,EAAYpjB,OAAAF,IAAA,CAA7B,GAAaujB,GAAAD,EAAAtjB,GACN0kB,EAAUnB,EAAQoB,QAAGlJ,EAAMC,EAClC,IAAY,IAAPgJ,EAAc,MAAMA,EACVD,GAAqBA,GAAWlB,EAAMpb,MAAcgS,aAOlE,MAJAzY,GACc+iB,EAElB,kDAEJ,GAEAnC,EAAAhgB,UAAOsiB,QAAP,SAAqB5R,GACZ,MACDyB,MAAgBoQ,gBAAK7R,IACrByB,KAAeqQ,eAAK9R,IACpByB,KAAesQ,eAAK/R,IACpByB,KAAcuQ,cAEtBhS,IAEAsP,EAAAhgB,UAAQ2iB,SAAR,WACQ,OAAmBpd,EAAK4M,KAChCqE,QAEAwJ,EAAAhgB,UAAoB4gB,qBAApB,WACQ,MAAKzO,MAAgB8N,gBAAOriB,OAAI,EAC9BuU,KAAgB8N,gBAAG,GAAMpa,MAEnC,MAEAma,EAAAhgB,UAAwB0gB,yBAAxB,WACM,IAAiB,GAAAhjB,GAAY,EAAZsjB,EAAI7O,KAAQ+N,QAAZxiB,EAAAsjB,EAAYpjB,OAAAF,IAAA,CAA5B,GAAY4Z,GAAA0J,EAAAtjB,EACZ,IAAO4Z,YAA0B/Q,KAAU+Q,EAAgBkK,eACtD,MAAOlK,GACfzR,MAEI,MACR,OAEAma,EAAAhgB,UAAe+N,gBAAf,WACQ,MAAYqK,IAAcE,cAAKnG,KAAMrJ,OAC7C,IADqDqJ,KAAQ+N,QAAOtiB,QAG5DoiB,EAAAhgB,UAAeuiB,gBAAvB,SAAqC7R,GACnC,GAAakS,GAAMlS,EAAItQ,IAAM0I,IAC1B,OAAYsP,IAAcE,cAAKnG,KAAOrJ,MAE5BqJ,KAAKrJ,KAAOzE,OACzBue,GAGQzQ,KAAKrJ,KAAWiO,WAAS6L,IAAQzQ,KAAKrJ,KAAOlL,SAAYglB,EAAOhlB,OAExE,GAOMoiB,EAAAhgB,UAAcwiB,eAAtB,SAAoC9R,GAC9B,IAAkB,GAAAhT,GAAoB,EAApBsjB,EAAI7O,KAAgB8N,gBAApBviB,EAAAsjB,EAAoBpjB,OAAAF,IAAA,CAArC,GAAaujB,GAAAD,EAAAtjB,EAEb,KACOujB,EAAMpb,MAAagS,kBAE5BnX,KADIgQ,EAAM7K,MAAQob,EAAOpb,OAElB,OACR,EAEI,OACR,GAEQma,EAAAhgB,UAAcyiB,eAAtB,SAAoC/R,GAC9B,IAAiB,GAAAhT,GAAY,EAAZsjB,EAAI7O,KAAQ+N,QAAZxiB,EAAAsjB,EAAYpjB,OAAAF,IAC5B,IADYsjB,EAAAtjB,GACI4kB,QAAM5R,GACjB,OACR,CAEI,QACR,GAKQsP,EAAAhgB,UAAa0iB,cAArB,SAAmChS,GAC9B,QAAKyB,KAAQgO,UAAShO,KAAQgO,QAAoB0C,oBAAK1Q,KAAQ8O,QAAOvQ,IAGjEyB,KAAMiO,OAAQjO,KAAMiO,MAAoByC,oBAAK1Q,KAAQ8O,QAAOvQ,KAM9DsP,EAAAhgB,UAAgBugB,iBAAxB,SAAqCuB,GAC7B1iB,EACC0iB,EAAS3f,SAAOvE,QAAQuU,KAAQ8O,QAAOrjB,OAGhD,iCACDoiB,KAQD/Z,GAAA,WAwBE,QAAA6c,GAA+BhhB,GAAZqQ,KAAIrQ,KAAWA,EASpC,MA1BSghB,GAAUzL,WAAjB,SAA4BvR,GACnB,OAAMA,GACX,IAAQ,IACA,MAAWgd,GAAWC,SAC9B,KAAS,KACD,MAAWD,GAAoBE,kBACvC,KAAS,KACD,MAAWF,GAAO5c,KAC1B,KAAS,KACD,MAAW4c,GAAuBG,qBAC1C,KAAQ,IACA,MAAWH,GAAcI,YACjC,SACQ,MAAKlkB,GAAqB,qBAEtC8G,KAIAgd,EAAA9iB,UAAQ8S,SAAR,WACQ,MAAKX,MACbrQ,MAEAghB,EAAA9iB,UAAMqE,OAAN,SAAwBkQ,GAChB,MAAKpC,MAAKrQ,OAAUyS,EAC5BzS,MA/BOghB,EAASC,UAAG,GAAcD,GAAM,KAChCA,EAAkBE,mBAAG,GAAcF,GAAO,MAC1CA,EAAK5c,MAAG,GAAc4c,GAAO,MAC7BA,EAAYI,aAAG,GAAcJ,GAAM,KACnCA,EAAqBG,sBAAG,GAAcH,GAAO,MA4BrDA,KAEDvc,GAAA,WACE,QAAA4c,GACyBtd,EACFC,EACGtF,GAFjB2R,KAAKtM,MAAWA,EAChBsM,KAAErM,GAAYA,EACdqM,KAAK3R,MACXA,EAsEL,MApEE2iB,GAAAnjB,UAAOsiB,QAAP,SAAqB5R,GAChB,GAAKyB,KAAMtM,MAAcgS,aAAE,CACtBzY,EACA+S,KAAM3R,gBAAoBme,IAE9B,oDACF,IAAcyE,GAAOjR,KAAmB3R,MACxB6iB,EAAcjL,GAAWhC,WAAI1F,EAAItQ,IAAUgjB,EAAMhjB,IAC3D,OAAK+R,MAAkBmR,kBAC/BD,GACE,GAAShG,GAAM3M,EAAM7K,MAAKsM,KAAQtM,MAC5B,YAAkBnF,KAAd2c,GAAsBlL,KAAaoR,aAC/ClG,IAGM8F,EAAAnjB,UAAYujB,aAApB,SAAsC/iB,GAEjC,MAAK2R,MAAM3R,MAAU+c,YAAU/c,EAAW+c,WAGlCpL,KAAkBmR,kBAAM9iB,EAAUoV,UAAKzD,KACpD3R,SAEQ2iB,EAAAnjB,UAAiBsjB,kBAAzB,SAA4CD,GACnC,OAAKlR,KAAMrM,IAChB,IAAeG,IAAU8c,UACjB,MAAWM,GAAK,CACxB,KAAepd,IAAmB+c,mBAC1B,MAAWK,IAAM,CACzB,KAAepd,IAAMC,MACb,MAAkB,KAAPmd,CACnB,KAAepd,IAAaid,aACpB,MAAWG,GAAK,CACxB,KAAepd,IAAsBgd,sBAC7B,MAAWI,IAAM,CACzB,SACQ,MAAKrkB,GAAsB,sBAAOmT,KAE9CrM,MAEAqd,EAAAnjB,UAAYwhB,aAAZ,WACQ,MAAKrP,MAAGrM,KAAeG,GAC/BC,OAEAid,EAAAnjB,UAAWgiB,YAAX,WAIS,MACD7P,MAAMtM,MAAkBuR,kBAAOjF,QAAGrM,GAAkBqM,KAAM3R,OAIlE2iB,EAAAnjB,UAAMqE,OAAN,SAAoBkQ,GACf,MAAMA,aAA2B4O,IAE5BhR,KAAGrM,GAAOzB,OAAMkQ,EAAIzO,KACpBqM,KAAMtM,MAAOxB,OAAMkQ,EAAO1O,QAC1BsM,KAAM3R,MAAO6D,OAAMkQ,EAE3B/T,QAKF2iB,EAAAnjB,UAAQ8S,SAAR,WACQ,MAAQX,MAAMtM,MAAkBuR,kBAAA,IAAQjF,KAAGrM,GAAA,IAAQqM,KAAM3R,MACjEA,SACD2iB,KAKDhd,GAAA,WACE,QAAAA,GAAmCN,GAAhBsM,KAAKtM,MAAcA,EAsBxC,MApBEM,GAAAnG,UAAOsiB,QAAP,SAAqB5R,GACnB,GAAS2M,GAAM3M,EAAM7K,MAAKsM,KAAQtM,MAC5B,YAAkBnF,KAAd2c,GACZ,OADiCA,EAAQ7c,SAGzC2F,EAAAnG,UAAWgiB,YAAX,WACQ,MAAK7P,MAAMtM,MAAkBuR,kBACrC,YAEAjR,EAAAnG,UAAQ8S,SAAR,WACQ,MAAQX,MAAMtM,MAAkBuR,kBACxC,YAEAjR,EAAAnG,UAAMqE,OAAN,SAAoBkQ,GACf,MAAMA,aAAuBpO,IACnBgM,KAAMtM,MAAOxB,OAAMkQ,EAChC1O,QAIHM,KAKDG,GAAA,WACE,QAAAA,GAAmCT,GAAhBsM,KAAKtM,MAAcA,EAsBxC,MApBES,GAAAtG,UAAOsiB,QAAP,SAAqB5R,GACnB,GAAS2M,GAAM3M,EAAM7K,MAAKsM,KAAOtM,OAASrF,OACpC,OAAwB,gBAAb6c,IAAsBtc,MACzCsc,IAEA/W,EAAAtG,UAAWgiB,YAAX,WACQ,MAAK7P,MAAMtM,MAAkBuR,kBACrC,WAEA9Q,EAAAtG,UAAQ8S,SAAR,WACQ,MAAQX,MAAMtM,MAAkBuR,kBACxC,WAEA9Q,EAAAtG,UAAMqE,OAAN,SAAoBkQ,GACf,MAAMA,aAAsBjO,IAClB6L,KAAMtM,MAAOxB,OAAMkQ,EAChC1O,QAIHS,KAkCD8a,GAAA,WAIE,QAAAA,GAAuCtf,GAAZqQ,KAAIrQ,KAAWA,EAK5C,MAHEsf,GAAAphB,UAAQ8S,SAAR,WACQ,MAAKX,MACbrQ,MAPOsf,EAASC,UAAG,GAAaD,GAAQ,OACjCA,EAAUoC,WAAG,GAAapC,GAAS,QAO3CA,KAgBDqC,GAAA,WACE,QAAAC,GAA2CvhB,EAA0BwhB,GAAhDxR,KAAQhQ,SAAcA,EAAWgQ,KAAMwR,OAAYA,EAoE1E,MAlEED,GAAA1jB,UAAWgiB,YAAX,WAGM,IAAoB,GADTA,GAAO7P,KAAOwR,OAAO,KAAQ,KACpBjmB,EAAa,EAAbsjB,EAAI7O,KAAShQ,SAAbzE,EAAAsjB,EAAapjB,OAAAF,IACxBskB,GAAa4B,GADN5C,EAAAtjB,EAGd,OACRskB,IAMA0B,EAAA1jB,UAAmB6iB,oBAAnB,SAAsC5B,EAAevQ,GAC7CtR,EACA+S,KAAShQ,SAAOvE,QAAWqjB,EAAOrjB,OAEtC,iDAEE,KAAC,GADSylB,GAAK,EACT9e,EAAI,EAAGA,EAAO4N,KAAShQ,SAAOvE,OAAK2G,IAAG,CAC9C,GAAsBsf,GAAU5C,EAAI1c,GACrBqf,EAAOzR,KAAShQ,SAAIoC,EAChC,IAAiBsf,EAAMhe,MAAcgS,aAChCzY,EACKwkB,YAAoBjF,IAE7B,+DACQ0E,EAAcjL,GAAWhC,WACVwN,EAAIxjB,IACxBsQ,EAEPtQ,SAAQ,CACN,GAAc0jB,GAAMpT,EAAM7K,MAAiBge,EAAQhe,MAC7CzG,OACkBsB,KAAdojB,EAER,kEACQT,EAAYO,EAAUhO,UAClCkO,GAIG,GAHiBD,EAAI1C,MAAcC,GAAYoC,aACtCH,IACZ,GACqB,IAAPA,EAEd,MAEI,MAAKlR,MAAOwR,OAAaN,GAAK,EAAaA,EACnD,GAEAK,EAAA1jB,UAAMqE,OAAN,SAA0BkQ,GACrB,GAAgB,OAAVA,EACD,OACR,CACG,IACGpC,KAAOwR,SAAUpP,EAAOoP,QACxBxR,KAAShQ,SAAOvE,SAAU2W,EAASpS,SACxCvE,OACO,OACR,CACI,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAShQ,SAAOvE,OAAK2G,IAAG,CAC9C,GAAkBwf,GAAO5R,KAAShQ,SAAIoC,GACnByf,EAAQzP,EAASpS,SAAIoC,EAClC,OAAawf,GAAO1f,OAC5B2f,GACM,OACR,GACDN,KAKD5C,GAAA,WAIE,QAAAmD,GAA4Cpe,EAAiBsb,GAAjChP,KAAKtM,MAAWA,MACpBnF,KAAfygB,IACFA,EAAYC,GACjBC,WACIlP,KAAIgP,IAAOA,EACXhP,KAAa+R,aAAQre,EAC3BgS,aA4BF,MA1BEoM,GAAAjkB,UAAOqiB,QAAP,SAAoBlJ,EAAcC,GAChC,GAAgBiK,GAAOlR,KAAa+R,aACxBtL,GAAaM,aAAGC,EAAKC,GACrBR,GAAeS,eAAKlH,KAAMtM,MAAIsT,EAAMC,EACzC,QAAKjH,KAAOgP,KACjB,IAAcC,IAAUC,UAChB,MAAYgC,EACpB,KAAcjC,IAAWoC,WACjB,OAAG,EAAcH,CACzB,SACQ,MAAKrkB,GAAsB,sBAAOmT,KAE9CgP,OAEA8C,EAAAjkB,UAAWgiB,YAAX,WAEQ,MAAK7P,MAAMtM,MAAkBuR,kBAAOjF,QAAIgP,KAGhD8C,EAAAjkB,UAAQ8S,SAAR,WACQ,MAAQX,MAAMtM,MAAkBuR,kBAAA,KAASjF,KAAIgP,IACrD,KAEA8C,EAAAjkB,UAAMqE,OAAN,SAAqBkQ,GACb,MAAKpC,MAAIgP,MAAU5M,EAAI4M,KAAQhP,KAAMtM,MAAOxB,OAAMkQ,EAC1D1O,QACDoe,KAEqBpD,GAAG,GAAWC,IAAUtJ,GAAWM,WAAWsJ,GAAYC,WACzDC,GAAG,GAAWR,IAC1BtJ,GAAWM,WACXsJ,GACToC,Y6BtsBaW,GAAaC,OAAkD,iDAE9EC,GAAA,WAqCE,QAAAC,GAAoCC,EAAwBC,GAAvCrS,KAAOoS,QAAQA,EAAWpS,KAAKqS,MAAQA,EACpDplB,EAAMolB,GAAK,EAAwC,uCAAUA,GAC7DplB,EAAMolB,EAAM,IAAsC,qCAAUA,GAE5DplB,EACGmlB,IAAgB,YACW,mCAClCA,GAEInlB,EAAQmlB,EAAe,aAAkC,iCACjEA,GAwBF,MAtESD,GAAGG,IAAV,WACQ,MAAUH,GAAsBI,sBAAK1mB,KAC7CymB,QAEOH,EAAQK,SAAf,SAA0BC,GAClB,MAAUN,GAAsBI,sBAAKE,EAC7CC,YAEOP,EAAqBI,sBAA5B,SAAiDI,GAC/C,GAAaP,GAAOjR,KAAMC,MAAauR,EAAS,IAE1C,OAAC,IAAaR,GAAQC,EADwB,KAAzBO,EAAkB,IAARP,KAIhCD,EAAaS,cAApB,SAAgCC,GAK9B,GAASR,GAAK,EACAS,EAAYd,GAAK3gB,KAAMwhB,EAElC,IADG5lB,IAAW6lB,EAAuB,sBAAQD,GACnCC,EAAI,GAAE,CAEjB,GAAWC,GAAYD,EAAI,EACpBC,IAAWA,EAAe,aAAOC,OAAE,EAAK,GAC1CX,EAAW1jB,SAAQokB,EAC1B,IAGA,GAAUN,GAAG,GAAQ5mB,MAAMgnB,EAGrB,OAAC,IAAaV,GAFAhR,KAAMC,MAAKqR,EAAUC,UAAS,KAGpDL,IAcAF,EAAAtkB,UAAMue,OAAN,WACQ,MAAC,IAAQvgB,MAAKmU,KACtBiT,wBAEAd,EAAAtkB,UAAmBolB,oBAAnB,WACQ,MAAoB,KAAfjT,KAAQoS,QAAcpS,KAAMqS,MACzC,KAEAF,EAAAtkB,UAAS4V,UAAT,SAA0BrB,GACrB,MAAKpC,MAAQoS,UAAUhQ,EAASgQ,QACPrgB,EAAKiO,KAAMqS,MAAOjQ,EAC9CiQ,OAC0BtgB,EAAKiO,KAAQoS,QAAOhQ,EAChDgQ,UAEAD,EAAAtkB,UAAMqE,OAAN,SAAuBkQ,GACf,MAAMA,GAAQgQ,UAASpS,KAAQoS,SAAShQ,EAAMiQ,QAASrS,KAC/DqS,OAEAF,EAAAtkB,UAAQ8S,SAAR,WACQ,MAAqB,qBAAOX,KAAQoS,QAAa,WAAOpS,KAAMqS,MACtE,KACDF,KCvEDe,GAAA,WAmBE,QAAAC,GAAgDC,GAApBpT,KAASoT,UAAcA,EAuBrD,MArCSD,GAAgBE,iBAAvB,SAAqChlB,GACnC,GAAa+jB,GAAOjR,KAAMC,MAAM/S,EAAQ,IAElC,OAAC,IAAmB8kB,GAAC,GAAajB,IAAQE,EAD5B/jB,EAAO,IAAO,OAI7B8kB,EAAaG,cAApB,SAAqCjlB,GAC7B,MAAC,IAAmB8kB,GAC5B9kB,IAEO8kB,EAAaI,cAApB,WACQ,MAAgBJ,GACxBK,KAIAL,EAAAtlB,UAAS4V,UAAT,SAAgCrB,GACxB,MAAKpC,MAAUoT,UAAU3P,UAAMrB,EACvCgR,YAEAD,EAAAtlB,UAAMqE,OAAN,SAA6BkQ,GACrB,MAAKpC,MAAUoT,UAAOlhB,OAAMkQ,EACpCgR,YAGAD,EAAAtlB,UAAc4lB,eAAd,WAEQ,MAA6B,KAAxBzT,KAAUoT,UAAQhB,QAAapS,KAAUoT,UAAMf,MAC5D,KAEAc,EAAAtlB,UAAQ8S,SAAR,WACQ,MAAmB,mBAAOX,KAAUoT,UAC5C,KAEAD,EAAAtlB,UAAW6lB,YAAX,WACQ,MAAK1T,MACboT,WAxCgBD,EAAGK,IAAG,GAAmBL,GAAC,GAAajB,IAAE,EAAM,IAyChEiB,MF1CD,SAAwBpI,GAEtBA,IAAA,UAAM,SAKNA,IAAA,2BAAuB,0BAGvBA,IAAA,mBACF,mBAXwBA,YAgBxB,IG4DC4I,IH5DDC,GAAA,WACE,QAAAC,GAEqBnV,EAKMoV,EAEGC,EAEiCC,EAON1d,OAPhD,KAAA0d,MAAkDd,GAAIM,SAOtD,KAAAld,MAAgDnJ,KAhBhD6S,KAAKtB,MAAOA,EAKZsB,KAAQ8T,SAAUA,EAElB9T,KAAO+T,QAAcA,EAErB/T,KAAegU,gBAAuCA,EAOtDhU,KAAW1J,YACjBA,EA4BL,MAtBEud,GAAAhmB,UAAMomB,OAAN,SAGCC,GACO,MAAC,IAAaL,GACd7T,KAAMtB,MACNsB,KAAS8T,SACT9T,KAAQ+T,QACLG,EAAgBF,gBAChBE,EAEX5d,cAEAud,EAAAhmB,UAAMqE,OAAN,SAAuBkQ,GACd,MACDpC,MAAS8T,WAAU1R,EAAS0R,UAC5B9T,KAAQ+T,UAAU3R,EAAQ2R,SAC1B/T,KAAgBgU,gBAAO9hB,OAAMkQ,EAAiB4R,kBAC9ChU,KAAY1J,cAAU8L,EAAY9L,aAClC0J,KAAMtB,MAAOxM,OAAMkQ,EAE3B1D,QACDmV,KvC+oGGM,GAAqBnU,MAAQA,KAAKD,WAAa,WAC/C,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC5FD,EAAED,UAAYE,IACb,SAAUD,EAAGC,GACd,IAAK,GAAIC,KAAKD,GACNA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAG1C,OAAO,UAAUF,EAAGC,GAEhB,QAASE,KACLP,KAAK9O,YAAckP,EAFvBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,Q0C9sGvF6T,GAAA,WACE,QAAAC,GAAwCC,GAAnBtU,KAAMsU,OAAaA,EAO1C,MAHED,GAAAxmB,UAAMqE,OAAN,SAAuBkQ,GACf,MAAKjQ,GAAiB6N,KAAOsU,OAAOlS,EAC5CkS,SACDD,KAQDE,GAAA,WACE,QAAAA,MAMF,MAHEA,GAAA1mB,UAAMqE,OAAN,SAAgCkQ,GACxB,MAAMA,aACdmS,IAJOA,EAAQ9U,SAAG,GAA+B8U,GAKlDA,KAGDC,GAAA,WACE,QAAAA,GAC2B9gB,EACa+gB,GAD7BzU,KAAKtM,MAAWA,EAChBsM,KAASyU,UACjBA,EAOL,MALED,GAAA3mB,UAAMqE,OAAN,SAA4BkQ,GACnB,MACDpC,MAAMtM,MAAOxB,OAAMkQ,EAAO1O,QAAQsM,KAAUyU,UAAOviB,OAAMkQ,EAEjEqS,YACDD,KAGDE,GAAA,WACE,QAAAA,GAI0C/N,EAQMgO,GARrC3U,KAAO2G,QAAwBA,EAQ/B3G,KAAgB2U,iBACxBA,EACL,MAACD,OAED,SAAwBf,GACtBA,IAAA,OAAG,MACHA,IAAA,SAAK,QACLA,IAAA,aAAS,YACTA,IAAA,UACF,UALwBA,YAYxB,I9B1DCne,I8B0DDof,GAAA,WAGE,QAAAC,GAC8CC,EACZC,GADhB/U,KAAU8U,WAAkBA,EAC5B9U,KAAM+U,OAAUA,EAE1B9nB,MACoBsB,KAAdumB,OAAsCvmB,KAAdwmB,EAGtC,kEA4CF,MAzCSF,GAAME,OAAb,SAA6BA,GACrB,MAAC,IAAgBF,OAAUtmB,GACnCwmB,IAGOF,EAAUC,WAAjB,SAA0CnO,GAClC,MAAC,IAAgBkO,GACzBlO,IAGAzY,OAAAwR,eAAImV,EAAAhnB,UAAM,U1CqtGJgK,I0CrtGN,WACQ,WAA8BtJ,KAAzByR,KAAW8U,gBACxBvmB,KAD8CyR,KAAO+U,Q1CutG/ClS,YAAY,EACZC,c0CvtGL,IAMD+R,EAAAhnB,UAAUmnB,WAAV,SAAyCC,GACpC,WAA+B1mB,KAA1ByR,KAAW8U,WAEPG,YAAoBxO,KAAYwO,EAAQtO,QAAOzU,OAAK8N,KAEhE8U,gBAAqCvmB,KAAtByR,KAAO+U,OACZ/U,KAAQ+U,OACCE,YACjBxO,IAC0B,OAATwO,GAAqBA,YACtC5N,KAEMpa,EAAK+S,KAAOkV,OAAkC,iCAEtD,IAGFL,EAAAhnB,UAAMqE,OAAN,SAA0BkQ,GACjB,MACDlQ,GAAY8N,KAAW8U,WAAO1S,EAAY0S,aAC1C9U,KAAO+U,SAAU3S,EAEzB2S,QArDgBF,EAAIM,KAAG,GAAmBN,GAsD3CA,KAwCDO,GAAA,mBAAAC,MAgEA,MAxBYA,GAAAxnB,UAAgBynB,iBAA1B,SAAyDL,GAClC,MAATA,GACJhoB,EACIgoB,EAAIhnB,IAAOiE,OAAK8N,KAAK/R,KAGjC,8DASeonB,EAAsBE,uBAAvC,SACgCN,GAE3B,MAASA,aAAqBxO,IAChBwO,EACjBtO,QACwBuM,GACxBM,KAEH6B,KAMDG,GAAA,SAAA/U,GACE,QAAAgV,GAC2BxnB,EACEI,EACQqnB,GAHrC,GAAAhV,GAKED,EAAAtS,KAAO6R,OACRA,I1CyqGK,O0C9qGKU,GAAGzS,IAAaA,EAChByS,EAAKrS,MAAaA,EAClBqS,EAAYgV,aAAcA,EAK5BhV,EAAI3Q,KAA6B4jB,GAAKgC,IAF/CjV,EAiDF,MAxDiCyT,IAAAsB,EAAQhV,GAWvCgV,EAAA5nB,UAAqB+nB,sBAArB,SACgCX,EACAY,GAE1B7V,KAAiBsV,iBAAWL,GAE1BhoB,EACmC,MAAzB4oB,EAAiBlB,iBAE/B,6CAMF,IAAahO,GAAWyO,GAAuBG,uBAAWN,EACpD,WAAaxO,IAAKzG,KAAI/R,IAAS0Y,EAAM3G,KAAM3R,OAC9BwY,mBAErB,KAEA4O,EAAA5nB,UAAgBioB,iBAAhB,SACgCb,EACL3I,GAItB,GAFCtM,KAAiBsV,iBAAWL,IAEvBjV,KAAa0V,aAAWV,WAAWC,GACpC,MACRA,EAEA,IAAatO,GAAWyO,GAAuBG,uBAAWN,EACpD,WAAaxO,IAAKzG,KAAI/R,IAAS0Y,EAAM3G,KAAM3R,OAC9BwY,mBAErB,KAEA4O,EAAA5nB,UAAMqE,OAAN,SAAsBkQ,GACb,MACAA,aAAuBqT,IACxBzV,KAAI/R,IAAOiE,OAAMkQ,EAAKnU,MACtB+R,KAAM3R,MAAO6D,OAAMkQ,EAAO/T,QAC1B2R,KAAa0V,aAAOxjB,OAAMkQ,EAElCsT,eACDD,GAAAL,IAeDW,GAAA,SAAAtV,GACE,QAAAuV,GAC2B/nB,EACC2Y,EACGqP,EACMP,GAJrC,GAAAhV,GAMED,EAAAtS,KAAO6R,OACRA,I1CopGK,O0C1pGKU,GAAGzS,IAAaA,EAChByS,EAAIkG,KAAaA,EACjBlG,EAASuV,UAAWA,EACpBvV,EAAYgV,aAAcA,EAK5BhV,EAAI3Q,KAA6B4jB,GAAOuC,MAFjDxV,EAoFF,MA5FmCyT,IAAA6B,EAAQvV,GAYzCuV,EAAAnoB,UAAqB+nB,sBAArB,SACgCX,EACAY,GAe3B,GAbC7V,KAAiBsV,iBAAWL,GAE1BhoB,EACmC,MAAzB4oB,EAAiBlB,iBAE/B,iDAQO3U,KAAa0V,aAAWV,WAAWC,GACpC,MACRA,EAEA,IAAatO,GAAWyO,GAAuBG,uBAAWN,GAC7CkB,EAAOnW,KAAcoW,cAAWnB,EACvC,WAAaxO,IAAKzG,KAAI/R,IAAS0Y,EAASwP,GAC3BtP,mBAErB,KAEAmP,EAAAnoB,UAAgBioB,iBAAhB,SACgCb,EACL3I,GAItB,GAFCtM,KAAiBsV,iBAAWL,IAEvBjV,KAAa0V,aAAWV,WAAWC,GACpC,MACRA,EAEA,IAAatO,GAAWyO,GAAuBG,uBAAWN,GAC7CkB,EAAOnW,KAAcoW,cAAWnB,EACvC,WAAaxO,IAAKzG,KAAI/R,IAAS0Y,EAASwP,GAC3BtP,mBAErB,KAEAmP,EAAAnoB,UAAMqE,OAAN,SAAsBkQ,GACb,MACAA,aAAyB4T,IAC1BhW,KAAI/R,IAAOiE,OAAMkQ,EAAKnU,MACtB+R,KAAUiW,UAAO/jB,OAAMkQ,EAAW6T,YAClCjW,KAAa0V,aAAOxjB,OAAMkQ,EAElCsT,eAOQM,EAAAnoB,UAAauoB,cAArB,SAAoDnB,GAClD,GAAsBrO,EAMhB,OAJAA,GADMqO,YAAqBxO,IAChBwO,EACjBrO,KACoB+F,GACpBnG,MACWxG,KAAYqW,YACzBzP,IAEQoP,EAAAnoB,UAAWwoB,YAAnB,SAAqCzP,GAC/B,IAAoB,GAAArb,GAAqB,EAArBsjB,EAAI7O,KAAUiW,UAAO3B,OAArB/oB,EAAAsjB,EAAqBpjB,OAAAF,IAAA,CAAxC,GAAe+qB,GAAAzH,EAAAtjB,GACJgrB,EAAOvW,KAAK4G,KAAMlT,MAAY4iB,EAEtC1P,OADqBrY,KAAfgoB,EACC3P,EAAIqG,IAAUqJ,EAC3BC,GACa3P,EAAO7H,OACpBuX,GAEI,MACR1P,IACDoP,GAAAZ,IAWDoB,GAAA,SAAA/V,GAQE,QAAAgW,GAC2BxoB,EACiByoB,GAF5C,GAAAhW,GAIED,EAAAtS,KAAO6R,OACRA,I1C2nGK,O0C/nGKU,GAAGzS,IAAaA,EAChByS,EAAegW,gBAAkBA,EATnChW,EAAI3Q,KAA6B4jB,GAAWgD,UAK5CjW,EAAYgV,aAAed,GAAOG,QAAO,GAOlDrU,EAwHF,MArIuCyT,IAAAsC,EAAQhW,GAe7CgW,EAAA5oB,UAAqB+nB,sBAArB,SACgCX,EACAY,GAE1B7V,KAAiBsV,iBAAWL,GAE1BhoB,EACmC,MAAzB4oB,EAAiBlB,iBAE/B,mDACF,IAAsBA,GAAiBkB,EAAmBlB,gBAQvD,KAAM3U,KAAa0V,aAAWV,WAAWC,GACpC,MACRA,EAEA,IAAS1W,GAAOyB,KAAgB4W,gBAAW3B,GAC9BkB,EAAOnW,KAAgB6W,gBAAItY,EAAKqI,KAAoB+N,EAC3D,WAAalO,IAAKzG,KAAI/R,IAAKsQ,EAAQoI,QAASwP,GAC/BtP,mBAErB,KAEA4P,EAAA5oB,UAAgBioB,iBAAhB,SACgCb,EACL3I,GAItB,GAFCtM,KAAiBsV,iBAAWL,IAEvBjV,KAAa0V,aAAWV,WAAWC,GACpC,MACRA,EAEA,IAAS1W,GAAOyB,KAAgB4W,gBAAW3B,GACrBN,EAAO3U,KAAsB8W,sBAAiBxK,GACvD6J,EAAOnW,KAAgB6W,gBAAItY,EAAKqI,KAAoB+N,EAC3D,WAAalO,IAAKzG,KAAI/R,IAAKsQ,EAAQoI,QAASwP,GAC/BtP,mBAErB,KAEA4P,EAAA5oB,UAAMqE,OAAN,SAAsBkQ,GACb,MACAA,aAA6BqU,IAC9BzW,KAAI/R,IAAOiE,OAAMkQ,EAAKnU,MACtBkE,EAAiB6N,KAAgB0W,gBAAOtU,EAAiBsU,kBACzD1W,KAAa0V,aAAOxjB,OAAMkQ,EAElCsT,eAQQe,EAAA5oB,UAAe+oB,gBAAvB,SAAsD3B,GAC9ChoB,EACIgoB,YAAoBxO,IACC,8BAC7BwO,EACF,IAAS1W,GAAyB0W,CAK5B,OAJAhoB,GACDsR,EAAItQ,IAAOiE,OAAK8N,KAAK/R,KAExB,mDAEJsQ,GAWQkY,EAAA5oB,UAAqBipB,sBAA7B,SAAuDxK,GAEjD,IAAyB,GADPqI,MACOppB,EAAoB,EAApBsjB,EAAI7O,KAAgB0W,gBAApBnrB,EAAAsjB,EAAoBpjB,OAAAF,IAAA,CAA5C,GAAoBwrB,GAAAlI,EAAAtjB,GACRkpB,EAAiBsC,EAAWtC,SACxC,MAAUA,YAAqCF,KAG1C,MAAK1nB,GAAkC,kCAC/C4nB,EAHkBE,GAAK7b,KAAC,GAAwBuT,IAChDC,IAII,MACRqI,IAEQ8B,EAAA5oB,UAAegpB,gBAAvB,SACmBjQ,EACa+N,GAExB1nB,EACY0nB,EAAOlpB,SAASuU,KAAgB0W,gBAAOjrB,OAEvD,oCAEE,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAgB0W,gBAAOjrB,OAAK2G,IAAG,CACrD,GAAoB2kB,GAAO/W,KAAgB0W,gBAAItkB,GAChCqiB,EAAiBsC,EAAWtC,UAC5B6B,EAAiBS,EAAOrjB,KACpC,MAAU+gB,YAAqCF,KAG1C,MAAK1nB,GAAkC,kCAC/C4nB,EAHM7N,GAAOA,EAAIqG,IAAUqJ,EAAkB3B,EAC7CviB,IAII,MACRwU,IACD6P,GAAArB,IAGD4B,GAAA,SAAAvW,GACE,QAAAwW,GAAqChpB,EAAqCynB,GAA1E,GAAAhV,GACED,EAAAtS,KAAO6R,OACRA,I1C4lGK,O0C9lGeU,GAAGzS,IAAaA,EAAWyS,EAAYgV,aAAcA,EAIjEhV,EAAI3Q,KAA6B4jB,GAAQuD,OAFlDxW,EAgDF,MAnDoCyT,IAAA8C,EAAQxW,GAO1CwW,EAAAppB,UAAqB+nB,sBAArB,SACgCX,EACAY,GAaxB,MAXF7V,MAAiBsV,iBAAWL,GAE1BhoB,EACmC,MAAzB4oB,EAAiBlB,iBAE/B,iDAMK,GAActN,IAAKrH,KAAI/R,IAAiBilB,GACjDM,MAEAyD,EAAAppB,UAAgBioB,iBAAhB,SACgCb,EACL3I,GAItB,MAFCtM,MAAiBsV,iBAAWL,GAEvBjV,KAAa0V,aAAWV,WAAWC,IAI/BA,GACLhoB,EACIgoB,EAAIhnB,IAAOiE,OAAK8N,KAAK/R,KAGjC,qDACO,GAAcoZ,IAAKrH,KAAI/R,IAAiBilB,GACjDK,kBATE0B,GAWFgC,EAAAppB,UAAMqE,OAAN,SAAsBkQ,GACb,MACAA,aAA0B6U,IAC3BjX,KAAI/R,IAAOiE,OAAMkQ,EAAKnU,MACtB+R,KAAa0V,aAAOxjB,OAAMkQ,EAElCsT,eACDuB,GAAA7B,ICvmBD+B,GAAA,WAEE,QAAAA,GAAgCC,GAAbpX,KAAKoX,MAAWA,EAKrC,MAHSD,GAAAtpB,UAAMqE,OAAb,SAAoCkQ,GAC5B,MAAMA,IAASA,EAAMgV,QAASpX,KACtCoX,OACDD,M/BMD,SAAY3hB,GACVA,IAAA,MAAM,KACNA,IAAA,aAAa,YACbA,IAAA,WAAW,UACXA,IAAA,oBAAoB,mBACpBA,IAAA,qBAAqB,oBACrBA,IAAA,aAAa,YACbA,IAAA,kBAAkB,iBAClBA,IAAA,qBAAqB,oBACrBA,IAAA,oBAAoB,kBACpBA,IAAA,sBAAsB,qBACtBA,IAAA,uBAAuB,sBACvBA,IAAA,YAAY,UACZA,IAAA,iBAAiB,eACjBA,IAAA,kBAAkB,gBAClBA,IAAA,aAAa,WACbA,IAAA,gBAAgB,cAChBA,IAAA,cACF,aAlBYA,YgCJZ,IC8DC6hB,ID9DDC,GAAA,WAGE,QAAAC,GAA6DtT,GAAzCjE,KAAUiE,WAA+BA,EACvDjE,KAAK4G,KAAG,GAAaW,IAAiBvH,KAC5CiE,YA2HF,MArHSsT,GAAWC,YAAlB,SAA6CxrB,GAC3C,GAAQyrB,GAAG,GAAaF,GAAOvrB,EAAaiY,WAItC,OAHHjY,GAAQ6C,QAAC,SAAGZ,GACTwpB,EAAOA,EAAIzY,IACjB/Q,KAEFwpB,GAEAF,EAAA1pB,UAAG6pB,IAAH,SAAWC,GACH,MACR,QADa3X,KAAK4G,KAAI/O,IAAM8f,IAG5BJ,EAAA1pB,UAAK+pB,MAAL,WACQ,MAAK5X,MAAK4G,KAClBwB,UAEAmP,EAAA1pB,UAAIgqB,KAAJ,WACQ,MAAK7X,MAAK4G,KAClByB,UAEAna,OAAAwR,eAAI6X,EAAA1pB,UAAI,Q5Cm9HFgK,I4Cn9HN,WACQ,MAAKmI,MAAK4G,KAClBrC,M5Co9HM1B,YAAY,EACZC,c4Cr9HL,IAEDyU,EAAA1pB,UAAO8D,QAAP,SAAegmB,GACP,MAAK3X,MAAK4G,KAAQjV,QAC1BgmB,IAGAJ,EAAA1pB,UAAOgB,QAAP,SAA6BipB,GACvB9X,KAAK4G,KAAiB0B,iBAAC,SAAKE,EAAYC,GAEpC,MADJqP,GAAItP,IAER,KAIF+O,EAAA1pB,UAAckqB,eAAd,SAA4BC,EAAuBF,GAEjD,IADA,GAAUG,GAAOjY,KAAK4G,KAAgBkC,gBAAMkP,EAAK,IACtCC,EAAU1O,WAAG,CACtB,GAAUoO,GAAOM,EAAW5O,SACzB,IAAKrJ,KAAWiE,WAAK0T,EAAI1pB,IAAO+pB,EAAI,KAAM,EAAQ,MACnDF,GAAKH,EACT1pB,OAMFspB,EAAA1pB,UAAYqqB,aAAZ,SAAqCJ,EAAWnf,GAC9C,GAA2Dsf,EAM3D,KAJMA,MADkB1pB,KAAfoK,EACIqH,KAAK4G,KAAgBkC,gBAClCnQ,GACaqH,KAAK4G,KAClB+B,cACWsP,EAAU1O,WAGhB,IADcuO,EADAG,EAAW5O,UACApb,KAE9B,QAIFspB,EAAA1pB,UAAiBsqB,kBAAjB,SAAyBR,GACvB,GAAUM,GAAOjY,KAAK4G,KAAgBkC,gBAAO6O,EACvC,OAAKM,GAAU1O,UAAO0O,EAAU5O,UAAIpb,IAC5C,MAGAspB,EAAA1pB,UAAGmR,IAAH,SAAW2Y,GACH,MAAK3X,MAAK4H,KAAK5H,KAAK4G,KAAOkB,OAAM6P,GAAOhQ,OAAKgQ,GACrD,KAGAJ,EAAA1pB,UAAMkR,OAAN,SAAc4Y,GACT,MAAM3X,MAAI0X,IAAOC,GACT3X,KAAK4H,KAAK5H,KAAK4G,KAAOkB,OACnC6P,IAFmC3X,MAInCuX,EAAA1pB,UAAOiB,QAAP,WACQ,MAAKkR,MAAK4G,KAClB9X,WAEAyoB,EAAA1pB,UAASuqB,UAAT,SAA6BhW,GAC3B,GAAUnT,GAAsB+Q,IAI1B,OAHDoC,GAAQvT,QAAC,SAAI8oB,GACV1oB,EAASA,EAAI+P,IACrB2Y,KAEF1oB,GAEAsoB,EAAA1pB,UAAMqE,OAAN,SAA0BkQ,GACrB,KAAQA,YAAuBmV,IAAO,OAAO,CAC7C,IAAKvX,KAAKuE,OAAUnC,EAAMmC,KAAO,OAAO,CAI3C,KAFA,GAAY8T,GAAOrY,KAAK4G,KAAe+B,cAC1B2P,EAAQlW,EAAKwE,KAAe+B,cAC5B0P,EAAU9O,WAAG,CACxB,GAAcgP,GAASF,EAAUhP,UAAKpb,IACvBuqB,EAAUF,EAAUjP,UAAKpb,GACrC,IAA4C,IAAvC+R,KAAWiE,WAASsU,EAAYC,GAAc,OACxD,EACM,OACR,GAEAjB,EAAA1pB,UAAQ8S,SAAR,WACE,GAAY1R,KAEN,OADF+Q,MAAQnR,QAAC,SAAI8oB,GAAI,MAAM1oB,GAAK6J,KAAM6e,KACnB,aAAS1oB,EAC9B,KAEQsoB,EAAA1pB,UAAI+Z,KAAZ,SAAwChB,GACtC,GAAY3X,GAAG,GAAasoB,GAAKvX,KAAaiE,WAExC,OADAhV,GAAK2X,KAAQA,EAErB3X,GACDsoB,K/B/H6B1hB,GAAG,GAAa0R,IACjCtB,GACXhC,YAMsBlO,GAAG,GAAawR,IAC3BtB,GACXhC,YAM8BhO,GAAG,GAAasR,IACnCtB,GACXhC,YAM0B9N,GAAG,GAAamhB,IAAYrR,GAAahC,YgClBrEwU,GAAA,WACE,QAAAC,GAIkD1E,EAImB2E,EAK3BC,GATxB5Y,KAAegU,gBAAiBA,EAIhChU,KAAa2Y,cAAsCA,EAK5D3Y,KAAe4Y,gBACrBA,EAyBL,MAvBEF,GAAA7qB,UAAiBgrB,kBAAjB,SAAoCta,GAC9ByB,KAAgB4Y,gBAAO5Y,KAAgB4Y,gBAAOjR,OAAIpJ,EAAItQ,IAC5DsQ,IAEAma,EAAA7qB,UAA6BirB,8BAA7B,SAAgDhF,GAY1C9T,KAAc2Y,cAAU7E,IACnBiF,QAAE,GAAkBC,IACZhF,gBAAiBd,GAAIM,IACjByF,oBAAqB5B,GAAe6B,eAC5C5iB,YAEfnJ,MACDurB,MAQD,SAA+BrB,GAE7BA,IAAA,QAAI,OAEJA,IAAA,kBAAc,iBAEdA,IAAA,eACF,eAP+BA,YA4C/B,I/B7CC8B,I+B6CkBC,GAAoBljB,KAEvC8iB,GAAA,mBAAAA,KACUhZ,KAAIqZ,KAiBdD,GAAA,MAfElrB,QAAAwR,eAAIsZ,EAAAnrB,UAAS,a7CkmIPgK,I6ClmIN,WACQ,MAAKmI,MACbqZ,M7CmmIMxW,YAAY,EACZC,c6CpmIL,IAEDkW,EAAAnrB,UAAGmR,IAAH,SAAoB/Q,GACd+R,KAAKqZ,KAAOrZ,KAAKqZ,KAAIra,IAC3B/Q,IAEA+qB,EAAAnrB,UAAMkR,OAAN,SAAuB9Q,GACjB+R,KAAKqZ,KAAOrZ,KAAKqZ,KAAOta,OAC9B9Q,IAEA+qB,EAAAnrB,UAAMqE,OAAN,SAA0BkQ,GAClB,MAAe,QAATA,GAAiBpC,KAAKqZ,KAAOnnB,OAAMkQ,EACjDiX,OACDL,KAEDM,GAAA,mBAAAA,KACEtZ,KAAcuZ,eAAiCH,GAC/CpZ,KAAgBwZ,iBA0BlBJ,GAAA,MAxBEE,GAAAzrB,UAAa4rB,cAAb,SAAkChC,GAChC,GAAUxoB,GAAQwoB,CAGZ,OAFFzX,MAAeuZ,eAAQ1qB,QAAC,SAAGZ,GAAI,MAAOgB,GAASA,EAAI+P,IAAM/Q,KACzD+R,KAAiBwZ,iBAAQ3qB,QAAC,SAAGZ,GAAI,MAAOgB,GAASA,EAAO8P,OAAM9Q,KAEpEgB,GAEAqqB,EAAAzrB,UAAGmR,IAAH,SAAoB/Q,GACd+R,KAAeuZ,eAAOvZ,KAAeuZ,eAAIva,IAAM/Q,GAC/C+R,KAAiBwZ,iBAAOxZ,KAAiBwZ,iBAAOza,OACtD9Q,IAEAqrB,EAAAzrB,UAAMkR,OAAN,SAAuB9Q,GACjB+R,KAAeuZ,eAAOvZ,KAAeuZ,eAAOxa,OAAM9Q,GAClD+R,KAAiBwZ,iBAAOxZ,KAAiBwZ,iBAAIxa,IACnD/Q,IAEAqrB,EAAAzrB,UAAMqE,OAAN,SAA2BkQ,GAClB,MACS,QAATA,GACDpC,KAAeuZ,eAAOrnB,OAAMkQ,EAAgBmX,iBAC5CvZ,KAAiBwZ,iBAAOtnB,OAAMkQ,EAEtCoX,mBACDF,K/B5HDI,GAAA,WACE,QAAAA,GAEqCC,EAEAC,EAEZ3rB,EAKoB4rB,GATpC7Z,KAAgB2Z,iBAAYA,EAE5B3Z,KAAgB4Z,iBAAYA,EAE5B5Z,KAAG/R,IAAaA,EAKhB+R,KAAM6Z,OACZA,EACL,MAACH,MAEDI,GAAA,WACE,QAAAA,GAC2BhG,EACciG,GADhC/Z,KAAQ8T,SAAUA,EAClB9T,KAAe+Z,gBACrBA,EACL,MAACD,OAED,SAAkCX,GAChCA,IAAA,YAAQ,WACRA,IAAA,SAAK,QACLA,IAAA,WAAO,UACPA,IAAA,WAAO,UACPA,IAAA,SACF,SANkCA,YAQlC,IAAAa,IAAA,WACE,QAAAC,GAEsCC,EAERC,EAO2B7jB,EAEb8jB,OAFnC,KAAA9jB,MAAgDnJ,SAEhD,KAAAitB,MAAmC,MAXnCpa,KAAKka,MAAwBA,EAE7Bla,KAASma,UAAYA,EAOrBna,KAAW1J,YAAqCA,EAEhD0J,KAAKoa,MACXA,EACL,MAACH,MAMDI,GAAA,WACE,QAAAC,GAC0CtG,EACyBuG,EACXC,GAF9Cxa,KAAegU,gBAAiBA,EACvBhU,KAAaua,cAAmCA,EAO1Dva,KAAgBya,oBAMjBza,KAAa2Y,iBAGb3Y,KAAe4Y,gBAAsBhjB,IAGrCoK,KAAM0a,QAAS,EAhBjB1a,KAAuBwa,uBAAWxrB,EACxCwrB,GAkMF,MAhLEF,GAAAzsB,UAAGmR,IAAH,SAA4B2b,GACpB1tB,GAAM+S,KAAO0a,OAAoD,kDACxDC,YAAgCjB,IACzC1Z,KAAkB4a,kBACxBD,GAAsBA,YAA8BX,IAC9Cha,KAAgB6a,gBACtBF,GAAsBA,YAAkCb,IAClD9Z,KAAyB8a,yBAC/BH,GACM9tB,EAAyB,yBAC/B8tB,IAIFL,EAAAzsB,UAAUktB,WAAV,SAAsCC,GAAtC,GAAAta,GAGCV,IAFO/S,IAAM+S,KAAO0a,OAAoD,kDAC3DM,EAAQnsB,QAAC,SAAMwH,GAAI,MAAIqK,GAAI1B,IAAQ3I,MAOjDikB,EAAAzsB,UAAiBotB,kBAAjB,cAAAva,GAiBCV,KAhBoB2Y,EAAO3Y,KAAe2Y,aAWnC,OAREnqB,GAAmBwR,KAAc2Y,cAAE,SAAQ7E,GACxCpT,EAAewa,eAAWpH,UACb6E,GACtB7E,KAIE9T,KAAO0a,QAAQ,EACZ,GAAejC,IAChBzY,KAAgBgU,gBACP2E,EACT3Y,KAER4Y,kBAEQ0B,EAAAzsB,UAAkBstB,mBAA1B,SAA6CrH,GAC3C,GAAUzd,GAAO2J,KAAc2Y,cAAW7E,EAWpC,OAVMzd,KAEJA,GACe4iB,oBAAqB5B,GAAK+D,KAC9BpH,gBAAMhU,KAAgBgU,gBAC9B+E,QAAE,GAAmBO,IACjBhjB,YACXnJ,KACE6S,KAAc2Y,cAAU7E,GAC9Bzd,GAEFA,GAUUikB,EAAAzsB,UAAcqtB,eAAxB,SAA2CpH,GAClC,OACI9lB,EAAcgS,KAAuBwa,uBAAW1G,IACjD9lB,EAAcgS,KAAcua,cAExCzG,IAEQwG,EAAAzsB,UAAiB+sB,kBAAzB,SAAwDS,GAGlD,IAAmB,GAFXC,IAAS,EAEE/vB,EAA0B,EAA1BsjB,EAASwM,EAAiB1B,iBAA1BpuB,EAAAsjB,EAA0BpjB,OAAAF,IAAA,CAA5C,GAAcuoB,GAAAjF,EAAAtjB,EACd,IAAKyU,KAAekb,eAAWpH,GAAE,CAClC,GAAYzd,GAAO2J,KAAmBmb,mBAAWrH,EAC3Czd,GAAQ0iB,QAAI/Z,IAAUqc,EAAMptB,KAC1BqtB,GACV,GAGE,IAAmB,GAAAxL,GAA0B,EAA1BC,EAASsL,EAAiBzB,iBAA1B9J,EAAAC,EAA0BtkB,OAAAqkB,IAAA,CAA5C,GAAcgE,GAAA/D,EAAAD,EACd,IAAK9P,KAAekb,eAAWpH,GAAE,CAClC,GAAYzd,GAAO2J,KAAmBmb,mBAAWrH,EAC3Czd,GAAQ0iB,QAAOha,OAAUsc,EAAMptB,KAC7BqtB,GACV,GAMWD,EAAOxB,QAAayB,IAC3Btb,KAAgB4Y,gBAAO5Y,KAAgB4Y,gBAAOjR,OACvC0T,EAAIptB,IACJotB,EAEbxB,UAGMS,EAAAzsB,UAAegtB,gBAAvB,SAAuDU,GAAvD,GAAA7a,GAsDCV,IArDaub,GAAUpB,UAAQtrB,QAAC,SAAQilB,GACrC,GAAYzd,GAAOqK,EAAmBya,mBAAWrH,EAC1C,QAAayH,EAASrB,OAC3B,IAA2Bf,IAASqC,SAC1B9a,EAAewa,eAAWpH,IAEhB1d,GAAOC,EAAcklB,EACvCjlB,YACM,MACR,KAA2B6iB,IAAM7hB,MAG3BoJ,EAAqB+a,qBAAW3H,GACvB9lB,EAAc0S,EAAuB8Z,uBAAY1G,KAItDzd,EAAQ0iB,QAAG,GAAoBO,IAC/BjjB,EAAoB4iB,oBAAsB5B,GAAM+D,WAC3C1a,GAAiB+Z,iBAC9B3G,IACgB1d,GAAOC,EAAcklB,EAAcjlB,YAC7C,MACR,KAA2B6iB,IAAQ1hB,QAK7BiJ,EAAqB+a,qBAAW3H,GAC9B7mB,GACSsuB,EAAMnB,MAEnB,wDACI,MACR,KAA2BjB,IAAQuC,QACzBhb,EAAewa,eAAWpH,KAC1Bzd,EAAoB4iB,oBAAsB5B,GAAasE,YAC7CvlB,GAAOC,EAAcklB,EACvCjlB,aACM,MACR,KAA2B6iB,IAAMyC,MACvBlb,EAAewa,eAAWpH,KAI1Bzd,EAAQ0iB,QAAG,GAAmBC,IACpB5iB,GAAOC,EAAcklB,EACvCjlB,aACM,MACR,SACMzJ,EAAsC,sCAAe0uB,EAE/DrB,WAOMI,EAAAzsB,UAAoB4tB,qBAA5B,SAA+C3H,GAC7C,GAAc+H,IAAQ7b,KAAuBwa,uBAAU1G,IAAM,GAAK,CAC/C,KAAP+H,QACC7b,MAAuBwa,uBACpC1G,GACM9T,KAAuBwa,uBAAU1G,GACvC+H,GAGMvB,EAAAzsB,UAAwBitB,yBAAhC,SAA8DzkB,GACpD2J,KAAekb,eAAO7kB,EAAWyd,YACnC9T,KAAiBya,iBAAOpkB,EAAUyd,UAASzd,EACjD0jB,kBAEHO,KC5OewB,GAAI,WAClB,GAAUC,KAGJ,OAFFA,GAAU9M,GAAUC,UAAMvf,MAAe,YACzCosB,EAAU9M,GAAWoC,WAAM1hB,MAAgB,aAEjDosB,KAEeC,GAAI,WACjB,GAASC,KAMH,OALHA,GAAWnoB,GAAU8c,UAAMjhB,MAAe,YAC1CssB,EAAWnoB,GAAmB+c,mBAAMlhB,MAAwB,qBAC5DssB,EAAWnoB,GAAaid,aAAMphB,MAAkB,eAChDssB,EAAWnoB,GAAsBgd,sBAAMnhB,MAA2B,wBAClEssB,EAAWnoB,GAAMC,MAAMpE,MAAW,QAEvCssB,KAyCAC,GAAA,WACE,QAAAC,GACgCnZ,EACIxR,GAD1BwO,KAAUgD,WAAYA,EACtBhD,KAAOxO,QACdA,EAqjCL,MAnjCU2qB,GAAAtuB,UAAeV,gBAAvB,WACK,MAAK6S,MAAQxO,QAAe4qB,cAE/B,GACS,GAActpB,YACvB,IAGMqpB,EAAAtuB,UAAyBwuB,0BAAjC,SAA6DC,GAGrD,MACRA,IAEAH,EAAAtuB,UAAa0uB,cAAb,SAAgChnB,GAC9B,GAAUjB,OACiB/F,KAAnBgH,EAAKjB,KACH3G,GAAQ8G,QACMgB,EAAOF,EAAOjB,KAChC,OAAC,IAAkB5G,IAAK4G,EAAQiB,EAAQxI,SAChD,KASQovB,EAAAtuB,UAAW6lB,YAAnB,SAAwCN,GAChC,OACGhB,QAAWgB,EAAQhB,QACrBC,MAAWe,EAAMf,QAKlB8J,EAAAtuB,UAAaylB,cAArB,SAAmDb,GAI9C,GAA0B,gBAAdA,GAIP,MAAUP,IAAcU,cAChCH,EACQxlB,KAAOwlB,EAAqD,kDAIlE,IAAaL,GAAa5b,GAAKic,EAAQL,SAAS,KACrCC,EAAOI,EAAMJ,OAAM,CACxB,OAAC,IAAaH,IAAQE,EAC9BC,IAUM8J,EAAAtuB,UAAO2uB,QAAf,SAA2BC,GACtB,MAAKzc,MAAQxO,QAAe4qB,cACjBK,EACd1a,WAEa/B,KAA0Bqc,0BAAMI,EAC7Cxa,iBAQMka,EAAAtuB,UAAQ6uB,SAAhB,SAA0CC,GACrC,MAA0B,gBAAdA,IACP1vB,EACA+S,KAAQxO,QAAc4qB,cAE1B,2EACSpf,GAAiByE,iBAC9Bkb,KACQ1vB,GACC+S,KAAQxO,QAAc4qB,cAE3B,6EACSpf,GAAe4E,eAC5B+a,KAGFR,EAAAtuB,UAAS+uB,UAAT,SAAkCjW,GAC1B,MAAK3G,MAAY0T,YAAQ/M,EACjC+M,gBAEAyI,EAAAtuB,UAAWgvB,YAAX,SAA2BlW,GAEnB,MADA1Z,KAAU0Z,EAAkD,gDAC5CuM,GAAcI,cAAKtT,KAAcsT,cACzD3M,KAEAwV,EAAAtuB,UAAcivB,eAAd,SAAqC9Z,EAAoBrM,GACjD,MAAKqJ,MAAyB+c,yBAAY/Z,GACxCkB,MAAa,aACbA,MAAMvN,GAEhBsO,mBAEAkX,EAAAtuB,UAAgBmvB,iBAAhB,SAA6BrtB,GAC3B,GAAcstB,GAAe3kB,GAAW4M,WAAOvV,EAKzC,OAJA1C,GACA+S,KAAoBkd,oBAAUD,GACC,oCAAWA,GAGlDA,GAEAd,EAAAtuB,UAAMsvB,OAAN,SAAuBlvB,GACf,MAAK+R,MAAe8c,eAAK9c,KAAWgD,WAAK/U,EACjD0I,OAEAwlB,EAAAtuB,UAAQuvB,SAAR,SAAqBztB,GACnB,GAAcstB,GAAOjd,KAAiBgd,iBAAOrtB,EAgBvC,OAfA1C,GACIgwB,EAAIplB,IAAG,KAASmI,KAAWgD,WAAUO,UACM,oDACzC0Z,EAAIplB,IAAG,GACT,OACFmI,KAAWgD,WACjBO,WACItW,GACMgwB,EAAIplB,IAAG,KAASmI,KAAWgD,WAAUQ,UACrCyZ,EAAIplB,IAAG,KAASmI,KAAWgD,WAASQ,SACM,qDAC1CyZ,EAAIplB,IAAG,GACT,OACFmI,KAAWgD,WACjBQ,UACK,GAAeyC,IAAKjG,KAAiCqd,iCAC9DJ,KAEAd,EAAAtuB,UAAWyvB,YAAX,SAA8B3mB,GACzB,MAAmB,KAAdA,EAAOlL,OAGFuU,KACbud,kBACWvd,KAAe8c,eAAK9c,KAAWgD,WAC5CrM,IAEAwlB,EAAAtuB,UAAa2vB,cAAb,SAA0B7tB,GACxB,GAAkB8tB,GAAOzd,KAAiBgd,iBAAOrtB,EAC9C,OAA2B,KAAd8tB,EAAOhyB,OACF6M,GACrBC,WACWyH,KAAiCqd,iCAC9CI,IAEAvvB,OAAAwR,eAAIyc,EAAAtuB,UAAiB,qBfy8IfgK,Iez8IN,WAOQ,MANO,IAAgBS,KACjB,WACN0H,KAAWgD,WAAUO,UACd,YACPvD,KAAWgD,WACdQ,WAELyB,mBfq8IMpC,YAAY,EACZC,cet8IL,IAEOqZ,EAAAtuB,UAAwBkvB,yBAAhC,SAAuD/Z,GAC/C,MAAC,IAAgB1K,KACX,WACA0K,EAAUO,UACT,YACDP,EAEdQ,YAEQ2Y,EAAAtuB,UAAgCwvB,iCAAxC,SAC4BI,GAMpB,MAJAxwB,GACQwwB,EAAOhyB,OAAI,GAAuC,cAAvBgyB,EAAI5lB,IAAG,GACX,oCAAe4lB,GAEjCA,EAASnZ,SAC9B,IAEQ6X,EAAAtuB,UAAmBqvB,oBAA3B,SAA8CvmB,GAErC,MACDA,GAAOlL,QAAK,GACU,aAAtBkL,EAAIkB,IAAG,IAGf,cAFQlB,EAAIkB,IAAG,IAIfskB,EAAAtuB,UAAO6vB,QAAP,SAAkCxS,GAC7B,GAAIA,YAAsBtX,IACrB,OAAY+pB,UACpB,aAAM,IAAQzS,YAAsBI,IAC5B,OAAesS,aAAK1S,EAC5B7c,QAFU,IAEI6c,YAAsBU,IAC5B,OAAeiS,aAAI,GAAM3S,EACjC7c,QAFU,IAEI6c,YAAsBjX,IAAe,CACjD,GAAiB6pB,GAAM5S,EAAS7c,OAC7B,IAAK2R,KAAQxO,QAAe4qB,cAAE,CAI5B,GAAMxtB,MAAckvB,GACf,OAAcA,YACtB,MAAM,IAAgBA,IAAc/R,IAC5B,OAAc+R,YACtB,WAAU,IAAYA,KAAK,IACnB,OAAcA,YACtB,aAEI,OAAcA,YAAK5S,EAC3B7c,SAfU,MAeI6c,aAAsBe,KACd8R,YAAK7S,EAC3B7c,SAAc6c,YAAsByB,KACjBqR,SAAMhe,KAAWie,WACpC/S,IAAcA,YAAsBqC,KACf2Q,WAAMle,KAAame,aACxCjT,IAAcA,YAAsBiB,KAElBiS,eAAMpe,KAAY0T,YAAIxI,EAExCG,gBAAcH,YAAsBwB,KAEnB2R,eACH7b,SAAK0I,EAAQ7c,QAASmU,SACrBC,UAAKyI,EAAQ7c,QAG5BoU,YAAcyI,YAAsBqB,KAEtB+R,WAAMte,KAAQwc,QAAItR,EAEhC7c,UAAc6c,YAAsBsB,KAElB+R,eAAMve,KAAe8c,eAAI5R,EAAWlI,WAAKkI,EAAIjd,IAE/D0I,OACa9J,EAAsB,sBAAOH,KAAUC,UACpDue,KAGFiR,EAAAtuB,UAAS2wB,UAAT,SAAwBlzB,GAAxB,GAAAoV,GAwDCV,KAtDWjQ,EAAezE,EAAe,UACrC,IAAOmL,GAAInL,EAAMyE,EAAe,aAC3B,MAAW6D,IACnBC,QAAM,IAAW4C,GAAInL,EAAMyE,EAAkB,gBACrC,MAAWub,IAAgBE,GAAIlgB,EACvCsyB,aAFU,IAEOnnB,GAAInL,EAAMyE,EAAkB,gBACrC,MAAC,IAAc6b,IAAwBpV,GAAIlL,EACnDuyB,cAFU,IAEOpnB,GAAInL,EAAMyE,EAAiB,eAAE,CACzC,GAAKiQ,KAAQxO,QAAe4qB,cAAE,CAE5B,GAAmC,QAA9B9wB,EAAmBwyB,YACnB,MAAW7pB,IACnBC,GAAM,IAA4C,aAAnC5I,EAAmBwyB,YAC1B,MAAW7pB,IACnB6X,iBAAU,IAAyC,cAApCxgB,EAAmBwyB,YAC1B,MAAW7pB,IACnB+X,kBAGI,MAAC,IAAc/X,IAAgB3I,EACvCwyB,aAbU,GAaOrnB,GAAInL,EAAMyE,EAAiB,eACpC,MAAC,IAAckc,IAAgB3gB,EACvCyyB,YAFU,IAEOtnB,GAAInL,EAAMyE,EAAc,YACjC,MAAKiQ,MAAWye,WAAInzB,EAAU0yB,SAAO1J,WADnC,IAEO7d,GAAInL,EAAMyE,EAAgB,cAAE,CAE9BwG,GAAIjL,EAAW4yB,WAAgB,aAC5C,IAAYQ,GAAMpzB,EAAY4yB,WAAOQ,UAC/B,WAAenR,IAAWmR,EAAW1yB,IAAC,SAACyc,GAAI,MAAI/H,GAAU8d,UAAG/V,MAJ1D,GAKOhS,GAAInL,EAAMyE,EAAoB,kBAEvC,MADOwG,IAAIjL,EAAe8yB,eAAoB,kBAC7C,GAAcjS,IACfnM,KAAcsT,cAAIhoB,EAE1B8yB,gBALU,IAKO3nB,GAAInL,EAAMyE,EAAmB,iBAAE,CACjCwG,GAAIjL,EAAc+yB,cAAmB,gBAClD,IAAc7b,GAAMlX,EAAe+yB,cAAS7b,UAAM,EACnCC,EAAMnX,EAAe+yB,cAAU5b,WAAM,CAC9C,OAAC,IAAciK,IAAe,GAAY3P,IAASyF,EAC3DC,IALU,GAKOhM,GAAInL,EAAMyE,EAAgB,cAAE,CAC9BwG,GAAIjL,EAAWgzB,WAAgB,aAC5C,IAAU3B,GAAO3c,KAAS0c,SAAIpxB,EAAcgzB,WACtC,OAAC,IAAc/R,IACvBoQ,GAJU,GAIOlmB,GAAInL,EAAMyE,EAAoB,kBAAE,CAClCwG,GAAIjL,EAAeizB,eAAoB,iBACpD,IAAkBd,GAAOzd,KAAiBgd,iBAAI1xB,EAAkBizB,gBACtDI,EAAG,GAActb,IAAaoa,EAAI5lB,IAAG,GAAc4lB,EAAI5lB,IAAK,IAC7D5J,EAAG,GAAegY,IACrBjG,KAAiCqd,iCACrCI,GACI,OAAC,IAAcjR,IAAcmS,EACrC1wB,GACQ,MAAKpB,GAAuB,uBAAOH,KAAUC,UACrDrB,KAIF6wB,EAAAtuB,UAAkB+wB,mBAAlB,SACkB3wB,EACcqmB,GAExB,OACA3kB,KAAMqQ,KAAOmd,OAAKlvB,GAChBqmB,OAAMtU,KAAS6e,SAEzBvK,KAEA6H,EAAAtuB,UAAUixB,WAAV,SAA6BC,GAKrB,MAJA9xB,IACK8xB,EAAkBlY,kBAE3B,8CAEIlX,KAAMqQ,KAAOmd,OAAS4B,EAAK9wB,KACzBqmB,OAAMtU,KAAS6e,SAASE,EAAMnY,MAC1BkO,WAAM9U,KAAY0T,YAASqL,EAAQpY,QAEjD+M,iBAEAyI,EAAAtuB,UAAYmxB,aAAZ,SAAmCD,GAC3B,MAAC,IAAYtY,IACbzG,KAASod,SAAS2B,EAAOpvB,MACzBqQ,KAAY6c,YAASkC,EAAajK,YAClC9U,KAAWye,WAASM,EAAOzK,aACZzN,mBAEvB,KAEAsV,EAAAtuB,UAAQgxB,SAAR,SAAuCvK,GAAvC,GAAA5T,GAMCV,KALa/Q,IAIN,OAHAqlB,GAAQzlB,QAAC,SAAIZ,EAAOI,GAClBY,EAAKhB,GAAOyS,EAAQgd,QAC5BrvB,KAEFY,GAEAktB,EAAAtuB,UAAU4wB,WAAV,SAAqB/hB,GAArB,GAAAgE,GAQCV,KANUhU,EAA0C0Q,EACzCzN,EAAa0d,GAAmBnG,KAIpC,OAHH3X,GAAY7C,EAAE,SAAIiC,EAAOI,GACpBY,EAASA,EAAIge,IAAC,GAAa5H,KAAOpX,IAAMyS,EAAU8d,UAC1DnwB,MAEFY,GAEAktB,EAAAtuB,UAAUowB,WAAV,SAAsCjyB,GAC9B,OACEsoB,OAAMtU,KAAS6e,SAEzB7yB,KAEAmwB,EAAAtuB,UAAYswB,aAAZ,SAAyCtc,GAAzC,GAAAnB,GAMCV,KALa/Q,IAIN,OAHD4S,GAAQhT,QAAC,SAAKR,GACXY,EAAK6J,KAAK4H,EAAQgd,QAC1BrvB,OACeqwB,OACjBzvB,IAEQktB,EAAAtuB,UAASoxB,UAAjB,SAAoD1gB,GAC5CtR,IACCsR,EAAM2gB,MAEX,kEACW3oB,GAAIgI,EAAO2gB,MAAKvvB,KAAoB,kBACpC4G,GAAIgI,EAAO2gB,MAAWpK,WAA0B,uBAC7D,IAAS7mB,GAAO+R,KAASod,SAAI7e,EAAO2gB,MAAQvvB,MAC/BgX,EAAO3G,KAAY6c,YAAIte,EAAO2gB,MAAcpK,YAC7CR,EAAOtU,KAAWye,WAAIlgB,EAAO2gB,MAAO5K,WAC1C,OAAC,IAAY7N,IAAIxY,EAAS0Y,EAAQ2N,GAAqBzN,mBAC/D,KAEQsV,EAAAtuB,UAAWsxB,YAAnB,SAAyDlwB,GACjDhC,IACIgC,EAAQmwB,QAEhB,kEACInyB,IACIgC,EAASowB,SAEjB,+DACF,IAASpxB,GAAO+R,KAASod,SAAOnuB,EAAWmwB,SAC9BzY,EAAO3G,KAAY6c,YAAO5tB,EAAYowB,SAC7C,OAAC,IAAchY,IAAIpZ,EAC3B0Y,IAEAwV,EAAAtuB,UAAiByxB,kBAAjB,SAAuDrwB,GAErD,GAAUc,GAAkBd,EAAgB,WACzC,OAAOwH,IAAOxH,EAAMc,EAAW,SACrBiQ,KAAUif,UACvBhwB,GAAiBwH,GAAOxH,EAAMc,EAAa,WAC9BiQ,KAAYmf,YACzBlwB,GACWpC,EAA+B,+BAAOH,KAAUC,UAC7DsC,KAEQktB,EAAAtuB,UAAwB0xB,yBAAhC,SAC+BrF,GAEtB,OAASA,GACd,IAA2Bf,IAAM7hB,MACzB,MAAO,KACf,KAA2B6hB,IAAQuC,QAC3B,MAAW,SACnB,KAA2BvC,IAASqC,SAC5B,MAAa,WACrB,KAA2BrC,IAAQ1hB,QAC3B,MAAU,QAClB,KAA2B0hB,IAAMyC,MACzB,MAAS,OACjB,SACQ,MAAK/uB,GAAmC,mCAEpDqtB,KAEAiC,EAAAtuB,UAAiB2xB,kBAAjB,SAA0C7E,GACrC,GAAYA,YAAkCb,IACzC,OACE3U,QACCiS,MAAauD,EAAgBZ,gBAAM3C,MAChCtD,SAAa6G,EAG3B7G,UACG,IAAY6G,YAAgCjB,IAAE,CAC5C,GAAYiB,EAAOd,iBAAqBpT,IAAE,CAC3C,GAASlI,GAAcoc,EAAQd,MACzB,QACU4F,gBACJV,UACFpvB,KAAMqQ,KAAOmd,OAAI5e,EAAKtQ,KACpBqmB,OAAMtU,KAAS6e,SAAItgB,EAAMqI,MACrBkO,WAAM9U,KAAU4c,UAAIre,EAC/BoI,UACQwT,UAAaQ,EAAiBhB,iBACvBC,iBAAae,EAGnCf,mBAAM,GAAgBe,EAAOd,iBAAuBxS,IAAE,CACpD,GAAS9I,GAAcoc,EAAQd,MACzB,QACU6F,gBACJX,SAAM/e,KAAOmd,OAAI5e,EAAKtQ,KACtBoxB,SAAMrf,KAAU4c,UAAIre,EAASoI,SACrBiT,iBAAae,EAGnCf,mBAAU,GAA6B,OAAjBe,EAAOd,OACrB,OACU8F,gBACJZ,SAAM/e,KAAOmd,OAAYxC,EAAK1sB,KACtB2rB,iBAAae,EAGnCf,mBAEC,GAAYe,YAA8BX,IAAE,CAC7C,GAASI,OAAqC7rB,EAOxC,OANSosB,GAAOP,QACfA,GACC9lB,KAAoBoB,EAAYilB,EAAMP,MAAM9lB,MACzCvH,QAAa4tB,EAAMP,MAE9BrtB,WAEcwuB,cACMqE,iBAAM5f,KAAyBuf,yBAAY5E,EAAOT,OACzDC,UAAaQ,EAAUR,UACrB7jB,YAAM0J,KAA0Bqc,0BAAY1B,EAAarkB,aAC/D8jB,MAGXA,IACM,MAAKvtB,GAA8B,8BAAOH,KAAUC,UAC5DguB,KAEAwB,EAAAtuB,UAAegyB,gBAAf,SAA0CxpB,GAExC,GAC6BskB,GADnB5qB,EAAkBsG,EAAgB,WAEzC,IAAOI,GAAOJ,EAAMtG,EAAkB,gBAAE,CAC5BwG,GAAOF,EAAaklB,aAAkB,eAGnD,IAAWrB,GAAOla,KAA2B8f,2BACrCzpB,EAAcklB,aAAiBqE,kBACrC,aACazF,EAAqB9jB,EAAcklB,aAAUpB,cAC3C7jB,EACTD,EAAcklB,aAAYjlB,aAAQ0J,KAAmB7S,kBAC7C4yB,EAAS1pB,EAAcklB,aAAOnB,MACnCA,EAAa2F,GAAQ/f,KAAcuc,cAAawD,EAChDpF,GAAG,GAAqBX,IAC5BE,EACIC,EACE7jB,EACN8jB,GAET,UAAM,IAAW3jB,GAAOJ,EAAMtG,EAAoB,kBAAE,CACrCwG,GAAOF,EAAeopB,eAAoB,kBAC1ClpB,GAAOF,EAAgBopB,eAASV,SAAyB,uBACzDxoB,GACLF,EAAgBopB,eAAUV,SAAKpvB,KAErC,gCACW4G,GACLF,EAAgBopB,eAAUV,SAAWjK,WAE3C,qCACF,IAAkBkL,GAAS3pB,EAAiBopB,eACnCxxB,EAAO+R,KAASod,SAAa4C,EAAUjB,SAAQpvB,MAC3CgX,EAAO3G,KAAY6c,YAAamD,EAAUjB,SAAcjK,YACzDR,EAAOtU,KAAWye,WAAauB,EAAUjB,SAAOzK,YACnD/V,EAAA,GAAekI,IAAIxY,EAAS0Y,EAAQ2N,GAC1BzN,mBAChB,IACmB8S,EAAeqG,EAAU7F,cACzBP,EAAeoG,EAAiBpG,oBAC3Ce,GAAG,GAAuBjB,IACnBC,EACAC,EACbrb,EAAItQ,IAGXsQ,OA1BU,IA0BO9H,GAAOJ,EAAMtG,EAAoB,kBAAE,CACrCwG,GAAOF,EAAeqpB,eAAoB,kBAC1CnpB,GAAOF,EAAgBqpB,eAASX,SAA6B,0BAC1E,IAAekB,GAAS5pB,EAAiBqpB,eAChCzxB,EAAO+R,KAASod,SAAU6C,EAAYlB,UAClCpY,EAAYsZ,EAASZ,SAC1Brf,KAAY6c,YAAUoD,EAAUZ,UACrBnM,GAAiBK,gBAC3BhV,EAAG,GAAc8I,IAAIpZ,EAAW0Y,GACnBiT,EAAYqG,EAAiBrG,oBACxCe,GAAG,GAAuBjB,OAAqBE,EAAKrb,EAAItQ,IACrEsQ,OAXU,IAWO9H,GAAOJ,EAAMtG,EAAoB,kBAAE,CACrCwG,GAAOF,EAAespB,eAAoB,kBAC1CppB,GAAOF,EAAgBspB,eAASZ,SAAoB,iBACjE,IAAemB,GAAS7pB,EAAiBspB,eAChC1xB,EAAO+R,KAASod,SAAU8C,EAAYnB,UACzBnF,EAAYsG,EAAiBtG,oBACxCe,GAAG,GAAuBjB,OAAqBE,EAAK3rB,EACjE,UAPU,KAOOwI,GAAOJ,EAAMtG,EAAY,UAUlC,MAAKlD,GAAuB,uBAAOH,KAAUC,UACrD0J,GATeE,IAAOF,EAAO8O,OAAY,UAC1B5O,GAAOF,EAAQ8O,OAAS2O,SAAqB,kBAC1D,IAAY3O,GAAS9O,EAAQ8O,OAClBiS,EAAUjS,EAAMiS,OAAM,EACZ2C,EAAG,GAAmB5C,IAAQC,GACrCtD,EAAU3O,EAAW2O,QACxB6G,GAAG,GAAyBb,IAAShG,EAClDiG,GAGM,MACRY,IAEAwB,EAAAtuB,UAA0BiyB,2BAA1B,SACyC5F,GAEpC,MAAuB,cAAjBA,EACsBf,GAC/BqC,SAA2B,QAAXtB,EACef,GAC/B7hB,MAA8B,WAAd4iB,EACef,GAC/B1hB,QAA+B,YAAfyiB,EACef,GAC/BuC,QAA6B,UAAbxB,EACef,GAC/ByC,MACa/uB,EAAsC,sCACnDqtB,IAGFiC,EAAAtuB,UAAyBsyB,0BAAzB,SAAoD9pB,GAM/C,IAAQI,GAAOJ,EADUA,EAAkB,cACJ,gBAClC,MAAgB6c,IACxBM,GACA,IAAkB+H,GAASllB,EAAeklB,YACvC,OAAaA,GAAUpB,WAAgBoB,EAAUpB,UAAQ1uB,OACpCynB,GACxBM,IACiB+H,EAAU8D,SAGhBrf,KAAY6c,YAAatB,EACtC8D,UAH0BnM,GACxBM,KAIF2I,EAAAtuB,UAAUuyB,WAAV,SAA6BC,GAA7B,GACwBpxB,GADxByR,EA+BCV,IA7BI,IAASqgB,YAAwB7K,IAC5BvmB,GACEglB,OAAMjU,KAAmB4e,mBAASyB,EAAIpyB,IAAUoyB,EAE1DhyB,YAAM,IAAagyB,YAA2BrJ,IACtC/nB,GAAW8P,OAAMiB,KAAOmd,OAASkD,EACzCpyB,UAFU,IAESoyB,YAA0BtK,IACrC9mB,GACEglB,OAAMjU,KAAmB4e,mBAASyB,EAAIpyB,IAAUoyB,EAAMzZ,MAClD0Z,WAAMtgB,KAAeugB,eAASF,EAE5CpK,gBALU,MAKSoK,YAA8B7J,KAUzC,MAAK3pB,GAAyB,yBAAWwzB,EACjDtwB,KAVQd,IACKwlB,WACCsK,SAAM/e,KAAOmd,OAASkD,EAAKpyB,KACpByoB,gBAAA2J,EAA0B3J,gBAAI1qB,IAAC,SAASyoB,GACrD,MAAI/T,GAAiB8f,iBAAW/L,OAYlC,MAJO4L,GAAa3K,aAAQR,SAC1BjmB,EAAgBwxB,gBAAOzgB,KAAe0gB,eAASL,EACvD3K,eAGFzmB,GAEAktB,EAAAtuB,UAAY8yB,aAAZ,SAA6BC,GAA7B,GAAAlgB,GA+BCV,KA9BmB0V,EAAQkL,EAAgBH,gBAClCzgB,KAAiB6gB,iBAAMD,EAAiBH,iBAChC7L,GAAMO,IAEnB,IAAMyL,EAAQ3M,OAAE,CACJ1d,GAAMqqB,EAAO3M,OAAKtkB,KAAU,OACzC,IAAS1B,GAAO+R,KAASod,SAAMwD,EAAO3M,OAAQtkB,MACnCtB,EAAO2R,KAAWye,WAAMmC,EAAO3M,OAAOK,WAC9C,IAAMsM,EAAYN,WAAE,CACrB,GAAerK,GAAOjW,KAAiB8gB,iBAAMF,EAAaN,WACpD,OAAC,IAAiBvK,IAAI9nB,EAAOI,EAAW4nB,EAChDP,GACQ,MAAC,IAAeF,IAAIvnB,EAAOI,EACnCqnB,GACI,GAAUkL,EAAQ7hB,OAAE,CACxB,GAAS9Q,GAAO+R,KAASod,SAAMwD,EAAS7hB,OAClC,OAAC,IAAkBiY,IAAI/oB,EAC/BynB,GAHU,GAGMkL,EAAWnM,UAAE,CAC3B,GAASxmB,GAAO+R,KAASod,SAAMwD,EAAUnM,UAAYsK,UAChCrI,EAAAkK,EAAkBnM,UAAiBiC,gBAAI1qB,IAAC,SAASyoB,GACpE,MAAI/T,GAAmBqgB,mBAAWtM,IAM9B,OAJAxnB,IACwB,IAAhByoB,EAAOX,OAEnB,yDACK,GAAqByB,IAAIvoB,EAClCyoB,GACQ,MAAK7pB,GAA2B,2BAAOH,KAAUC,UACzDi0B,KAGMzE,EAAAtuB,UAAc6yB,eAAtB,SAAiDhL,GAE5C,MADGzoB,IAAcyoB,EAAOR,OAA2C,6CAC5B3mB,KAA1BmnB,EAAWZ,YAEbA,WAAM9U,KAAU4c,UAAalH,EAE3CZ,iBAA6CvmB,KAAtBmnB,EAAOX,QACbA,OAAcW,EAC/BX,QACaloB,EACb,yBAGMsvB,EAAAtuB,UAAgBgzB,iBAAxB,SAAuDnL,GAClD,WAAuCnnB,KAA1BmnB,EAAWZ,WACNF,GAAWE,WAAK9U,KAAY6c,YAAanH,EAC9DZ,iBAA6CvmB,KAAtBmnB,EAAOX,OACTH,GAAOG,OAAaW,EACzCX,QACqBH,GACrBO,MAGMgH,EAAAtuB,UAAemzB,gBAAvB,SAA8CJ,GAA9C,GAAAlgB,GAYCV,KAVc2G,EAAQia,EAAW9L,WACxB9U,KAAY6c,YAAM+D,EAAY9L,YAC7B,KACWH,EAAwC,IAMtD,OALGiM,GAAkBjM,mBACTA,EAAAiM,EAAyBjM,iBAAI3oB,IAAC,SAAMiD,GAClD,MAAIyR,GAAU8d,UAAQvvB,MAGnB,GAAkBylB,IAAQ/N,EACnCgO,IAEAwH,EAAAtuB,UAAgBozB,iBAAhB,SAAsDC,GAAtD,GAAAxgB,GAECV,IADO,QAAQkhB,OAAWl1B,IAAC,SAAK40B,GAAI,MAAIlgB,GAAgBsgB,gBAAOJ,MAGxDzE,EAAAtuB,UAAgB2yB,iBAAxB,SAAuDzJ,GAK/C,MAJA9pB,GACU8pB,EAAUtC,oBAAoCF,IACvC,sBAAiBwC,EACtCtC,YAES6B,UAAgBS,EAAMrjB,MAAkBuR,kBACjCkc,iBAEpB,iBAEQhF,EAAAtuB,UAAkBkzB,mBAA1B,SAAoDH,GAC5C3zB,EACsC,iBAArC2zB,EAAkBO,iBACI,4BAAOz0B,KAAUC,UAC5Ci0B,GACF,IAAetK,GAAYjR,GAAiBO,iBAAMgb,EAAatK,UACzD,OAAC,IAAkB9B,IAAU8B,EAA0B/B,GAC/D9U,WAEA0c,EAAAtuB,UAAiBuzB,kBAAjB,SAA8B1iB,GACtB,OAAY5C,WAAOkE,KAAYsd,YAAM5e,EAC7C/H,SAEAwlB,EAAAtuB,UAAmBwzB,oBAAnB,SAAwDC,GACtD,GAAWlK,GAAkBkK,EAAWxlB,UAAQrQ,MAC1CwB,GACO,IAANmqB,EAC8C,oDACnDA,EACF,IAAUznB,GAAkB2xB,EAAWxlB,UAAI,EACrC,OAAM8R,IAAOS,OAAKrO,KAAcwd,cACxC7tB,KAEAwsB,EAAAtuB,UAAa0zB,cAAb,SAA0B7iB,GAExB,GAAYzP,IAAqCuyB,mBAC9C,IAAM9iB,EAAK/H,KAAW7H,UACjBG,EAAOwyB,OAAOzhB,KAAYsd,YAAahlB,GAC/CC,gBAAQ,CACN,GAAU5B,GAAQ+H,EAAM/H,IAClB1J,GACA0J,EAAOlL,OAAI,GAAM,EAErB,oDACIwD,EAAOwyB,OAAOzhB,KAAYsd,YAAK3mB,EAAY6N,WAC3CvV,EAAiBuyB,gBAAKE,OAAkBC,aAAMhrB,EACtD+N,gBAEA,GAAWkd,GAAO5hB,KAAS6hB,SAAMnjB,EAAUqP,QACjC6T,KACF3yB,EAAiBuyB,gBAAMI,MAC/BA,EAEA,IAAa9S,GAAO9O,KAAQ8hB,QAAMpjB,EAAUoQ,QAChCA,KACJ7f,EAAiBuyB,gBAAQ1S,QACjCA,EAEA,IAAWzK,GAAOrE,KAAQ+hB,QAAMrjB,EAAQ2F,MAYlC,YAXkB9V,KAAf8V,IACDpV,EAAiBuyB,gBAAMnd,MAC/BA,GAES3F,EAASsP,UACV/e,EAAiBuyB,gBAAQxT,QAAOhO,KAASgiB,SAAMtjB,EACvDsP,UACStP,EAAOuP,QACRhf,EAAiBuyB,gBAAMvT,MAAOjO,KAASgiB,SAAMtjB,EACrDuP,QAGFhf,GAEAktB,EAAAtuB,UAAeo0B,gBAAf,SAAuCvnB,GACrC,GAAQ/D,GAAOqJ,KAAcwd,cAAO9iB,EAAU+mB,QAEnC/iB,EAAShE,EAAkB8mB,gBACvBU,EAAQxjB,EAAKgjB,KAAQhjB,EAAKgjB,KAAOj2B,OAAK,CAClD,IAAUy2B,EAAK,EAAE,CACZj1B,EACW,IAANi1B,EAET,uEACF,IAAUR,GAAQhjB,EAAMgjB,KAAI,EACxB/qB,GAAOA,EAAMuN,MAAKwd,EACxBC,cAEA,GAAYQ,KACHzjB,GAAOkjB,QACNO,EAAOniB,KAAWoiB,WAAM1jB,EAClCkjB,OAEA,IAAW9S,KACFpQ,GAASoQ,UACTA,EAAO9O,KAAUqiB,UAAM3jB,EAChCoQ,SAEA,IAASzK,GAAuB,IACvB3F,GAAO2F,QACTA,EAAQ3F,EACf2F,MAEA,IAAW2J,GAAsB,IACxBtP,GAASsP,UACTA,EAAOhO,KAAWsiB,WAAM5jB,EACjCsP,SAEA,IAASC,GAAsB,IAKzB,OAJGvP,GAAOuP,QACTA,EAAOjO,KAAWsiB,WAAM5jB,EAC/BuP,QAEO,GAASL,IAAKjX,EAASmY,EAAUqT,EAAO9d,EAAS2J,EAC1DC,IAEAkO,EAAAtuB,UAAqB00B,sBAArB,SACsBC,GAEpB,GAAWn0B,GAAO2R,KAAQyiB,QAAUD,EAAUzO,QAC3C,OAAe,OAAT1lB,EAET,MAEsBq0B,mBAEtBr0B,IAGM8tB,EAAAtuB,UAAO40B,QAAf,SAAqC1O,GAC5B,OAAWA,GAChB,IAAiBhJ,IAAO4X,OAChB,MAAM,KACd,KAAiB5X,IAAwB6X,wBACjC,MAA6B,2BACrC,KAAiB7X,IAAgB8X,gBACzB,MAAkB,gBAC1B,SACQ,MAAKh2B,GAA+B,+BAEhDknB,KAEAoI,EAAAtuB,UAAQi1B,SAAR,SAA6BN,GAC3B,GAAuBvzB,GACZyP,EAAY8jB,EAAO9jB,KAgBxB,OAbEzP,GADCyP,EAAmB9C,mBACNE,UAAMkE,KAAkBohB,kBAC9C1iB,KACkBA,MAAMsB,KAAcuhB,cACtC7iB,IAEMzP,EAAS6kB,SAAY0O,EAAU1O,SAExB0O,EAAYlsB,YAAO7K,OAAK,IAC7BwD,EAAYqH,YAAO0J,KAA0Bqc,0BACxCmG,EAEblsB,cAGFrH,GAEQktB,EAAAtuB,UAAQg0B,SAAhB,SAAkC9T,GAAlC,GAAArN,GAYCV,IAXI,IAAsB,IAAd+N,EAAOtiB,OAAf,CACH,GAAYy1B,GAAAnT,EAAc/hB,IACxB,SAAMmZ,GACJ,MAAMA,aAA0B/Q,IACxBsM,EAAiBqiB,iBAAQ5d,GACzBzE,EAAcsiB,cAAQ7d,IAE/B,OAAqB,KAAd+b,EAAOz1B,OACFy1B,EACf,IACwB+B,iBAAMtvB,GAAO,MAASoa,QAChDmT,MAEQ/E,EAAAtuB,UAAUu0B,WAAlB,SAAiDjd,GAAjD,GAAAzE,GAcCV,IAbI,OAASmF,OAEgC5W,KAA3B4W,EAAY+d,aACfljB,KAAgBmjB,gBAC9Bhe,QAA4C5W,KAA3B4W,EAAY1R,aACfuM,KAAmBojB,mBACjCje,QAAgD5W,KAA/B4W,EAAgB8d,gBACzB9d,EAAuB8d,gBAASlV,QAChC/hB,IAAC,SAACq3B,GAAI,MAAI3iB,GAAW0hB,WAAGiB,KACrBC,OAAC,SAAMC,EAAS1d,GAAK,MAAK0d,GAAOj3B,OAASuZ,KAExChZ,EAAmB,mBAAOH,KAAUC,UACjDwY,QAGMgX,EAAAtuB,UAAOi0B,QAAf,SAAmC0B,GAAnC,GAAA9iB,GAGCV,IAFI,IAAuB,IAAdwjB,EAAO/3B,OACb,MAAA+3B,GAAax3B,IAAC,SAAKoL,GAAI,MAAIsJ,GAAgB+iB,gBAAOrsB,MAGlD+kB,EAAAtuB,UAASw0B,UAAjB,SAAuCmB,GAAvC,GAAA9iB,GAECV,IADO,OAAAwjB,GAAax3B,IAAC,SAAKoL,GAAI,MAAIsJ,GAAkBgjB,kBAAOtsB,MAGpD+kB,EAAAtuB,UAAOk0B,QAAf,SAAoC1d,GAC/B,IAAWjR,EAA0BiR,GAChC,MACRA,IAIM8X,EAAAtuB,UAAQm0B,SAAhB,SAA8B2B,GAA9B,GAAAjjB,GAKCV,IAJO,QACEwR,OAAQmS,EAAOnS,OACfkN,OAAAiF,EAAiB3zB,SAAIhE,IAAC,SAASylB,GAAI,MAAI/Q,GAAQgd,QAAWjM,OAI5D0K,EAAAtuB,UAAUy0B,WAAlB,SAAqCqB,GAArC,GAAAjjB,GAICV,KAHawR,IAAWmS,EAAQnS,OACjBxhB,EAAA2zB,EAAiBjF,OAAI1yB,IAAC,SAASylB,GAAI,MAAI/Q,GAAU8d,UAAW/M,IACpE,OAAC,IAASH,IAASthB,EAC3BwhB,IAGA2K,EAAAtuB,UAAW+1B,YAAX,SAA0B5U,GAClB,MAAW8M,IAAI9M,EACvBrf,OAGAwsB,EAAAtuB,UAAag2B,cAAb,SAAiD7U,GACxC,OAAOA,GACZ,IAAgB,YACR,MAAUC,IAAWC,SAC7B,KAAiB,aACT,MAAUD,IAAYoC,UAC9B,SACQ,SAKZ8K,EAAAtuB,UAAci2B,eAAd,SAA6BnwB,GACrB,MAAUqoB,IAAGroB,EACrBhE,OAEAwsB,EAAAtuB,UAAgBk2B,iBAAhB,SAAsCpwB,GAC7B,OAAMA,GACX,IAAY,QACJ,MAAWG,IAAOC,KAC1B,KAAmB,eACX,MAAWD,IAAcid,YACjC,KAA4B,wBACpB,MAAWjd,IAAuBgd,qBAC1C,KAAgB,YACR,MAAWhd,IAAW8c,SAC9B,KAAyB,qBACjB,MAAW9c,IAAoB+c,kBACvC,KAA2B,uBACnB,MAAKhkB,GAAyB,uBACtC,SACQ,MAAKA,GAEjB,sBAEAsvB,EAAAtuB,UAAoBm2B,qBAApB,SAAoCrtB,GAC5B,OAAY2f,UAAM3f,EAC1BsO,oBAEAkX,EAAAtuB,UAAsBo2B,uBAAtB,SAAyDC,GACjD,MAAU7e,IAAiBO,iBAAese,EAClD5N,YAGA6F,EAAAtuB,UAAe41B,gBAAf,SAAgC3U,GACxB,OACCpb,MAAMsM,KAAqBgkB,qBAAQlV,EAAOpb,OACtCywB,UAAMnkB,KAAY4jB,YAAQ9U,EAEvCE,OAEAmN,EAAAtuB,UAAiB61B,kBAAjB,SAAoC5U,GAC5B,MAAC,IAAWH,IACZ3O,KAAuBikB,uBAAQnV,EAAQpb,OACvCsM,KAAc6jB,cAAQ/U,EAE9BqV,aAGAhI,EAAAtuB,UAAgBk1B,iBAAhB,SAA+B5d,GAC1B,MAAOA,aAA2B/Q,KAEtBX,aACJC,MAAMsM,KAAqBgkB,qBAAO7e,EAAOzR,OAC5CC,GAAMqM,KAAe8jB,eAAO3e,EAAIxR,IAC7BtF,MAAM2R,KAAQ0d,QAAOvY,EAGhC9W,SACaxB,EAAwB,wBAAOH,KAAUC,UACtDwY,KAGFgX,EAAAtuB,UAAkBu1B,mBAAlB,SAAqCje,GAC7B,MAAC,IAAkB/Q,IACnB4L,KAAuBikB,uBAAO9e,EAAa1R,YAAQC,OACnDsM,KAAiB+jB,iBAAO5e,EAAa1R,YAAKE,IAC1CqM,KAAUwe,UAAOrZ,EAAa1R,YAEtCpF,SAGA8tB,EAAAtuB,UAAam1B,cAAb,SAA4B7d,GACvB,MAAOA,aAAsBhR,KAEjB+uB,aACJxvB,MAAMsM,KAAqBgkB,qBAAO7e,EAAOzR,OAC5CC,GAGR,WAAiBwR,YAAuBnR,KAEzBkvB,aACJxvB,MAAMsM,KAAqBgkB,qBAAO7e,EAAOzR,OAC5CC,GAGR,YACa9G,EAAwB,wBAAOH,KAAUC,UACtDwY,KAGFgX,EAAAtuB,UAAes1B,gBAAf,SAAkChe,GACzB,OAAOA,EAAa+d,YAAOvvB,IAChC,IAAa,SACX,GAAcywB,GAAOpkB,KAAuBikB,uBACpC9e,EAAa+d,YACnBxvB,MACI,OAAC,IAAaS,IAAWiwB,EACjC,KAAc,UACZ,GAAeC,GAAOrkB,KAAuBikB,uBACrC9e,EAAa+d,YACnBxvB,MACI,OAAC,IAAcM,IAAYqwB,EACnC,KAA2B,uBACnB,MAAKx3B,GAAuB,qBACpC,SACQ,MAAKA,GAEjB,oBAEAsvB,EAAAtuB,UAAc0yB,eAAd,SAAmCtK,GAC3B,OACMqO,WAAArO,EAAkB3B,OAAItoB,IAAC,SAAK0H,GAAI,MAAKA,GAAkBuR,sBAIrEkX,EAAAtuB,UAAgBizB,iBAAhB,SAAwCF,GACtC,GAAW2D,GAAQ3D,EAAW0D,eAClBhQ,EAAAiQ,EAAYv4B,IAAC,SAAI2K,GAAI,MAAS0O,IAAiBO,iBAAMjP,IAC3D,OAAC,IAAayd,IACtBE,IACD6H,Kfu1IGqI,GAAgB15B,EAAoB,GAGpC25B,GAAO35B,EAAoB,I8Cp/K/B45B,GAAA,WAQE,QAAAC,GAAmE54B,GAP3DiU,KAAa4kB,cAA2B,KACxC5kB,KAAc6kB,eAA+C,KAC7D7kB,KAAgB8kB,iBAAiC,KAMnD9kB,KAAO+kB,OAAOh5B,EAAQg5B,OACtB/kB,KAAQglB,QAAOj5B,EACrBi5B,QAgDF,MA9CEL,GAAA92B,UAAMo3B,OAAN,SAA2BC,GACnBj4B,GAAM+S,KAAc4kB,cAAoC,kCAC1D5kB,KAAc4kB,cACpBM,GAEAP,EAAA92B,UAAOs3B,QAAP,SAAgDD,GACxCj4B,GAAM+S,KAAe6kB,eAAqC,mCAC5D7kB,KAAe6kB,eACrBK,GAEAP,EAAA92B,UAASu3B,UAAT,SAAoCF,GAC5Bj4B,GAAM+S,KAAiB8kB,iBAAuC,qCAChE9kB,KAAiB8kB,iBACvBI,GAEAP,EAAA92B,UAAKw3B,MAAL,WACMrlB,KACNglB,WAEAL,EAAA92B,UAAIy3B,KAAJ,SAAWj6B,GACL2U,KAAO+kB,OACb15B,IAEAs5B,EAAA92B,UAAU03B,WAAV,WACQt4B,EACuB,OAAvB+S,KAAc4kB,cACuB,kDAEvC5kB,KACN4kB,iBAEAD,EAAA92B,UAAW23B,YAAX,SAAgCC,GACxBx4B,EACwB,OAAxB+S,KAAe6kB,eACc,mDAE/B7kB,KAAe6kB,eACrBY,IAEAd,EAAA92B,UAAa63B,cAAb,SAAoBr6B,GACZ4B,EAC0B,OAA1B+S,KAAiB8kB,iBACc,qDAEjC9kB,KAAiB8kB,iBACvBz5B,IACDs5B,KC/CYgB,GAAgB,aAOAC,GAAiB,eAAev5B,GAI7Dw5B,GAAA,WAuBE,QAAAC,GAA8BC,GACxB/lB,KAAWgD,WAAO+iB,EAAY/iB,WAC9BhD,KAAKgmB,KAAG,GAAgBvB,IAAA,SAC5B,IAAW7D,GAAOmF,EAAI5iB,IAAU,QAAU,MACtCnD,MAAQimB,QAAQrF,EAAQ,MAAOmF,EACrC7iB,KAmRF,MA7QU4iB,GAAAj4B,UAAuBq4B,wBAA/B,SACoCC,EACftrB,GAEhB,GAAOA,EACJ,IAAC,GAAYurB,KAASvrB,GAAawrB,YAC5BxrB,EAAYwrB,YAAet4B,eAASq4B,KACpCD,EAAQC,GAAQvrB,EAAYwrB,YACrCD,GAGGD,GAAqB,qBAA2BP,GAGhDO,EAAgC,gCACrC,YAAgBnmB,KAAWgD,WAAUO,UAAG,cACvBvD,KAAWgD,WAChCQ,UAEAsiB,EAAAj4B,UAAMy4B,OAAN,SAAsBC,EAAcnsB,EAAqBS,GAAzD,GAAA6F,GA2ECV,KA1EUwmB,EAAOxmB,KAAQymB,QAAUF,EAE5B,WAAY/B,IAAA,EAAC,SAAuBlqB,EAAkBC,GACtDmG,EAAKslB,KAAUU,UAAC,SAASC,GACxBA,EAAWC,WAAUnC,GAAA,UAASoC,SAAE,WACjC,IACS,OAAIF,EAAsBG,oBAC/B,IAAcrC,IAAA,UAASsC,SACrB,GAAUC,GAAML,EAAmBM,iBAChC97B,GAAcw6B,GAAiB,gBAAMj5B,KAAUC,UAAQq6B,IACnD1sB,EAAO0sB,EACR,MACR,KAAcvC,IAAA,UAAQyC,QACjB36B,EAAc,QAAUg6B,EAA6B,0BAClDhsB,EACJ,GAAkB7M,IAAKC,GAAkB+G,kBACzC,oBACI,MACR,KAAc+vB,IAAA,UAAW0C,WACvB,GAAYC,GAAMT,EAAaU,WAC5B96B,GACM,QAAUg6B,EAA0B,wBACrCa,EACU,iBACbT,EACHW,mBACQF,EAAK,EACP7sB,EACJ,GAAkB7M,IACKiI,EAAQyxB,GACE,gCAAMT,EAG3CY,mBAGKh7B,EAAco5B,GAAS,QAAUY,EAA0B,uBACxDhsB,EACJ,GAAkB7M,IAAKC,GAAYkH,YAEvC,uBACM,MACR,SACMhI,EACK,QACE05B,EACuB,gDAE3BI,EAAmBG,mBAClB,KACDH,EAAea,eAI5B,iBAAC,QACIr8B,EAAcw6B,GAAS,QAAUY,EAAmB,gBACnD7lB,EAAKslB,KAAcyB,cACzBd,KAGF,IAAmBe,GAAOh7B,KAAUC,UAAUyN,EAC3CjP,GAAcw6B,GAAiB,gBAAKa,EAAM,IAAkBkB,EAM/D,IAAavB,IAAwBwB,eAAiB,aAElDjnB,GAAwBwlB,wBAAQC,EAAStrB,GAE1C8rB,EAAKrB,KAAIkB,EAAQ,OAAekB,EAASvB,EA/HxB,SAoI1BL,EAAAj4B,UAAU+5B,WAAV,SAA0BrB,EAAqB1rB,GAC7C,GAAgBgtB,GAAuB/B,EAA2BgC,2BAAUvB,GAC5DwB,EAAuBjC,EAAwBkC,wBAAUzB,EAC1DsB,IAAgBE,GACzBl7B,EAAqB,qBAC3B05B,EACA,IAAc0B,IACRjoB,KAAQimB,QACT,IACO4B,EACP,IACOE,EAEV,YACuBG,EAA+Bh6B,OAAAu2B,GAAA,6BAC3CrqB,GAKU+tB,uBAAM,EAGTC,mBAAc,aACdC,sBACPC,aAAM,EACKC,wBACtB,EACEvoB,MAAwBkmB,wBAAQ9rB,EAAmBiuB,mBAASxtB,EAChE,IAAS2rB,GAAWyB,EAAKr2B,KAAK,GAC3BzG,GAAcw6B,GAAyB,wBAAMa,EAAM,IAAYpsB,EAElE,IAAaouB,GAAsBN,EAAiBO,iBAAIjC,EAAkBpsB,GAOhEsuB,GAAS,EAKTC,GAAS,EAGDC,EAAA,GAAmBlE,KAC7BK,OAAE,SAAS15B,GACHs9B,EASPx9B,EAAcw6B,GAA6C,4CAChEt6B,IATcq9B,IACPv9B,EAAcw6B,GAAmC,iCAC7C6C,EAAQK,OACTH,GACR,GACGv9B,EAAcw6B,GAAuB,sBAAOt6B,GACxCm9B,EAAKlD,KACdj6B,KAIK25B,QAAE,WAAM,MAAOwD,GAAQnD,WAONyD,EAAG,SACD/4B,EACFtB,GAIjB+5B,EAAOO,OAAKh5B,EAAE,SAAWi5B,GAC9B,IACIv6B,EACJu6B,GAAQ,MAAGp8B,GACCq8B,WAAC,WACT,KACFr8B,IACF,MA2EE,OAvEck8B,GAAWrE,GAAA,WAAUyE,UAAKC,KAAE,WAClCR,GACPx9B,EAAcw6B,GACnB,kCAGkBmD,EAAWrE,GAAA,WAAUyE,UAAME,MAAE,WACnCT,IACJA,GAAQ,EACXx9B,EAAcw6B,GAAiC,+BACtCiD,EACdpD,iBAGkBsD,EAAWrE,GAAA,WAAUyE,UAAM18B,MAAE,SAASi5B,GAC5CkD,IACJA,GAAQ,EACXx9B,EAAcw6B,GAAiC,gCAAOF,GAC7CmD,EAAYpD,YACtB,GAAkB93B,IACZC,GAAYkH,YAItB,4CAGkBi0B,EAAWrE,GAAA,WAAUyE,UAAQG,QAAE,SAASh+B,GACvD,IAASs9B,EAAE,CAIZ,GAAaW,GAAMj+B,EAAKub,KAAI,EACtB3Z,KAAUq8B,EAA4C,yCAK5D,IAAW78B,GAAU68B,EAAU78B,OAAQ68B,EAAG,IAAWA,EAAG,GAAQ78B,KAC7D,IAAOA,EAAE,CACPtB,EAAcw6B,GAA8B,6BAASl5B,EAExD,IAAY88B,GAAgB98B,EAAQ8I,OAC5BjB,EAAuBgB,EAASi0B,GAC7Bx8B,EAAQN,EAASM,YACLwB,KAAf+F,IACFA,EAAO3G,GAAUiH,SACd7H,EACmB,yBAClBw8B,EACU,iBACX98B,EACTM,SAEM47B,GAAQ,EACFC,EAAYpD,YAAC,GAAkB93B,IAAK4G,EAAYvH,IACrDy7B,EACTnD,YACKl6B,GAAcw6B,GAAwB,uBAAW2D,GACxCV,EAAclD,cAC5B4D,MAIML,WAAC,WAKGL,EACdrD,cAAM,GAERqD,GAGA9C,EAAAj4B,UAAO44B,QAAP,SAAuBF,GACrB,GAASC,IAAQxmB,KAAQimB,QAAK,IA5SA,UAsTxB,OATHO,GAAK1tB,KAAe,cACpB0tB,EAAK1tB,KAAKkH,KAAWgD,WAAYO,WAEjCijB,EAAK1tB,KAAgB,eACrB0tB,EAAK1tB,KAAKkH,KAAWgD,WAAWQ,UAChCgjB,EAAK1tB,KAAe,cAEpB0tB,EAAK1tB,KAAM,KACX0tB,EAAK1tB,KAAUytB,GACRC,EAAK50B,KACjB,KArSek0B,EAA0BgC,4BAClC0B,MAAsC,qCACrC7G,OACN,sCAMamD,EAAuBkC,yBAC/BwB,MAAS,QACR7G,OACN,UA0RHmD,KCzUD2D,GAAA,WAKE,QAAAC,KAFS1pB,KAAe7S,gBAAM,GAGxB6S,KAAgB/M,gBACtB,mBADoC0O,MAkBtC,MAfE+nB,GAAA77B,UAAc87B,eAAd,SAAyCC,GACjC,MAAQpF,IAAA,EAAQlqB,QAAC,GAAwBurB,IACjD+D,KAEAF,EAAA77B,UAAag8B,cAAb,SAAoC7mB,GAC5B,MAAC,IAAuBkZ,IAAWlZ,GAAiBoZ,eAC5D,KAEAsN,EAAA77B,UAAI8T,KAAJ,SAAoBmoB,GACZ,MAAKnoB,MACbmoB,IAEAJ,EAAA77B,UAAImU,KAAJ,SAAgB+nB,GACR,MAAK/nB,MACb+nB,IACDL,ICtBct8B,IAAYyS,YAAC,GAAuB4pB,IjCSnD,IkCmBCO,IlCnBDlzB,GAAA,WAUE,QAAAwO,KhBs5LM,IgBt5LM,GAAA2kB,MAAA1+B,EAAuB,EAAvBA,EAAAC,UAAuBC,OAAAF,IAAvB0+B,EAAA1+B,GAAAC,UAAuBD,EACQmE,GAC5B,YACDu6B,EACE,aAEZ,EAEE,KAAC,GAAK73B,GAAI,EAAGA,EAAa63B,EAAOx+B,SAAK2G,EAErC,GADYtC,EAAY,YAAU,SAAGsC,EAAY63B,EAAK73B,IAC1B,IAAjB63B,EAAG73B,GAAO3G,OACtB,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACsB,0EAM7CoS,MAAcxC,EAAG,GAAqB6H,IAC5C4kB,GAeF,MAHgB3kB,GAAU4kB,WAAxB,WACQ,MAAU5kB,GAClB6kB,GANwB7kB,EAAY6kB,EAAG,GAAa7kB,GACjCD,GAAWM,WAC5BV,mBAKHK,KAKazO,GAAaob,OAAkB,kBkCpD7C,SAAuB+X,GAMrBA,IAAA,WAAO,UAOPA,IAAA,WAAO,UAOPA,IAAA,UACF,UArBuBA,YCTvB,IAKC3yB,KALD,SAAsBA,GACpBA,IAAA,SAAK,QACLA,IAAA,WAAO,UACPA,IAAA,YAAQ,WACRA,IAAA,YACF,YALsBA,YAYtB,IAGC+yB,KAHD,SAAqBA,GACnBA,IAAA,SAAK,QACLA,IAAA,UACF,UAHqBA,YASrB,ICtBCC,IDsBDC,GAAA,WAKE,QAAAC,KAJQvqB,KAASwqB,UAAG,GAAajjB,IACpBtB,GAGEhC,YAuFjB,MArFEsmB,GAAA18B,UAAK48B,MAAL,SAAgCp0B,GAC9B,GAASpI,GAASoI,EAAIkI,IAAKtQ,IACZy8B,EAAO1qB,KAAUwqB,UAAI3yB,IAAM5J,EACvC,KAAYy8B,EAGf,YAFM1qB,KAAUwqB,UAAOxqB,KAAUwqB,UAAO7iB,OAAI1Z,EAAUoI,GAM9CA,GAAKtG,OAAesH,GAAMC,OACvBozB,EAAK36B,OAAesH,GAC9BG,SACKwI,KAAUwqB,UAAOxqB,KAAUwqB,UAAO7iB,OAAI1Z,EAC5CoI,GACQA,EAAKtG,OAAesH,GAASG,UAC1BkzB,EAAK36B,OAAesH,GAC9BI,QACKuI,KAAUwqB,UAAAxqB,KAAiBwqB,UAAO7iB,OAAI1Z,GACpC8B,KAAW26B,EAAK36B,KACjBwO,IAAQlI,EAEfkI,MACQlI,EAAKtG,OAAesH,GAASE,UAC1BmzB,EAAK36B,OAAesH,GAC9BE,SACKyI,KAAUwqB,UAAAxqB,KAAiBwqB,UAAO7iB,OAAI1Z,GACpC8B,KAAYsH,GAASE,SACtBgH,IAAQlI,EAEfkI,MACQlI,EAAKtG,OAAesH,GAASE,UAC1BmzB,EAAK36B,OAAesH,GAC9BC,MACK0I,KAAUwqB,UAAAxqB,KAAiBwqB,UAAO7iB,OAAI1Z,GACpC8B,KAAYsH,GAAMC,MACnBiH,IAAQlI,EAEfkI,MACQlI,EAAKtG,OAAesH,GAAQI,SACzBizB,EAAK36B,OAAesH,GAC9BC,MACK0I,KAAUwqB,UAAOxqB,KAAUwqB,UAAO1iB,OACxC7Z,GACQoI,EAAKtG,OAAesH,GAAQI,SACzBizB,EAAK36B,OAAesH,GAC9BE,SACKyI,KAAUwqB,UAAAxqB,KAAiBwqB,UAAO7iB,OAAI1Z,GACpC8B,KAAYsH,GAAQI,QACrB8G,IAAWmsB,EAElBnsB,MACQlI,EAAKtG,OAAesH,GAAMC,OACvBozB,EAAK36B,OAAesH,GAC9BI,QACKuI,KAAUwqB,UAAAxqB,KAAiBwqB,UAAO7iB,OAAI1Z,GACpC8B,KAAYsH,GAASE,SACtBgH,IAAQlI,EAEfkI,MAQM1R,EACoC,uCAChCH,KAAUC,UAAQ0J,GACb,UACL3J,KAAUC,UAEpB+9B,KAGFH,EAAA18B,UAAU88B,WAAV,WACE,GAAaC,KAMP,OALF5qB,MAAUwqB,UAAiBliB,iBAC7B,SAAiBra,EAA4BoI,GACpCu0B,EAAK9xB,KACdzC,KAGJu0B,GACDL,KE1GDM,GAAA,WAcE,QAAAC,GAAqC7a,GAI7BjQ,KAAWiE,WADRgM,EACW,SAAajJ,EAAcC,GAC3C,MAAIgJ,GAAGjJ,EAAKC,IAAehB,GAAWhC,WAAG+C,EAAI/Y,IAAIgZ,EAAKhZ,MAEtC,SAAa+Y,EAAcC,GAC3C,MAAWhB,IAAWhC,WAAG+C,EAAI/Y,IAAIgZ,EAAKhZ,MAGtC+R,KAAS+qB,SAAiBj1B,IAC1BkK,KAAUgrB,UAAG,GAAazjB,IAAqBvH,KACrDiE,YAiHF,MAvIS6mB,GAAQG,SAAf,SAAmCC,GAC3B,MAAC,IAAeJ,GAAOI,EAC/BjnB,aAsBA6mB,EAAAj9B,UAAG6pB,IAAH,SAAoBzpB,GACZ,MACR,OADa+R,KAAS+qB,SAAIlzB,IAAK5J,IAG/B68B,EAAAj9B,UAAGgK,IAAH,SAAoB5J,GACZ,MAAK+R,MAAS+qB,SAAIlzB,IAC1B5J,IAEA68B,EAAAj9B,UAAK+pB,MAAL,WACQ,MAAK5X,MAAUgrB,UACvB5iB,UAEA0iB,EAAAj9B,UAAIgqB,KAAJ,WACQ,MAAK7X,MAAUgrB,UACvB3iB,UAEAyiB,EAAAj9B,UAAOiB,QAAP,WACQ,MAAKkR,MAAUgrB,UACvBl8B,WAOAg8B,EAAAj9B,UAAOs9B,QAAP,SAAwBl9B,GAChBhB,EACA+S,KAAI0X,IAAKzpB,GAC4C,0DACzDA,EACF,IAASsQ,GAAOyB,KAAS+qB,SAAIlzB,IAAM5J,EAC7B,OAAK+R,MAAUgrB,UAAkB/iB,kBACzC1J,IAMAusB,EAAAj9B,UAAO8D,QAAP,SAAwB1D,GACtB,GAASsQ,GAAOyB,KAAS+qB,SAAIlzB,IAAM5J,EAC7B,OAAIsQ,GAAOyB,KAAUgrB,UAAQr5B,QAAK4M,IAC1C,GAEArQ,OAAAwR,eAAIorB,EAAAj9B,UAAI,QrDkmMFgK,IqDlmMN,WACQ,MAAKmI,MAAUgrB,UACvBzmB,MrDmmMM1B,YAAY,EACZC,cqDpmML,IAGDgoB,EAAAj9B,UAAOgB,QAAP,SAAmCipB,GAC7B9X,KAAUgrB,UAAiB1iB,iBAAC,SAAEE,EAAGC,GAE7B,MADJqP,GAAItP,IAER,KAIFsiB,EAAAj9B,UAAGmR,IAAH,SAAiBT,GAEf,GAAS0O,GAAOjN,KAAOjB,OAAIR,EAAMtQ,IAC3B,OAAIgf,GAAKrF,KACVqF,EAAS8d,SAAOpjB,OAAIpJ,EAAItQ,IAAMsQ,GAC9B0O,EAAU+d,UAAOrjB,OAAIpJ,EAE5B,QAGAusB,EAAAj9B,UAAMkR,OAAN,SAAuB9Q,GACrB,GAASsQ,GAAOyB,KAAInI,IAAM5J,EACvB,OAAMsQ,GAIEyB,KAAK4H,KAAK5H,KAAS+qB,SAAOjjB,OAAK7Z,GAAM+R,KAAUgrB,UAAOljB,OACnEvJ,IAHEyB,MAKF8qB,EAAAj9B,UAAMqE,OAAN,SAA4CkQ,GACvC,KAAQA,YAAyB0oB,IAAO,OAAO,CAC/C,IAAK9qB,KAAKuE,OAAUnC,EAAMmC,KAAO,OAAO,CAI3C,KAFA,GAAY8T,GAAOrY,KAAUgrB,UAAeriB,cAC/B2P,EAAQlW,EAAU4oB,UAAeriB,cACjC0P,EAAU9O,WAAG,CACxB,GAAa6hB,GAAS/S,EAAUhP,UAAKpb,IACvBo9B,EAAU/S,EAAUjP,UAAKpb,GACpC,KAASm9B,EAAOl5B,OAAWm5B,GAAO,OACvC,EACM,OACR,GAEAP,EAAAj9B,UAAQ8S,SAAR,WACE,GAAgB2qB,KAIb,OAHCtrB,MAAQnR,QAAC,SAAG0P,GACJ+sB,EAAKxyB,KAAIyF,QAEO,IAAd+sB,EAAO7/B,OAErB,iBAC4B,oBAAa6/B,EAAK15B,KAAQ,QACtD,OAGMk5B,EAAAj9B,UAAI+Z,KAAZ,SAC4CmjB,EACNC,GAEpC,GAAYO,GAAG,GAAkBT,EAI3B,OAHAS,GAAWtnB,WAAOjE,KAAYiE,WAC9BsnB,EAASR,SAAYA,EACrBQ,EAAUP,UAAaA,EAE/BO,GACDT,KChJDU,GAAA,WAWE,QAAAC,GAAsDC,GAAlC1rB,KAAQ0rB,SAA0BA,EAJ9C1rB,KAAK2rB,SA2Ef,MApEEF,GAAA59B,UAAGgK,IAAH,SAAgB5J,GACd,GAAQ29B,GAAO5rB,KAAS0rB,SAAMz9B,GACjBkiB,EAAOnQ,KAAM2rB,MAAKC,EAC5B,QAAuBr9B,KAAf4hB,EAGP,IAA4B,GAAA5kB,GAAO,EAAPsgC,EAAO1b,EAAP5kB,EAAAsgC,EAAOpgC,OAAAF,IAAA,CAA5B,GAAAsjB,GAAAgd,EAAiBtgC,GAAhBugC,EAAAjd,EAAQ,GAAExgB,EAAAwgB,EAAK,EACtB,IAASid,EAAO55B,OAAMjE,GACjB,MACRI,KAKJo9B,EAAA59B,UAAG6pB,IAAH,SAAgBzpB,GACR,WACRM,KADayR,KAAInI,IAAK5J,IAItBw9B,EAAA59B,UAAGof,IAAH,SAAgBhf,EAAkBI,GAChC,GAAQu9B,GAAO5rB,KAAS0rB,SAAMz9B,GACjBkiB,EAAOnQ,KAAM2rB,MAAKC,EAC5B,QAAuBr9B,KAAf4hB,EAGX,YAFMnQ,KAAM2rB,MAAIC,KAAQ39B,EAAUI,IAG9B,KAAC,GAAK+D,GAAI,EAAGA,EAAU+d,EAAO1kB,OAAK2G,IAClC,GAAQ+d,EAAG/d,GAAG,GAAOF,OAAMjE,GAG9B,YAFSkiB,EAAG/d,IAAOnE,EAASI,GAIvB8hB,GAAKrX,MAAK7K,EACnBI,KAKAo9B,EAAA59B,UAAMkR,OAAN,SAAmB9Q,GACjB,GAAQ29B,GAAO5rB,KAAS0rB,SAAMz9B,GACjBkiB,EAAOnQ,KAAM2rB,MAAKC,EAC5B,QAAuBr9B,KAAf4hB,EACH,OACR,CACI,KAAC,GAAK/d,GAAI,EAAGA,EAAU+d,EAAO1kB,OAAK2G,IAClC,GAAQ+d,EAAG/d,GAAG,GAAOF,OAAMjE,GAMtB,MALmB,KAAdkiB,EAAO1kB,aACLuU,MAAM2rB,MACnBC,GACSzb,EAAO4b,OAAE35B,EAClB,IAEF,CAEI,QACR,GAEAq5B,EAAA59B,UAAOgB,QAAP,SAAkDJ,GACzCI,EAAamR,KAAM2rB,MAAE,SAAEj6B,EAASs6B,GACjC,IAAiB,GAAAzgC,GAAO,EAAP0gC,EAAOD,EAAPzgC,EAAA0gC,EAAOxgC,OAAAF,IAAA,CAAjB,GAAAsjB,GAAAod,EAAM1gC,GAALid,EAAAqG,EAAC,GAAEpG,EAAAoG,EAAC,EACZpgB,GAAE+Z,EAAKC,OAKfgjB,EAAA59B,UAAOiB,QAAP,WACQ,MAAQA,GAAakR,KAC7B2rB,QACDF,KC7EDS,GAAA,mBAAAA,KAGSlsB,KAASmsB,aAClB,MAACD,MAeDE,GAAA,WAOE,QAAAC,GAA0CC,GAAtBtsB,KAAUssB,WAAYA,EANlCtsB,KAAOusB,QAAA,GAAgBf,IAA4B,SAACgB,GAC1D,MAACA,GAAc3c,gBAGT7P,KAAWysB,YAA2BzC,GAAS0C,QAGjD1sB,KAAWssB,WAAUK,UACnB3sB,KAAS4sB,SAAK71B,KAAMiJ,MACpBA,KAAQ6sB,QAAK91B,KAErBiJ,OAmFF,MAjFEqsB,GAAAx+B,UAAMk7B,OAAN,SAA8B+D,GAC5B,GAAWpuB,GAAWouB,EAAOpuB,MACdquB,GAAS,EAEXC,EAAOhtB,KAAQusB,QAAI10B,IAAQ6G,EAYrC,OAXYsuB,KACFD,GAAQ,EACVC,EAAG,GAAyBd,IACjClsB,KAAQusB,QAAItf,IAAMvO,EACxBsuB,IACSA,EAAUb,UAAKrzB,KAAWg0B,GAE3BA,EAAqBG,qBAAKjtB,KAAcysB,aAEnCO,EAAUE,UAASJ,EAAeK,eAAUH,EAAWE,UAEpDH,EACR/sB,KAAgBssB,WAAOvD,OAAOrqB,GAAK0uB,KAAC,SAAQtZ,GAE1C,MADIkZ,GAASlZ,SAAYA,EAEjCA,IAEc0Q,GAAA,EAAQlqB,QAAU0yB,EAClClZ,WAGFuY,EAAAx+B,UAAQw/B,SAAR,SAAgCP,GAC9B,GAAWpuB,GAAWouB,EAAOpuB,MACf4uB,GAAS,EAERN,EAAOhtB,KAAQusB,QAAI10B,IAAQ6G,EACvC,IAAWsuB,EAAE,CACd,GAAO56B,GAAY46B,EAAUb,UAAQx6B,QAAWm7B,EAC3C16B,IAAM,IACA46B,EAAUb,UAAOJ,OAAE35B,EAAK,GACvBk7B,EACZ,IADwBN,EAAUb,UAAO1gC,QAIxC,MAAY6hC,IACTttB,KAAQusB,QAAOxtB,OAAQL,GAChBsB,KAAWssB,WAASe,SACjC3uB,IACgB8lB,GAAA,EAChBlqB,WAGF+xB,EAAAx+B,UAAQ++B,SAAR,SAAkCW,GAC5B,IAAmB,GAAAhiC,GAAS,EAATiiC,EAASD,EAAThiC,EAAAiiC,EAAS/hC,OAAAF,IAAA,CAA3B,GAAc2hC,GAAAM,EAAAjiC,GACNmT,EAAWwuB,EAAOxuB,MACdsuB,EAAOhtB,KAAQusB,QAAI10B,IAAQ6G,EACvC,IAAWsuB,EAAE,CACV,IAAmB,GAAAne,GAAmB,EAAnBiB,EAASkd,EAAUb,UAAnBtd,EAAAiB,EAAmBrkB,OAAAojB,IAAvBiB,EAAAjB,GACMse,eAAWD,EAE3BF,GAASE,SACpBA,KAIJb,EAAAx+B,UAAOg/B,QAAP,SAAoBnuB,EAAcjS,GAChC,GAAeugC,GAAOhtB,KAAQusB,QAAI10B,IAAQ6G,EACvC,IAAWsuB,EACR,IAAmB,GAAAzhC,GAAmB,EAAnBsjB,EAASme,EAAUb,UAAnB5gC,EAAAsjB,EAAmBpjB,OAAAF,IAAA,CAArC,GAAcuhC,GAAAje,EAAAtjB,EACTuhC,GAAQD,QAAQpgC,GAMxBuT,KAAQusB,QAAOxtB,OACrBL,IAEA2tB,EAAAx+B,UAAoBo/B,qBAApB,SAA6CR,GACvCzsB,KAAYysB,YAAeA,EAC3BzsB,KAAQusB,QAAQ19B,QAAC,SAAE6C,EAAWs7B,GAC5B,IAAmB,GAAAzhC,GAAmB,EAAnBsjB,EAASme,EAAUb,UAAnB5gC,EAAAsjB,EAAmBpjB,OAAAF,IAAvBsjB,EAAAtjB,GACY0hC,qBAAcR,MAIlDJ,KAsBDoB,GAAA,WAaE,QAAAC,GACuBhvB,EACwBivB,EACtBn8B,GAFdwO,KAAKtB,MAAOA,EACbsB,KAAa2tB,cAAwBA,EAVvC3tB,KAAkB4tB,oBAAS,EAM3B5tB,KAAWysB,YAA2BzC,GAAS0C,QAOjD1sB,KAAQxO,QAAUA,MAsI1B,MAnIEk8B,GAAA7/B,UAAcs/B,eAAd,SAAiCU,GAM5B,GALG5gC,EACA4gC,EAAWvvB,WAAO7S,OAAI,GAAQoiC,EAAiBC,iBAEnD,2CAEO9tB,KAAQxO,QAAgCu8B,+BAAE,CAG7C,IAAoB,GADRzvB,MACQ/S,EAAe,EAAfsjB,EAAIgf,EAAWvvB,WAAf/S,EAAAsjB,EAAepjB,OAAAF,IAAA,CAAlC,GAAe8vB,GAAAxM,EAAAtjB,EACL8vB,GAAKtrB,OAAesH,GAAUG,UAC/B8G,EAAKxF,KACjBuiB,GAEEwS,GACGnvB,MAAMmvB,EAAMnvB,MACb2a,KAAMwU,EAAKxU,KACRlb,QAAM0vB,EAAQ1vB,QACXG,aACDG,UAAMovB,EAAUpvB,UACTuvB,iBAAMH,EAAiBG,iBACvBF,iBAAMD,EAE1BC,kBAES9tB,KAAoB4tB,mBAId5tB,KAAiBiuB,iBAAOJ,IACjC7tB,KAAc2tB,cAAK3nB,KACzB6nB,GALU7tB,KAAwBkuB,wBAAKL,EAAM7tB,KAAcysB,cACnDzsB,KAAkBmuB,kBACxBN,GAKE7tB,KAAK6tB,KACXA,GAEAH,EAAA7/B,UAAOg/B,QAAP,SAAoBpgC,GACduT,KAAc2tB,cAAMlhC,MAC1BA,IAEAihC,EAAA7/B,UAAoBo/B,qBAApB,SAA6CR,GACvCzsB,KAAYysB,YAAeA,EAEzBzsB,KAAK6tB,OACJ7tB,KAAmB4tB,oBACpB5tB,KAAwBkuB,wBAAKluB,KAAK6tB,KACvCpB,IACKzsB,KAAkBmuB,kBAAKnuB,KAC7B6tB,OAGMH,EAAA7/B,UAAuBqgC,wBAA/B,SACoBL,EACMpB,GAQrB,GANGx/B,GACC+S,KAAmB4tB,mBAExB,yEAGOC,EAAWpvB,UACZ,OACR,CAIA,IAAiB2vB,GAAc3B,IAAgBzC,GAAQqE,MAGpD,OAAKruB,MAAQxO,QAAsB88B,uBAAgBF,GAC9CnhC,EACA4gC,EAAUpvB,UAEd,qDAEJ,IAGYovB,EAAKxU,KAAUvqB,WAAe29B,IAAgBzC,GAC5DqE,QAEQX,EAAA7/B,UAAgBogC,iBAAxB,SAA2CJ,GAKtC,GAAKA,EAAWvvB,WAAO7S,OAAK,EACvB,OACR,CAEA,IAA6B8iC,GACvBvuB,KAAK6tB,MAAQ7tB,KAAK6tB,KAAiBG,mBAASH,EAAkBG,gBACjE,UAAKH,EAAiBC,mBAA4BS,KAErD,IADavuB,KAAQxO,QAA4Bg9B,6BAS3Cd,EAAA7/B,UAAiBsgC,kBAAzB,SAA4CN,GACpC5gC,GACC+S,KAAmB4tB,mBAExB,kDACEC,GACGnvB,MAAMmvB,EAAMnvB,MACb2a,KAAMwU,EAAKxU,KACRlb,QAAa0sB,GAASI,SAAK4C,EAAMxU,MAC9B/a,WAAeovB,EAAsBe,sBAAMZ,GAC5CpvB,UAAMovB,EAAUpvB,UACTuvB,iBAAMH,EAAiBG,iBACvBF,kBAChB,GACE9tB,KAAmB4tB,oBAAQ,EAC3B5tB,KAAc2tB,cAAK3nB,KACzB6nB,IAGeH,EAAqBe,sBAApC,SACoBZ,GAElB,GAAY5+B,KAIN,OAHF4+B,GAAKxU,KAAQxqB,QAAC,SAAG0P,GACbtP,EAAK6J,MAAO/I,KAAYsH,GAAMC,MAAKiH,IAC3CA,MAEFtP,GACDy+B,KCvRDrzB,GAAA,WAeE,QAAAq0B,GAAsExJ,GAAtE,GAAAxkB,GAmBCV,IA/BOA,MAAY2uB,aAAkC,KAC9C3uB,KAAa4uB,cAA8B,KAG3C5uB,KAAM/Q,WAA4BV,GAClCyR,KAAKvT,MAAa,KAClBuT,KAAM6uB,QAAS,EAIf7uB,KAAgB8uB,kBAAS,EAGvB5J,EACN,SAAK72B,GACCqS,EAAOmuB,QAAQ,EACfnuB,EAAOzR,OAASZ,EACZqS,EAAciuB,cAGhBjuB,EAAaiuB,aACnBtgC,IAEF,SAAK5B,GACCiU,EAAOmuB,QAAQ,EACfnuB,EAAMjU,MAASA,EACXiU,EAAekuB,eACjBluB,EAAckuB,cACpBniC,KA8HR,MAzHEiiC,GAAA7gC,UAAKkhC,MAAL,SAC+CtgC,GAEvC,MAAKuR,MAAKgG,SAAUzX,GAC5BE,IAEAigC,EAAA7gC,UAAImY,KAAJ,SACiCgpB,EACHC,GAF9B,GAAAvuB,GAwBCV,IAhBI,OAJKA,MAAkB8uB,kBACpBjiC,EACN,yDACImT,KAAiB8uB,kBAAQ,EACrB9uB,KAAQ6uB,OACL7uB,KAAOvT,MAGHuT,KAAYkvB,YAAQD,EAAMjvB,KACvCvT,OAHauT,KAAYmvB,YAAOH,EAAMhvB,KACtC/Q,QAIM,GAAuBy/B,GAAI,SAAQp0B,EAAQC,GAC3CmG,EAAaiuB,aAAG,SAAStgC,GACvBqS,EAAYyuB,YAAOH,EAAQ3gC,GAAK2X,KAAQ1L,EAC9CC,IACImG,EAAckuB,cAAG,SAAWniC,GAC1BiU,EAAYwuB,YAAQD,EAAQxiC,GAAKuZ,KAAQ1L,EAC/CC,OAKNm0B,EAAA7gC,UAASuhC,UAAT,cAAA1uB,GAICV,IAHO,WAAYwkB,IAAA,EAAC,SAAQlqB,EAAQC,GAC7BmG,EAAKsF,KAAQ1L,EACnBC,MAGMm0B,EAAA7gC,UAAgBwhC,iBAAxB,SACqC5gC,GAEnC,IACE,GAAYQ,GAAQR,GACjB,OAAOQ,aAA+By/B,GAEzCz/B,EAC2By/B,EAAQp0B,QACnCrL,GACM,MAAGrC,GACH,MAAmB8hC,GAAOn0B,OAClC3N,KAGM8hC,EAAA7gC,UAAWshC,YAAnB,SAC4CH,EAClC3gC,GAEL,MAAQ2gC,GACHhvB,KAAsBqvB,iBAAC,WAAM,MAAML,GAAO3gC,KAIvBqgC,EAAQp0B,QACnCjM,IAGMqgC,EAAA7gC,UAAWqhC,YAAnB,SACyCD,EAC7BxiC,GAEP,MAASwiC,GACJjvB,KAAsBqvB,iBAAC,WAAM,MAAOJ,GAAOxiC,KAExBiiC,EAAOn0B,OAClC9N,IAKKiiC,EAAOp0B,QAAd,SAA4BrL,GACpB,UAAuBy/B,GAAI,SAAQp0B,EAAQC,GACxCD,EACTrL,MAGKy/B,EAAMn0B,OAAb,SAA2B9N,GACnB,UAAuBiiC,GAAI,SAAQp0B,EAAQC,GACzCA,EACR9N,MAGKiiC,EAAOY,QAAd,SACqCC,GAE7B,MAAAA,GAAWjM,OAAC,SAAQkM,EAAaC,EAAKC,GACpC,MAAAF,GAAaxpB,KAAC,WACZ,MACRypB,MACmBf,EACvBp0B,YAEOo0B,EAAG1iC,IAAV,SAA+CujC,GAC7C,GAAan+B,MACJwmB,GAAQ,EAEJ+X,EAAqBjB,EAAQp0B,QAAiB,KACrD,OAAAi1B,GACGjM,OAAC,SAAQkM,EAAaC,GACrB,MAAAD,GAAaxpB,KAAC,SAAM/W,GAKlB,MAJK2oB,IACFxmB,EAAK0H,KACd7J,GACK2oB,GAAS,EAEhB6X,KACSE,GACN3pB,KAAC,SAAM/W,GAEJ,MADCmC,GAAK0H,KAAS7J,GAEvBmC,KAELs9B,KCpKDkB,GAAA,mBAAAC,KACW7vB,KAAO8vB,SAAQ,EAKhB9vB,KAAO+vB,WAMP/vB,KAAgBgwB,iBAyD1B95B,KAAA,MAvDE25B,GAAAhiC,UAAgBoiC,iBAAhB,SAA6CC,GACvClwB,KAAQ+vB,QAAKj3B,KAAgBo3B,GACpBA,EAAoBC,oBACnCnwB,OAEA6vB,EAAAhiC,UAAmBuiC,oBAAnB,SAAgDF,GAC1ClwB,KAAQ+vB,QAAOhE,OAAK/rB,KAAQ+vB,QAAQp+B,QAAeu+B,GAAK,GAC/CA,EAAoBC,oBACnC,OAEAN,EAAAhiC,UAAsBwiC,uBAAtB,SAAuCpiC,GACjC+R,KAAiBgwB,iBAAOhwB,KAAiBgwB,iBAAIhxB,IACnD/Q,IAEA4hC,EAAAhiC,UAAcyiC,eAAd,SACoCv1B,GADpC,GAAA2F,GAsBCV,KAnBeuwB,KACCC,EAAoBt6B,IAiB7B,OAfF8J,MAAiBgwB,iBAAQnhC,QAAC,SAAGZ,GAC/B,GAAoBwiC,GAAO/vB,EAAyBgwB,yBAAI31B,EAAO9M,EACvDsiC,GAAKz3B,KAAA23B,EACQzqB,KAAC,SAAO2qB,GAKnB,MAHOA,KACAH,EAAcA,EAAIxxB,IAC/B/Q,IACyBoM,GAC3BC,eAKA0F,KAAiBgwB,iBAAoB95B,KACnCmE,GAA2Bi1B,QAAUiB,GAAKvqB,KAAC,WAAM,MAAWwqB,MAGpEX,EAAAhiC,UAAwB6iC,yBAAxB,SACoC31B,EAClB9M,GAEhB,GAAa0hC,GAAqBt1B,GAAQC,SAAQ,EAC5C,OAAA0F,MAAa+vB,QACb/jC,IAAC,SAAM4kC,GAAI,kBAAM,MAAMA,GAAYC,YAAI91B,EAAM9M,MAC1Cq1B,OAA8B,SAAQkM,EAAaC,GAClD,MAAAD,GAAaxpB,KAAC,SAAM/W,GACrB,MAAQA,GACgBoL,GAAQC,SACnC,GAEAm1B,OAGRE,IACDE,KC9EDiB,GAAA,WACE,QAAAC,GACuBryB,EACasyB,EACEC,GAF3BjxB,KAAKtB,MAAOA,EACZsB,KAASgxB,UAAgBA,EACzBhxB,KAAWixB,YACnBA,EAqBL,MAnBSF,GAAYG,aAAnB,SAA8CC,GAIxC,IAAoB,GAHXH,GAAoB96B,KAClB+6B,EAAoB/6B,KAEX3K,EAAuB,EAAvBsjB,EAAYsiB,EAAW7yB,WAAvB/S,EAAAsjB,EAAuBpjB,OAAAF,IAAA,CAA1C,GAAe8vB,GAAAxM,EAAAtjB,EACX,QAAU8vB,EAAQtrB,MACvB,IAAesH,IAAMC,MACV05B,EAAYA,EAAIhyB,IAAUqc,EAAI9c,IAAMtQ,IACvC,MACR,KAAeoJ,IAAQI,QACVw5B,EAAcA,EAAIjyB,IAAUqc,EAAI9c,IAAMtQ,MAOjD,MAAC,IAAoB8iC,GAAaI,EAAMzyB,MAAWsyB,EAC3DC,IACDF,KCPDK,GAAA,mBAAAC,KAEUrxB,KAASsxB,UAAG,GAAaha,IAAaia,GAAexqB,cAGrD/G,KAAYwxB,aAAG,GAAala,IAAaia,GAAoBE,mBAG7DzxB,KAAgB0xB,iBAiF1B,WA9EEL,GAAAxjC,UAAOiB,QAAP,WACQ,MAAKkR,MAAUsxB,UACvBxiC,WAGAuiC,EAAAxjC,UAAY8jC,aAAZ,SAA6B1jC,EAAwB29B,GACnD,GAASgG,GAAG,GAAgBL,IAAItjC,EAAM29B,EAClC5rB,MAAUsxB,UAAOtxB,KAAUsxB,UAAItyB,IAAM4yB,GACrC5xB,KAAawxB,aAAOxxB,KAAawxB,aAAIxyB,IAC3C4yB,IAGAP,EAAAxjC,UAAagkC,cAAb,SAAkCpa,EAAwBmU,GAA1D,GAAAlrB,GAECV,IADKyX,GAAQ5oB,QAAC,SAAGZ,GAAI,MAAIyS,GAAaixB,aAAI1jC,EAAK29B,MAOhDyF,EAAAxjC,UAAeikC,gBAAf,SAAgC7jC,EAAwB29B,GAClD5rB,KAAU+xB,UAAC,GAAgBR,IAAItjC,EACrC29B,KAEAyF,EAAAxjC,UAAgBmkC,iBAAhB,SAAqCva,EAAwBmU,GAA7D,GAAAlrB,GAECV,IADKyX,GAAQ5oB,QAAC,SAAGZ,GAAI,MAAIyS,GAAgBoxB,gBAAI7jC,EAAK29B,MAOnDyF,EAAAxjC,UAAqBokC,sBAArB,SAA4CrG,GAA5C,GAAAlrB,GAOCV,KANekyB,EAAcjsB,GAAOO,MACrB2rB,EAAG,GAAgBZ,IAASW,EAAMtG,GACpCwG,EAAG,GAAgBb,IAASW,EAAItG,EAAM,EAC9C5rB,MAAawxB,aAAezZ,gBAAUoa,EAASC,GAAE,SAAGR,GAClDlxB,EAAUqxB,UAChBH,MAGFP,EAAAxjC,UAAmBwkC,oBAAnB,cAAA3xB,GAECV,IADKA,MAAUsxB,UAAQziC,QAAC,SAAG+iC,GAAI,MAAIlxB,GAAUqxB,UAAKH,MAG3CP,EAAAxjC,UAASkkC,UAAjB,SAAmCH,GAC7B5xB,KAAUsxB,UAAOtxB,KAAUsxB,UAAOvyB,OAAM6yB,GACxC5xB,KAAawxB,aAAOxxB,KAAawxB,aAAOzyB,OAAM6yB,GACf,OAA3B5xB,KAAiB0xB,kBACnB1xB,KAAiB0xB,iBAAuBrB,uBAAIuB,EAClD3jC,MAGFojC,EAAAxjC,UAAeykC,gBAAf,SAAsC1G,GACpC,GAAcsG,GAAcjsB,GAAOO,MACrB2rB,EAAG,GAAgBZ,IAASW,EAAMtG,GACpCwG,EAAG,GAAgBb,IAASW,EAAItG,EAAM,GAC1CnU,EAAoBvhB,IAItB,OAHF8J,MAAawxB,aAAezZ,gBAAUoa,EAASC,GAAE,SAAGR,GAClDna,EAAOA,EAAIzY,IAAI4yB,EACrB3jC,OAEFwpB,GAEA4Z,EAAAxjC,UAAmBsiC,oBAAnB,SAA6DuB,GACvD1xB,KAAiB0xB,iBACvBA,GAEAL,EAAAxjC,UAAWgjC,YAAX,SACoC91B,EAClB9M,GAEhB,GAAS2jC,GAAG,GAAgBL,IAAItjC,EAAK,GACvBskC,EAAOvyB,KAAUsxB,UAAkBnZ,kBAAMyZ,EACjD,OAAmBv3B,IAAQC,QACd,OAATi4B,GAAgBtkC,EAAOiE,OAASqgC,EAE5CtkC,OACDojC,KAEDE,GAAA,WACE,QAAAiB,GACyBvkC,EACmBwkC,GADnCzyB,KAAG/R,IAAaA,EAChB+R,KAAeyyB,gBACrBA,EAiBL,MAdSD,GAAYzrB,aAAnB,SAAsC/U,EAAqBC,GAClD,MACMgU,IAAWhC,WAAKjS,EAAI/D,IAAOgE,EAAKhE,MACxB8D,EAAKC,EAAgBygC,gBAAOxgC,EAEnDwgC,kBAGOD,EAAiBf,kBAAxB,SAA2Cz/B,EAAqBC,GACvD,MACcF,GAAKC,EAAgBygC,gBAAOxgC,EAAiBwgC,kBACrDxsB,GAAWhC,WAAKjS,EAAI/D,IAAOgE,EAE1ChE,MACDukC,KP1IkBE,GAAK,GAExB,SAAiBrI,GACfA,IAAA,cAAc,aACdA,IAAA,cACF,cAHiBA,YAYjB,IQsDCsI,IRtDDC,GAAA,WAGE,QAAAA,GAAuCC,EAAyBC,OAAvB,KAAAA,MAAuB,GAA5C9yB,KAAW6yB,YAAQA,CAErC,IAA2BE,GAAaD,GAAkBJ,IAAkBA,GACxDM,EAAYF,EAAyBC,CASnD/yB,MAAWizB,WARCD,GAAgBH,EAQOE,EAAO/yB,KAChD6yB,aAS0BE,EAAO/yB,KAAgB6yB,cAAE,GACnDH,IAeJ,MAZEE,GAAA/kC,UAAImY,KAAJ,WAEQ,MADFhG,MAAWizB,YAAK,GAAkBP,GAC3B1yB,KACbizB,YAEOL,EAAaM,cAApB,SAA4CJ,GACpC,WADa,KAAAA,MAAuB,GACnC,GAAqBF,GAAavI,GAAW8I,WACtDL,IAEOF,EAAaQ,cAApB,WACQ,MAAC,IAAqBR,GAAavI,GAC3CgJ,aACDT,KnChCDU,GAAA,WACE,QAAAA,GAAmCrlC,GAAhB+R,KAAG/R,IAAgBA,EACxC,MAACqlC,MACDC,GAAA,WACE,QAAAA,GAAmCtlC,GAAhB+R,KAAG/R,IAAgBA,EACxC,MAACslC,MA4BDC,GAAA,WAeE,QAAAC,GACsB/0B,EAEmBg1B,GAF/B1zB,KAAKtB,MAAOA,EAEZsB,KAAe0zB,gBAAgBA,EAjBjC1zB,KAAS2zB,UAA0B,KAOnC3zB,KAAO6F,SAAS,EAGhB7F,KAAc4zB,eAAoB19B,KAElC8J,KAAW6zB,YAAoB39B,KAOjC8J,KAAY8zB,YAAG,GAAejJ,IAAMnsB,EAAcC,cAAK5H,KAC7D2H,IAkQF,MAtPE+0B,GAAA5lC,UAAiBkmC,kBAAjB,SAC8Bz1B,EACS01B,GAFvC,GAAAtzB,GA+GCV,KA3GgBi0B,EAAkBD,EACdA,EAAUC,UACzB,GAAwB3J,IACR4J,EAAkBF,EACnBA,EAAYF,YACvB9zB,KAAa8zB,YACHK,EAAkBH,EACjBA,EAAYH,YACvB7zB,KAAa6zB,YACHO,EAAkBF,EACrBG,GAAS,EAWJC,EACdt0B,KAAMtB,MAAW8R,YAAkB0jB,EAAK3vB,OAASvE,KAAMtB,MAAM2F,MAC/C6vB,EAAOrc,OAChB,IAiER,IA/DOvZ,EAAiBgK,iBACzB,SAAiBra,EAA4BsmC,GAC3C,GAAYC,GAAiBN,EAAIr8B,IAAM5J,GAC7B4rB,EAAc0a,YAAoB9tB,IAAc8tB,EAAQ,IAwB/D,IAvBQ1a,IACH5sB,EACDgB,EAAOiE,OAAO2nB,EAAK5rB,KACwB,+CACzCA,EACG,OACA4rB,EACR5rB,KACI4rB,EAAOnZ,EAAMhC,MAAQyR,QAAQ0J,GAASA,EAC9C,MACWA,GACKua,EAAiBA,EAAIp1B,IAAS6a,GAE5Bsa,EADNta,EAAmBhT,kBACIstB,EAAIn1B,IACrC/Q,GACiCkmC,EAAOp1B,OACxC9Q,KAEcmmC,EAAiBA,EAAOr1B,OAAM9Q,GAC9BkmC,EAAiBA,EAAOp1B,OACxC9Q,IAGUumC,GAAW3a,EAAE,CACrB,GAAe4a,GAASD,EAAK5tB,KAAO1U,OAAO2nB,EAAOjT,KAEtC6tB,IACJD,EAAkB3tB,oBAAWgT,EACpChT,oBAEe4tB,EACHR,EAAMxJ,OAAO16B,KAAYsH,GAASG,SAAK+G,IAClDsb,IACWoa,EAAMxJ,OAAO16B,KAAYsH,GAASE,SAAKgH,IAClDsb,IAGgBya,GACV5zB,EAAMhC,MAAcC,cAAOkb,EAAiBya,GACjD,IAIYD,GACb,SAEcG,GAAW3a,EAClBoa,EAAMxJ,OAAO16B,KAAYsH,GAAMC,MAAKiH,IAC/Csb,IAAiB2a,IAAY3a,IAClBoa,EAAMxJ,OAAO16B,KAAYsH,GAAQI,QAAK8G,IAAYi2B,IACxCF,IAIND,GACb,MAIEr0B,KAAMtB,MAAY8R,WAExB,KAAqB4jB,EAAK7vB,KAAOvE,KAAMtB,MAAO2F,OAAG,CAC/C,GAAYmwB,GAAiBJ,EAAQvc,MACvBuc,GAAiBA,EAAOr1B,OAAQy1B,EAAMvmC,KAC3CgmC,EAAMxJ,OAAO16B,KAAYsH,GAAQI,QAAK8G,IACjDi2B,IAMI,MAJAvnC,IACQonC,IAAoBL,EAEhC,mEAEWF,YAAgBM,EAClBH,YACEI,cACAR,YAEfM,IAUAV,EAAA5lC,UAAY6mC,aAAZ,SACiCp2B,EACJid,GAF7B,GAAA7a,GAwCCV,IApCO/S,IAAYqR,EAAY+1B,YAA6C,0CAC3E,IAAal2B,GAAO6B,KAAa8zB,WAC7B9zB,MAAY8zB,YAAax1B,EAAaw1B,YACtC9zB,KAAY6zB,YAAav1B,EAAau1B,WAE1C,IAAajJ,GAAatsB,EAAU21B,UAActJ,YAC3CC,GAAK+J,KAAC,SAAGz9B,EAAIC,GACX,MACYF,IAAGC,EAAKnH,KAAIoH,EAAMpH,OAC/B2Q,EAAMhC,MAAcC,cAAGzH,EAAIqH,IAAIpH,EAEvCoH,MAEA,IAAkBq2B,GAAO50B,KAAkB60B,kBAAetZ,GAC9CuZ,EAAiC,IAA1B90B,KAAe4zB,eAAKrvB,MAAcvE,KAAS6F,QAC5CkvB,EAASD,EAAY1K,GAAO4K,OAAY5K,GAAO6K,MAC3CnH,EAAeiH,IAAS/0B,KAAW2zB,SAGtD,OAFC3zB,MAAU2zB,UAAgBoB,EAEN,IAAbnK,EAAOn/B,QAA4BqiC,GAKlC5vB,UACDQ,MAAMsB,KAAMtB,MACb2a,KAAY/a,EAAYw1B,YACrB31B,UACGG,WAASssB,EACVnsB,UAAcs2B,IAAc3K,GAAM6K,MAC3BnH,mBACAE,kBAAa1vB,EAAYu1B,YAC1C/kC,WACW8lC,aAEhBA,IAduBA,aACvBA,IAmBMnB,EAAA5lC,UAAeqnC,gBAAvB,SAAwCjnC,GAEnC,OAAK+R,KAAgB0zB,gBAAIhc,IAAMzpB,MAIzB+R,KAAY8zB,YAAIpc,IAAMzpB,KAOvB+R,KAAY8zB,YAAIj8B,IAAM5J,GAAmB4Y,mBAW3C4sB,EAAA5lC,UAAiBgnC,kBAAzB,SAC6BtZ,GAD7B,GAAA7a,GAuDCV,IApDI,IAAcub,EAAE,CACjB,GAAmB4Z,GAAe5Z,EAASxC,OASpC,QARUoc,YAAyBnc,IACpChZ,KAAgB0zB,gBAAgByB,EACtCr5B,UAAwBq5B,YAA0B7b,MAC5CtZ,KAAgB0zB,gBAAgByB,EAAc1b,cAC5CzZ,KAER0zB,kBAEoBnY,EAAuBtC,qBACzC,IAAwB5B,IAAYsE,YAC9B3b,KAAQ6F,SAAQ,CACd,MACR,KAAwBwR,IAAe6B,eACjClZ,KAAQ6F,SAAS,CACf,MACR,KAAwBwR,IAAK+D,KACrB,KACR,SACMvuB,EAC+B,kCAAe0uB,EAGxDtC,sBAKA,GAAuBmc,GAAOp1B,KAAgB4zB,cAC1C5zB,MAAe4zB,eAAoB19B,KAC/B8J,KAAS6F,SACX7F,KAAY8zB,YAAQjlC,QAAC,SAAG0P,GAClBmC,EAAgBw0B,gBAAI32B,EAAMtQ,OAC5ByS,EAAekzB,eAAOlzB,EAAekzB,eAAI50B,IAAIT,EACnDtQ,OAKJ,IAAa28B,KAWP,OAVWwK,GAAQvmC,QAAC,SAAGZ,GAClByS,EAAekzB,eAAIlc,IAAMzpB,IACzB28B,EAAK9xB,KAAC,GAAwBy6B,IACvCtlC,MAEE+R,KAAe4zB,eAAQ/kC,QAAC,SAAGZ,GACPmnC,EAAI1d,IAAMzpB,IACvB28B,EAAK9xB,KAAC,GAAsBw6B,IACrCrlC,MAGJ28B,GACD6I,K4CjSD4B,GAAA,WACE,QAAAA,GAIqB32B,EAKMoV,EAMUxd,EAOlBg/B,GAlBVt1B,KAAKtB,MAAOA,EAKZsB,KAAQ8T,SAAUA,EAMlB9T,KAAW1J,YAAiBA,EAO5B0J,KAAIs1B,KACVA,EACL,MAACD,MAgBDE,GAAA,WAoBE,QAAAlC,GACgCmC,EACEC,EACPC,GAFjB11B,KAAUw1B,WAAYA,EACtBx1B,KAAWy1B,YAAaA,EACxBz1B,KAAW01B,YAAMA,EAtBnB11B,KAAW21B,YAA4B,KACvC31B,KAAY41B,aAA6B,KAEzC51B,KAAiB61B,kBAAA,GAAgBrK,IAAmB,SAACgB,GAC3D,MAACA,GAAc3c,gBAET7P,KAAkB81B,sBAClB91B,KAAiB+1B,kBAAG,GAAaxuB,IAC5BtB,GACXhC,YACMjE,KAAiBg2B,qBACjBh2B,KAAiBi2B,kBAAG,GAAmB7E,IACvCpxB,KAAck2B,eAAG,GAA4BtG,IAE7C5vB,KAAqBm2B,yBAGrBn2B,KAAiBo2B,kBAAoBxD,GAM1CQ,gBAudL,MApdEC,GAAAxlC,UAAS8+B,UAAT,SAAkCgJ,EAA4BC,GACtD3oC,EACgB,OAAT0oC,GAAkC,OAATC,EAEpC,0CACI3oC,EACqB,OAArB+S,KAAY21B,aAAuC,OAAtB31B,KAAa41B,aAE9C,wCACE51B,KAAY21B,YAAeA,EAC3B31B,KAAa41B,aAAgBA,EAC7B51B,KAAek2B,eAAiBjG,iBAAKjwB,KAC3Ci2B,oBAOA5C,EAAAxlC,UAAMk7B,OAAN,SAAmBrqB,GAAnB,GAAAgC,GA0CCV,IAnCO,OANFA,MAAiBq2B,iBAAa,YAC5BppC,GACC+S,KAAkB61B,kBAAIne,IAAOhZ,GACA,mCAClCA,GAEIsB,KAAgBw1B,WAAcc,cAAO53B,GAAK0uB,KAAC,SAAS5K,GAClD,MAAA9hB,GAAgB80B,WACPe,aAAO73B,GACf0uB,KAAC,SAAI/T,GACF,MAAA3Y,GAAgB80B,WACDgB,mBAAUhU,EAAU1O,UAClCsZ,KAAC,SAAUqJ,GACd,GAAUnB,GAAG,GAAQ9B,IAAM90B,EAAc+3B,GACrBC,EAAOpB,EAAkBvB,kBAAO1a,GACpCsd,EAAOrB,EAAaZ,aAAiBgC,EAC/CzpC,GACgC,IAA1B0pC,EAAa/B,aAAOnpC,OAE9B,+DACIwB,IACQ0pC,EAASz4B,SAErB,4DAEF,IAAU0I,GAAG,GAAayuB,IACnB32B,EACI8jB,EAAS1O,SACT0O,EAAYlsB,YAErBg/B,EACE50B,GAAkBm1B,kBAAI5oB,IAAMvO,EAAQkI,GACpClG,EAAmBo1B,mBAAUtT,EAAU1O,UAAQlN,EAC/ClG,EAAai1B,aAAYgB,EAAaz4B,WACtCwC,EAAY+0B,YAAO1M,OACzBvG,OAEC4K,KAAC,WACE,MAAU5K,GAClB1O,cAKNuf,EAAAxlC,UAAQw/B,SAAR,SAAqB3uB,GAArB,GAAAgC,GAYCV,IAXKA,MAAiBq2B,iBAAe,aAEpC,IAAeO,GAAO52B,KAAkB61B,kBAAIh+B,IAAS6G,EAG/C,OAFAzR,KAAY2pC,EAA0C,yCAAUl4B,GAEhEsB,KAAgBw1B,WAAaqB,aAAOn4B,GAAK0uB,KAAC,WAExC,MADF1sB,GAAY+0B,YAASpI,SAAUuJ,EAAW9iB,UACxCpT,EAA2Bo2B,sBAAWF,GAAKxJ,KAAC,WAC1C,MAAK1sB,GAAW80B,WACxBlF,sBAcJ+C,EAAAxlC,UAAKkpC,MAAL,SAAuBC,EAA8BC,GAArD,GAAAv2B,GAWCV,IATO,OADFA,MAAiBq2B,iBAAY,WAC3Br2B,KAAgBw1B,WACT0B,WAAOF,GACb5J,KAAC,SAAMn+B,GAEJ,MADFyR,GAAoBy2B,oBAAOloC,EAAQmoC,QAAgBH,GAC5Cv2B,EAAgC22B,gCAAOpoC,EACpD27B,WACKwC,KAAC,WACE,MAAK1sB,GAAY+0B,YACzB6B,uBAIIjE,EAAAxlC,UAAuB0pC,wBAA/B,SAA4C9qC,GACpC,MACRA,IAmBA4mC,EAAAxlC,UAAc2pC,eAAd,SAC0DC,EAC7CC,GAFb,GAAAh3B,GAuCCV,SArCC,KAAA03B,MAAW,GAELzqC,EAAQyqC,GAAK,EAAqD,kDACxE,IAAiBC,GAAO33B,KAAYy1B,YAAqBmC,mBAoBnD,OAnBwB,YAC5B,IACE,GAAiBC,GAAiBJ,EAAcE,EAC7C,QACgBvkC,EAAaykC,IAClBA,EAAM9I,OACN8I,EACbzK,KAKKyK,EAAkB9I,MAAC,SAACniC,GAClB,MAAQ43B,IAAA,EAAOjqB,OAAQmG,EAAwB62B,wBACvD3qC,MANgB43B,GAAA,EAAOjqB,OACdvN,MAET,+CAIM,MAAGJ,GACH,MAAQ43B,IAAA,EAAOjqB,OAAQmG,EAAwB62B,wBACvD3qC,QAEiCwgC,KAAC,SAAMn+B,GAClC,MAAA0oC,GACKG,SACJ1K,KAAC,WACE,MACRn+B,KACM8/B,MAAC,SAAKtiC,GACP,MAAe,KAAPirC,EACKlT,GAAA,EAAOjqB,OACvB9N,GAEWiU,EAAe82B,eAAeC,EAASC,EACpD,QAINrE,EAAAxlC,UAAgBkqC,iBAAhB,SAAyCC,GAAzC,GAAAt3B,GAgDCV,IAHO,OA5CFA,MAAiBq2B,iBAAuB,sBAGpC7nC,EACKwpC,EAAcrf,cACzB,SAAS7E,EAAcyH,GACrB,GAAc0c,GAAOv3B,EAAkBs1B,kBAAWliB,EAExCmkB,IACI1c,EAAoBtC,sBACX5B,GAAYsE,cACrBqc,EAAgBpf,gBAAI/gB,IACjCogC,IAyBYD,EAAkBnf,kBAC3B,GAAcxR,IAAS4wB,EAAaD,EAExChkB,oBAIEhU,KAAgBw1B,WAAiBuC,iBAAaC,GAAK5K,KAAC,SAAOxC,GACzD,MAAKlqB,GAAgC22B,gCAAQzM,EACrDoN,MAGF3E,EAAAxlC,UAAYqqC,aAAZ,SAA+BpkB,EAAqB2R,GAApD,GAAA/kB,GAkCCV,IAjCKA,MAAiBq2B,iBAAoB,kBACzC,IAAc4B,GAAOj4B,KAAkBg2B,kBAAWliB,EAC/C,IAAUmkB,EAAE,CAGTj4B,KAAkB+1B,kBAAO/1B,KAAkB+1B,kBAAOjuB,OAAWmwB,SACtDj4B,MAAkBg2B,kBAAWliB,EASxC,IAAUqkB,GAAG,GAAa5wB,IACbtB,GACXhC,WACIk0B,GAASA,EAAOxwB,OACZswB,EACR,GAAc5wB,IAAS4wB,EAAiB/kB,GACxCK,iBACF,IAAW6kB,GAAG,GAAe3f,IAAgBvF,GAAIM,OAAc2kB,EACzD,OAAKn4B,MAAiB+3B,iBAC9BK,GACE,GAAeC,GAAOr4B,KAAmB81B,mBAAWhiB,EAE9C,OADA7mB,KAAYorC,EAAsB,qBAAavkB,GAC/C9T,KAAgBw1B,WAAaqB,aAAUwB,EAAO35B,OAAK0uB,KAAC,WAClD,MAAA1sB,GAA2Bo2B,sBAAWuB,GAAKjL,KAAC,WAC5C1sB,EAAck1B,aAAUyC,EAAM35B,MACpC+mB,QAKN4N,EAAAxlC,UAAoByqC,qBAApB,SAC0CC,GAD1C,GAAA73B,GAmBCV,IALO,OAXFA,MAAiBq2B,iBAA2B,0BAM5Cr2B,KAAoBw4B,oBACHD,EAAMvB,MAAQI,QAEjC,MAEIp3B,KAAgBw1B,WACHiD,iBAAqBF,GACjCnL,KAAC,SAAOxC,GACL,MAAKlqB,GAAgC22B,gCAC7CzM,MAGJyI,EAAAxlC,UAAiB6qC,kBAAjB,SAAkCtB,EAAuB3qC,GAAzD,GAAAiU,GAYCV,IAHO,OARFA,MAAiBq2B,iBAAwB,uBAMzCr2B,KAAoBw4B,oBAAQpB,EAAS3qC,GAEnCuT,KAAgBw1B,WAAYmD,YAASvB,GAAKhK,KAAC,SAAOxC,GAChD,MAAKlqB,GAAgC22B,gCAC7CzM,MAGMyI,EAAAxlC,UAAmBspC,oBAA3B,SACkBC,EACQlS,GAExB,GAAgB0T,GAAO54B,KAAsBm2B,sBAAKn2B,KAAY01B,YAAUmD,QACtDD,KACJA,EAAG,GAAarxB,IAG9BxV,IACY6mC,EAAeA,EAAOjxB,OAAQyvB,EAAYlS,GAClDllB,KAAsBm2B,sBAAKn2B,KAAY01B,YAASmD,SACtDD,GAMQvF,EAAAxlC,UAAmB2qC,oBAA3B,SAA4CpB,EAAqB3qC,GAC/D,GAAgBmsC,GAAO54B,KAAsBm2B,sBAAKn2B,KAAY01B,YAAUmD,QAIrE,IAAcD,EAAE,CACjB,GAAc1T,GAAe0T,EAAI/gC,IAAUu/B,EAC9BlS,KACLj4B,EACGmqC,IAAiBwB,EAASxwB,SAEjC,8CACQ3b,EACAy4B,EAAO3qB,OACjB9N,GACUy4B,EACV5qB,UACYs+B,EAAeA,EAAO9wB,OACpCsvB,IACIp3B,KAAsBm2B,sBAAKn2B,KAAY01B,YAASmD,SACtDD,IAGMvF,EAAAxlC,UAAqBipC,sBAA7B,SAAkDF,GAK1C,MAJF52B,MAAkB61B,kBAAO92B,OAAU63B,EAAQl4B,aACpCsB,MAAmB81B,mBAAUc,EAAW9iB,UAE/C9T,KAAkBi2B,kBAAsBhE,sBAAU2E,EAAW9iB,UACtD9T,KACb84B,oBAEQzF,EAAAxlC,UAAmBkrC,oBAA3B,SACoBjlB,EACiB8gB,GAE/B,IAAsB,GAAArpC,GAAY,EAAZytC,EAAYpE,EAAZrpC,EAAAytC,EAAYvtC,OAAAF,IAAA,CAAjC,GAAiB0tC,GAAAD,EAAAztC,EACL0tC,aAA+B3F,KACxCtzB,KAAkBi2B,kBAAatE,aAAYsH,EAAIhrC,IAAY6lB,GAC3D9T,KAAiBk5B,iBACvBD,IAAsBA,YAAiC1F,KAClDpoC,EApakB,aAoa6B,gCAAc8tC,EAAMhrC,KAClE+R,KAAkBi2B,kBAAgBnE,gBAAYmH,EAAIhrC,IACxD6lB,IACMjnB,EAAyB,yBAAOH,KAAUC,UAChDssC,IAEI,MAAKj5B,MACb84B,oBAEQzF,EAAAxlC,UAAgBqrC,iBAAxB,SAAwDD,GACtD,GAAShrC,GAAcgrC,EAAKhrC,GACzB,KAAM+R,KAAkB+1B,kBAAIl+B,IAAM5J,GAAE,CAClC9C,EAhboB,aAgbqB,0BAAQ8C,EACpD,IAAmBkrC,GAAOn5B,KAAkBo2B,kBAAQpwB,OACzCtH,EAAQkP,GAAOS,OAAIpgB,EAAO0I,KACjCqJ,MAAkBg2B,kBAAemD,GAAOlrC,EACxC+R,KAAYy1B,YAAO1M,OACrB,GAAanV,IAAMlV,EAAey6B,EAAcpuB,GAChD4X,SACE3iB,KAAkB+1B,kBAAO/1B,KAAkB+1B,kBAAOpuB,OACjD1Z,EAGPkrC,KAGM9F,EAAAxlC,UAAgBirC,iBAAxB,cAAAp4B,GAkBCV,IAfO,OAAAA,MAAoBk2B,eACT5F,eAAM,MAChBtqB,KAAC,SAAIyR,GACJA,EAAQ5oB,QAAC,SAAGZ,GACd,GAAmBkrC,GAAOz4B,EAAkBq1B,kBAAIl+B,IAAM5J,EAC3B,QAAVkrC,IAIbz4B,EAAY+0B,YAASpI,SAAgB8L,GACrCz4B,EAAkBq1B,kBAAOr1B,EAAkBq1B,kBAAOjuB,OAAM7Z,SACjDyS,GAAkBs1B,kBAC/BmD,QAGN/J,aAGAiE,EAAAxlC,UAAgBurC,iBAAhB,WACQ,MAAKp5B,MACb+1B,mBAEQ1C,EAAAxlC,UAA+BwpC,gCAAvC,SAC2BzM,EACAoN,GAF3B,GAAAt3B,GAsDCV,KAlDeq5B,KACYC,KACJC,IAwChB,OAtCFv5B,MAAkB61B,kBAAQhnC,QAAC,SAAE6C,EAAWklC,GAC1B2C,EAAKzgC,KAAA0rB,GAAA,EACFlqB,UACV8yB,KAAC,WACJ,GAAoBsJ,GAAYE,EAAKtB,KAAkBvB,kBAAUnJ,EAC9D,OAAgB8L,GAAarC,YAM1B3zB,EAAgB80B,WAAae,aAAUK,EAAOl4B,OAAK0uB,KAAC,SAAI/T,GACtD,MAAUud,GAAKtB,KAAkBvB,kBAAK1a,EAC9Cqd,KANAA,IAQGtJ,KAAC,SAAoCsJ,GACxC,GAAkBnb,GACLyc,GAAeA,EAAcrf,cAAUie,EAAW9iB,UAC/C6iB,EAAYC,EAAKtB,KAAaZ,aAC9BgC,EAEdnb,EACI,OAAA7a,GAAyBq4B,oBACpBnC,EAAS9iB,SACR6iB,EACX/B,cAAKxH,KAAC,WACF,GAAWuJ,EAAUz4B,SAAE,CAChBm7B,EAAKvgC,KAAW69B,EAAWz4B,SACnC,IAAgBI,GAAmBwyB,GAAaI,aACpCyF,EACVz4B,SACkBo7B,GAAKxgC,KAC3BwF,WAMJkmB,GAAA,EAAY+K,IAAkBgK,GAC7BnM,KAAC,WAEE,MADF1sB,GAAai1B,YAAW0D,GACjB34B,EAAW80B,WAAuBgE,uBAC/CF,KACKlM,KAAC,WACE,MAAK1sB,GAAW80B,WACxBlF,oBAGI+C,EAAAxlC,UAAgBwoC,iBAAxB,SAAuCoD,GAC/BxsC,EACqB,OAArB+S,KAAY21B,aAAuC,OAAtB31B,KAAa41B,aAC7B,kBAAS6D,EAE9B,iCAEApG,EAAAxlC,UAAgB6rC,iBAAhB,SAA2BC,GAA3B,GAAAj5B,GAUCV,IARO,OADFA,MAAY01B,YAAQiE,EAClB35B,KAAgBw1B,WACHkE,iBAAMC,GAClBvM,KAAC,SAAOxC,GACL,MAAKlqB,GAAgC22B,gCAC7CzM,KACKwC,KAAC,WACE,MAAK1sB,GAAY+0B,YAAiBiE,iBAC1CC,MAELtG,KCzjB2BuG,IAAM,EAKlCC,GAAA,WACE,QAAAC,GACyB1C,EACS9qB,EACJytB,GAFrB/5B,KAAOo3B,QAASA,EAChBp3B,KAAcsM,eAAWA,EACzBtM,KAAS+5B,UACfA,EAsGL,MA3FED,GAAAjsC,UAAqB+nB,sBAArB,SACqBla,EACWuZ,EACE+kB,GAEnB/kB,GACLhoB,EACIgoB,EAAIhnB,IAAOiE,OAAQwJ,GAC3B,8BAAoCA,EAAA,uCAC1BuZ,EAEdhnB,IAEA,IAAqBgsC,GAAcD,EAAiBC,eAC9ChtC,GACWgtC,EAAOxuC,SAASuU,KAAU+5B,UAAOtuC,OAChD,6CACOuU,KAAU+5B,UAAOtuC,OAAA,yCACNwuC,EAAOxuC,OACzB,KAEE,KAAC,GAAK2G,GAAI,EAAGA,EAAO4N,KAAU+5B,UAAOtuC,OAAK2G,IAAG,CAC/C,GAAciuB,GAAOrgB,KAAU+5B,UAAI3nC,EAChC,IAASiuB,EAAIpyB,IAAOiE,OAASwJ,GAAE,CAChC,GAAoBma,GAAkBokB,EAAI7nC,EAClC6iB,GAAWoL,EAAsBzK,sBAASX,EACpDY,IAEI,MACRZ,IASA6kB,EAAAjsC,UAAgBioB,iBAAhB,SACqBpa,EACWuZ,GAEjBA,GACLhoB,EACIgoB,EAAIhnB,IAAOiE,OAAQwJ,GAC3B,6BAAmCA,EAAA,uCACzBuZ,EAEdhnB,IAEI,KAAC,GAAKmE,GAAI,EAAGA,EAAO4N,KAAU+5B,UAAOtuC,OAAK2G,IAAG,CAC/C,GAAciuB,GAAOrgB,KAAU+5B,UAAI3nC,EACvBiuB,GAAIpyB,IAAOiE,OAASwJ,KACtBuZ,EAAWoL,EAAiBvK,iBAASb,EAAMjV,KACrDsM,iBAEI,MACR2I,IAEA6kB,EAAAjsC,UAAI4pB,KAAJ,WAGM,IAAmB,GAFbyiB,GAAoBhkC,KAEP3K,EAAc,EAAdsjB,EAAI7O,KAAU+5B,UAAdxuC,EAAAsjB,EAAcpjB,OAAAF,IAAA,CAAhC,GAAc80B,GAAAxR,EAAAtjB,EACX2uC,GAASA,EAAIl7B,IAASqhB,EAAMpyB,KAE9B,MACRisC,IAEAJ,EAAAjsC,UAAMqE,OAAN,SAA2BkQ,GAClB,MACDpC,MAAQo3B,UAAUh1B,EAAQg1B,SAC1BjlC,EAAiB6N,KAAU+5B,UAAO33B,EAE1C23B,YAUAD,EAAAjsC,UAAWssC,YAAX,WACQ,MACR,KADan6B,KAAU+5B,UAAOtuC,QAI9BquC,EAAAjsC,UAAWusC,YAAX,WACQ,MAAC,IAAiBN,GAAK95B,KAAQo3B,QAAMp3B,KAAesM,oBAE7DwtB,KAGDO,GAAA,WACE,QAAAC,GAC+BtD,EACUuD,EACGN,EACLO,EAKGC,GAR/Bz6B,KAAKg3B,MAAeA,EACpBh3B,KAAau6B,cAAiBA,EAC9Bv6B,KAAei6B,gBAAkBA,EACjCj6B,KAAWw6B,YAAiBA,EAK5Bx6B,KAAWy6B,YACnBA,EA0CL,MAnCSH,GAAI5Y,KAAX,SACsBsV,EACUuD,EACLnpC,EACGopC,GAEtBvtC,EACC+pC,EAAU+C,UAAOtuC,SAAY2F,EAAO3F,OACxB,kBACVurC,EAAU+C,UAAOtuC,OACS,gCACxB2F,EACT3F,OAIE,KAAC,GAFSivC,GAAwB1kC,KACvB+jC,EAAQ/C,EAAW+C,UACxB3nC,EAAI,EAAGA,EAAY2nC,EAAOtuC,OAAK2G,IAAG,CAC1C,GAAWuU,GAAUvV,EAAGgB,GAASuU,OACZ,QAAVA,IAGFA,EACT4zB,GAEUG,EAAaA,EAAO/yB,OAAUoyB,EAAG3nC,GAAInE,IACjD0Y,GAEM,MAAC,IAAuB2zB,GACvBtD,EACQuD,EACNnpC,EACIopC,EAGfE,IACDJ,K5CtIeriC,GAAY,IACFG,GAAY,IACtBF,GAAY,IACTC,GAAY,ICM/BwiC,GAAA,WACE,QAAAA,GAAkCvoB,EAAsBC,GAArCrS,KAAOoS,QAAQA,EAASpS,KAAKqS,MAAWA,EAC7D,MAACsoB,MAaD1gC,GAAA,WAIE,QAAAA,GAAkC2gC,EAAiCC,GAAhD76B,KAAO46B,QAAQA,EAAS56B,KAAgB66B,iBAAWA,EACxE,MAHS5gC,GAAKb,MAAW,QAGxBa,KAWDd,GAAA,WAOE,QAAAA,GAIuB2hC,EAOiBC,EAURC,GAjBvBh7B,KAAM86B,OAAQA,EAOd96B,KAAuB+6B,wBAAQA,EAU/B/6B,KAAeg7B,gBACrBA,EACL,MA5BS7hC,GAAKC,MAAoB,iBAGzBD,EAAOE,QAAY,SAyB3BF,KAYDG,GAAA,WAOE,QAAAA,GAIuBwhC,EAKE1D,EAKQ6D,EAMFlB,GAhBtB/5B,KAAM86B,OAAQA,EAKd96B,KAAOo3B,QAASA,EAKhBp3B,KAAgBi7B,iBAAQA,EAMxBj7B,KAAS+5B,UACfA,EACL,MA3BSzgC,GAAKF,MAAe,YAGpBE,EAAOD,SAAY,SAAa,WAwBxCC,KAgBDS,GAAA,WA0CE,QAAAmhC,MACF,MApCSA,GAAaC,cAApB,SAAmCL,GAC3B,OACRA,IAMOI,EAAaE,cAApB,SACgBN,EACInkC,GAEZ,OAAQmkC,EAAQpjC,GACxBf,KAMOukC,EAAGjtC,IAAV,SACgB6sC,EACInkC,EACFygC,GAEV,OAAQ0D,EAAQpjC,GAAMf,GAC9BygC,IA/BO8D,EAAK9hC,MAAuB,oBAuC5B8hC,EAAWG,YAAG,GAAyBH,GAG/CA,KAYDI,GAAA,WACE,QAAAA,GAAiC3kC,EAA8B0oB,GAA5Crf,KAAIrJ,KAAUA,EAASqJ,KAAQqf,SAAgBA,EACpE,MAACic,MAUDthC,GAAA,WAGE,QAAAA,GAKwCuhC,EAKFxc,GAL7B/e,KAAUu7B,WAAqBA,EAK/Bv7B,KAAQ+e,SACdA,EACL,MAdS/kB,GAAKZ,MAAqB,kBAclCY,KAuBDJ,GAAA,WAgBE,QAAAA,GAS2Bka,EAICjE,EAMEwP,EAkBF/oB,EAeaklC,EAQlB98B,GAnDdsB,KAAQ8T,SAAUA,EAIlB9T,KAAW6P,YAAQA,EAMnB7P,KAAQqf,SAAaA,EAkBrBrf,KAAW1J,YAAQA,EAenB0J,KAAwBw7B,yBAAQA,EAQhCx7B,KAAKtB,MACXA,EACL,MA7ES9E,GAAKR,MAAa,UAGlBQ,EAAOP,QAAc,WAGrBO,EAAqBC,sBAAuB,oBAO5CD,EAAmBE,qBAAiB,cAAc,YAgE1DF,KAaDL,GAAA,WAaE,QAAAA,GAI2Bua,EAIOnd,GAJzBqJ,KAAQ8T,SAAUA,EAIlB9T,KAAIrJ,KACVA,EACL,MArBS4C,GAAKH,MAAqB,kBAG1BG,EAAOF,SAAc,WAAU,QAG/BE,EAAoBE,qBAA0B,uBAG9CF,EAAsBG,wBAAU,OAAc,YAYtDH,KAaDW,GAAA,WAQE,QAAAA,GAMkCuhC,EAMUC,EASGC,GAftC37B,KAAey7B,gBAAUA,EAMzBz7B,KAA2B07B,4BAAQA,EASnC17B,KAAyB27B,0BAC/BA,EACL,MA1BSzhC,GAAGjM,IAAqB,kBACxBiM,EAAKd,MAAkB,eAyB/Bc,KAMsB0hC,IACNziC,GAAMC,MACNE,GAAMF,MACHW,GAAMX,MACRY,GAAMZ,MACdQ,GAAMR,MACPa,GAAMb,MACCc,GAAMd,MACJG,GAChBH,OCtbFyiC,GAAA,WAwFE,QAAAC,GAAmC9iC,GAAfgH,KAAEhH,GAAgBA,EA4BxC,MAlHS8iC,GAAYC,aAAnB,SACcpsC,EACGgX,EAC0Cq1B,GAOnD,MALA/uC,GACI6uC,EAAcG,cAEtB,mDACG9wC,EApBkB,WAoBW,oBAAQwE,GACpC,GAAuB0K,IAAW,SAAQC,EAAQC,GAKtD,GAAaH,GAAS8hC,OAAUC,UAAKtT,KAAKl5B,EAAWgX,EAE9CvM,GAAUI,UAAG,SAAaC,GAC/B,GAAQzB,GAASyB,EAA4BC,OAAQzL,MAC9CqL,GAAC,GAAYwhC,GACtB9iC,KAEOoB,EAAQO,QAAG,SAAkBF,GAC5BF,EAAOE,EAA4BC,OAC3CjO,QAEO2N,EAAgBgiC,gBAAG,SAA6B3hC,GAChDtP,EAtCc,WAwCL,aAAOwE,EAAqC,mCACnD8K,EACLxB,WAOF,IAAQD,GAASyB,EAA4BC,OAAQzL,MAC3C+sC,GAAGhjC,EAAOyB,EACtBxB,eAEJm2B,aAGO0M,EAAM/8B,OAAb,SAA0BpP,GAElB,MADDxE,GAzDkB,WAyDY,qBAAQwE,GACzBwK,GAAa+hC,OAAUC,UAAeE,eAAO1sC,IACjEy/B,aAGO0M,EAAWG,YAAlB,WACK,GAA8B,mBAAhBC,SAA6C,MAAnBA,OAAUC,UAC7C,OACR,CASA,IAAQG,GAASJ,OAAUK,UAAWC,SAYnC,SACCF,EAAQ3qC,QAAS,SAAI,GACrB2qC,EAAQ3qC,QAAY,YAAI,GACxB2qC,EAAQ3qC,QAAS,SACpB,IASHmqC,EAAAjuC,UAAc2pC,eAAd,SACgCiF,EACRC,EACoDC,GAE1E,GAAiBhF,GAAG,GAAuBx8B,IAAK6E,KAAGhH,GAAMyjC,EAAgBC,GAChDE,EAAAD,EAA6BhF,GAC9C5I,MAAC,SAAKtiC,GAIJ,MADKkrC,GAASkF,QACKxiC,GAAOE,OAClC9N,KACa2iC,WAKT,OAAAuI,GAA8BmF,kBAAK1P,KACvC,WAAM,MAAmBwP,MAI7Bd,EAAAjuC,UAAKw3B,MAAL,WACMrlB,KAAGhH,GACTqsB,SACDyW,KAODiB,GAAA,WAIE,QAAAA,GAAgDC,GAA5Bh9B,KAAQg9B,SAAoBA,EAHxCh9B,KAAUi9B,YAAS,EACnBj9B,KAAOk9B,QAEoC,KAqCrD,MAnCEhvC,QAAAwR,eAAIq9B,EAAAlvC,UAAM,UpB08QJgK,IoB18QN,WACQ,MAAKmI,MACbi9B,YpB28QMp6B,YAAY,EACZC,coB58QL,IAED5U,OAAAwR,eAAIq9B,EAAAlvC,UAAS,apB68QPgK,IoB78QN,WACQ,MAAKmI,MACbk9B,SpB88QMr6B,YAAY,EACZC,coB/8QL,IAED5U,OAAAwR,eAAIq9B,EAAAlvC,UAAM,UpBg9QJof,IoBh9QN,SAAoC5e,GAC9B2R,KAASg9B,SACf3uC,GpBi9QMwU,YAAY,EACZC,coBl9QL,IAKDi6B,EAAAlvC,UAAIsvC,KAAJ,WACMn9B,KAAWi9B,YACjB,GAMAF,EAAAlvC,UAAIuvC,KAAJ,SAAmCnvC,GAC7B+R,KAAQk9B,QACdjvC,GAOA8uC,EAAAlvC,UAAMkR,OAAN,WACQ,MAAY5E,IAAW6F,KAASg9B,SACxCj+B,WACDg+B,KA8BD5hC,GAAA,WAYE,QAAAkiC,GAA2BrkC,EAAcyjC,EAA6Ba,GAAtE,GAAA58B,GAgBCV,IA1BOA,MAAOu9B,SAAS,EAWlBv9B,KAAY23B,YAAK3+B,EAAY2+B,YACd2F,EAEjBb,GAEEz8B,KAAkB88B,kBAAA,GAActY,IAAA,EAAO,SAAQlqB,EAAQC,GAGrDmG,EAAYi3B,YAAQ6F,QAAO98B,EAAYi3B,YAAW8F,WAAG,SAAKhjC,GAE9DH,KACIoG,EAAYi3B,YAAQh9B,QAAG,SAAaF,GAChCF,EAAOE,EAAsBC,OACrCjO,UA4BN,MAxBE4wC,GAAAxvC,UAAKgvC,MAAL,WACW78B,KAASu9B,UACXpyC,EA3OgB,WA2OmB,yBACpC6U,KAAQu9B,SAAQ,EAChBv9B,KAAY23B,YAClBkF,UAYFQ,EAAAxvC,UAAKuL,MAAL,SACmBskC,GAEjB,GAAWtkC,GAAO4G,KAAY23B,YAAYgG,YAAYD,EAEhD,OADAzwC,KAAQmM,EAA0C,yCAAcskC,GAC/D,GAAiBE,IAC1BxkC,IACDikC,KAYDO,GAAA,WACE,QAAAC,GAAyCzkC,GAArB4G,KAAK5G,MAAmBA,EAsM9C,MA3LEykC,GAAAhwC,UAAGiwC,IAAH,SACiCC,EACd1vC,GAEjB,GAAY+L,EAQN,YAPkB7L,KAAfF,GACFlD,EA/RgB,WA+RD,MAAM6U,KAAM5G,MAAKzJ,KAAYouC,EAAS1vC,GACnD+L,EAAO4F,KAAM5G,MAAI0kC,IAAMzvC,EAChC0vC,KACO5yC,EAlSgB,WAkSD,MAAM6U,KAAM5G,MAAKzJ,KAAc,aAAcouC,GAC1D3jC,EAAO4F,KAAM5G,MAAI0kC,IAC1BC,IACkB5jC,GACpBC,IASAyjC,EAAAhwC,UAAGgK,IAAH,SAAgB5J,GAAhB,GAAAyS,GAWCV,IARO,OAAA7F,IAFc6F,KAAM5G,MAAIvB,IAAM5J,IAEC+X,KAAC,SAAM/W,GAMpC,WAJmBV,KAAfU,IACFA,EACR,MACK9D,EAvTgB,WAuTD,MAAMuV,EAAMtH,MAAKzJ,KAAK1B,EAAUgB,GAEtDA,KAGF4uC,EAAAhwC,UAAMkR,OAAN,SAAiC9Q,GAGzB,MAFD9C,GA7TkB,WA6TA,SAAM6U,KAAM5G,MAAKzJ,KAAO1B,GAE7BkM,GADE6F,KAAM5G,MAAO2F,OAAM9Q,KAOzC4vC,EAAAhwC,UAAOmwC,QAAP,SACqCC,EAChBjmB,GAEnB,GAAY2L,GAAO3jB,KAAO2jB,OAAK3jB,KAAQxO,QAAaysC,EAAUjmB,IACjD5mB,IACP,OAAA4O,MAAmBk+B,cAAOva,EAAE,SAAI11B,EAAOI,GACpC+C,EAAK0H,KACdzK,KAAO2X,KAAC,WACA,MACR5U,MAMFysC,EAAAhwC,UAASswC,UAAT,SACqCF,EAChBjmB,GAEd7sB,EAzVkB,WAyVI,aAAM6U,KAAM5G,MAAOzJ,KAC9C,IAAa6B,GAAOwO,KAAQxO,QAAaysC,EAASjmB,EAC3CxmB,GAAS4sC,UAAS,CACzB,IAAYza,GAAO3jB,KAAO2jB,OAAUnyB,EAC9B,OAAAwO,MAAmBk+B,cAAOva,EAAE,SAAI11B,EAAOI,EAASgwC,GAO9C,MAAQA,GAChBt/B,YAsBF8+B,EAAAhwC,UAAOywC,QAAP,SACyEC,EACzBrZ,GAE9C,GAAY1zB,EACE0zB,GAIL1zB,EACT+sC,GAJS/sC,KACC0zB,EACVqZ,EAGA,IAAY5a,GAAO3jB,KAAO2jB,OAAUnyB,EAC9B,OAAKwO,MAAck+B,cAAOva,EAClCuB,IAEQ2Y,EAAAhwC,UAAaqwC,cAArB,SAC2BM,EACc/vC,GAEvC,GAAa2C,KACP,WAAuBiJ,IAAC,SAAQC,EAAQC,GAC/BikC,EAAQ7jC,QAAG,SAAaF,GAC7BF,EAAOE,EAAsBC,OACrCjO,QACa+xC,EAAUhkC,UAAG,SAAaC,GACrC,GAAYkpB,GAA6BlpB,EAAsBC,OAAQzL,MACpE,KAAS00B,EAGZ,WAFYrpB,IAGZ,IAAgBmkC,GAAG,GAAuB1B,IAASpZ,GACnC+a,EAAKjwC,EAAOk1B,EAAWgb,WAAQhb,EAAMt1B,MAAcowC,EACrDC,aAA+BrkC,KACpCjJ,EAAK0H,KACd4lC,GACcD,EAAQ5P,OAEtBv0B,IAAyC,OAApBmkC,EAAUG,UACvBjb,EACRkb,WACQlb,EAASkb,SAAWJ,EAC5BG,cAEG54B,KAAC,WACA,MAAmB3L,IAAQi1B,QACnCl+B,MAGMysC,EAAAhwC,UAAO2D,QAAf,SACqCysC,EAChBjmB,GAEnB,GAAa8mB,OAAiCvwC,EAYxC,YAXyBA,KAAf0vC,IACuB,gBAAdA,GACZa,EACXb,GACQhxC,MACesB,KAAdypB,EAEL,uDACGA,EACPimB,KAEYt5B,MAAWm6B,EAAO9mB,MAClCA,IAEQ6lB,EAAAhwC,UAAM81B,OAAd,SAAsCnyB,GACpC,GAAa2yB,GAAU,MAIpB,IAHQ3yB,EAASutC,UACT5a,EACX,QACW3yB,EAAOmT,MAAE,CAClB,GAAWA,GAAO3E,KAAM5G,MAAMuL,MAAQnT,EAAQmT,MAC3C,OAAQnT,GAAU4sC,SACPz5B,EAAcq6B,cACjBxtC,EAAMwmB,MAGjBmM,GACcxf,EAAWs6B,WAAQztC,EAAMwmB,MACvCmM,GAEM,MAAKnkB,MAAM5G,MAAW6lC,WACnBztC,EAAMwmB,MAGjBmM,IAEH0Z,KC7bDqB,GAAA,WAiBE,QAAAC,GAKwBrE,EACasE,GAD3Bp/B,KAAM86B,OAAQA,EACd96B,KAAUo/B,WAAiBA,EAR7Bp/B,KAAgB0xB,iBASrB,KAkdL,MA3cSyN,GAAOE,QAAd,SAAyB1F,EAA6ByF,GAO9C,MAFAnyC,GAAgB,KAAX0sC,EAAI2F,IAAgD,uCAExD,GAA0BH,GADdxF,EAAoB4F,oBAAK,GAAO5F,EAAM2F,IAE3DF,IAEAD,EAAAtxC,UAAK8K,MAAL,SAAyCg/B,GAAzC,GAAAj3B,GAmCCV,IAlCO,OAAAm/B,GAA6CK,sBAAa7H,GACzD3xB,KAAC,SAAWy5B,GAET,MADF/+B,GAAY++B,YAAeA,EACLvkC,GAAay8B,GAAI9/B,IAAK6I,EAClDo6B,UACK90B,KAAC,SAAiC05B,GAelC,MAdWA,KACJA,EAAG,GAAmBvmC,IACxBuH,EAAOo6B,OACIlB,GAGnB,KACIl5B,EAASg/B,SAAYA,EAOjBh/B,EAASg/B,SAAwB3E,yBAAQr6B,EAAa++B,YACtD/+B,EAAgBi/B,WAAahI,GAAK3xB,KAAC,SAAK45B,GAOtC,MANA3yC,GACC2yC,EAEL,8DAEEl/B,EAASg/B,SAAwB3E,wBAAmBnB,GAC9B1+B,GAAay8B,GAAImG,IAAKp9B,EAClDg/B,YAEyBrlC,GAC3BC,aAQC6kC,EAAqBK,sBAA5B,SAC6BzkC,GAE3B,GAAc8kC,GAAmBjG,EAC3B,OAAA9+B,IAAoBC,GAChBujC,SAAUS,SAAQ,GAAE,SAAI9wC,EAAO+oC,EAASqH,GACvC,GAAAvD,GAAA7sC,EAAM,EAKV,IALYA,EAAe,GACL4xC,IACbA,EAAQ7I,EACpBI,SAEkB,KAAR0D,EAIDuD,EACTlB,WAAQ,CACN,GAAc2C,GAAuBztC,EAASyoC,EACvCuD,GAAKjB,MACd0C,OAEG95B,KAAC,WAAM,MAAU65B,GAAI,KAG9BV,EAAAtxC,UAAU8xC,WAAV,SAA8ChI,GAC5C,GAASiI,IAAQ,EACN5nB,EAAc+nB,YAAMpwB,MACzB3P,KAAcggC,cAAOryB,OAAmB3B,mBACxChM,KAAcggC,cAAOryB,OACzB7B,mBACI,OAAAhR,IAA4B68B,GACxB2G,SAAQtmB,MAAEA,GAAE,SAAI/pB,EAAOI,EAASgwC,GACjCuB,GAAS,EACPvB,EACTlB,SACKn3B,KAAC,WAAM,MAAK45B,MAGrBT,EAAAtxC,UAAcoyC,eAAd,SACqCtI,GAE7B,MAAmBt9B,IAAQC,QAAK0F,KACxCy/B,cAEAN,EAAAtxC,UAA6BqyC,8BAA7B,SACqCvI,GAE7B,MAAmBt9B,IAAQC,QAAK0F,KAAS0/B,SACjD3E,0BAEAoE,EAAAtxC,UAAgB4qC,iBAAhB,SACqCd,EACfX,EACQwD,GAE5B,GAAapD,GAAQJ,EAASI,OASxB,OARAnqC,GACGmqC,EAAOp3B,KAAS0/B,SAAwB3E,wBAE/C,mDAEE/6B,KAAS0/B,SAAwB3E,wBAAW3D,EAC5Cp3B,KAAS0/B,SAAgB1E,gBAAsBpgC,GAAc4/B,GAEvCt/B,GAAay8B,GAAImG,IAAK99B,KAClD0/B,WAEAP,EAAAtxC,UAAkBsyC,mBAAlB,SACqCxI,GAE7B,MAAmBt9B,IAAQC,QAAK0F,KAAS0/B,SACjD1E,kBAEAmE,EAAAtxC,UAAkBuyC,mBAAlB,SACqCzI,EACP6C,GAGtB,MADFx6B,MAAS0/B,SAAgB1E,gBAAsBpgC,GAAc4/B,GACvCt/B,GAAay8B,GAAImG,IAAK99B,KAClD0/B,WAEAP,EAAAtxC,UAAgBwyC,iBAAhB,SACqC1I,EACVrrB,EACJytB,GAHvB,GAAAr5B,GAgCCV,KA3Bco3B,EAAOp3B,KAAay/B,WAC7Bz/B,MAAey/B,aACnB,IAAWzI,GAAG,GAAiB6C,IAAQzC,EAAgB9qB,EAAaytB,GAEvDuG,EAAOtgC,KAAWo/B,WAAkBmB,kBAAKvgC,KAAO86B,OAAS9D,EAEhE,OAAAl8B,IAA4B68B,GAC5BmG,IAASwC,GACRt6B,KAAC,WAEA,IAAmB,GADTuqB,MACShlC,EAAS,EAATi1C,EAASzG,EAATxuC,EAAAi1C,EAAS/0C,OAAAF,IAAA,CAA3B,GAAc80B,GAAAmgB,EAAAj1C,GAEHk1C,GADyB/oC,GAAgB2oB,EAAIpyB,IAAO0I,MAC/BoD,GAAI9L,IACjCyS,EAAOo6B,OACHza,EAAIpyB,IAAK0I,KAEjBygC,GACoBn8B,IAAa08B,GAAImG,IAC7B2C,EACU1mC,GAClBshC,aAEE,MAAmBhhC,IAAQi1B,QACnCiB,KACKvqB,KAAC,WACE,MACRgxB,MAGJmI,EAAAtxC,UAAmB6yC,oBAAnB,SACqC/I,EACnBP,GAFlB,GAAA12B,GAUCV,IANO,OAAAlF,IAA4B68B,GAC5B9/B,IAAKmI,KAAcggC,cAAU5I,IAC5BpxB,KACH,SAAOs6B,GACL,MAAOA,GAAO5/B,EAAW0+B,WAAoBuB,oBAASL,GAAO,QAIrEnB,EAAAtxC,UAAgC+yC,iCAAhC,SACqCjJ,EACnBP,GAFlB,GAAA12B,GAkBCV,KAdYgY,EAAc+nB,YAAWc,WAAK7gC,KAAcggC,cAAQ5I,EAAO,IACxD0J,EAA8B,IACtC,OAAAhmC,IAA4B68B,GACxB2G,SAAQtmB,MAAEA,GAAE,SAAI/pB,EAASqyC,EAASjC,GAC7BiC,EAAOxF,SAASp6B,EAAQo6B,SAC3B7tC,EACGqzC,EAAQlJ,QAAUA,EACU,oCACnCA,GACQ0J,EAAOpgC,EAAW0+B,WAAoBuB,oBAClDL,IACOjC,EACTlB,SACKn3B,KAAC,WAAM,MAAU86B,MAG1B3B,EAAAtxC,UAAqBkzC,sBAArB,SACqCpJ,GADrC,GAAAj3B,GAYCV,KATYgY,EAAc+nB,YAAMpwB,MACzB3P,KAAcggC,cAAiBpG,IAC/B55B,KAAcggC,cAAOryB,OACzB7B,mBACI,OAAAhR,IAA4B68B,GACxBqG,QAAOhmB,GACVhS,KAAC,SAASg7B,GACb,MAAAA,GAAah1C,IAAC,SAAOs0C,GAAI,MAAI5/B,GAAW0+B,WAAoBuB,oBAASL,QAI3EnB,EAAAtxC,UAAmCozC,oCAAnC,SACqCtJ,EACnBP,GAFlB,GAAA12B,GAaCV,KATYgY,EAAc+nB,YAAMpwB,MACzB3P,KAAcggC,cAAiBpG,IAC/B55B,KAAcggC,cAClB5I,GACI,OAAAt8B,IAA4B68B,GACxBqG,QAAOhmB,GACVhS,KAAC,SAASg7B,GACb,MAAAA,GAAah1C,IAAC,SAAOs0C,GAAI,MAAI5/B,GAAW0+B,WAAoBuB,oBAASL,QAI3EnB,EAAAtxC,UAAyCqzC,0CAAzC,SACqCvJ,EACXwJ,GAF1B,GAAAzgC,GAiDCV,KA3CkBohC,EAAqBrnC,GAAcqhC,cAC9Cp7B,KAAO86B,OACAqG,EACXxqC,MACc0qC,EAActB,YAAWc,WAAcO,GAE1ChwC,IACP,OAAA6J,IAAoC08B,GAChC2G,SAAQtmB,MAAcqpB,GAAE,SAASZ,EAAG/uC,EAAS2sC,GAC5C,GAAAiD,GAAAb,EAAM,GAAEc,EAAAd,EAAW,GAAEe,EAAAf,EAAoB,GAStC9pC,EAAsB0B,GAAqBkpC,EAClD,IAAOD,IAAS5gC,EAAOo6B,SAAgBqG,EAAKxqC,KAAOzE,OAAOyE,GAG7D,WAFS0nC,GAAQlB,MAGjB,IAAiBsE,GAAO/gC,EAAcs/B,cAAUwB,EAK1C,OAAA1mC,IAA4B68B,GAC5B9/B,IAAa4pC,GACZz7B,KAAC,SAAOs6B,GACU,OAAVA,GACLzzC,EAC4C,+CACpC4zC,EACW,oBAGzBgB,GACOrwC,EAAK0H,KAAK4H,EAAW0+B,WAAoBuB,oBAClDL,QAECt6B,KAAC,WAAM,MAAO5U,MAGvB+tC,EAAAtxC,UAAmC6zC,oCAAnC,SACqC/J,EACvBj5B,GAFd,GAAAgC,GA2ECV,IAvEO/S,IACEyR,EAAkB9C,kBAExB,+CAEF,IAAe+lC,GAAQjjC,EAAM/H,KACAirC,EAAYD,EAAOl2C,OAAK,EAapC21C,EAAqBrnC,GAAcqhC,cAC9Cp7B,KAAO86B,OAEX6G,GAEcN,GADoBD,EAAI,GACVrB,YAAWc,WAAcO,IAKrCS,EAAG,GAAavqB,IAA+BvlB,EAC3D,OAAAkJ,IAAoC08B,GAChC2G,SAAQtmB,MAAcqpB,GAAE,SAASZ,EAAG/uC,EAAS2sC,GAC5C,GAAAiD,GAAAb,EAAM,GAAEc,EAAAd,EAAW,GAAEe,EAAAf,EAAoB,GACtC9pC,EAAsB0B,GAAqBkpC,EAClD,IAAOD,IAAS5gC,EAAOo6B,SAAc6G,EAAW/8B,WAAOjO,GAG1D,WAFS0nC,GAAQlB,MAQTxmC,GAAOlL,SAA6Bm2C,IAG9BC,EAAiBA,EAAI7iC,IACrCwiC,MACKx7B,KAAC,WACJ,GAAa5U,MACCm/B,IAmBR,OAjBQsR,GAAQhzC,QAAC,SAAO2yC,GAC5B,GAAiBC,GAAO/gC,EAAcs/B,cAAUwB,EACxCjR,GAAKz3B,KAAAgC,GACgB68B,GACrB9/B,IAAa4pC,GACZz7B,KAAC,SAAQqa,GACU,OAAVA,GACNxzB,EAC4C,+DAIlD40C,GACOrwC,EAAK0H,KAAK4H,EAAW0+B,WAAoBuB,oBAClDtgB,SAGAhmB,GAA2Bi1B,QAAUiB,GAAKvqB,KAAC,WAAM,MAAO5U,QAIpE+tC,EAAAtxC,UAAqBi0C,sBAArB,SACqCnK,EACXoK,GAMpB,IAAgB,GAJXhnC,GAAiBD,GAAc68B,GAC1BqK,EAAyB/mC,GAAc08B,GACvCpH,KrBkuRN0R,EAASjiC,KqBhuRGzU,EAAO,EAAP22C,EAAOH,EAAPx2C,EAAA22C,EAAOz2C,OAAAF,IAAA,CAAtB,GAAWyrC,GAAAkL,EAAA32C,IrB6sRE,SqB7sRFyrC,GACd,GAAWhf,GAAc+nB,YAAKoC,KAACF,EAAkBjC,cAAMhJ,EAAWI,UACpDgL,EAAK,EACAC,EAAAtnC,EAAcujC,SAAQtmB,MAAEA,GAAE,SAAI/pB,EAAOI,EAASgwC,GAEzD,MADO+D,KACC/D,EAChBt/B,UACQwxB,GAAKz3B,KAAAupC,EACOr8B,KAAC,WACX/Y,EACY,IAANm1C,EACkD,6DACrDpL,EAEXI,WAEE,KAAmB,GAAA7rC,GAAe,EAAfsjB,EAAKmoB,EAAU+C,UAAfxuC,EAAAsjB,EAAepjB,OAAAF,IAAA,CAAjC,GAAc80B,GAAAxR,EAAAtjB,GACHk1C,EAAqB1mC,GAAI9L,IACrCg0C,EAAWnH,OACHza,EAAIpyB,IAAK0I,KACZqgC,EACLI,QACM7G,GAAKz3B,KAASkpC,EAAOjjC,OAAY0hC,IACN,OAA/BwB,EAAqBvQ,kBACvBuQ,EAAqBvQ,iBAAuBrB,uBAAShQ,EACvDpyB,OAzBY+oC,GA4BV,MAAmB38B,IAAQi1B,QACnCiB,IAEA4O,EAAAtxC,UAAuBy0C,wBAAvB,SAC6BvnC,GAD7B,GAAA2F,GAiCCV,IA9BO,OAAAA,MAAgB2/B,WAAK5kC,GAAKiL,KAAC,SAAK45B,GACjC,IAAQA,EACH,MAAmBvlC,IAC3BC,SAIA,IAAgBioC,GAAcxC,YAAWc,WACrB9mC,GAAcohC,cAAKz6B,EACrCo6B,SAC8B0H,IAC1B,OAAAvnC,IAA4BF,GACxBujC,SAAQtmB,MAAcuqB,GAAE,SAAIt0C,EAAGyD,EAAS2sC,GAE3C,GADepwC,EAAI,KACHyS,EAAQo6B,OAG3B,WAFSuD,GAAQlB,MAGf,IAAUxmC,GAAsB0B,GAAWpK,EAAK,GACtBu0C,GAAK1pC,KACjCnC,KAEGqP,KAAC,WACE/Y,EACmC,IAAbu1C,EAAO/2C,OAC4D,8FAAA+2C,EAC7Dx2C,IAAC,SAACsU,GAAI,MAACA,GAAkB2E,0BAMnEk6B,EAAAtxC,UAAmBsiC,oBAAnB,SAA+CsS,GACzCziC,KAAiB0xB,iBACvB+Q,GAEAtD,EAAAtxC,UAAWgjC,YAAX,SAC6B91B,EACX9M,GAFlB,GAAAyS,GAiBCV,KAbeygC,EAAqB1mC,GAAcqhC,cAAKp7B,KAAO86B,OAAK7sC,EAAO0I,MACxD4qC,EAAWd,EAAI,GAChB8B,EAAcxC,YAAWc,WAAWJ,GACrC5P,GAAS,CAClB,OAAA51B,IAA4BF,GACxBujC,SAAQtmB,MAAYuqB,EAAUnE,UAAQ,GAAE,SAAInwC,EAAGyD,EAAS2sC,GACvD,GAAAiD,GAAArzC,EAAM,GAAEoL,EAAApL,EAAO,EAAEA,GAAe,GAC7BqzC,IAAS5gC,EAAOo6B,QAAWzhC,IAAiBkoC,IACzC1Q,GACb,GACOwN,EACTlB,SACKn3B,KAAC,WAAM,MAAW6qB,MAOnBsO,EAAAtxC,UAAamyC,cAArB,SAAsC5I,GAC9B,OAAMp3B,KAAO86B,OACrB1D,IACD+H,KC1eDuD,GAAA,WACE,QAAAC,GAA+CvD,GAA3Bp/B,KAAUo/B,WAAiBA,EAMvCp/B,KAAyB27B,0BAAkBzoB,GAAKM,IAKhDxT,KAAQ0/B,SAAG,GAAkBxlC,IACb,EACS,EAChBgZ,GAAIM,IACnBE,eAGM1T,KAAgB0xB,iBAAiC,KAoO3D,MAlOEiR,GAAA90C,UAAK8K,MAAL,SAAyCg/B,GAAzC,GAAAj3B,GAaCV,IAZO,OAAA1E,IAA+Bq8B,GAC/B9/B,IAAeqC,GAAKjM,KACnB+X,KAAC,SAAQ05B,GACT,GAAmB,OAAVA,EAAY,CAClBh/B,EAASg/B,SAAYA,CACzB,IAAsBkD,GAAWlD,EAA2B/D,yBACxDj7B,GAA0Bi7B,0BAAkBzoB,GAAcI,cAC5D,GAAapB,IAAiB0wB,EAAQxwB,QAAkBwwB,EAE5DvwB,QACM,MAAmBhY,IAC3BC,aAGJqoC,EAAA90C,UAAkBg1C,mBAAlB,WACQ,MAAK7iC,MAAS0/B,SACtBjE,iBAEAkH,EAAA90C,UAA4Bi1C,6BAA5B,WACQ,MAAK9iC,MACb27B,2BAEAgH,EAAA90C,UAA4Bk1C,6BAA5B,SACqCpL,EACH3jB,GAI1B,MAFFhU,MAA0B27B,0BAAmB3nB,EAC7ChU,KAAS0/B,SAA0B/D,0BAAkB3nB,EAAeN,cAChDpY,GAAaq8B,GAAImG,IACzB5jC,GAAIjM,IACd+R,KAER0/B,WAEAiD,EAAA90C,UAAYm1C,aAAZ,SACqCrL,EACfnV,GAFtB,GAAA9hB,GAgBCV,KAZe8T,EAAY0O,EAAU1O,SACbmvB,EAAe7nC,GAAau8B,GAAImG,IACjD99B,KAAWo/B,WAAW8D,WAC1B1gB,GACC,OAAS1O,GAAO9T,KAAS0/B,SAAiBjE,iBACvCz7B,KAAS0/B,SAAgBjE,gBAAY3nB,EACnCmvB,EAAuBj9B,KAAC,WAC5B,MAAiB1K,IAAaq8B,GAAImG,IAAe5jC,GAAIjM,IAAMyS,EAAUg/B,aAIzEuD,GAGFN,EAAA90C,UAAes1C,gBAAf,SACqCxL,EACfnV,GAEd,MAAAxiB,MAAmCojC,8BAC5BzL,EACFnV,EACV1O,UAAK9N,KAAC,WACO5K,GAAau8B,GAAO54B,OAAUyjB,EAC5C1O,aAGF6uB,EAAA90C,UAAYw1C,aAAZ,SACqC1L,EACvBj5B,GAFd,GAAAgC,GA2BCV,KApBkB6P,EAAQnR,EAAemR,cAC7BmI,EAAc+nB,YAAMpwB,OACjBE,EAAQlC,OAAmB3B,oBAC3B6D,EAAQlC,OACpB7B,oBACQ7c,EAA0B,IAC9B,OAAAmM,IAA0Bu8B,GACtB2G,SACCtmB,QAAOrT,MAAU/K,GAAwBC,uBAChD,SAAI5L,EAAOI,EAASgwC,GAClB,GAAWnf,GAAOxe,EAAW0+B,WAAakE,aAAQj1C,EAGzCqQ,GAAOxM,OAAMgtB,EAAQxgB,SACtBzP,EAASiwB,EACRmf,EACTlB,UAGCn3B,KAAC,WAAM,MAAM/W,MAGtB0zC,EAAA90C,UAAe01C,gBAAf,SAC6BxoC,EACP0c,EACF3D,GAIlB,GAAcyc,MACHn3B,EAAsBmC,GAAMR,EAKjC,OAJF0c,GAAQ5oB,QAAC,SAAGZ,GACd,GAAU0I,GAAsBe,GAAWzJ,EAAO0I,KAC1C45B,GAAKz3B,KAAMM,EAAI0kC,IAAC,GAAoBvkC,IAASua,EACvDnd,OACyB0D,GAAQi1B,QACnCiB,IAEAoS,EAAA90C,UAAkB21C,mBAAlB,SAC6BzoC,EACP0c,EACF3D,GAHpB,GAAApT,GAiBCV,KAVeuwB,KACHn3B,EAAsBmC,GAAMR,EAQjC,OAPF0c,GAAQ5oB,QAAC,SAAGZ,GACd,GAAU0I,GAAsBe,GAAWzJ,EAAO0I,KAC1C45B,GAAKz3B,KAAMM,EAAO2F,QAAU+U,EAAUnd,KACX,OAA3B+J,EAAiBgxB,kBACnBhxB,EAAiBgxB,iBAAuBrB,uBAC9CpiC,KAEuBoM,GAAQi1B,QACnCiB,IAEAoS,EAAA90C,UAA6Bu1C,8BAA7B,SAC6BroC,EACT+Y,GAElB,GAAW1a,GAAsBmC,GAAMR,GAC5Bid,EAAc+nB,YAAMpwB,OACnBmE,IACDA,EAAK,IACM,GAEpB,EACI,OAAA9T,MAA4ByjC,uBAAI1oC,EAAQid,GAAKhS,KAAC,WAClD,MAAK5M,GAAO2F,OAAOiZ,MAIf2qB,EAAA90C,UAAsB41C,uBAA9B,SAC6B1oC,EACTid,GAFpB,GAAAtX,GAsBCV,KAlBY5G,EAAsBmC,GAAMR,EACpC,OAA+B,QAA1BiF,KAAiB0xB,kBAAiB1xB,KAAiB0xB,iBAAS5B,QAG5D12B,EAAcklC,SAAQtmB,QAAUomB,UAAQ,GAAE,SAAInwC,EAAGyD,EAAS2sC,GAC9D,GAAU1nC,GAAsB0B,GAAWpK,EAAK,IACpCyN,EAAG,GAAeuK,IAAOtP,EAG/B1J,GAC0B,OAA1ByT,EAAiBgxB,iBAErB,oEACEhxB,EAAkBgxB,iBAAuBrB,uBAC/C30B,KAEyBrB,GAC3BC,WAGFqoC,EAAA90C,UAA0B61C,2BAA1B,SAC6B3oC,EACT+Y,GAElB,GACWkE,GAAc+nB,YAAMpwB,OACnBmE,IACDA,EAAK,IACM,GAEpB,GACS1a,EAAsBmC,GAAMR,GAC7B9L,EAAoBiH,IAExB,OAAAkD,GACIklC,SAAQtmB,QAAUomB,UAAQ,GAAE,SAAInwC,EAAGyD,EAAS2sC,GAClD,GAAU1nC,GAAsB0B,GAAWpK,EAAK,IACpCyN,EAAG,GAAeuK,IAAOtP,EAC/B1H,GAASA,EAAI+P,IACrBtD,KACKsK,KAAC,WAAM,MAAM/W,MAGtB0zC,EAAA90C,UAAmBsiC,oBAAnB,SAA+CsS,GACzCziC,KAAiB0xB,iBACvB+Q,GAEAE,EAAA90C,UAAWgjC,YAAX,SACoC91B,EAClB9M,GAEVhB,EACQ,OAAT8N,EAEH,qEACF,IAAUpE,GAAsBe,GAAWzJ,EAAO0I,MACvCqhB,EAAc+nB,YAAMpwB,OACvBhZ,IACa/D,EAAO+D,KACN,GAEpB,GACOygB,EAAK,CACR,OAAA7b,IAA0BR,GACtBujC,SAEC35B,MAAkBpL,GAAqBE,qBACpC2kC,UAAM,EACTpmB,MACNA,GACD,SAAI/pB,EAAGyD,EAAS2sC,GACNjnB,IACDinB,EACTlB,SAEGn3B,KAAC,WAAM,MAAKoR,GAAI,KAE1BurB,KCxQDgB,GAAA,WACE,QAAAC,GAA+CxE,GAA3Bp/B,KAAUo/B,WAAoBA,EAqDpD,MAnDEwE,GAAA/1C,UAAQg2C,SAAR,SACqClM,EACPmM,GAEtB,MAAqBtoC,IAAam8B,GAAImG,IACrCriC,GAAcqoC,EAAK71C,KACpB+R,KAAWo/B,WAAmB2E,mBAEtCD,KAEAF,EAAA/1C,UAAWm2C,YAAX,SACqCrM,EACXwJ,GAElB,MAAqB3lC,IAAam8B,GAAO54B,OAAMtD,GACvD0lC,KAEAyC,EAAA/1C,UAAQo2C,SAAR,SACqCtM,EACXwJ,GAF1B,GAAAzgC,GAWCV,IAPO,OAAAxE,IAAkCm8B,GAClC9/B,IAAM4D,GAAc0lC,IACnBn7B,KAAC,SAAWk+B,GACT,MAAYA,GACVxjC,EAAW0+B,WAAqB+E,qBAAaD,GAEvD,QAGJN,EAAA/1C,UAAyBu2C,0BAAzB,SACqCzM,EACvBj5B,GAFd,GAAAgC,GAoBCV,KAhBY5O,EAAiB0E,IAIdoT,EAAQxK,EAAK/H,KAAWgF,UAC3Bqc,EAAc+nB,YAAWc,WAAW33B,EACzC,OAAA1N,IAAkCm8B,GAC9B2G,SAAQtmB,MAAEA,GAAE,SAAI/pB,EAAai2C,EAAS7F,GAC5C,GAAcppB,GAAOvU,EAAW0+B,WAAqB+E,qBAAcD,EACzDxlC,GAAK/H,KAAWiO,WAASqQ,EAAIhnB,IAAO0I,MAE3Bse,YAAoBxO,KAAS/H,EAAQyR,QAAW8E,KAC1D7jB,EAAUA,EAAOuW,OAASsN,EAAIhnB,IACvCgnB,IAHSopB,EACTlB,SAIGn3B,KAAC,WAAM,MAAO5U,MAExBwyC,KC9CDS,GAAA,WACE,QAAAC,GAAyDC,GAArCvkC,KAAgBukC,iBAAwBA,EA0G9D,MAvGED,GAAAz2C,UAAoBs2C,qBAApB,SAAgDK,GAC3C,GAAUA,EAAUzlB,SACf,MAAK/e,MAAiBukC,iBAAavlB,aAAUwlB,EACrDzlB,SAAM,IAAcylB,EAAYjJ,WAAE,CAChC,GAASttC,GAAcgY,GAAaK,aAAUk+B,EAAWjJ,WAAO5kC,MAClD0oB,EAAYmlB,EAAWjJ,WAAUlc,SAChCjM,EAAG,GAAalB,IAASmN,EAAQjN,QAAUiN,EAAQhN,MAC5D,OAAC,IAAchL,IAAIpZ,EAAiBilB,GAAcI,cAC1DF,IACQ,MAAKvmB,GACb,gCAIFy3C,EAAAz2C,UAAkBk2C,mBAAlB,SAA0C9uB,GACrC,GAASA,YAAqBxO,IAAE,CACjC,GAASlI,GAAOyB,KAAiBukC,iBAAWzlB,WAAW7J,EACjD,OAAC,IAAoBjb,IAAK,KAClCuE,GACE,GAAU5H,GAAWse,EAAIhnB,IAAK0I,KAAWgF,UAC1ByX,EAAW6B,EAAQtO,QAAe+M,cACnC2L,EAAG,GAAesb,IAAUvnB,EAAQhB,QAAWgB,EAAQf,MAC/D,OAAC,IAAoBrY,IAAC,GAAgBshC,IAAK3kC,EAAW0oB,GAC9D,OAIFilB,EAAAz2C,UAAiB0yC,kBAAjB,SAAgCzF,EAAsB9D,GAAtD,GAAAt2B,GAUCV,KAT0BykC,EAAAzN,EAAkB+C,UAAI/tC,IAAC,SAAC04C,GAC/C,MAAIhkC,GAAiB6jC,iBAAWnkB,WAAGskB,IAE/B,OAAC,IAAmBprC,IAClBwhC,EACD9D,EAAQI,QACRJ,EAAe1qB,eAAsB2G,sBAG9CwxB,IAGAH,EAAAz2C,UAAmB8yC,oBAAnB,SAA4CL,GAA5C,GAAA5/B,GAMCV,KALgB+5B,EAAAuG,EAAoBvG,UAAI/tC,IAAC,SAAC04C,GACvC,MAAIhkC,GAAiB6jC,iBAAa5jB,aAAG+jB,KAExBtxB,EAAYlB,GAAsBK,sBAAQ+tB,EAAmBrF,iBACtE,OAAC,IAAiBpB,IAAQyG,EAAQlJ,QAAWhkB,EACrD2mB,IAGAuK,EAAAz2C,UAAYy1C,aAAZ,SAA+BqB,GAC7B,GAKiBjmC,GALH2gB,EAAG,GAAanN,IACpByyB,EAAStlB,SAAQjN,QACjBuyB,EAAStlB,SACjBhN,OACW1L,EAAkBuM,GAAcI,cAAW+L,EAOlD,OAJC3gB,GADY9C,GAAS+oC,EAAQjmC,OACtBsB,KAAiBukC,iBAAoBljB,oBAASsjB,EAC5DjmC,OACcsB,KAAiBukC,iBAAgBtiB,gBAAS0iB,EACxDjmC,OACO,GAAakV,IACblV,EACGimC,EAAS7wB,SACL/I,GAAO4X,OACZhc,EACCg+B,EAEZruC,cAGAguC,EAAAz2C,UAAUq1C,WAAV,SAA+B1gB,GACvBv1B,EACQ8d,GAAO4X,SAAcH,EAAQzO,QACb,6BACdhJ,GAAO4X,OACG,uBACbH,EACXzO,QACF,IAEwB6wB,GAFTxxB,EAAYoP,EAAgBxO,gBAAeN,cACzCmxB,EAAG,GAAelK,IAAUvnB,EAAQhB,QAAWgB,EAAQf,MAG5DuyB,GADCpiB,EAAM9jB,MAAmB9C,kBACnBoE,KAAiBukC,iBAAkBnjB,kBAAUoB,EAChE9jB,OACmBsB,KAAiBukC,iBAAchjB,cAAUiB,EAC5D9jB,OACMzR,EACqC,gBAAzBu1B,GAAYlsB,YAE5B,oDACF,IAAiBA,GAAYksB,EAAuBlsB,WAG9C,OAAC,IAAYsD,IACR4oB,EAAS1O,SACT0O,EAAM9jB,MAAcmR,cAClBg1B,EACAvuC,EACV,EAGLsuC,IACDN,KuChG6BQ,GACY,oKAqC1CC,GAAA,WA0BE,QAAAC,GAA0BC,EAAiC7F,GAfnDp/B,KAAO46B,QAAe56B,KAAmBklC,kBAgB3CllC,KAAOmlC,OAASF,EAAuBD,EAAeI,cACtDplC,KAAWo/B,WAAG,GAAmBiF,IAAajF,GAC9Cp/B,KAAmBqlC,mBACzBJ,EAySF,MAvSED,GAAAn3C,UAAK8K,MAAL,cAAA+H,GAqBCV,IApBI,OAAsBglC,GAAe/I,eAQlChvC,GAAM+S,KAAQslC,QAA0C,wCAC1DtlC,KAAQslC,SAAQ,EAEdzJ,GAAsBE,aAAK/7B,KAAOmlC,O5C1GZ,E4C0GgDpsC,IACrEq0B,KAAC,SAAEp0B,GACF0H,EAAS6kC,SACfvsC,IACKo0B,KAAC,WAAM,MAAI1sB,GAAuB8kC,yBAClCpY,KAAC,WACA1sB,EAA+B+kC,8BAC/B/kC,EACNglC,6BAlBI1lC,KAAiB2lC,iBAAG,GAAkBj4C,IACpCC,GAAcoF,cApES,sIAuEfyxB,GAAA,EAAOjqB,OAAKyF,KAC5B2lC,oBAgBFX,EAAAn3C,UAAQ+3C,SAAR,cAAAllC,GAQCV,IAHO,OAJA/S,GAAK+S,KAAQslC,QAAkD,gDACjEtlC,KAAQslC,SAAS,EACjBtlC,KAA0B6lC,yBAC1B7lC,KAA2B8lC,0BACzB9lC,KAAyB+lC,oBAAK3Y,KAAC,WAC/B1sB,EAAS6kC,SACflgB,WAGF2f,EAAAn3C,UAAgBm4C,iBAAhB,SAA2BrM,GACnB,MAAuBuF,IAAQG,QAAK1F,EAAM35B,KAClDo/B,aAEA4F,EAAAn3C,UAAao4C,cAAb,WACQ,MAAC,IAAuBvD,IAAK1iC,KACrCo/B,aAEA4F,EAAAn3C,UAAsBq4C,uBAAtB,WACQ,MAAC,IAAgCvC,IAAK3jC,KAC9Co/B,aAEA4F,EAAAn3C,UAAc2pC,eAAd,SACgBjvB,EACwD49B,GAFxE,GAAAzlC,GAgBCV,IAZI,OAAKA,MAAkB2lC,iBACVnhB,GAAA,EAAOjqB,OAAKyF,KAC5B2lC,mBAEGx6C,EArIgC,uBAqIO,wBAAUod,GAI9CvI,KAAculC,SAAe/N,eAAY,YAAYoE,GAAE,SAAG7gC,GAExD,MAAA2F,GAAsB0lC,iBAAKrrC,GAAKiL,KAAC,WAAM,MAASmgC,GAAKprC,SAIxDiqC,EAAW/I,YAAlB,WACQ,MAASJ,IACjBI,eAMO+I,EAAkBqB,mBAAzB,SAAoDzc,GAQlD,GAAYpmB,GAAeomB,EAAW5mB,WAAWO,SAK3C,OAJWqmB,GAAW5mB,WAAmBsjC,oBACrC9iC,GAAO,IAAeomB,EAAW5mB,WAC3CQ,UAEmB,aAAeomB,EAAe3mB,eAAM,IAAWO,EACpE,KAMQwhC,EAAAn3C,UAAoB23C,qBAA5B,cAAA9kC,GA8BCV,IA3BO,OAAAA,MAAculC,SAAe/N,eAAY,aAAUv9B,GAAOb,OAAE,SAAG2B,GACnE,GAAW3B,GAAM2B,EAAM3B,MAA6Ba,GAAQb,MACtD,OAAAA,GAAUvB,IAAS,SAAKmO,KAAC,SAAOugC,GACjC,GAAM7lC,EAAW8lC,WAAUD,GAoBtB,MATHp7C,GA5L0B,uBA8LmB,+CAE9Co7C,GACE7lC,EAAiBilC,iBAAG,GAAkBj4C,IACpCC,GAAoBuH,oBAExB4vC,IACuBzqC,GAAOE,OAAWmG,EAC7CilC,iBApBE,IAAgBc,GAAG,GAAWxsC,IAAKyG,EAAQk6B,QAAM/uC,KAAQymB,MAQnD,OAPHnnB,GAnL0B,uBAqL4B,wDAChDo7C,EACK,aAEZE,GACUrtC,EAAI0kC,IAAQ,QAC1B2I,QAiBEzB,EAAAn3C,UAAiBk4C,kBAAzB,cAAArlC,GAcCV,IAXO,OAAAA,MAAculC,SAAe/N,eAAY,aAAUv9B,GAAOb,OAAE,SAAG2B,GACnE,GAAW3B,GAAM2B,EAAM3B,MAA6Ba,GAAQb,MACtD,OAAAA,GAAUvB,IAAS,SAAKmO,KAAC,SAAOugC,GACjC,MAAiB,QAATA,GAAoBA,EAAQ3L,UAASl6B,EAASk6B,SACpDzvC,EAnN0B,uBAmNgB,0BACjCiO,EAAO2F,OACrB,UAC2B1E,GAC3BC,eAUE0qC,EAAAn3C,UAAgBu4C,iBAAxB,SAAiDrrC,GAAjD,GAAA2F,GAaCV,IAXO,OADWjF,GAAM3B,MAA6Ba,GAAQb,OAC5CvB,IAAS,SAAKmO,KAAC,SAAOugC,GACjC,MAAiB,QAATA,GAAoBA,EAAQ3L,UAASl6B,EAASk6B,SACnDl6B,EAAiBilC,iBAAG,GAAkBj4C,IACpCC,GAAoBuH,oBAExB4vC,IACuBzqC,GAAOE,OAAWmG,EAC7CilC,mBAC2BtrC,GAC3BC,aAWI0qC,EAAAn3C,UAAU24C,WAAlB,SAA0CD,GACxC,GAASj0B,GAAOzmB,KAAOymB,MACJo0B,EAAMp0B,EAtPO,IAuPbq0B,EAAOr0B,CACvB,SAAkB,OAAVi0B,GAEOA,EAAiB1L,iBAAiB6L,IAElCH,EAAiB1L,iBAAiB8L,GAC/Cp6C,EACsD,wDAEvDg6C,GAEJ,GAAkBA,EAAQ3L,UAAS56B,KAAqB4mC,uBAWlD5B,EAAAn3C,UAA2B43C,4BAAnC,cAAA/kC,GAmBCV,IAfKA,MAAwB6mC,wBAAAC,YAAe,WAC3BpmC,EAAsB82B,eAA0B,0BAAE,SAAGz8B,GAI3D,MADWA,GAAM3B,MAA6Ba,GAAQb,OAC5C0kC,IAAQ,QAAE,GAAW7jC,IAAKyG,EAAQk6B,QAAM/uC,KAC1DymB,UAEcyc,MAAC,SAAMgY,GAGhBx6C,EAAew6C,GACdrmC,EACNolC,6BA5RuC,MAgSnCd,EAAAn3C,UAAuBi4C,wBAA/B,WACU9lC,KAAyB6mC,0BAClBG,cAAKhnC,KAA0B6mC,yBACxC7mC,KAAwB6mC,wBAC9B,OAYM7B,EAAAn3C,UAAsB63C,uBAA9B,cAAAhlC,GAUCV,IATKA,MAAoBinC,oBAAG,WAErBvmC,EAAkBwmC,kBAAKxmC,EAAUk6B,SAIjCl6B,EACNklC,YACM1J,OAAiBiL,iBAAS,SAAMnnC,KACxCinC,sBAEQjC,EAAAn3C,UAAsBg4C,uBAA9B,WACU7lC,KAAqBinC,sBACrB/K,OAAoBkL,oBAAS,SAAMpnC,KAAsBinC,qBAC3DjnC,KAAoBinC,oBAC1B,OAQMjC,EAAAn3C,UAAiB+4C,kBAAzB,WACE,IACE,GAAoBS,GAASnL,OAAaoL,aAAQC,QAC5CvnC,KACJwnC,8BAEI,OADHr8C,GAlV8B,uBAkVsB,qCAAkBk8C,GAE3EA,EAAQ,MAAGz6C,GAGH,MADHL,GAtV8B,uBAsVkB,iCAAKK,GAE1D,OAOMo4C,EAAAn3C,UAAiBq5C,kBAAzB,SAAsDO,GACpD,IAC6B,OAAVA,EACTvL,OAAaoL,aAAWI,WAAK1nC,KACrCwnC,+BACQtL,OAAaoL,aAAQK,QACrB3nC,KAA8BwnC,8BAGtCC,GACM,MAAG76C,GAENL,EA3W8B,uBA2WkB,iCACrDK,KAGMo4C,EAAAn3C,UAA2B25C,4BAAnC,WACQ,MAAKxnC,MAAmBqlC,mBAxWwB,kBA2WhDL,EAAAn3C,UAAeq3C,gBAAvB,WAEQ,MAAOpkC,IACfE,SAjUOgkC,EAAaI,cAAU,OAkU/BJ,KClXD4C,GAAA,WACE,QAAAC,GACkDC,EACZC,GAD5B/nC,KAAmB8nC,oBAAqBA,EACxC9nC,KAAa+nC,cACpBA,EA2LL,MAnLEF,GAAAh6C,UAAWm6C,YAAX,SACqCrQ,EACnB1pC,GAFlB,GAAAyS,GASCV,IALO,OAAAA,MAAyB8nC,oBACpB7D,SAAYtM,EAAM1pC,GACtB+X,KAAC,SAASw+B,GACP,MAAK9jC,GAAqBunC,qBAAYtQ,EAAK1pC,EACnDu2C,MASJqD,EAAAh6C,UAAYq6C,aAAZ,SACqCvQ,EACflgB,GAFtB,GAAA/W,GAkBCV,KAdeuwB,KACHn/B,EAAsBwE,GAY3B,OAXF6hB,GAAQ5oB,QAAC,SAAGZ,GACNsiC,EAAKz3B,KAAA4H,EACKsnC,YAAYrQ,EAAM1pC,GAAK+X,KAAC,SAAQiP,GAEhCA,IACJA,EAAG,GAAc5N,IAAIpZ,EAAiBilB,GAChDK,kBACOniB,EAAUA,EAAOuW,OAAI1Z,EAC9BgnB,QAGE5a,GAA2Bi1B,QAAUiB,GAAKvqB,KAAC,WAAM,MAAO5U,MAIhEy2C,EAAAh6C,UAAyBu2C,0BAAzB,SACqCzM,EACvBj5B,GAET,MAAYuH,IAAcE,cAAMzH,EAAO/H,MAC7BqJ,KAAkCmoC,kCAAYxQ,EAAOj5B,EAClE/H,MACaqJ,KAAoCooC,oCAAYzQ,EAC7Dj5B,IAGMmpC,EAAAh6C,UAAiCs6C,kCAAzC,SACqCxQ,EACdlnB,GAGf,MAAAzQ,MAAiBgoC,YACVrQ,EACX,GAAe1xB,IAChBwK,IAAKzK,KAAC,SAAQiP,GACb,GAAUhmB,GAAiB6G,GAIrB,OAHMmf,aAAqBxO,MACzBxX,EAASA,EAAO0Y,OAASsN,EAAIhnB,IACrCgnB,IAEFhmB,KAGM44C,EAAAh6C,UAAmCu6C,oCAA3C,SACqCzQ,EACvBj5B,GAFd,GAQ2BtN,GAR3BsP,EA2DCV,IAlDO,OAAAA,MAAyB8nC,oBACH1D,0BAAYzM,EAAQj5B,GACzCsH,KAAC,SAAYqiC,GACV,MAAK3nC,GAAsB4nC,sBAAY3Q,EAC/C0Q,KACKriC,KAAC,SAAeuiC,GAIb,MAHCn3C,GAAmBm3C,EAGf7nC,EAAcqnC,cAAoCrG,oCAChD/J,EAGfj5B,KACKsH,KAAC,SAAuBwiC,GAEvB,IAAgB,GADJC,GAAoBvyC,KAChB3K,EAAuB,EAAvBm9C,EAAuBF,EAAvBj9C,EAAAm9C,EAAuBj9C,OAAAF,IACrC,IAAmB,GADTyrC,GAAA0R,EAAAn9C,GACSsjB,EAAe,EAAfiB,EAAKknB,EAAU+C,UAAflrB,EAAAiB,EAAerkB,OAAAojB,IAAA,CAAjC,GAAcwR,GAAAvQ,EAAAjB,EAGLzd,GAAIyG,IAASwoB,EAAMpyB,OACjBw6C,EAAeA,EAAIzpC,IAASqhB,EAC1CpyB,MAKJ,GAAcsiC,KAUR,OATMkY,GAAQ55C,QAAC,SAAGZ,GACdsiC,EAAKz3B,KAAA4H,EACKsnC,YAAYrQ,EAAM1pC,GAAK+X,KAAC,SAAGzH,GAClCA,YAAqBkI,MACnBrV,EAAUA,EAAOuW,OAAIpJ,EAAItQ,IAClCsQ,SAImBlE,GAAQi1B,QACnCiB,KACKvqB,KAAC,WASE,MANC5U,GAAQvC,QAAC,SAAIZ,EAAKsQ,GACbG,EAAQyR,QAAM5R,KACfnN,EAAUA,EAAO0W,OAC1B7Z,MAIJmD,KAYIy2C,EAAAh6C,UAAoBo6C,qBAA5B,SACqCtQ,EACXwJ,EACMpiB,GAExB,MAAA/e,MAAmB+nC,cACmB7G,0CAAYvJ,EAAcwJ,GAC/Dn7B,KAAC,SAAO+7B,GACP,IAAgB,GAAAx2C,GAAO,EAAP22C,EAAOH,EAAPx2C,EAAA22C,EAAOz2C,OAAAF,IAAA,CAAtB,GAAWyrC,GAAAkL,EAAA32C,EACNwzB,GAAQiY,EAAiBlhB,iBAAYqrB,EAAYpiB,GAErD,MACRA,MAWI8oB,EAAAh6C,UAAqBy6C,sBAA7B,SACqC3Q,EACb77B,GAFxB,GAAA4E,GAmBCV,KAfeuwB,IAcR,OAbGz0B,GAAQjN,QAAC,SAAIZ,EAAKsQ,GACjBgyB,EAAKz3B,KAAA4H,EACcunC,qBAAYtQ,EAAK1pC,EAAMsQ,GAAKyH,KAAC,SAAU2iC,GAChDA,YAAqBliC,IACxB3K,EAAYA,EAAO6L,OAAWghC,EAAI16C,IAC7C06C,GAAqBA,YAAuBthC,IACjCvL,EAAYA,EAAOgM,OAAW6gC,EACzC16C,KACMpB,EAA0B,0BAChC87C,QAIAtuC,GAA2Bi1B,QAAUiB,GAAKvqB,KAAC,WAAM,MAASlK,MAEnE+rC,KCpMDe,GAAA,WAGE,QAAAC,GAA4Df,GAAxC9nC,KAAmB8nC,oBAAqBA,EAFpD9nC,KAAO4qB,QAEgDh1B,IA0DjE,MAvDEizC,GAAAh7C,UAAQg2C,SAAR,SAAqCC,GACnC,GAAalZ,GAAO5qB,KAAiB8oC,eACjC9oC,MAAQ4qB,QAAUA,EAAOjjB,OAAcm8B,EAAI71C,IACjD61C,IAeA+E,EAAAh7C,UAAQo2C,SAAR,SACqCtM,EACXwJ,GAExB,GAAavW,GAAO5qB,KAAiB8oC,gBAElBC,EAAUne,EAAI/yB,IAAcspC,EAC5C,OAAe4H,GACS1uC,GAAQC,QACnCyuC,GACa/oC,KAAoB8nC,oBAAS7D,SAAYtM,EACtDwJ,IAOF0H,EAAAh7C,UAAKzB,MAAL,SAAyCurC,GAAzC,GAAAj3B,GAYCV,KAXc4qB,EAAO5qB,KAAiB8oC,gBAEvBvY,IAQR,OAPC3F,GAAQ/7B,QAAC,SAAIZ,EAAUgnB,GACpBsb,EAAKz3B,KAAK4H,EAAoBonC,oBAASjE,SAAYlM,EAC7D1iB,MAGIjV,KAAQ4qB,QAAQ,KAEKvwB,GAAQi1B,QACnCiB,IAGQsY,EAAAh7C,UAAai7C,cAArB,WAEQ,MADA77C,GAAsB,OAAjB+S,KAAQ4qB,QAAiD,sCACzD5qB,KACb4qB,SACDie,KCmBDG,GAAA,WA0CE,QAAA7V,GAEkC8V,EACfC,EAMyBxX,GAPlC1xB,KAAWipC,YAAaA,EAOxBjpC,KAAgB0xB,iBAAkBA,EAhCpC1xB,KAAmBmpC,oBAAG,GAAmB/X,IAMzCpxB,KAASma,aAGTna,KAAiBo2B,kBAAoBxD,GAAiBM,gBAYtDlzB,KAAgBopC,oBAalBppC,KAAc+nC,cAAckB,EAAiBjD,iBAAckD,GAC3DlpC,KAAgBqpC,gBAAcJ,EAA0B/C,yBACxDlmC,KAAWspC,WAAcL,EAAiBhD,gBAC1CjmC,KAAeupC,eAAG,GAAsB3B,IACtC5nC,KAAgBqpC,gBAChBrpC,KACJ+nC,eACE/nC,KAAiB0xB,iBAAiBzB,iBAAKjwB,KAAsBmpC,qBAC7DnpC,KAAiB0xB,iBAAiBzB,iBAAKjwB,KAAaspC,YACpDtpC,KAAiB0xB,iBAAiBzB,iBAAKjwB,KAC7C+nC,eAspBF,MAnpBE5U,GAAAtlC,UAAK8K,MAAL,cAAA+H,GAICV,IAHO,OAAAA,MAAiBipC,YAAezR,eAAmB,mBAAE,SAAGz8B,GACtD,MAAA2F,GAAwB8oC,mBAAKzuC,GAAKiL,KAAC,WAAM,MAAItF,GAAgB+oC,gBAAK1uC,QAU5Eo4B,EAAAtlC,UAAgB6rC,iBAAhB,SAA2BC,GAA3B,GAAAj5B,GAwCCV,IAvCO,OAAAA,MAAiBipC,YAAezR,eAAqB,qBAAE,SAAGz8B,GAG9D,GAAgC2uC,EAC1B,OAAAhpC,GAAmBqnC,cACDhH,sBAAKhmC,GACtBiL,KAAC,SAAkB2jC,GAMhB,MALID,GAAsBC,EAE5BjpC,EAAiBgxB,iBAAoBtB,oBAAK1vB,EAAgBqnC,eAC1DrnC,EAAcqnC,cAAOrnC,EAAYuoC,YAAiBjD,iBAAOrM,GACzDj5B,EAAiBgxB,iBAAiBzB,iBAAKvvB,EAAgBqnC,eAChDrnC,EAAmB8oC,mBAChCzuC,KACKiL,KAAC,WAOE,MAJFtF,GAAe6oC,eAAG,GAAsB3B,IACtClnC,EAAgB2oC,gBAChB3oC,EACJqnC,eACSrnC,EAAcqnC,cAAsBhH,sBACjDhmC,KACKiL,KAAC,SAAU4jC,GAGV,IAAkB,GADPC,GAAoB3zC,KACb3K,EAAwB,EAAxBsjB,GAAW66B,EAAaE,GAAxBr+C,EAAAsjB,EAAwBpjB,OAAAF,IACxC,IAAgB,GADJw2C,GAAAlzB,EAAAtjB,GACIukB,EAAO,EAAPoyB,EAAOH,EAAPjyB,EAAAoyB,EAAOz2C,OAAAqkB,IACrB,IAAmB,GADTknB,GAAAkL,EAAApyB,GACSC,EAAe,EAAf+5B,EAAK9S,EAAU+C,UAAfhqB,EAAA+5B,EAAer+C,OAAAskB,IAAA,CAAjC,GAAcsQ,GAAAypB,EAAA/5B,EACN85B,GAAcA,EAAI7qC,IAASqhB,EAAMpyB,KAO5C,MAAKyS,GAAe6oC,eAAarB,aAAIntC,EAC7C8uC,QAIE1W,EAAAtlC,UAAe47C,gBAAvB,SAC6B1uC,GAD7B,GAAA2F,GAOCV,IAJO,OAAAA,MAAgBspC,WAAM3wC,MAAKoC,GAAKiL,KAAC,WACrC,GAAc8N,GAAOpT,EAAW4oC,WAAsBzG,oBAClDniC,GAAkB01B,kBAAoBxD,GAAcM,cAC1Dpf,MAGMqf,EAAAtlC,UAAkB27C,mBAA1B,SAC6BzuC,GAD7B,GAAA2F,GAkCCV,IA/BO,OAAAA,MAAmB+nC,cACjBpvC,MAAKoC,GACNiL,KAAC,WAOE,MADFtF,GAAiB0oC,oBACV1oC,EAAcqnC,cAA8B7H,8BACzDnlC,KACKiL,KAAC,SAAU+jC,GAIX,MAAWA,KAAqBnQ,GACtBl5B,EAAcqnC,cAAoC9G,oCACxDlmC,EAGPgvC,GAC2B1vC,GAAQC,cAGhC0L,KAAC,SAAYgkC,GACb,MAAaA,GAAOv+C,OAAK,EACfiV,EAAcqnC,cAAsBjG,sBAAI/mC,EACrDivC,GAC2B3vC,GAC3BC,aAKN64B,EAAAtlC,UAAUqpC,WAAV,SAAgC6C,GAAhC,GAAAr5B,GAkBCV,IAjBO,OAAAA,MAAiBipC,YAAezR,eAA0B,0BAAE,SAAGz8B,GACnE,GAAyBi8B,GACL1qB,EAAY4F,GAAOI,KACjC,OAAA5R,GAAmBqnC,cACN1H,iBAAItlC,EAAgBuR,EAAYytB,GAC5C/zB,KAAC,SAAaikC,GACZjT,EAAiBiT,CAItB,IAAUxyB,GAAQuf,EAAQvf,MACpB,OAAK/W,GAAe6oC,eAAarB,aAAIntC,EAC7C0c,KACKzR,KAAC,SAAmCkkC,GACjC,OAAU9S,QAAOJ,EAAQI,QAASxM,QAC1Csf,QAkBN/W,EAAAtlC,UAAgB4qC,iBAAhB,SACkCuB,GADlC,GAAAt5B,GAiCCV,IA9BO,OAAAA,MAAiBipC,YAAezR,eAAoB,oBAAE,SAAGz8B,GAC7D,GAA6BovC,EACvB,OAAAzpC,GAAmBqnC,cACNtP,iBAAI19B,EAAai/B,EAAMhD,MAAagD,EAAaQ,aAC7Dx0B,KAAC,WACD,GAAKtF,EAAsB0pC,sBAAYpQ,EAAgBO,eAGlD,MAFF75B,GAAiB0oC,iBAAKtwC,KAAckhC,GAChCmQ,EAAoBj0C,KACHmE,GAC3BC,SACE,IAAoB+vC,GAAG,GAA8BzB,IAC/CloC,EACJ2oC,gBACI,OAAA3oC,GAAyB4pC,oBAC1BvvC,GACUi/B,GAEdqQ,GAAKrkC,KAAC,SAAoBukC,GAEnB,MADEJ,GAAwBI,EACXF,EAAMj+C,MAC7B2O,OAGCiL,KAAC,WACE,MAAKtF,GAAcqnC,cAAwBzF,wBACnDvnC,KACKiL,KAAC,WACE,MAAKtF,GAAe6oC,eAAarB,aAAIntC,EAC7CovC,QAUNhX,EAAAtlC,UAAW8qC,YAAX,SAA4BvB,GAA5B,GAAA12B,GAkCCV,IAjCO,OAAAA,MAAiBipC,YAAezR,eAAe,eAAE,SAAGz8B,GACxD,GAA4ByvC,GACKC,CAC3B,OAAA/pC,GAAmBqnC,cACHrH,oBAAI3lC,EAAUq8B,GAC7BpxB,KAAC,SAAuC0kC,GAOrC,MANAz9C,GACoB,MAARy9C,EAEhB,wCACMF,EAAqBE,EAEvBhqC,EAAmBqnC,cACO7H,8BAAKnlC,GAC9BiL,KAAC,SAAS2kC,GAKP,MAJA19C,GACGmqC,EAAYuT,EAEnB,2CAEJH,MAECxkC,KAAC,WACE,MAAKtF,GAAoBkqC,oBAAI7vC,EACrCyvC,KACKxkC,KAAC,SAAoBukC,GAElB,MADME,GAAwBF,EACzB7pC,EAAcqnC,cAAwBzF,wBACnDvnC,KACKiL,KAAC,WACE,MAAKtF,GAAe6oC,eAAarB,aAAIntC,EAC7C0vC,QAKNtX,EAAAtlC,UAAkBsyC,mBAAlB,cAAAz/B,GAICV,IAHO,OAAAA,MAAiBipC,YAAezR,eAAwB,wBAAE,SAAGz8B,GAC3D,MAAK2F,GAAcqnC,cAAmB5H,mBAC9CplC,MAQFo4B,EAAAtlC,UAAkBuyC,mBAAlB,SAA+C5F,GAA/C,GAAA95B,GAICV,IAHO,OAAAA,MAAiBipC,YAAezR,eAAwB,wBAAE,SAAGz8B,GAC3D,MAAK2F,GAAcqnC,cAAmB3H,mBAAIrlC,EAClDy/B,MAOFrH,EAAAtlC,UAA4Bi1C,6BAA5B,WACQ,MAAK9iC,MAAWspC,WACxBxG,gCAUA3P,EAAAtlC,UAAgBkqC,iBAAhB,SAAyCC,GAAzC,GAAAt3B,GA4HCV,KA3HqB6qC,EAAG,GAA8BjC,IAAK5oC,KAAkBqpC,gBACtE,OAAArpC,MAAiBipC,YAAezR,eAAqB,qBAAE,SAAGz8B,GAC9D,GAAcw1B,KACN/hC,GACKwpC,EAAcrf,cACzB,SAAmB7E,EAAsBzd,GAEvC,GAAamsB,GAAO9hB,EAAUyZ,UAAWrG,EACtC,IAAY0O,EAAZ,CAEH,GAAazJ,GAAuC1iB,EAAS0iB,OAC1D,IAASA,EAEP,GAAQA,YAAyBC,IAC1BuX,EAAKz3B,KAAA4H,EACI4oC,WACiBlG,8BAAIroC,EAAW+Y,GACxC9N,KAAC,WACE,MAAKtF,GAAW4oC,WAAgB/F,gBACjCxoC,EACIge,EAAUjd,UAGrBgY,UAEA,MAAYiF,YAA0BO,KAapC,MAAKzsB,GAAyB,yBAAOH,KAAUC,UACvDosB,GAbUwX,GAAKz3B,KAAA4H,EACI4oC,WACM9F,mBAAIzoC,EAASge,EAAiBS,iBAAW1F,GACvD9N,KAAC,WACE,MAAKtF,GAAW4oC,WAAgB/F,gBACjCxoC,EACIge,EAAeQ,eAG1BzF,MASR,GAAiBxd,GAASD,EAAaC,WACxBA,GAAO7K,OAAK,IAChB+2B,IAAmBvO,QACf3d,cACI0d,gBAAQ3d,EACtB2d,kBACCtT,EAAUyZ,UAAUrG,GAAa0O,EAC7B+N,EAAKz3B,KAAK4H,EAAW4oC,WAAatG,aAAIjoC,EAChDynB,OAIJ,IAAkBsoB,GAAoB50C,IAC3B8hC,GAAgBpf,gBAAQ/pB,QAAC,SAAIZ,EAAKsQ,GAC7BusC,EAAiBA,EAAI9rC,IAAM/Q,GACjCsiC,EAAKz3B,KAAA+xC,EACY5G,SAAIlpC,EAAM9M,GAAK+X,KAAC,SAAW+kC,GAM3B,MAARA,GACRxsC,EAAQoI,QAAOzU,OAAgBghB,GAAKM,MACpCjV,EAAQoI,QAAUlD,UAAYsnC,EAASpkC,UAC3C,EACekkC,EAAShH,SACzBtlC,GACKpT,EA3bY,aA6bwB,sCAClC8C,EACiB,qBACT88C,EAAQpkC,QACF,kBACdpI,EAEPoI,SAIIjG,EAAiBgxB,iBAAuBrB,uBAC9CpiC,OAQJ,IAAuB+8C,GAAOtqC,EAAW4oC,WAAgCxG,+BACtDmI,EAAcjT,EAAiBhkB,eAChCi3B,GAAO/4C,OAAgBghB,GAAMM,OACvCvmB,EACSg+C,EAAUxnC,UAAmBunC,IAAK,EACA,gDAChCC,EACR,MAEPD,GACMza,EAAKz3B,KACP4H,EAAW4oC,WAA6BvG,6BAAIhoC,EAEpDkwC,IAEA,IAAsCC,EAChC,OAAA7wC,IAA2Bi1B,QAAUiB,GACpCvqB,KAAC,WAAM,MAAItF,GAAwByqC,wBAAIpwC,EAAiB8vC,KACxD7kC,KAAC,SAAyBolC,GAEvB,MADWF,GAA6BE,EACzBP,EAAMz+C,MAC7B2O,KACKiL,KAAC,WACE,MAAKtF,GAAe6oC,eAAarB,aAClCntC,EACW+vC,EAAU1yB,UAE5B8yB,SAON/X,EAAAtlC,UAAsB2rC,uBAAtB,SAAsD6R,GAAtD,GAAA3qC,GAuBCV,IAtBO,OAAAA,MAAiBipC,YAAezR,eAA4B,4BAAE,SAAGz8B,GAEjE,IAAe,GADLw1B,MACKhlC,EAAW,EAAX+/C,EAAWD,EAAX9/C,EAAA+/C,EAAW7/C,OAAAF,IAAA,CAAzB,GAAU+pC,GAAAgW,EAAA//C,IlEkkUK,SkElkUL+pC,GACL/E,EAAKz3B,KAAA4H,EACI4oC,WACAjG,aAAItoC,EAAMu6B,EAAO52B,OACzBsH,KAAC,SAA4Bwc,GAC1Bv1B,EACc,OAATu1B,EAET,gDACF,IAAc1O,GAAa0O,EAAU1O,QACjCpT,GAAoByoC,oBAActX,cAAKyD,EAAUtE,UAAYld,GAC7DpT,EAAoByoC,oBAAiBnX,iBACnCsD,EAAYrE,YAGpBnd,OAfSwhB,GAkBT,MAAmBj7B,IAAQi1B,QACnCiB,MASF4C,EAAAtlC,UAAiB09C,kBAAjB,SAAwCC,GAAxC,GAAA9qC,GAUCV,IATO,OAAAA,MAAiBipC,YAAezR,eAA0B,0BAAE,SAAGz8B,GAI7D,WAHyBxM,KAAfi9C,IACFA,EACd5R,IACWl5B,EAAcqnC,cAAiCnH,iCACrD7lC,EAGPywC,MAOFrY,EAAAtlC,UAAY49C,aAAZ,SAA6Bx9C,GAA7B,GAAAyS,GAICV,IAHO,OAAAA,MAAiBipC,YAAezR,eAAgB,gBAAE,SAAGz8B,GACnD,MAAK2F,GAAe6oC,eAAYvB,YAAIjtC,EAC5C9M,MAQFklC,EAAAtlC,UAAayoC,cAAb,SAA0B53B,GAA1B,GAAAgC,GA2BCV,IA1BO,OAAAA,MAAiBipC,YAAezR,eAAiB,iBAAE,SAAGz8B,GAC1D,GAAyBynB,EACnB,OAAA9hB,GAAgB4oC,WACPjG,aAAItoC,EAAQ2D,GACpBsH,KAAC,SAAyB0lC,GAC1B,GAAQA,EAKH,MADGlpB,GAAUkpB,EACMrxC,GAC3BC,SACE,IAAcwZ,GAAOpT,EAAkB01B,kBAAQpwB,MAEzC,OADGwc,GAAG,GAAa5O,IAAMlV,EAAUoV,EAAc/I,GAAS4X,QACrDjiB,EAAW4oC,WAAatG,aAAIjoC,EACzCynB,KAEGxc,KAAC,WAME,MALA/Y,IACCyT,EAAUyZ,UAAUqI,EAAU1O,UACa,iDAChDpV,GACEgC,EAAUyZ,UAAUqI,EAAU1O,UAAa0O,EAEjDA,OAKN2Q,EAAAtlC,UAAYgpC,aAAZ,SAAyBn4B,GAAzB,GAAAgC,GAmCCV,IAlCO,OAAAA,MAAiBipC,YAAezR,eAAgB,gBAAE,SAAGz8B,GACnD,MAAA2F,GAAgB4oC,WACPjG,aAAItoC,EAAQ2D,GACpBsH,KAAC,SAA4Bwc,GAO7B,MANGv1B,GACa,MAARu1B,EAC6B,uCACtC9jB,GACEgC,EAAoByoC,oBAAsBlX,sBAAWzP,EAAW1O,gBACzDpT,GAAUyZ,UAAWqI,EAAW1O,UACnCpT,EAAiBgxB,iBAAS5B,QACrBpvB,EAAW4oC,WAAgBnG,gBAAIpoC,EAC5CynB,GAC2BnoB,GAC3BC,YAEG0L,KAAC,WAGD,GAASlX,EAAa4R,EAAYyZ,WAAE,CACrC,GAAoBwxB,GAAG,GAA8B/C,IAC/CloC,EACJ2oC,gBACI,OAAA3oC,GAA6ByqC,wBAC9BpwC,EAEJ4wC,GAAK3lC,KAAC,WACS2lC,EAAMv/C,MACtB2O,KAEM,MAAmBV,IAC3BC,eASR64B,EAAAtlC,UAAY0oC,aAAZ,SAAyB73B,GAAzB,GAAAgC,GAICV,IAHO,OAAAA,MAAiBipC,YAAezR,eAAgB,gBAAE,SAAGz8B,GACnD,MAAK2F,GAAe6oC,eAA0BnF,0BAAIrpC,EAC1D2D,MAOFy0B,EAAAtlC,UAAkB2oC,mBAAlB,SAAqC1iB,GAArC,GAAApT,GAICV,IAHO,OAAAA,MAAiBipC,YAAezR,eAAuB,uBAAE,SAAGz8B,GAC1D,MAAK2F,GAAW4oC,WAA2B5F,2BAAI3oC,EACvD+Y,MASFqf,EAAAtlC,UAAcyiC,eAAd,cAAA5vB,GAYCV,IATO,OAAAA,MAAiBipC,YAAezR,eAAqB,qBAAE,SAAGz8B,GACxD,MAAA2F,GAAsBgxB,iBAAepB,eAAKv1B,GAAKiL,KAAC,SAAO4lC,GAC3D,GAAcrb,KAIR,OAHCqb,GAAQ/8C,QAAC,SAAGZ,GACTsiC,EAAKz3B,KAAK4H,EAAgB2oC,gBAAYrF,YAAIjpC,EACpD9M,MACyBoM,GAAQi1B,QACnCiB,QAII4C,EAAAtlC,UAAuBs9C,wBAA/B,SAC6BpwC,EACe8vC,GAGtC,IAAsB,GADXgB,MACWtgD,EAAqB,EAArBsjB,EAAI7O,KAAiBopC,iBAArB79C,EAAAsjB,EAAqBpjB,OAAAF,IAAA,CAA1C,GAAiByuC,GAAAnrB,EAAAtjB,EACjB,KAAMyU,KAAoB8rC,oBAAY9R,EAAgBO,eAEzD,KACSsR,GAAK/yC,KAAckhC,GAG3B,MAAwB,KAAd6R,EAAOpgD,OACO4O,GAAQC,QACnCpE,OACM8J,KAAiBopC,iBAAOrd,OAAE,EAAW8f,EAASpgD,QACvCuU,KAAoBsqC,oBAAIvvC,EAAW8wC,EAChDhB,KAGM1X,EAAAtlC,UAAmBi+C,oBAA3B,SAAoDnlC,GAGlD,GAAuBqkC,GAAOhrC,KAAWspC,WAAgCxG,8BAClE,OACEn8B,GAAUlD,UAAmBunC,IAAK,GACjCl8C,EAAakR,KAEzBma,YAEQgZ,EAAAtlC,UAAqBu8C,sBAA7B,SAAsDzjC,GAE7C,OACA3G,KAAoB8rC,oBAASnlC,IAAQ3G,KAAiBopC,iBAAO39C,OAEtE,GAEQ0nC,EAAAtlC,UAAmBy8C,oBAA3B,SAC6BvvC,EACQgxC,EACOlB,GAGtC,IAAsB,GAN5BnqC,GAiBCV,KAZiBgsC,EAAqB3xC,GAAWC,UACtB/O,EAAY,EAAZ0gD,EAAYF,EAAZxgD,EAAA0gD,EAAYxgD,OAAAF,IAAA,CAAjC,GAAiByuC,GAAAiS,EAAA1gD,IlEyhUJ,SkEzhUIyuC,GACRgS,IAAoBhmC,KAAC,WAC/B,MAAItF,GAA4BwrC,4BAAInxC,EAAai/B,EAAiB6Q,MAFhD7Q,GAKhB,MAAAgS,GAAkBhmC,KAAC,WACjB,MAAAtF,GAA2BohC,sBAC5B/mC,EAAAgxC,EACa//C,IAAC,SAAMiD,GAAI,MAAMA,GAAM+nC,YAKrC7D,EAAAtlC,UAAmB+8C,oBAA3B,SAC6B7vC,EACPi8B,GAEd,MAAKh3B,MAAsB8hC,sBAAI/mC,GACvCi8B,KAGQ7D,EAAAtlC,UAAqBi0C,sBAA7B,SAC6B/mC,EACHgnC,GAGpB,IAAgB,GADJoK,GAAoBj2C,KAChB3K,EAAO,EAAP6gD,EAAOrK,EAAPx2C,EAAA6gD,EAAO3gD,OAAAF,IACrB,IAAmB,GADTyrC,GAAAoV,EAAA7gD,GACSsjB,EAAe,EAAfiB,EAAKknB,EAAU+C,UAAflrB,EAAAiB,EAAerkB,OAAAojB,IAAA,CAAjC,GAAcwR,GAAAvQ,EAAAjB,GACR5gB,EAAWoyB,EAAKpyB,GACbk+C,GAAeA,EAAIntC,IAAM/Q,GAInC,MAAA+R,MAAmB+nC,cACDjG,sBAAI/mC,EAAUgnC,GAC/B/7B,KAAC,WAAM,MAAYmmC,MAGpBhZ,EAAAtlC,UAA2Bq+C,4BAAnC,SAC6BnxC,EACKi/B,EACU6Q,GAE1C,GAAW7T,GAAcgD,EAAOhD,MACnBqV,EAAQrV,EAAQvf,OACbu0B,EAAqB3xC,GAAWC,SA8B1C,OA7BC+xC,GAAQx9C,QAAC,SAAM6M,GACRswC,IACLhmC,KAAC,WACE,MAAe6kC,GAAS5G,SAAIlpC,EACpCW,KACKsK,KAAC,SAAgCw+B,GACpC,GAAOjmC,GAAaimC,EACJ8H,EAActS,EAAYS,YAAI5iC,IAAS6D,EACjDzO,GACe,OAATq/C,EAEV,wDACM/tC,GAAOA,EAAQoI,QAAUlD,UAAa6oC,GAAK,KAC9C/tC,EAAQy4B,EAAsBphB,sBAAOla,EAAK6C,EAAey7B,GACnDz7B,EAUOssC,EAAShH,SACzBtlC,GAVQtR,GACMu3C,EACO,kBACVxN,EACkB,wBACdwN,EAGf,0BAOVwH,GACD7Y,KCzyBDoZ,GAAA,mBAAAC,KAKUxsC,KAAa+nC,iBAGb/nC,KAAWy/B,YAAc,EAGzBz/B,KAA0BysC,2BAA4B7S,GAMtD55B,KAAeg7B,gBAAsC7tC,IAGrD6S,KAAgB0xB,iBAAiC,KAGjD1xB,KAAoB0sC,qBAAG,GAAap1B,IAAaia,GAsa3DxqB,cAAA,MApaEylC,GAAA3+C,UAAK8K,MAAL,SAAyCg/B,GAcjC,MAR8B,KAA5B33B,KAAc+nC,cAAOt8C,SACvBuU,KAAYy/B,YAAK,EACjBz/B,KAA2BysC,2BACjC7S,IACM3sC,EACA+S,KAA2BysC,2BAAOzsC,KAAYy/B,YAElD,gEACuBplC,GAC3BC,WAEAkyC,EAAA3+C,UAAU8xC,WAAV,SAA8ChI,GACtC,MAAmBt9B,IAAQC,QACnC,IADwC0F,KAAc+nC,cAAOt8C,SAG7D+gD,EAAA3+C,UAAcoyC,eAAd,SACqCtI,GAE7B,MAAmBt9B,IAAQC,QAAK0F,KACxCy/B,cAEA+M,EAAA3+C,UAA6BqyC,8BAA7B,SACqCvI,GAE7B,MAAmBt9B,IAAQC,QAAK0F,KACxCysC,6BAEAD,EAAA3+C,UAAgB4qC,iBAAhB,SACqCd,EACfX,EACQwD,GAE5B,GAAapD,GAAQJ,EAASI,OACxBnqC,GACGmqC,EAAOp3B,KAA2BysC,2BAEzC,kDAEF,IAAgBE,GAAO3sC,KAAuB4sC,uBAAQxV,EAAkB,gBAG7D1sB,EAAO1K,KAAc+nC,cAAa4E,EAevC,OAdA1/C,GACGmqC,IAAU1sB,EAAQ0sB,QACgB,0CAChCA,EACO,eACT1sB,EACP0sB,SACInqC,GACEyd,EAAcyvB,cAEpB,gDAEEn6B,KAA2BysC,2BAAWrV,EACtCp3B,KAAgBg7B,gBAAeR,EACVngC,GAC3BC,WAEAkyC,EAAA3+C,UAAkBsyC,mBAAlB,SACqCxI,GAE7B,MAAmBt9B,IAAQC,QAAK0F,KACxCg7B,kBAEAwR,EAAA3+C,UAAkBuyC,mBAAlB,SACqCzI,EACP6C,GAGtB,MADFx6B,MAAgBg7B,gBAAeR,EACVngC,GAC3BC,WAEAkyC,EAAA3+C,UAAgBwyC,iBAAhB,SACqC1I,EACVrrB,EACJytB,GAEf9sC,EAAuB,IAAb8sC,EAAOtuC,OAAgD,uCAEvE,IAAa2rC,GAAOp3B,KAAay/B,WAC7Bz/B,MAAey/B,cAEXz/B,KAAc+nC,cAAOt8C,OAAK,GAE1BwB,EADY+S,KAAc+nC,cAAK/nC,KAAc+nC,cAAOt8C,OAAM,GAEjD2rC,QAAUA,EAG3B,2DAEA,IAAWJ,GAAG,GAAiB6C,IAAQzC,EAAgB9qB,EAAaytB,EAChE/5B,MAAc+nC,cAAKjvC,KAAQk+B,EAG3B,KAAmB,GAAAzrC,GAAS,EAATi1C,EAASzG,EAATxuC,EAAAi1C,EAAS/0C,OAAAF,IAAA,CAA3B,GAAc80B,GAAAmgB,EAAAj1C,EACbyU,MAAqB0sC,qBAAO1sC,KAAqB0sC,qBAAI1tC,IACvD,GAAgBuyB,IAASlR,EAAIpyB,IAC7BmpC,IAGE,MAAmB/8B,IAAQC,QACnC08B,IAEAwV,EAAA3+C,UAAmB6yC,oBAAnB,SACqC/I,EACnBP,GAEV,MAAmB/8B,IAAQC,QAAK0F,KAAkB6sC,kBAC1DzV,KAEAoV,EAAA3+C,UAAgC+yC,iCAAhC,SACqCjJ,EACnBP,GAEhB,GAAU7yB,GAAOvE,KAAc+nC,cAAQt8C,MAKhC2rC,GAAOj2B,KAAI2rC,IAAQ1V,EAAI,EAAMp3B,KAA6BysC,2BAQ5D,KAJL,GAAcM,GAAO/sC,KAAegtC,eAAU5V,GACrCzyB,EAAWooC,EAAI,EAAI,EAAYA,EAG5BpoC,EAAOJ,EAASI,IAAG,CAC7B,GAAWqyB,GAAOh3B,KAAc+nC,cAAQpjC,EACrC,KAAOqyB,EAAemD,cACjB,MAAmB9/B,IAAQC,QACnC08B,GAEI,MAAmB38B,IAAQC,QACnC,OAEAkyC,EAAA3+C,UAAqBkzC,sBAArB,SACqCpJ,GAE7B,MAAmBt9B,IAAQC,QAC3B0F,KAAqCitC,qCAAKjtC,KAAc+nC,cAEhEt8C,UAEA+gD,EAAA3+C,UAAmCozC,oCAAnC,SACqCtJ,EACnBP,GAEhB,GAAWhgB,GAAOpX,KAAc+nC,cAAQt8C,OAE5ByhD,EAAOltC,KAAegtC,eAAU5V,EAWtC,OAVM8V,GAAK,EACPA,EACV,EAAmBA,GAAU91B,EACnB81B,EACV91B,EAIA81B,IAEyB7yC,GAAQC,QAC3B0F,KAAqCitC,qCAE7CC,KAEAV,EAAA3+C,UAAyCqzC,0CAAzC,SACqCvJ,EACXwJ,GAF1B,GAAAzgC,GAqBCV,KAjBYrH,EAAG,GAAgB44B,IAAY4P,EAAK,GACtCvoC,EAAG,GAAgB24B,IAAY4P,EAAQxzB,OAAoB7B,mBACxD7c,IAcN,OAbF+Q,MAAqB0sC,qBAAe30B,gBAAOpf,EAAMC,GAAE,SAAGg5B,GAClD3kC,EACOk0C,EAAOjvC,OAAI0/B,EAAK3jC,KAE3B,kDACF,IAAW+oC,GAAOt2B,EAAkBmsC,kBAAIjb,EAAkBa,gBACpDxlC,GACU,OAAT+pC,EAEL,qDACI/nC,EAAK6J,KACbk+B,KAEyB38B,GAAQC,QACnCrL,IAEAu9C,EAAA3+C,UAAmC6zC,oCAAnC,SACqC/J,EACvBj5B,GAFd,GAAAgC,GAmDCV,KA7CailC,EAAQvmC,EAAM/H,KACOw2C,EAASlI,EAAOx5C,OAAK,EAMzC2hD,EAAUnI,CACPh/B,IAAcE,cAAYinC,KAC/BA,EAAYA,EAAMlpC,MAC7B,IAEA,IAAWvL,GAAG,GAAgB44B,IAAC,GAAetrB,IAAWmnC,GAAK,GAI5CvL,EAAG,GAAavqB,IAA8BvlB,EAE5DiO,MAAqB0sC,qBAAax0B,aAAC,SAAG0Z,GACxC,GAAgByb,GAAMzb,EAAI3jC,IAAM0I,IAC7B,SAAQsuC,EAAWrgC,WAAayoC,KAQnBA,EAAO5hD,SAAiC0hD,IACtCtL,EAAiBA,EAAI7iC,IAAI4yB,EACzCa,mBAEF,IACQ95B,EAIV,IAAY1J,KAON,OANQ4yC,GAAQhzC,QAAC,SAAOuoC,GAC5B,GAAWJ,GAAOt2B,EAAkBmsC,kBAAUzV,EAC3B,QAAVJ,GACD/nC,EAAK6J,KACbk+B,KAEuB38B,GAAQC,QACnCrL,IAEAu9C,EAAA3+C,UAAqBi0C,sBAArB,SACqCnK,EACXoK,GAExB,GAAgBuL,GAAUvL,EAAQt2C,MAC5BwB,GAAWqgD,EAAI,EAAkD,+CAEvE,IAAkBC,GAAUxL,EAAG,GAAS3K,QACxBoW,EAAOxtC,KAAc+nC,cAAQt8C,OAI7BgiD,EAAOztC,KAAuB4sC,uBAAaW,EAAa,UAClEtgD,GACA+S,KAAc+nC,cAAY0F,GAAQrW,UAAiBmW,EAEvD,0CAKF,KAFA,GAAcZ,GAAK,EACLe,EAAaD,EAAK,EACfd,EAAaW,GAAcI,EAAaF,GAAG,CAC1D,GAAWxW,GAAOh3B,KAAc+nC,cAAa2F,EACpC1W,GAAemD,cACTuT,KAITzgD,EACC+pC,EAAQI,UAAY2K,EAAY4K,GAAQvV,QAE7C,mDACWuV,IAEfe,KAKG,GAAkB,IAAPD,EAAS,CAChB,KAAYC,EAAaF,EAAcE,IAAG,CAC7C,GAAW1W,GAAOh3B,KAAc+nC,cAAa2F,EAC1C,KAAO1W,EAAemD,cAEzB,MAEF,GAAYwT,GAAaD,EAAcD,CACnCztC,MAAc+nC,cAAOhc,OAAW0hB,EACtCE,OAEM,KAAC,GAAKv7C,GAAaq7C,EAAGr7C,EAAas7C,EAAKt7C,IACtC4N,KAAc+nC,cAAG31C,GAAO4N,KAAc+nC,cAAG31C,GAC/CgoC,aAIE,KAAgB,GADNwT,GAAO5tC,KAAsB0sC,qBACvBnhD,EAAO,EAAP22C,EAAOH,EAAPx2C,EAAA22C,EAAOz2C,OAAAF,IAErB,IAAmB,GAFTyrC,GAAAkL,EAAA32C,GACD6rC,EAAQJ,EAASI,QACPvoB,EAAe,EAAfiB,EAAKknB,EAAU+C,UAAflrB,EAAAiB,EAAerkB,OAAAojB,IAAA,CAAjC,GAAcwR,GAAAvQ,EAAAjB,GACR5gB,EAAWoyB,EAAKpyB,GACU,QAA3B+R,KAAiB0xB,kBACnB1xB,KAAiB0xB,iBAAuBrB,uBAC9CpiC,EAEA,IAAS2jC,GAAG,GAAgBL,IAAItjC,EAAWmpC,EACjCwW,GAAaA,EAAO7uC,OAAM6yB,GAIlC,MADF5xB,MAAqB0sC,qBAAckB,EACdvzC,GAC3BC,WAEAkyC,EAAA3+C,UAAmBsiC,oBAAnB,SAA6DuB,GACvD1xB,KAAiB0xB,iBACvBA,GAEA8a,EAAA3+C,UAAWgjC,YAAX,SAC6B91B,EACX9M,GAEhB,GAAS2jC,GAAG,GAAgBL,IAAItjC,EAAK,GACvBskC,EAAOvyB,KAAqB0sC,qBAAkBv0B,kBAAMyZ,EAC5D,OAAmBv3B,IAAQC,QAAIrM,EAAOiE,OAASqgC,GAAYA,EACnEtkC,OAEAu+C,EAAA3+C,UAAuBy0C,wBAAvB,SAC6BvnC,GAQrB,MAN8B,KAA5BiF,KAAc+nC,cAAOt8C,QACrBwB,EACA+S,KAAqB0sC,qBAAU59C,UAGvC,+EACyBuL,GAC3BC,WAOQkyC,EAAA3+C,UAAoCo/C,qCAA5C,SACkBC,GAIZ,IAAC,GAFOj+C,MAEFmD,EAAI,EAAGA,EAAW86C,EAAK96C,IAAG,CAClC,GAAW4kC,GAAOh3B,KAAc+nC,cAAI31C,EAC1B4kC,GAAemD,eACjBlrC,EAAK6J,KACbk+B,GAGI,MACR/nC,IAUQu9C,EAAA3+C,UAAsB++C,uBAA9B,SAA+CxV,EAAgB7uB,GAC7D,GAAW5D,GAAO3E,KAAegtC,eAAU5V,EAKrC,OAJAnqC,GACC0X,GAAK,GAASA,EAAO3E,KAAc+nC,cAAOt8C,OACpB,4BAC3B8c,GAEJ5D,GAWQ6nC,EAAA3+C,UAAcm/C,eAAtB,SAAuC5V,GAClC,MAAiC,KAA5Bp3B,KAAc+nC,cAAOt8C,OAG7B,EAOc2rC,EADWp3B,KAAc+nC,cAAG,GAAS3Q,SAQ7CoV,EAAA3+C,UAAiBg/C,kBAAzB,SAA0CzV,GACxC,GAAWzyB,GAAO3E,KAAegtC,eAAU5V,EACxC,IAAMzyB,EAAI,GAASA,GAAQ3E,KAAc+nC,cAAQt8C,OAC5C,MACR,KAEA,IAAWurC,GAAOh3B,KAAc+nC,cAAQpjC,EAElC,OADA1X,GAAM+pC,EAAQI,UAAYA,EAA+B,6BACnDJ,EAAcmD,cAAO,KACnCnD,GACDwV,KC/bDqB,GAAA,mBAAAC,KAIU9tC,KAAOusB,QAAA,GAAgBf,IAAmB,SAACgB,GAAI,MAACA,GAAc3c,gBAG9D7P,KAAyB27B,0BAAkBzoB,GAAKM,IAEhDxT,KAAey7B,gBAAe,EAK9Bz7B,KAAU4tC,WAAG,GAgGvBxc,IAAA,MA9FE0c,GAAAjgD,UAAK8K,MAAL,SAAyCg/B,GAEjC,MAAmBt9B,IAC3BC,WAEAwzC,EAAAjgD,UAA4Bi1C,6BAA5B,WACQ,MAAK9iC,MACb27B,2BAEAmS,EAAAjgD,UAAkBg1C,mBAAlB,WACQ,MAAK7iC,MACby7B,iBAEAqS,EAAAjgD,UAA4Bk1C,6BAA5B,SACqCpL,EACH3jB,GAG1B,MADFhU,MAA0B27B,0BAAmB3nB,EACxB3Z,GAC3BC,WAEAwzC,EAAAjgD,UAAYm1C,aAAZ,SACqCrL,EACfnV,GAEhBxiB,KAAQusB,QAAItf,IAAUuV,EAAM9jB,MAAa8jB,EAC7C,IAAc1O,GAAY0O,EAAU1O,QAI9B,OAHMA,GAAO9T,KAAiBy7B,kBAC9Bz7B,KAAgBy7B,gBACtB3nB,GACyBzZ,GAC3BC,WAEAwzC,EAAAjgD,UAAes1C,gBAAf,SACqCxL,EACfnV,GAId,MAFFxiB,MAAQusB,QAAOxtB,OAAUyjB,EAAQ9jB,OACjCsB,KAAW4tC,WAAsB3b,sBAAUzP,EAAW1O,UACjCzZ,GAC3BC,WAEAwzC,EAAAjgD,UAAYw1C,aAAZ,SACqC1L,EACvBj5B,GAEZ,GAAe8jB,GAAOxiB,KAAQusB,QAAI10B,IAAO6G,IAAS,IAC5C,OAAmBrE,IAAQC,QACnCkoB,IAEAsrB,EAAAjgD,UAAe01C,gBAAf,SAC6BxoC,EACP0c,EACF3D,GAGZ,MADF9T,MAAW4tC,WAAc/b,cAAKpa,EAAY3D,GACrBzZ,GAC3BC,WAEAwzC,EAAAjgD,UAAkB21C,mBAAlB,SAC6BzoC,EACP0c,EACF3D,GAGZ,MADF9T,MAAW4tC,WAAiB5b,iBAAKva,EAAY3D,GACxBzZ,GAC3BC,WAEAwzC,EAAAjgD,UAA6Bu1C,8BAA7B,SAC6BroC,EACT+Y,GAGZ,MADF9T,MAAW4tC,WAAsB3b,sBAAWne,GACvBzZ,GAC3BC,WAEAwzC,EAAAjgD,UAA0B61C,2BAA1B,SAC6B3oC,EACT+Y,GAElB,GAAkB20B,GAAOzoC,KAAW4tC,WAAgBtb,gBAAWxe,EACzD,OAAmBzZ,IAAQC,QACnCmuC,IAEAqF,EAAAjgD,UAAmBsiC,oBAAnB,SAA+CsS,GACzCziC,KAAW4tC,WAAoBzd,oBACrCsS,IAEAqL,EAAAjgD,UAAWgjC,YAAX,SACoC91B,EAClB9M,GAEV,MAAK+R,MAAW4tC,WAAY/c,YAAI91B,EACxC9M,IACD6/C,KC/GDC,GAAA,mBAAAC,KACUhuC,KAAIqZ,KA8CdzjB,IAAA,MA5CEo4C,GAAAngD,UAAQg2C,SAAR,SACqClM,EACPmM,GAGtB,MADF9jC,MAAKqZ,KAAOrZ,KAAKqZ,KAAO1R,OAAcm8B,EAAI71C,IAAiB61C,GACtCzpC,GAC3BC,WAEA0zC,EAAAngD,UAAWm2C,YAAX,SACqCrM,EACXwJ,GAGlB,MADFnhC,MAAKqZ,KAAOrZ,KAAKqZ,KAAOvR,OAAcq5B,GACjB9mC,GAC3BC,WAEA0zC,EAAAngD,UAAQo2C,SAAR,SACqCtM,EACXwJ,GAElB,MAAmB9mC,IAAQC,QAAK0F,KAAKqZ,KAAIxhB,IACjDspC,KAEA6M,EAAAngD,UAAyBu2C,0BAAzB,SACqCzM,EACvBj5B,GAQZ,IANA,GAAWtN,GAAiB0E,IAIhBmvC,EAAG,GAAeh/B,IAAMvH,EAAK/H,KAAMuN,MAAM,KACvCrD,EAAOb,KAAKqZ,KAAgBvQ,gBAASm8B,GACpCpkC,EAAU0I,WAAG,CACpB,GAAAsF,GAAAhO,EAA6CwI,UAA3Cpb,EAAA4gB,EAAG5gB,IAAEgnB,EAAApG,EAAuCxgB,KACjD,KAAOqQ,EAAK/H,KAAWiO,WAAI3W,EAAO0I,MAErC,KACYse,aAAoBxO,KAAS/H,EAAQyR,QAAW8E,KACnD7jB,EAAUA,EAAOuW,OAASsN,EAAIhnB,IACvCgnB,IAEI,MAAmB5a,IAAQC,QACnClJ,IACD48C,KC1CDC,GAAA,mBAAAC,KAQUluC,KAAcmuC,kBACdnuC,KAAmB8nC,oBAAG,GAAgCiG,IACtD/tC,KAAUspC,WAAG,GAAuBuE,IAEpC7tC,KAAOslC,SAwCjB,QAtCE4I,GAAArgD,UAAK8K,MAAL,WAIQ,MAHA1L,IAAM+S,KAAQslC,QAAuC,qCACvDtlC,KAAQslC,SAAQ,EAEN9gB,GAAA,EAChBlqB,WAEA4zC,EAAArgD,UAAQ+3C,SAAR,WAIQ,MAFA34C,GAAK+S,KAAQslC,QAA+C,6CAC9DtlC,KAAQslC,SAAS,EACP9gB,GAAA,EAChBlqB,WAEA4zC,EAAArgD,UAAgBm4C,iBAAhB,SAA2BrM,GACzB,GAASyU,GAAOpuC,KAAemuC,eAAKxU,EAAUd,QAKxC,OAJKuV,KACJA,EAAG,GAA0B7B,IAC9BvsC,KAAemuC,eAAKxU,EAASd,SACnCuV,GAEFA,GAEAF,EAAArgD,UAAao4C,cAAb,WACQ,MAAKjmC,MACbspC,YAEA4E,EAAArgD,UAAsBq4C,uBAAtB,WACQ,MAAKlmC,MACb8nC,qBAEAoG,EAAArgD,UAAc2pC,eAAd,SACgBjvB,EAC2D49B,GAGnE,MADDh7C,GAvD2B,oBAuDM,wBAAUod,GAChC49B,EAAC,GAAmCkI,KACtDjf,aACD8e,KAGDG,GAAA,mBAAAA,MAAsE,MAACA,MC7DvEC,GAAA,mBAAAC,KACWvuC,KAAO8vB,SAmBlB,QAjBEye,GAAA1gD,UAAgBoiC,iBAAhB,SAA6CC,KAI7Cqe,EAAA1gD,UAAmBuiC,oBAAnB,SAAgDF,KAIhDqe,EAAA1gD,UAAsBwiC,uBAAtB,SAAuCpiC,KAIvCsgD,EAAA1gD,UAAcyiC,eAAd,SACoCv1B,GAE5B,MAAmBV,IAAQC,QACnCpE,OACDq4C,KCrBDC,GAAA,WAKE,QAAAC,KAAA,GAAA/tC,GAKCV,IAJKA,MAAQwvB,QAAA,GAAchL,IAAA,EAAC,SAAqBlqB,EAAkBC,GAC5DmG,EAAQpG,QAAWA,EACnBoG,EAAOnG,OACbA,IAEJ,MAACk0C,MCVDC,GAAA,WAGE,QAAAC,GAMyCC,EAKDC,EAMHC,GAXlB9uC,KAAc4uC,eAAQA,EAKtB5uC,KAAa6uC,cAAQA,EAMrB7uC,KAAU8uC,WAAQA,EAE/B9uC,KACN+uC,QA2DF,MAlDEJ,GAAA9gD,UAAKkhD,MAAL,WACM/uC,KAAcgvC,cACpB,GAMAL,EAAA9gD,UAAUohD,WAAV,WACMjvC,KAAcgvC,cAAOhvC,KAC3B8uC,YAMAH,EAAA9gD,UAAcqhD,eAAd,WACE,GAASC,GAAG,GAAqBX,IAIVY,EAAOpvC,KAAcgvC,cAAOhvC,KAAiBqvC,eAsB9D,OArBErvC,MAAcgvC,cAAK,GACtB7jD,EAlE4B,qBAoE7B,mBAAoCikD,EAAM,oBACpBpvC,KAAcgvC,cAExC,QACU/lB,WAAC,WACNkmB,EACL70C,WAAsB80C,GAIlBpvC,KAAcgvC,eAAQhvC,KAAe6uC,cACjC7uC,KAAcgvC,cAAOhvC,KAAgB4uC,iBACvC5uC,KAAcgvC,cAAOhvC,KAC3B4uC,gBACQ5uC,KAAcgvC,cAAOhvC,KAAY8uC,aACnC9uC,KAAcgvC,cAAOhvC,KAC3B8uC,YAEUK,EACZ3f,SAGQmf,EAAA9gD,UAAawhD,cAArB,WACQ,OAAMluC,KAASE,SAAO,IAAOrB,KACrCgvC,eACDL,KzEo+WGW,GAA8BtvC,MAAQA,KAAKD,WAAa,WACxD,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC5FD,EAAED,UAAYE,IACb,SAAUD,EAAGC,GACd,IAAK,GAAIC,KAAKD,GACNA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAG1C,OAAO,UAAUF,EAAGC,GAEhB,QAASE,KACLP,KAAK9O,YAAckP,EAFvBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,S4DnjXvF,SAA0BoyB,GAMxBA,IAAA,WAAO,UAOPA,IAAA,QAAI,OAMJA,IAAA,QAAI,OAOJA,IAAA,SAAK,QAQLA,IAAA,WAAO,UAKPA,IAAA,WACF,WAxC0BA,YA+D1B,IjCWC4c,IiCX6BC,GAAQ,IAGZC,GAAK,IAEXC,GAAO,IAiC3BC,GAAA,WAaE,QAAAC,GAC2BxB,EACOyB,EACgBC,EAC1BhjB,EAEMijB,GALpB/vC,KAAKouC,MAAYA,EACfpuC,KAAU6vC,WAAYA,EACxB7vC,KAAmB8vC,oBAAqBA,EATxC9vC,KAAMgwC,OAA8C,KAIpDhwC,KAAQ8sB,SAA6B,KAUzC9sB,KAAQiwC,QAAG,GAAsBvB,IAChBqB,GAAiDP,GACtDE,GAEdD,IACEzvC,KAAMka,MAAwByY,GAASud,QACvClwC,KAAS8sB,SACfA,EA+NF,MAtNE8iB,GAAA/hD,UAASsiD,UAAT,WACS,MACDnwC,MAAMka,QAA0ByY,GAAQyd,SACxCpwC,KAAMka,QAA0ByY,GAAK0d,MACrCrwC,KAAMka,QAA0ByY,GAExC2d,MAMAV,EAAA/hD,UAAM0iD,OAAN,WACQ,MAAKvwC,MAAMka,QAA0ByY,GAC7C2d,MASAV,EAAA/hD,UAAK8K,MAAL,WACK,GAAKqH,KAAMka,QAA0ByY,GAAO3lC,MAG/C,WAFMgT,MAAkBwwC,gBAIlBvjD,GAAK+S,KAAMka,QAA0ByY,GAAQud,QAAqB,mBAEpElwC,KACNywC,QAQAb,EAAA/hD,UAAI6iD,KAAJ,WAEM1wC,KAAMka,MAAwByY,GAASge,QAIvC3wC,KAAS8sB,SAAQ,KAII,OAAjB9sB,KAAOgwC,SACThwC,KAAOgwC,OAAS3qB,QAChBrlB,KAAOgwC,OACb,OAWFJ,EAAA/hD,UAAc+iD,eAAd,WACQ3jD,GAAM+S,KAAYmwC,YAAiD,+CAErEnwC,KAAMka,MAAwByY,GAASud,QACvClwC,KAAQiwC,QACdlB,SAiBQa,EAAA/hD,UAAI4iD,KAAZ,cAAA/vC,GA8BCV,IA7BO/S,GACA+S,KAAMka,QAA0ByY,GAAQud,QAE5C,oCAEElwC,KAAMka,MAAwByY,GAAM0d,KAEpCrwC,KAAoB8vC,oBAASe,UAAyB,GAAKzjB,KAC7D,SAAKvyB,GAIC6F,EAAYowC,YAClBj2C,IACA,SAAapO,GACPiU,EAAM0tC,MAAS2C,SAAC,WACf,GAAKrwC,EAAMwZ,QAA0ByY,GAASge,QAAE,CAEjD,GAAcK,GAAG,GAAkBtjD,IAC7BC,GAAQ8G,QACkB,+BAAQhI,EACtCM,QACI,OAAK2T,GAAkBuwC,kBAC/BD,GACQ,MAAQxsB,IAAA,EAChBlqB,eAMAs1C,EAAA/hD,UAAWijD,YAAnB,SAAuCj2C,GAAvC,GAAA6F,GAgDCV,IA/CI,IAAKA,KAAMka,QAA0ByY,GAASge,QAA9C,CAKG1jD,EACA+S,KAAMka,QAA0ByY,GAAK0d,KAEzC,6CAIF,IAA0Ba,GAAG,SAAwBziD,GAC/CiS,EAAM0tC,MAAS2C,SAAC,WAEf,MAAKrwC,GAAMwZ,QAA0ByY,GAASge,QAEjDliD,IACgB+1B,GAAA,EAChBlqB,YAKuB,QAAnB0F,KAAS8sB,WACX9sB,KAAOgwC,OAAOhwC,KAASmxC,SAAQt2C,GAC/BmF,KAAOgwC,OAAO/qB,OAAC,WACGisB,EAAC,WAMb,MALAjkD,GACAyT,EAAMwZ,QAA0ByY,GAAK0d,KACM,gDAAO3vC,EACtDwZ,OACExZ,EAAMwZ,MAAwByY,GAAM2d,KAC7B5vC,EAAUosB,SACvB7H,aAEEjlB,KAAOgwC,OAAQ7qB,QAAC,SAAsB14B,GACpBykD,EAAC,WACb,MAAKxwC,GAAkBuwC,kBAC/BxkD,OAEEuT,KAAOgwC,OAAU5qB,UAAC,SAAiB/5B,GACjB6lD,EAAC,WACb,MAAKxwC,GAAU0kB,UACvB/5B,UAKEukD,EAAA/hD,UAAc2iD,eAAtB,cAAA9vC,GAsBCV,IArBO/S,GACA+S,KAAMka,QAA0ByY,GAAM3lC,MAE1C,gDACEgT,KAAMka,MAAwByY,GAASyd,QAEvCpwC,KAAQiwC,QAAiBf,iBAAK9hB,KAAC,WAG7B1sB,EAAM0tC,MAAS2C,SAAC,WACf,MAAKrwC,GAAMwZ,QAA0ByY,GAASge,QAEjCnsB,GAAA,EAChBlqB,WAEIoG,EAAMwZ,MAAwByY,GAASud,QACvCxvC,EAAS/H,QACP1L,EAAKyT,EAAYyvC,YAA0C,wCACnD3rB,GAAA,EAChBlqB,gBAIIs1C,EAAA/hD,UAAiBojD,kBAAzB,SAAgDxkD,GAoBxC,MAnBAQ,GAAK+S,KAAYmwC,YAAqD,mDACzEhlD,EAxV4B,mBAwVZ,qBAA8BsB,GAE7CuT,KAAOgwC,OAAQ,KAMfhwC,KAAMka,MAAwByY,GAAO3lC,MAEhCP,GAASA,EAAK6H,OAAS3G,GAAoBgH,qBAC/CxJ,EAnW0B,mBAsW3B,mEACE6U,KAAQiwC,QACdhB,cAEWjvC,KAAU8sB,SAAQ3H,QAC/B14B,IACDmjD,KAqBDwB,GAAA,SAAA3wC,GAKE,QAAA2wC,GACoCxnB,EACjBwkB,EACKyB,EACU7zC,EACOojC,EACVtS,EACDijB,GAP9B,GAAArvC,GASED,EAAAtS,KAAA6R,KAAWouC,EAAYyB,EAAa7zC,EAAU8wB,EAAsBijB,IACrE/vC,I5Dk8WK,O4D38WIU,GAAYkpB,aAAcA,EAI1BlpB,EAAU0+B,WAAqBA,EAKzC1+B,EAgDF,MA/D4C4uC,IAAA8B,EAI3C3wC,GAaW2wC,EAAAvjD,UAAQsjD,SAAlB,SACqBt2C,GAEb,MAAKmF,MAAW6vC,WAAWjoB,WAAS,SAC5C/sB,IAEUu2C,EAAAvjD,UAASu3B,UAAnB,SAAwDisB,GAElDrxC,KAAQiwC,QAASlB,OAErB,IAAiBp0B,GAAO3a,KAAWo/B,WAAgBvf,gBAAmBwxB,GACxDnzC,EAAO8B,KAAWo/B,WAA0Bjf,0BAExDkxB,EACI,OAAKrxC,MAAU8sB,SAAcwkB,cAAY32B,EACjDzc,IAQAkzC,EAAAvjD,UAAK0jD,MAAL,SAA0B/uB,GACxB,GAAapoB,KACNA,GAASoJ,SAAOxD,KAAWo/B,WAAmB7hB,kBAC9CnjB,EAAUo3C,UAAOxxC,KAAWo/B,WAAStc,SAAYN,EAExD,IAAYivB,GAAOzxC,KAAWo/B,WAAsB7c,sBAAYC,EACrDivB,KACFr3C,EAAOq3C,OAChBA,GAEIzxC,KAAQgwC,OAAK1qB,KACnBlrB,IAMAg3C,EAAAvjD,UAAO6jD,QAAP,SAA0B59B,GACxB,GAAa1Z,KACNA,GAASoJ,SAAOxD,KAAWo/B,WAAmB7hB,kBAC9CnjB,EAAau3C,aAAY79B,EAC5B9T,KAAQgwC,OAAK1qB,KACnBlrB,IACDg3C,GAAAzB,IAqCDiC,GAAA,SAAAnxC,GAOE,QAAAoxC,GACoCjoB,EACjBwkB,EACKyB,EACU7zC,EACOojC,EACVtS,EACDijB,GAP9B,GAAArvC,GASED,EAAAtS,KAAA6R,KAAWouC,EAAYyB,EAAa7zC,EAAU8wB,EAAsBijB,IACrE/vC,I5D65WK,O4Dt6WIU,GAAYkpB,aAAcA,EAI1BlpB,EAAU0+B,WAAqBA,EAPjC1+B,EAAkBoxC,GAAS,EAYnCpxC,EAoGF,MArH2C4uC,IAAAuC,EAI1CpxC,GA6BCvS,OAAAwR,eAAImyC,EAAAhkD,UAAiB,qB5Do5WfgK,I4Dp5WN,WACQ,MAAKmI,MACb8xC,G5Dq5WMjvC,YAAY,EACZC,c4Dt5WL,IAGD+uC,EAAAhkD,UAAK8K,MAAL,WACMqH,KAAmB8xC,GAAS,EAChCrxC,EAAA5S,UAAW8K,MAAAxK,KACb6R,OAEU6xC,EAAAhkD,UAAQsjD,SAAlB,SACqBt2C,GAEb,MAAKmF,MAAW6vC,WAAWjoB,WAAQ,QAC3C/sB,IAEUg3C,EAAAhkD,UAASu3B,UAAnB,SAAoD2sB,GAQ/C,GANG9kD,IACW8kD,EAAYvX,YAE3B,+CACEx6B,KAAgBg7B,gBAAgB+W,EAAcvX,YAEzCx6B,KAAoB8xC,EAQrB,CAIF9xC,KAAQiwC,QAASlB,OAErB,IAAa39C,GAAO4O,KAAWo/B,WAAiBne,iBACjC8wB,EACbC,cACiBzX,EAAOv6B,KAAWo/B,WAAYviB,YAClCk1B,EACbE,WACI,OAAKjyC,MAAU8sB,SAAiBolB,iBAAc3X,EACtDnpC,GAdQ,MALAnE,IACU8kD,EAAaC,cAA2C,IAA1BD,EAAaC,aAAOvmD,OAEhE,sCACEuU,KAAmB8xC,GAAQ,EACpB9xC,KAAU8sB,SACvBqlB,uBAqBFN,EAAAhkD,UAAcukD,eAAd,WACQnlD,EAAK+S,KAASuwC,SAAiD,+CAC/DtjD,GAAM+S,KAAmB8xC,EAAiC,8BAGhE,IAAa13C,KACNA,GAASoJ,SAAOxD,KAAWo/B,WAAmB7hB,kBACjDvd,KAAQgwC,OAAK1qB,KACnBlrB,IAGAy3C,EAAAhkD,UAAcwkD,eAAd,SAAoCtY,GAApC,GAAAr5B,GAmBCV,IAlBO/S,GAAK+S,KAASuwC,SAAiD,+CAC/DtjD,EACA+S,KAAmB8xC,EAEvB,uDACI7kD,EACA+S,KAAgBg7B,gBAAOvvC,OAAI,EAE/B,2CAEF,IAAa2O,IAGAogC,YAAMx6B,KAAuBg7B,gBAClCsX,OAAAvY,EAAe/tC,IAAC,SAAQq0B,GAAI,MAAI3f,GAAW0+B,WAAWhf,WAAUC,KAGpErgB,MAAQgwC,OAAK1qB,KACnBlrB,IACDy3C,GAAAlC,Ic1kBD4C,GAAA,WACE,QAAAC,GACoC5oB,EACTwkB,EACKyB,EACU7zC,EACDojC,EACH2Q,GAL5B/vC,KAAY4pB,aAAcA,EAC1B5pB,KAAKouC,MAAYA,EACjBpuC,KAAU6vC,WAAYA,EACtB7vC,KAAWhE,YAAqBA,EAChCgE,KAAUo/B,WAAqBA,EAC/Bp/B,KAAmB+vC,oBAC1BA,EAwEL,MAtESyC,GAAA3kD,UAAwB4kD,yBAA/B,SAC+B3lB,GAEvB,MAAC,IAAyB8kB,IAC1B5xC,KAAa4pB,aACb5pB,KAAMouC,MACNpuC,KAAW6vC,WACX7vC,KAAYhE,YACZgE,KAAWo/B,WACPtS,EACJ9sB,KAER+vC,sBAEOyC,EAAA3kD,UAAwB6kD,yBAA/B,SAC+B5lB,GAEvB,MAAC,IAA0BskB,IAC3BpxC,KAAa4pB,aACb5pB,KAAMouC,MACNpuC,KAAW6vC,WACX7vC,KAAYhE,YACZgE,KAAWo/B,WACPtS,EACJ9sB,KAER+vC,sBAEAyC,EAAA3kD,UAAMiqC,OAAN,SAA4BiC,GAA5B,GAAAr5B,GAUCV,KATa2yC,GACJL,OAAAvY,EAAe/tC,IAAC,SAAC04C,GAAI,MAAIhkC,GAAW0+B,WAAWhf,WAAGskB,KAEpD,OAAA1kC,MAAe4yC,UACX,SAETD,GAAKvlB,KAAC,SAA6BylB,GAC5B,MAAKnyC,GAAW0+B,WAAiBne,iBAAS4xB,EAClDb,iBAGFQ,EAAA3kD,UAAMilD,OAAN,SAA0Br7B,GAA1B,GAAA/W,GAqBCV,KApBa2yC,GACD72C,UAAA2b,EAAUzrB,IAAC,SAACwc,GAAI,MAAI9H,GAAW0+B,WAAOjiB,OAAG3U,KAE9C,OAAAxI,MAAe4yC,UACT,WAEXD,GAAKvlB,KAAC,SAA0CylB,GAC/C,GAAQx5B,GAAsBzjB,GACtBi9C,GAAQhkD,QAAC,SAAK+xB,GACpB,GAASriB,GAAOmC,EAAW0+B,WAAkB9f,kBAAQsB,EACjDvH,GAAOA,EAAO1R,OAAIpJ,EAAItQ,IAC5BsQ,IACA,IAAYtP,KAMN,OALFwoB,GAAQ5oB,QAAC,SAAGZ,GACd,GAASsQ,GAAO8a,EAAIxhB,IAAM5J,EACpBhB,KAAMsR,EAAyC,wCAAQtQ,GACvDgB,EAAK6J,KACbyF,KAEFtP,KAIMujD,EAAA3kD,UAAS+kD,UAAjB,SAAiCrsB,EAAcnsB,GAA/C,GAAAsG,GAKCV,IAHO,OAAAA,MAAiBhE,YAAS60C,UAAyB,GAAKzjB,KAAC,SAAKvyB,GAC5D,MAAK6F,GAAWmvC,WAAOvpB,OAAQC,EAASnsB,EAChDS,MAEH23C,KCnGDO,GAAA,WAME,QAAAC,GAAwCC,GAApBjzC,KAASizC,UAAWA,EAJhCjzC,KAAYkzC,aAAwBl9C,KACpCgK,KAAS+5B,aACT/5B,KAASmzC,WAE0B,EAoH7C,MAlHUH,GAAAnlD,UAAaulD,cAArB,SAAwC70C,GACtC,GAAc80C,GAAM90C,EAASoI,OACtBpI,aAAuB8I,MAElBgsC,EAAkBngC,GAC9BK,gBACA,IAAqB+/B,GAAOtzC,KAAakzC,aAAIr7C,IAAI0G,EAAMtQ,IACpD,IAA0B,OAAVqlD,GACd,IAAYD,EAAOnhD,OAAkBohD,GAEtC,KAAM,IAAkB5lD,IAClBC,GAAQwH,QAGhB,mDAEI6K,MAAakzC,aAAOlzC,KAAakzC,aAAOvrC,OAAIpJ,EAAItQ,IACtDolD,IAGFL,EAAAnlD,UAAMilD,OAAN,SAA0Br7B,GAA1B,GAAA/W,GAeCV,IAdI,OAAKA,MAAWmzC,UACH3uB,GAAA,EAAOjqB,OAGvB,sCACQyF,KAAU+5B,UAAOtuC,OAAK,EACd+4B,GAAA,EAAOjqB,OAGvB,kDACMyF,KAAeizC,UAAOH,OAAMr7B,GAAK2V,KAAC,SAAI/T,GAEpC,MADFA,GAAQxqB,QAAC,SAAG0P,GAAI,MAAImC,GAAc0yC,cAAK70C,KAE7C8a,KAGM25B,EAAAnlD,UAAKkpC,MAAb,SAAmCgD,GAC9B,GAAK/5B,KAAWmzC,UACjB,KAAM,IAAkBzlD,IAClBC,GAAoBuH,oBAG5B,qCACI8K,MAAU+5B,UAAO/5B,KAAU+5B,UAAOztC,OACxCytC,IAMQiZ,EAAAnlD,UAAY6nB,aAApB,SAAqCznB,GACnC,GAAa0Y,GAAO3G,KAAakzC,aAAIr7C,IAAM5J,EACxC,OAAS0Y,GACSiO,GAAWE,WAChCnO,GACqBiO,GACrBO,MAMM69B,EAAAnlD,UAAqB0lD,sBAA7B,SAA8CtlD,GAC5C,GAAa0Y,GAAO3G,KAAakzC,aAAIr7C,IAAM5J,EACxC,IAAQ0Y,GAAWA,EAAOzU,OAAgBghB,GAAkBK,iBAE7D,KAAM,IAAkB7lB,IAClBC,GAAoBuH,oBAG5B,8CAAM,OAAayR,GAEEiO,GAAWE,WAChCnO,GAGqBiO,GAAOG,QAC5B,IAGFi+B,EAAAnlD,UAAGof,IAAH,SAAoBhf,EAAqB2Y,GACnC5G,KAAM+2B,MAAKnwB,EAAY4sC,YAAIvlD,EAAM+R,KAAa0V,aACpDznB,MAEA+kD,EAAAnlD,UAAMomB,OAAN,SAAuBhmB,EAAwB2Y,GACzC5G,KAAM+2B,MAAKnwB,EAAY4sC,YAAIvlD,EAAM+R,KAAsBuzC,sBAC7DtlD,MAEA+kD,EAAAnlD,UAAMkR,OAAN,SAAuB9Q,GACjB+R,KAAM+2B,OAAE,GAAkB/f,IAAI/oB,EAAM+R,KAAa0V,aAASznB,MAG1D+R,KAAakzC,aAAOlzC,KAAakzC,aAAOvrC,OACvC1Z,EACYilB,GAEnBK,kBAEAy/B,EAAAnlD,UAAMiqC,OAAN,cAAAp3B,GAcCV,KAbcyzC,EAAOzzC,KAAckzC,YAK/B,OAHClzC,MAAU+5B,UAAQlrC,QAAC,SAAQwxB,GACpBozB,EAAYA,EAAO3rC,OAASuY,EACvCpyB,OACcwlD,EAAW3kD,UAKnBkR,KAAeizC,UAAOnb,OAAK93B,KAAW+5B,WAAK3M,KAAC,WAC5C1sB,EAAUyyC,WAChB,IANgB3uB,GAAA,EAAOjqB,OACdvN,MAET,gEAKHgmD,KCnEDU,GAAA,WA6CE,QAAAC,GACoC/pB,EACJgqB,EAKApe,EAEFyd,EACkCY,GATtD7zC,KAAY4pB,aAAcA,EAC1B5pB,KAAU4zC,WAAYA,EAKtB5zC,KAAUw1B,WAAYA,EAEtBx1B,KAASizC,UAAWA,EACpBjzC,KAAkB6zC,mBAAoCA,EAtDxD7zC,KAAa8zC,iBACb9zC,KAAa+zC,cAA4Bna,GAWzC55B,KAAaua,iBAgBbva,KAAsBwa,0BAEtBxa,KAAuBg0C,2BASvBh0C,KAAsBi0C,uBAAcjqB,GAAS0C,QAG7C1sB,KAAmBk0C,oBAaxB,EA2lBL,MAllBEP,GAAA9lD,UAAK8K,MAAL,cAAA+H,GAKCV,IAJO,OAAAA,MAAoBm0C,eAAK/mB,KAAC,WAExB,MAAK1sB,GACb42B,uBAGMqc,EAAA9lD,UAAuBumD,wBAA/B,WACMp0C,KAA8Bq0C,8BAAYrqB,GAChDsqB,UAEQX,EAAA9lD,UAAuB0mD,wBAA/B,WAOMv0C,KAAoBk0C,oBAAK,EACzBl0C,KAA8Bq0C,8BAAYrqB,GAChD0C,UAEQinB,EAAA9lD,UAA6B2mD,8BAArC,WAIUx0C,KAAuBi0C,yBAAgBjqB,GAASsqB,QAClDt0C,KACNu0C,4BACMv0C,KAAuBk0C,qBAnHQ,GAqH7Bl0C,KAA8Bq0C,8BAAYrqB,GAChDqE,SAIIslB,EAAA9lD,UAA6BwmD,8BAArC,SAA8D5nB,GAC5D,GAAegoB,GAAOz0C,KAAuBi0C,yBAAiBxnB,CAC1DzsB,MAAuBi0C,uBAAexnB,EAC5BgoB,GACRz0C,KAAmB6zC,mBACzBpnB,IAGMknB,EAAA9lD,UAAYsmD,aAApB,cAAAzzC,GAiBCV,IAHO,OAbFA,MAAY00C,YAAA10C,KAAiBizC,UAAyBP,0BAClDztB,OAAMjlB,KAAkB20C,kBAAK59C,KAAMiJ,MAClCmlB,QAAMnlB,KAAmB40C,mBAAK79C,KAAMiJ,MAC9BsxC,cAAMtxC,KAAoB60C,oBAAK99C,KAC3CiJ,QACCA,KAAY80C,YAAA90C,KAAiBizC,UAAyBR,0BAClDxtB,OAAMjlB,KAAkB+0C,kBAAKh+C,KAAMiJ,MAClCmlB,QAAMnlB,KAAmBg1C,mBAAKj+C,KAAMiJ,MACxBmyC,oBAAMnyC,KAAyBi1C,yBAAKl+C,KAAMiJ,MAC7CkyC,iBAAMlyC,KAAiBkyC,iBAAKn7C,KAC3CiJ,QAGGA,KAAgBw1B,WAAqB2K,qBAAK/S,KAAC,SAAKvyB,GAChD6F,EAAYo0C,YAAgB9Z,gBAClCngC,KAGF84C,EAAA9lD,UAAQ+3C,SAAR,WAMQ,MALHz6C,GAhKuB,cAgKuB,8BAC7C6U,KAA2Bk1C,0BAC3Bl1C,KAAY80C,YAAQpE,OACpB1wC,KAAY00C,YAAQhE,OAEVlsB,GAAA,EAAQlqB,YACxB/L,KAGAolD,EAAA9lD,UAAMk7B,OAAN,SAA2BvG,GACnBv1B,GACKe,EAAcgS,KAAcua,cAAWiI,EAAU1O,UAE1D,0CAEE9T,KAAcua,cAAUiI,EAAU1O,UAAa0O,EAC3CxiB,KAAY00C,YAAUnE,SACxBvwC,KAAiBm1C,iBACvB3yB,GAAgBxiB,KAAY00C,YAAavE,aAEnCnwC,KACNo1C,oBAIFzB,EAAA9lD,UAAQw/B,SAAR,SAA2BvZ,GACnB7mB,EACIe,EAAcgS,KAAcua,cAAWzG,GAE/C,+CACoB9T,KAAcua,cAAWzG,SACpC9T,MAAcua,cAAWzG,GAC5B9T,KAAY00C,YAAUnE,UACxBvwC,KAAmBq1C,mBACzBvhC,IAOM6/B,EAAA9lD,UAAgBsnD,iBAAxB,SAA6C3yB,GACvCxiB,KAA2Bs1C,2BAAU9yB,EAAW1O,UAChD9T,KAAY00C,YAAMnD,MACxB/uB,IAOQmxB,EAAA9lD,UAAkBwnD,mBAA1B,SAA6CvhC,GACvC9T,KAA2Bs1C,2BAAWxhC,GACtC9T,KAAY00C,YAAQhD,QAC1B59B,IAMQ6/B,EAAA9lD,UAA0BynD,2BAAlC,SAAqDxhC,GAE/C9T,KAAuBwa,uBAAU1G,IAC9B9T,KAAuBwa,uBAAU1G,IAAM,GAChD,GAEQ6/B,EAAA9lD,UAAgBunD,iBAAxB,WACQnoD,GAAM+S,KAAY00C,YAAYvE,YAAwC,sCACtEljD,EACA+S,KAAyBu1C,yBAE7B,oEACEv1C,KAAY00C,YAClB/7C,SAMQg7C,EAAA9lD,UAAsB0nD,uBAA9B,WACQ,OAAUzmD,EAAakR,KAC/Bua,gBAEQo5B,EAAA9lD,UAAuBqnD,wBAA/B,WAKMl1C,KAAwBg0C,2BACxBh0C,KAAuBwa,2BAGrBm5B,EAAA9lD,UAAiB8mD,kBAAzB,cAAAj0C,GAOCV,IADO,OAHExR,GAAmBwR,KAAcua,cAAE,SAASzG,EAAW0O,GACzD9hB,EAAiBy0C,iBACvB3yB,KACcgC,GAAA,EAChBlqB,WAEQq5C,EAAA9lD,UAAkB+mD,mBAA1B,SAAuDnoD,GAa/C,MAZFuT,MAA2Bk1C,0BAGvBl1C,KAA0Bu1C,0BAC5Bv1C,KAAiCw0C,gCACjCx0C,KACNo1C,oBAIMp1C,KACNu0C,0BACc/vB,GAAA,EAChBlqB,WAEQq5C,EAAA9lD,UAAmBgnD,oBAA3B,SAC0Bl6B,EACQ3G,GAK7B,GAFChU,KAA2Bo0C,0BAGlBz5B,YAA6BX,KAC7BW,EAAMT,QAA2Bf,GAAQ1hB,SACzCkjB,EACZP,MAGO,MAAKpa,MAAkBw1C,kBAC/B76B,EAKG,IADC3a,KAAwBg0C,wBAAKl7C,KAAc6hB,IAE7B3G,EAAO9hB,OAAgBghB,GAAKM,MAC7BQ,EAAUvQ,UACnBzD,KAAWw1B,WAChBsN,iCACF,EAAE,CACD,GAAalY,GAAO5qB,KAAyBg0C,uBAEvC,OADFh0C,MAAwBg0C,2BACjBh0C,KAAuBy1C,uBAAgBzhC,EACpD4W,GACQ,MAAQpG,IAAA,EAChBlqB,WAQMq5C,EAAA9lD,UAAsB4nD,uBAA9B,SACkCzhC,EACV4W,GAFxB,GAAAlqB,GAyHCV,KArHiB01C,EAAG,GAAyBr7B,IAC3BrG,EACXhU,KAAcua,cACdva,KACJwa,uBACQk7B,GAAW36B,WAAU6P,EAC/B,IAAiBoN,GAAa0d,EAAqBz6B,mBAE/Cjb,MAAuBwa,uBAAak7B,EAAwBl7B,sBAEhE,IAAc+V,KAwFR,OAtFE/hC,GACIknD,EAAiBj7B,iBAC3B,SAAmB3G,EAAyB3O,GAC1C,GAAeqd,GAAO9hB,EAAc6Z,cAAWzG,EAC5C,IAAY0O,EAAZ,CAIH,GAAW9jB,GAAY8jB,EAAO9jB,KAC3B,IAAMA,EAAmB9C,kBACvB,GAAoB,IAAbuJ,EAAMiS,MAAS,CAOvB,GAASnpB,GAAG,GAAegY,IAAMvH,EAAO/H,MACxBg/C,EAAG,GAActuC,IAAIpZ,EAAmB+lB,EAC7CgkB,GAAkBnf,kBAC/B88B,OACQ1oD,GACc,IAAZkY,EAAMiS,MACmC,gDAASjS,EAE5DiS,WACM,CAEN,GAAaoY,GAAA9uB,EAAkB80B,WACVgB,mBAAU1iB,GACxBsZ,KAAC,SAAawoB,GACd,GAAY5d,EAAcrf,cAAW7E,GAAE,CACxC,GAAaiF,GAAcif,EAAcrf,cAAU7E,GAASiF,OACvC,QAAVA,IACEA,YAA0BO,IACtBs8B,EAAU78B,EAAcU,cACvCm8B,IACQ3oD,EACG8rB,YAAwBC,IACmC,mEAElED,GACW68B,EAAU78B,EACzBjd,YAID,GAAc85C,EAAKrxC,OAAWY,EAAOiS,MAAE,CAI7B4gB,EAA8Blf,8BAAWhF,EAIpD,IAAkB+hC,GAAG,GAAajiC,IAC3BlV,EACGoV,EACC0O,EACTzO,QACErT,GAAc6Z,cAAUzG,GAAgB+hC,EAMxCn1C,EAAmB20C,mBAAWvhC,EAOlC,IAAsBgiC,GAAG,GAAaliC,IAC/BlV,EACGoV,EACI/I,GACZ6X,wBACEliB,GAAiBy0C,iBACvBW,KAEIvlB,GAAKz3B,KACf02B,OAIEhL,GAAA,EAAY+K,IAAUgB,GAAKnD,KAAC,WAiB1B,MAdE5+B,GAA0BwpC,EAAcrf,cAAE,SAAS7E,EAAQzd,GAC9D,GAAOA,EAAYC,YAAO7K,OAAK,EAAE,CAClC,GAAe+2B,GAAO9hB,EAAc6Z,cAAWzG,EAEjC0O,KACR9hB,EAAc6Z,cAAUzG,GAAA0O,EAAmBvO,QAClC3d,YAAQD,EAAYC,YAChB0d,gBAAQ3d,EAE3B2d,sBAKOtT,EAAW4rB,WAAiByL,iBACzCC,MAIM2b,EAAA9lD,UAAiB2nD,kBAAzB,SAAwD76B,GAAxD,GAAAja,GAgBCV,IAfO/S,KAAc0tB,EAAMP,MAA2C,wCACrE,IAAW3tB,GAAckuB,EAAQP,MACjB4xB,EAAUxnB,GAAA,EAAWlqB,SAY/B,OAXKqgB,GAAUR,UAAQtrB,QAAC,SAAQilB,GACxBk4B,IAAoB5e,KAAC,WAC5B,MAASp/B,GAAc0S,EAAc6Z,cAAYzG,UACvCpT,GAAc6Z,cAAWzG,GACzBpT,EAAW4rB,WAAa4L,aAASpkB,EAC9CrnB,IAEgB+3B,GAAA,EAChBlqB,cAIN0xC,GAOA2H,EAAA9lD,UAAiBypC,kBAAjB,cAAA52B,GAeCV,IAdI,OAAMA,MAAqB+1C,oBAGtB/1C,KAAgBw1B,WACF+V,kBAAKvrC,KAAe+zC,eACjC3mB,KAAC,SAAK4J,GACN,MAAgB,QAAVA,EACOxS,GAAA,EAChBlqB,WACMoG,EAAOo3B,OAAQd,GACRt2B,EACb42B,uBAVU9S,GAAA,EAChBlqB,WAwBFq5C,EAAA9lD,UAAiBkoD,kBAAjB,WACQ,MAAK/1C,MAAc8zC,cAAOroD,OAxeN,IA4e5BkoD,EAAA9lD,UAAiBmoD,kBAAjB,WACQ,MAAKh2C,MAAc8zC,cAC3BroD,QAOQkoD,EAAA9lD,UAAMiqC,OAAd,SAAmCd,GAC3B/pC,EACA+S,KAAoB+1C,oBAExB,+CACE/1C,KAAc+zC,cAAQ/c,EAASI,QAE/Bp3B,KAAc8zC,cAAKh7C,KAAQk+B,GAEtBh3B,KAAY80C,YAAa3E,YAEnBnwC,KAAY80C,YAAmBmB,mBACxCj2C,KAAY80C,YAAezC,eAAMrb,EACvC+C,WAHM/5B,KACNk2C,oBAKMvC,EAAA9lD,UAAgBqoD,iBAAxB,WACQjpD,GAAM+S,KAAY80C,YAAY3E,YAAwC,sCACxEnwC,KAAY80C,YAClBn8C,SAEQg7C,EAAA9lD,UAAiBknD,kBAAzB,WAGQ,MAFF/0C,MAAY80C,YAAkB1C,iBAEpB5tB,GAAA,EAChBlqB,WAEQq5C,EAAA9lD,UAAwBonD,yBAAhC,cAAAv0C,GAsBCV,IApBO,OAAAA,MAAgBw1B,WACD4K,mBAAKpgC,KAAY80C,YAAiB9Z,iBAChD5N,KAAC,WAcA,IAAgB,GAAA7hC,GAAkB,EAAlBsjB,EAAInO,EAAcozC,cAAlBvoD,EAAAsjB,EAAkBpjB,OAAAF,IAAA,CAAjC,GAAWyrC,GAAAnoB,EAAAtjB,EACVmV,GAAYo0C,YAAezC,eAAMrb,EAAY+C,eAKjD4Z,EAAA9lD,UAAgBqkD,iBAAxB,SACgC3X,EACLnpC,GAF3B,GAAAsP,GAsBCV,IAhBO/S,GACA+S,KAAc8zC,cAAOroD,OAAI,EAE7B,sCACF,IAAWurC,GAAOh3B,KAAc8zC,cAAUqC,QAC7BC,EAAsB/b,GAAK3Y,KACjCsV,EACQuD,EACNnpC,EACH4O,KAAY80C,YAChB9Z,gBACI,OAAAh7B,MAAgBssB,WAAqBgM,qBAAS8d,GAAKhpB,KAAC,WAGlD,MAAK1sB,GACb42B,uBAGMqc,EAAA9lD,UAAkBmnD,mBAA1B,SAAiDvoD,GAAjD,GAAAiU,GA8BCV,IA5BI,IAAKA,KAAc8zC,cAAOroD,OAAK,EAAE,CAC5BwB,IACGR,EAEP,uEAEF,IAAiB4pD,OAAA,EAWX,OARSA,GAFPr2C,KAAY80C,YAAmBmB,kBAEjBj2C,KAAiBs2C,iBACvC7pD,GAIsBuT,KAAqBu2C,qBAC3C9pD,GAEM4pD,EAAmBjpB,KAAC,WAGhB1sB,EAAcozC,cAAOroD,OAAI,IAASiV,EAAYo0C,YAAa3E,aAC7DzvC,EACNw1C,qBAII,MAAQ1xB,IAAA,EAChBlqB,WAGMq5C,EAAA9lD,UAAoB0oD,qBAA5B,SAAkD9pD,GAG7C,MAAiB4H,GAAM5H,EAAM6H,OAAS7H,EAAK6H,OAAS3G,GAASwH,SAC3DhK,EAvmBqB,cAymBkD,yEACpE6U,KAAY80C,YAChB9Z,iBACEh7B,KAAY80C,YAAgB9Z,gBAAqB7tC,IAE1C6S,KAAWw1B,WAAmB4K,mBAC3CjzC,MAGgBq3B,GAAA,EAChBlqB,WAGMq5C,EAAA9lD,UAAgByoD,iBAAxB,SAA8C7pD,GAA9C,GAAAiU,GAsBCV,IArBI,IAAiB3L,EAAM5H,EAAO6H,MAAE,CAGjC,GAAW0iC,GAAOh3B,KAAc8zC,cAAUqC,OAOpC,OAFFn2C,MAAY80C,YAAkBlE,iBAE5B5wC,KAAgBssB,WACFoM,kBAAM1B,EAAQI,QAAQ3qC,GACnC2gC,KAAC,WAGE,MAAK1sB,GACb42B,sBAGI,MAAQ9S,IAAA,EAChBlqB,WAGFq5C,EAAA9lD,UAAiB+pC,kBAAjB,WACQ,MAAC,IAAemb,IAAK/yC,KAC7BizC,YAEAU,EAAA9lD,UAAgB6rC,iBAAhB,SAA2BC,GAA3B,GAAAj5B,GA+BCV,IAhBO,OAdH7U,GAnpBuB,cAmpB2B,mCAAMwuC,EAAM2F,KAI7Dt/B,KAAc+zC,cAAmBna,GACjC55B,KAAc8zC,iBAGd9zC,KAAY00C,YAAQhE,OACpB1wC,KAAY80C,YAAQpE,OAEpB1wC,KAA2Bk1C,0BAGzBl1C,KAAoBm0C,eACnB/mB,KAAC,WAQE,MALE1sB,GAA0B60C,0BAC5B70C,EACN00C,mBAGW10C,EACb42B,sBACKlK,KAAC,WAGA1sB,EACN6zC,6BAELZ,KCjrBD6C,GAAA,WAcE,QAAAC,GAC4B32C,EACQ8pB,EACM5tB,EASV43C,GAXtB5zC,KAAQF,SAAUA,EAClBE,KAAY4pB,aAAcA,EAC1B5pB,KAAWhE,YAAqBA,EAShCgE,KAAU4zC,WACjBA,EA8RL,MA1PS6C,GAAA5oD,UAAK8K,MAAZ,SAAoC+9C,GAApC,GAAAh2C,GA0CCV,KAlCyB22C,EAAG,GAAqBnI,IAQzBoI,EAAG,GAAqBpI,IAEhCqI,GAAS,CAuBlB,OAtBF72C,MAAYhE,YAAsB86C,sBAAC,SAAInd,GACxBkd,EAOXn2C,EAAWkzC,WAAS7C,SAAC,WACjB,MAAKrwC,GAAiBg5B,iBAC9BC,MARWkd,GAAQ,EAEfn2C,EAAsBq2C,sBAAeL,EAAoBE,GACtDxpB,KAAC,WAAM,MAAI1sB,GAAes2C,eAAMrd,KAChCvM,KAAmBupB,EAAQr8C,QAAoBq8C,EACxDp8C,WAQEyF,KAAW4zC,WAAS7C,SAAC,WACjB,MAAmB4F,GAC3BnnB,UAKwBonB,EAC1BpnB,SAmBQinB,EAAA5oD,UAAqBkpD,sBAA7B,SACyBL,EACUE,GAFnC,GAAAl2C,GAgCCV,IA5BI,OAAgB02C,GACX12C,KAAiCi3C,4BAChC7pB,KAAkBwpB,EAASt8C,SAC1By0B,MAAC,SAAsBtiC,GAMxB,MAHcmqD,GAAOr8C,OAAQ9N,GAGvBiU,EAAYw2C,YAAQzqD,IAItBP,QAAKirD,KACuC,qEAGjD1qD,GACSiU,EACb02C,0BATkB5yB,GAAA,EAAOjqB,OACvB9N,MAcamqD,EAAWt8C,UACjB0F,KACbo3C,2BAGMX,EAAA5oD,UAAWqpD,YAAnB,SAAyCzqD,GAChC,MACAA,GAAK6H,OAAS3G,GAAoBuH,qBAClCzI,EAAK6H,OAAS3G,GAEvBoF,eAOQ0jD,EAAA5oD,UAAyBopD,0BAAjC,WAGMj3C,KAAiB0xB,iBAAG,GAA2B4c,GACnD,IAAmB+I,GAAuBtS,GAAmBsB,mBACvDrmC,KACJ4pB,cAEcwV,EAAA,GAA0BljB,IAAKlc,KAAa4pB,aAAW5mB,YACxDoZ,eACZ,GAEG,OADFpc,MAAYipC,YAAG,GAAwBlE,IAAcsS,EAAcjY,GAC5Dp/B,KAAYipC,YACzBtwC,SAOQ89C,EAAA5oD,UAAsBupD,uBAA9B,WAGQ,MAFFp3C,MAAiB0xB,iBAAG,GAA4B9B,IAChD5vB,KAAYipC,YAAG,GAAwBgF,IAChCjuC,KAAYipC,YACzBtwC,SAOQ89C,EAAA5oD,UAAcmpD,eAAtB,SAAiCrd,GAAjC,GAAAj5B,GAmDCV,IAlDO,OAAAA,MAAcF,SACH6pB,eAAK3pB,KAAc4pB,cAC7BwD,KAAC,SAAUyiB,GACVnvC,EAAW80B,WAAG,GAAcwT,IAC1BtoC,EAAYuoC,YACZtP,EACAj5B,EACJgxB,iBACF,IAAgB0N,GAAO1+B,EAASZ,SAAc+pB,cACxCnpB,EAAakpB,aACjB5mB,YACaiwC,EAAG,GAAaV,IACzB7xC,EAAakpB,aACblpB,EAAWkzC,WACL/D,EACNnvC,EAAY1E,YAEhBojC,GAE6BkY,EAAG,SAAyB7qB,GACrD/rB,EAAS62C,SAAqBtqB,qBACpCR,GAwBM,OAtBF/rB,GAAY+0B,YAAG,GAAeie,IAC5BhzC,EAAakpB,aACblpB,EAAWkzC,WACXlzC,EAAW80B,WACNyd,EAETqE,GAEE52C,EAAW4rB,WAAG,GAAciJ,IAC1B70B,EAAW80B,WACX90B,EAAY+0B,YAEhBkE,GAGEj5B,EAAY+0B,YAAWnJ,WAAO5rB,EAAY4rB,WAE1C5rB,EAAS62C,SAAG,GAAgBnrB,IAAK1rB,EAAa4rB,YAKvC5rB,EAAW80B,WACxB78B,UACKy0B,KAAC,WACE,MAAK1sB,GAAY+0B,YACzB98B,WAGI89C,EAAA5oD,UAAgB6rC,iBAAxB,SAAmCC,GAI3B,MAHF35B,MAAW4zC,WAA6B4D,4BAEvCrsD,EAxQyB,kBAwQC,iBAAOwuC,EAAM2F,KACjCt/B,KAAWssB,WAAiBoN,iBACzCC,IAEA8c,EAAA5oD,UAAQ+3C,SAAR,cAAAllC,GAUCV,IATO,OAAAA,MAAgB4zC,WACX7C,SAAC,WAEF,MADFrwC,GAAY1E,YAA4By7C,2BACjC/2C,EAAY+0B,YACzBmQ,aACKxY,KAAC,WAEE,MAAK1sB,GAAYuoC,YACzBrD,cAGJ6Q,EAAA5oD,UAAMk7B,OAAN,SACcrqB,EACoBg5C,EACVlmD,GAHxB,GAAAkP,GAUCV,KALe8sB,EAAG,GAAiBW,IAAM/uB,EAAUg5C,EAAWlmD,EAIvD,OAHFwO,MAAW4zC,WAAS7C,SAAC,WACjB,MAAKrwC,GAAS62C,SAAOxuB,OAC7B+D,KAEFA,GAEA2pB,EAAA5oD,UAAQw/B,SAAR,SAAgCP,GAAhC,GAAApsB,GAICV,IAHKA,MAAW4zC,WAAS7C,SAAC,WACjB,MAAKrwC,GAAS62C,SAASlqB,SAC/BP,MAGF2pB,EAAA5oD,UAAKkpC,MAAL,SAA2BgD,GAA3B,GAAAr5B,GAICV,KAHe23C,EAAG,GAAqBnJ,GAEhC,OADFxuC,MAAW4zC,WAAS7C,SAAC,WAAM,MAAIrwC,GAAW4rB,WAAMyK,MAAUgD,EAAW4d,KAC1DA,EACjBnoB,SAEAinB,EAAA5oD,UAAUmV,WAAV,WACQ,MAAKhD,MAAa4pB,aAC1B5mB,YAEAyzC,EAAA5oD,UAAW8pC,YAAX,SAC0DF,GAD1D,GAAA/2B,GAWCV,IAPO,OAAAA,MAAgB4zC,WACX7C,SAAC,WACF,MAAQvsB,IAAA,EAChBlqB,YACK8yB,KAAC,WACE,MAAK1sB,GAAW4rB,WAAekL,eACvCC,MAELgf,KCzVDmB,GAAA,WAOE,QAAAA,GAAyCF,GAArB13C,KAAQ03C,SAAaA,EAFjC13C,KAAK63C,OAE+B,EAuB9C,MArBED,GAAA/pD,UAAImY,KAAJ,SAAa3X,GACP2R,KAAc83C,cAAK93C,KAAS03C,SAAK1xC,KACvC3X,IAEAupD,EAAA/pD,UAAKpB,MAAL,SAAkBA,GACZuT,KAAc83C,cAAK93C,KAAS03C,SAAMjrD,MACxCA,IAEAmrD,EAAA/pD,UAAIkqD,KAAJ,WACM/3C,KAAM63C,OACZ,GAEQD,EAAA/pD,UAAaiqD,cAArB,SAAsDE,EAAUv9C,GAAhE,GAAAiG,GAQCV,IAPUA,MAAO63C,OACJ5uB,WAAC,WACAvoB,EAAOm3C,OACFG,EACdv9C,IAEJ,IAEHm9C,KC9BDK,GAAA,mBAAAC,KAEUl4C,KAAIm4C,KAAiC3zB,GAAA,EAAWlqB,UAIhD0F,KAAco4C,eAAK,EAOnBp4C,KAAmBq4C,qBAmE7B,QA3DEH,GAAArqD,UAAQkjD,SAAR,SAAgCp9C,EAAgB2kD,GAAhD,GAAA53C,GAoBCV,IAfI,IAJKA,KAASlT,SACXD,EAAiC,iCAAOmT,KAAQlT,QACtDC,UAEUurD,GAAM,GAAK,EAAE,CACjBt4C,KAAkBo4C,gBACtB,IAAcG,GAAG,GAAkB/J,GAS7B,OARIvlB,YAAC,WACLvoB,EAAiB83C,iBAAC,WACd,MAAA7kD,KAAUy5B,KAAC,SAAMn+B,GACbspD,EAAQj+C,QAClBrL,OAEEyR,EAAkB03C,kBACdE,GACKC,EACjB/oB,QACQ,MAAKxvB,MAAiBw4C,iBAC9B7kD,IAGMukD,EAAArqD,UAAgB2qD,iBAAxB,SAAgD7kD,GAAhD,GAAA+M,GAeCV,IADO,OAbFA,MAAKm4C,KAAAn4C,KAAYm4C,KAAK/qB,KAAC,WAEnB,MADF1sB,GAAoB23C,qBAAQ,EAC1B1kD,IACEo7B,MAAC,SAAKtiC,GAIV,KAHIiU,GAAQ5T,QAASL,EACjBiU,EAAoB23C,qBAAS,EAC9B9rD,EAAmC,6BAAOE,EAAMgsD,OAAShsD,EAAUM,SAExEN,IACK2gC,KAAC,WACA1sB,EAAoB23C,qBAC1B,MAEOr4C,KACbm4C,MAQAD,EAAArqD,UAAyB2pD,0BAAzB,WACQvqD,EACA+S,KAAoBq4C,oBAG5B,sEAEAH,EAAArqD,UAAK6qD,MAAL,WAKQ,MADAzrD,GAA0B,IAArB+S,KAAeo4C,eAAgD,wCACpEp4C,KAAc+wC,SAAC,WAAM,MAAOvsB,IAAA,EAAQlqB,YAAW/L,OAExD2pD,KCpFDS,GAAA,WASE,QAAAA,GAAuCrZ,GAAlBt/B,KAAGs/B,IAAkBA,EAqB5C,MAnBEqZ,GAAA9qD,UAAiB0xC,kBAAjB,WACQ,MACR,OADav/B,KAAIs/B,KAOjBqZ,EAAA9qD,UAAKgrC,MAAL,WACK,MAAK74B,MAAqBu/B,oBAE7B,iBACe,OAAOv/B,KACtBs/B,KAGFqZ,EAAA9qD,UAAMqE,OAAN,SAAsB0mD,GACd,MAAUA,GAAItZ,MAASt/B,KAC/Bs/B,KA3BgBqZ,EAAe7jD,gBAAG,GAAQ6jD,GAAO,MAIjCA,EAAkBE,mBAAG,GAAQF,GAA2B,0BACxDA,EAAWG,YAAG,GAAQH,GAAoB,mBAuB3DA,KvDYDI,GAAA,WAGE,QAAAA,GAAyB1qD,EAAmBsrC,GAAV35B,KAAI25B,KAAMA,EAF5C35B,KAAIjQ,KAAwB,QAGtBiQ,KAAYqmB,aAAkB2yB,cAAE,UACtC3qD,GACF,MAAC0qD,MA6BD98C,GAAA,WAQE,QAAAg9C,KAFQj5C,KAAYk5C,aAEL,KAoBjB,MAlBED,GAAAprD,UAAQgjD,SAAR,SAA8BsI,GACtB,MAAQ30B,IAAA,EAAQlqB,QACxB,OAEA2+C,EAAAprD,UAAqBipD,sBAArB,SAA4ChqB,GACpC7/B,GAAM+S,KAAak5C,aAAiD,+CACtEl5C,KAAak5C,aAAYpsB,EAErBA,EAAK6rB,GACf7jD,kBAEAmkD,EAAAprD,UAAwB4pD,yBAAxB,WACQxqD,EACsB,OAAtB+S,KAAak5C,aAEjB,0DACEl5C,KAAak5C,aACnB,MACDD,KAEDG,GAAA,WAmBE,QAAAC,GAAkDh6C,GAAlD,GAAAqB,GAkBCV,IAlB4BA,MAAGX,IAAkBA,EAd1CW,KAAas5C,cAAiD,KAS9Dt5C,KAAWu5C,YAAK,EAGhBv5C,KAAYk5C,aAA6B,KAK3Cl5C,KAAcs5C,cAAG,WACnB,GAAaE,GAAO94C,EAAW+4C,SACtB/4C,GAAYg1B,aAAY8jB,EAAOtnD,OAAKwO,EAAcg1B,eACrDh1B,EAAYg1B,YAAW8jB,EACvB94C,EAAe64C,cACX74C,EAAcw4C,cAChBx4C,EAAaw4C,aAAKx4C,EACxBg1B,eAIA11B,KAAYu5C,YAAK,EAGjBv5C,KAAIX,IAASzK,SAAqB8kD,qBAAK15C,KAC7Cs5C,eA0EF,MAxEED,GAAAxrD,UAAQgjD,SAAR,SAA8BsI,GAA9B,GAAAz4C,GA+BCV,IA9BO/S,GACsB,MAAtB+S,KAAcs5C,cAElB,oDAKF,IAAwBK,GAAO35C,KAAau5C,WACtC,OAAAv5C,MAASX,IAASzK,SAASi8C,SAAcsI,GAAK/rB,KAAC,SAASwsB,GAIzD,GAAKl5C,EAAY64C,cAAwBI,EAC1C,KAAM,IAAkBjsD,IAClBC,GAAQwH,QAGhB,sCACK,OAAWykD,IACN3sD,EACqC,gBAAzB2sD,GAAYC,YACiB,8CAC7CD,GACK,GAAcb,IAAUa,EAAYC,YAAMn5C,EACnDg1B,cAEA,QAKN2jB,EAAAxrD,UAAqBipD,sBAArB,SAA4ChqB,GACpC7/B,GAAM+S,KAAak5C,aAAiD,+CACtEl5C,KAAak5C,aAAYpsB,EAGrB9sB,KAAa01B,aACX5I,EAAK9sB,KACf01B,cAGF2jB,EAAAxrD,UAAwB4pD,yBAAxB,WACQxqD,EACsB,MAAtB+S,KAAcs5C,cAElB,2CACIrsD,EACsB,OAAtB+S,KAAak5C,aAEjB,iEACEl5C,KAAIX,IAASzK,SAAwBklD,wBAAK95C,KAAiBs5C,eAC3Dt5C,KAAcs5C,cAAQ,KACtBt5C,KAAak5C,aACnB,MAEQG,EAAAxrD,UAAO4rD,QAAf,WAEqD,kBAApCz5C,MAAIX,IAASzK,SAAOmlD,QAC7BltD,EAC2D,oFAIjE,IAAgBmtD,GAAOh6C,KAAIX,IAASzK,SAAUmlD,QAKxC,OAJA9sD,GACe,OAAT+sD,GAA2C,gBAAbA,GAChB,yBACxBA,GACK,GAAQrB,IACjBqB,IACDX,KAMDn9C,GAAA,WACE,QAAA+9C,GAAgDC,GAA5Bl6C,KAAUk6C,WAAqBA,EAyBrD,MAvBED,GAAApsD,UAAQgjD,SAAR,SAA8BsI,GAA9B,GAAAz4C,GAaCV,IAZO,WAAYwkB,IAAA,EAAe,SAAQlqB,EAAQC,GAE3CmG,EAAWw5C,WAEd,eAAC,SAAaztD,EAAsB0tD,GACzB1tD,EACF8N,EACR9N,GACS6N,EAAC,GAAcy+C,IAAaoB,EAAMxB,GAC3CE,0BAONoB,EAAApsD,UAAqBipD,sBAArB,SAA4ChqB,GAElCA,EAAK6rB,GACfE,qBAEAoB,EAAApsD,UAAwB4pD,yBAAxB,aACDwC,KAoBDG,GAAA,WAIE,QAAAC,GAA8BC,EAA8Bj+C,GAAxC2D,KAAIs6C,KAAMA,EAAUt6C,KAAY3D,aAAQA,EAH5D2D,KAAIjQ,KAA6B,aACjCiQ,KAAI25B,KAAOgf,GAAaG,YAGhB7rD,EACA+S,KAAKs6C,MACHt6C,KAAKs6C,KAAQ,MACbt6C,KAAKs6C,KAAQ,KAAmC,gCAG1D,6BAQF,MANEpsD,QAAAwR,eAAI26C,EAAAxsD,UAAW,ezB8naTgK,IyB9naN,WACQ,OACSmhD,cAAMh5C,KAAKs6C,KAAQ,KAAmC,oCAClDC,kBAAMv6C,KAE3B3D,ezB+naMwG,YAAY,EACZC,cyBhoaL,IACFu3C,KAODj+C,GAAA,WACE,QAAAo+C,GAA8BF,EAA8Bj+C,GAAxC2D,KAAIs6C,KAAMA,EAAUt6C,KAAY3D,aAAQA,EACpDpP,EACA+S,KAAKs6C,MACHt6C,KAAKs6C,KAAQ,MACbt6C,KAAKs6C,KAAQ,KAAmC,gCAG1D,6BAcF,MAZEE,GAAA3sD,UAAQgjD,SAAR,SAA8BsI,GACtB,MAAQ30B,IAAA,EAAQlqB,QAAC,GAAmB8/C,IAAKp6C,KAAKs6C,KAAMt6C,KAC5D3D,gBAIAm+C,EAAA3sD,UAAqBipD,sBAArB,SAA4ChqB,GAElCA,EAAK6rB,GACfG,cAEA0B,EAAA3sD,UAAwB4pD,yBAAxB,aACD+C,KzBmpaG/9C,GAAqC,kBAAXmE,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUvV,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXsV,SAAyBtV,EAAI4F,cAAgB0P,QAAUtV,IAAQsV,OAAO/S,UAAY,eAAkBvC,IAqD3QmvD,GAA4Bz6C,MAAQA,KAAKD,WAAa,WACtD,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC5FD,EAAED,UAAYE,IACb,SAAUD,EAAGC,GACd,IAAK,GAAIC,KAAKD,GACNA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAG1C,OAAO,UAAUF,EAAGC,GAEhB,QAASE,KACLP,KAAK9O,YAAckP,EAFvBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,QiF9gbvFrD,GAAA,mBAAAA,MAOA,MANSA,GAAM6B,OAAb,WACQ,MAAqB27C,IAC7Bj7C,UACOvC,EAAey9C,gBAAtB,WACQ,MAA8BC,IACtCn7C,UACDvC,KAEDw9C,GAAA,SAAAj6C,GACE,QAAAi6C,KjF2hbM,MiF1hbJj6C,GAAAtS,KAAO6R,OACTA,KAGF,MAN0Cy6C,IAAAC,EAAcj6C,GAK/Ci6C,EAAQj7C,SAAG,GAA2Bi7C,GAC9CA,GAAAx9C,IAED09C,GAAA,SAAAn6C,GACE,QAAAm6C,KjF6hbM,MiF5hbJn6C,GAAAtS,KAAO6R,OACTA,KAGF,MANmDy6C,IAAAG,EAAcn6C,GAKxDm6C,EAAQn7C,SAAG,GAAoCm7C,GACvDA,GAAA19C,IAU4B29C,GAAyBvtD,EACtC4P,GAEd,qCjF4hbEJ,GAAgD,kBAAX8D,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUvV,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXsV,SAAyBtV,EAAI4F,cAAgB0P,QAAUtV,IAAQsV,OAAO/S,UAAY,eAAkBvC,I2BvhbhQwvD,GAAc,WAGxCC,GAAA,WACE,QAAAC,GAC4Bp0C,EACUqP,EACMS,GAFjC1W,KAAI4G,KAAaA,EACjB5G,KAASiW,UAAkBA,EAC3BjW,KAAe0W,gBACvBA,EAgBL,MAdEskC,GAAAntD,UAAW2lD,YAAX,SAA4BvlD,EAA4BynB,GACtD,GAAeqkB,KAWT,OAVsB,QAApB/5B,KAAUiW,UACP8jB,EAAKjhC,KACZ,GAAiBid,IAAI9nB,EAAM+R,KAAK4G,KAAM5G,KAAUiW,UAEpDP,IACWqkB,EAAKjhC,KAAC,GAAe0c,IAAIvnB,EAAM+R,KAAK4G,KAC/C8O,IACQ1V,KAAgB0W,gBAAOjrB,OAAK,GACzBsuC,EAAKjhC,KAAC,GAAqB0d,IAAIvoB,EAAM+R,KAChD0W,kBAEFqjB,GACDihB,KAGDC,GAAA,WACE,QAAAC,GAC4Bt0C,EACGqP,EACaS,GAFjC1W,KAAI4G,KAAaA,EACjB5G,KAASiW,UAAWA,EACpBjW,KAAe0W,gBACvBA,EAWL,MATEwkC,GAAArtD,UAAW2lD,YAAX,SAA4BvlD,EAA4BynB,GACtD,GAAeqkB,IACb,GAAiBhkB,IAAI9nB,EAAM+R,KAAK4G,KAAM5G,KAAUiW,UAClCP,GAIV,OAHE1V,MAAgB0W,gBAAOjrB,OAAK,GACzBsuC,EAAKjhC,KAAC,GAAqB0d,IAAIvoB,EAAM+R,KAChD0W,kBAEFqjB,GACDmhB,MAOD,SAAmB3L,GACjBA,IAAA,OAAG,MACHA,IAAA,UAAM,SACNA,IAAA,cAAU,cAHOA,YAOnB,IAAA4L,IAAA,WAqBE,QAAAC,GACqCC,EACR99C,EACI5G,EACG+f,EACXT,GAJdjW,KAAUq7C,WAAgBA,EAC1Br7C,KAAUzC,WAAQA,EAClByC,KAAIrJ,KAAkBA,MAMGpI,KAAfmoB,GACb1W,KACNs7C,eACIt7C,KAAgB0W,gBAAkBA,MAClC1W,KAAUiW,UAAYA,MAiE9B,MA9DEmlC,GAAAvtD,UAAY0tD,aAAZ,SAA+C7nD,GAC7C,GAAgC8nD,EAIrBA,GAHmB,gBAAd9nD,GAIhB,KAC+B,MAAbsM,KAAKrJ,KAAe,KAAOqJ,KAAKrJ,KAAMuN,MACxDxQ,EACA,IAAa0J,GAAG,GAAgBg+C,GAC1Bp7C,KAAWq7C,WACXr7C,KAAWzC,WACNi+C,EACLx7C,KAAgB0W,gBAChB1W,KACJiW,UAQI,OAPwB,gBAAdviB,GAEP0J,EAAoBq+C,oBAC7B/nD,GAAoC,gBAAb,KAAAA,EAAA,YAAAoJ,GAAApJ,KAAsBA,YAAsB2R,KAE1DjI,EACTk+C,eAEFl+C,GAEAg+C,EAAAvtD,UAAWwP,YAAX,SAA0B0pC,GACxB,GAAsB2U,GACF,OAAd17C,KAAKrJ,MAAiBqJ,KAAKrJ,KAAU7H,UACnC,GACF,oBAAwBkR,KAAKrJ,KAAe,GAC5C,OAAC,IAAkBjJ,IACnBC,GAAiBC,iBACrB,YAAgBoS,KAAWzC,WAA+B,gCAClDwpC,EAGZ2U,IAEQN,EAAAvtD,UAAYytD,aAApB,WAGK,GAAoB,OAAft7C,KAAKrJ,KAGT,IAAC,GAAKvE,GAAI,EAAGA,EAAO4N,KAAKrJ,KAAOlL,OAAK2G,IACnC4N,KAAoBy7C,oBAAKz7C,KAAKrJ,KAAIkB,IACxCzF,KAGMgpD,EAAAvtD,UAAmB4tD,oBAA3B,SAA2C3jD,GACtC,GAAKkI,KAAU27C,WAAwBb,GAAKt1C,KAAU1N,GACvD,KAAUkI,MAAY3C,YACxB,iDAGM+9C,EAAAvtD,UAAO8tD,QAAf,WACS,MACD37C,MAAWq7C,aAAmB9L,GAAI55B,KAClC3V,KAAWq7C,aAAmB9L,GAEtCqM,QACDR,KAqBDn+C,GAAA,WACE,QAAAA,GAAyC+F,EAAyB/U,GAA/C+R,KAAUgD,WAAYA,EAAShD,KAAG/R,IAAgBA,EACvE,MAACgP,MAMD4+C,GAAA,WACE,QAAAC,GAAkDC,GAA9B/7C,KAAY+7C,aAAqBA,EAoSvD,MAjSED,GAAAjuD,UAAYmuD,aAAZ,SACoBz+C,EACN9M,EACiBe,GAH/B,GAAAkP,GA8BCV,KAzBc5C,EAAG,GAAgB+9C,IAChB5L,GAAI55B,IACRpY,EACD8H,GACT9M,WACiB4E,IAAsC,sCAASC,EAAS3M,EAE3E,IAAWmN,OAA8BrP,KAApBiD,EAAMoM,OAAwBpM,EAAMoM,MAE3Cq+C,EAActvC,GAAOnG,KAE3B3X,GAA6B4B,EAAE,SAAIxC,EAAOI,GAChD,GAAUsI,GAAG,GAAqBG,IAAK7I,GAAeuP,EAEpC+9C,EAAUn+C,EAAam+C,aAAO5kD,EAC3CtI,GAAOqS,EAAgBw7C,gBAAM7tD,EAAgBktD,EAElD,IAAiBY,GAAOz7C,EAAU07C,UAAM/tD,EAAgBktD,EACxCY,KACJF,EAAaA,EAAIhvC,IAAKtW,EAClCwlD,KAGF,IAAelmC,GAAQrY,EAAG,GAAawW,IAAQhX,EAAW6Y,WAAQ,IAC5D,OAAC,IAAiB8kC,IAAWkB,EAAWhmC,EAAS7Y,EACzDsZ,kBAGAolC,EAAAjuD,UAAewuD,gBAAf,SAAkC9+C,EAAc9M,GAAhD,GAAAiQ,GA6BCV,KA5Bc5C,EAAG,GAAgB+9C,IAChB5L,GAAOqM,OACXr+C,EACD8H,GACT9M,WACiB4E,IAAsC,sCAASC,EAAS3M,EAE3E,IAAoB6rD,MACNL,EAActvC,GAAOnG,KAC3B3X,GAA6B4B,EAAE,SAAIxC,EAAOI,GAChD,GAAUsI,GAAkC8G,GAAWF,EAAOtP,GAE5CstD,EAAUn+C,EAAam+C,aAAO5kD,EAE7C,KADEtI,EAAOqS,EAAgBw7C,gBAAM7tD,EAAgBktD,aACRb,IAE1B4B,EAAKxjD,KACrBnC,OAAQ,CACN,GAAiBwlD,GAAOz7C,EAAU07C,UAAM/tD,EAAgBktD,EAChC,OAATY,IACCG,EAAKxjD,KAAOnC,GAChBslD,EAAaA,EAAIhvC,IAAKtW,EAClCwlD,MAIJ,IAAUI,GAAG,GAAanoC,IAAiBkoC,EACrC,OAAC,IAAoBrB,IAAWgB,EAAMM,EAASn/C,EACvDsZ,kBAGAolC,EAAAjuD,UAAkB2uD,mBAAlB,SACoBj/C,EACe7J,EACrBrF,EACgBouD,GAE5B,GAAar/C,GAAG,GAAgB+9C,IAChB5L,GAAOqM,OACXr+C,EACD8H,GACT9M,YACQkf,GAAyBna,GAAWC,EAAU7J,IAC5CgrB,GAAWrwB,EAEpB,IAAoBouD,EAAOhxD,OAAI,GAAO,EACvC,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACrB,YAAsB2P,EAA4C,wGAKlE,KAAC,GAAKnL,GAAI,EAAGA,EAAsBqqD,EAAOhxD,OAAG2G,GAAK,EAChDqlB,EAAK3e,KACcwE,GAAWC,EAAqBk/C,EAGrDrqD,KACIssB,EAAK5lB,KAAoB2jD,EAAErqD,EACnC,GAKI,KAAC,GAHekqD,MACNL,EAActvC,GAAOnG,MAEzBpU,EAAI,EAAGA,EAAOqlB,EAAOhsB,SAAK2G,EAAG,CACrC,GAAUuE,GAAO8gB,EAAIrlB,GACHmpD,EAAUn+C,EAAam+C,aAAO5kD,GACrC+lD,EAAO18C,KAAgBk8C,gBAAOx9B,EAAGtsB,GAAgBmpD,EACzD,IAAMmB,YAAiChC,IAE1B4B,EAAKxjD,KACrBnC,OAAQ,CACN,GAAiBwlD,GAAOn8C,KAAUo8C,UAAMM,EAAgBnB,EAChC,OAATY,IACCG,EAAKxjD,KAAOnC,GAChBslD,EAAaA,EAAIhvC,IAAKtW,EAClCwlD,KAIJ,GAAUI,GAAG,GAAanoC,IAAiBkoC,EACrC,OAAC,IAAoBrB,IAAWgB,EAAMM,EAASn/C,EACvDsZ,kBAMAolC,EAAAjuD,UAAe8uD,gBAAf,SAAkCp/C,EAAc9M,GAC9C,GAAa2M,GAAG,GAAgB+9C,IAChB5L,GAAWqN,WACfr/C,EACD8H,GACT9M,YACUskD,EAAO78C,KAAUo8C,UAAM3rD,EAAW2M,EAMxC,OALAnQ,GAAe,MAAR4vD,EAA6C,mCACpD5vD,EACgC,IAA7BmQ,EAAgBsZ,gBAAOjrB,OAE9B,iDAEJoxD,GAGQf,EAAAjuD,UAAequD,gBAAvB,SAAoCzrD,EAAuB2M,GACzD,IACQ,MAAK4C,MAAa+7C,aAC1BtrD,GAAQ,MAAG7D,GACT,GAAaG,GAAe2Q,GAAI9Q,EAChC,MAAawQ,GAAYC,YAC3BtQ,KAYM+uD,EAAAjuD,UAASuuD,UAAjB,SAA8B3rD,EAAuB2M,GAEhD,IADE3M,EAAOuP,KAAgBk8C,gBAAMzrD,EAAW2M,aAClBvN,OAAE,CAIxB,IAASuN,EAAMzG,KAChB,KAAayG,GAAYC,YAC3B,kCAIM,OADCD,GAAU6Y,UAAKnd,KAAQsE,EAAOzG,MAC1BqJ,KAAW88C,WAAiBrsD,EACzC2M,GAAM,MAAwBP,IAAQpM,IACjB0M,GAA2B,2BAASC,EAAS3M,GACrDuP,KAAY+8C,YAAqBtsD,EAC9C2M,KAGaA,EAAMzG,MACRyG,EAAU6Y,UAAKnd,KAAQsE,EAChCzG,MACWqJ,KAAiBg9C,iBAAMvsD,EACpC2M,KAGM0+C,EAAAjuD,UAAUivD,WAAlB,SAAiCj7C,EAAuBzE,GAGlD,IAAgB,GAFRnO,MACEguD,EAAK,EACC1xD,EAAK,EAAL2xD,EAAKr7C,EAALtW,EAAA2xD,EAAKzxD,OAAAF,IAAA,CAApB,GAAW4xD,GAAAD,EAAA3xD,GACC6xD,EAAOp9C,KAAUo8C,UAAMe,EAAS//C,EAAam+C,aAAc0B,GAClD,OAATG,IAGFA,EAAYxpD,GACzBC,UACM5E,EAAK6J,KAAcskD,GACZH,IAET,MAAC,IAAc1vC,IACvBte,IAEQ6sD,EAAAjuD,UAAWkvD,YAAnB,SAAoCzxD,EAAuB8R,GAA3D,GAAAsD,GASCV,KARW/Q,EAAG,GAAasY,IAA0CxV,EAO9D,OANElD,GAAYvD,EAAE,SAAY2C,EAAYid,GAC5C,GAAiBixC,GAAOz7C,EAAU07C,UAAIlxC,EAAS9N,EAAam+C,aAAOttD,GAC3C,OAATkuD,IACPltD,EAASA,EAAO0Y,OAAI1Z,EAC5BkuD,MAEK,GAAexvC,IACxB1d,IAQQ6sD,EAAAjuD,UAAgBmvD,iBAAxB,SACc3uD,EACS+O,GAElB,GAAgB,OAAV/O,EACD,MAAUuF,IAClBC,QAAM,IAA+B,gBAAdxF,GAClB,MAAUgF,GAAsBhF,GAC1B,GAAgBud,IACzBvd,GACS,GAAe4F,IACxB5F,EALQ,IAM4B,iBAAfA,GACf,MAAaid,IAAGE,GACxBnd,EAFU,IAE2B,gBAAdA,GACf,MAAC,IAAe4d,IACxB5d,EAFU,IAEMA,YAAiBxC,MACzB,MAAC,IAAkBsgB,IAAU+F,GAASM,SAC9CnkB,GAFU,IAEMA,YAAqB0O,IAC7B,MAAC,IAAiB2P,IAC1Bre,EAFU,IAEMA,YAAiB2O,IACzB,MAAC,IAAauP,IACtBle,EAFU,IAEMA,YAAiC4O,IACzC,MAAC,IAAYuP,IAAMne,EAAW2U,WAAO3U,EAC7CJ,IAFU,IAEMI,YAA2B6O,IAAE,CACxC,GAAM7O,YAAiCqsD,IAErC,KAAQt9C,GAAWi+C,aAAmB9L,GAAQqM,OAClCx+C,EAAYC,YAG3B,uDACQpQ,EACgB,MAAbmQ,EAAKzG,MAAmByG,EAAKzG,KAAOlL,OAAI,EACW,0EAG/C2R,EAAYC,YACgC,4EAIvD,IAAUhP,YAA0CusD,IAAE,CACvD,GACMx9C,EAAWi+C,aAAmB9L,GAAI55B,KAClCvY,EAAWi+C,aAAmB9L,GACtCqM,OACC,KAAax+C,GAAYC,YACmC,wEAI3D,IAAuB,OAAfD,EAAKzG,KACd,KAAayG,GAAYC,YACwB,wEAS7C,OALCD,GAAgBsZ,gBAAK5d,KAC1B,GAAkB0b,IAAQpX,EAAKzG,KAA0B4d,GACzD9U,WAIJ,KACQ,MAAK5S,GAA4B,4BACzCwB,GAEA,KAAa+O,GAAYC,YACvB,4BAA4CxM,EAEhDxC,KAEHytD,K3B2/aGuB,GAAqC,kBAAXz8C,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUvV,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXsV,SAAyBtV,EAAI4F,cAAgB0P,QAAUtV,IAAQsV,OAAO/S,UAAY,eAAkBvC,IAiB3QgyD,GAAqBt9C,MAAQA,KAAKD,WAAa,WAC/C,GAAIE,GAAgB/R,OAAOgS,iBAAoBC,uBAA2BtQ,QAAS,SAAUuQ,EAAGC,GAC5FD,EAAED,UAAYE,IACb,SAAUD,EAAGC,GACd,IAAK,GAAIC,KAAKD,GACNA,EAAEtS,eAAeuS,KAAIF,EAAEE,GAAKD,EAAEC,IAG1C,OAAO,UAAUF,EAAGC,GAEhB,QAASE,KACLP,KAAK9O,YAAckP,EAFvBH,EAAcG,EAAGC,GAIjBD,EAAEvS,UAAkB,OAANwS,EAAanS,OAAOsS,OAAOH,IAAME,EAAG1S,UAAYwS,EAAExS,UAAW,GAAI0S,Q4Bz9brEg9C,GAA8B,2BAC/BC,IAAQ,EAsBzBC,GAAA,WAWE,QAAAC,GAAqCC,GAChC,OAA6BpvD,KAApBovD,EAAKz6C,KAAiB,CAC7B,OAA4B3U,KAAnBovD,EAAIx6C,IACd,KAAM,IAAkBzV,IAClBC,GAAiBC,iBAGzB,qDACIoS,MAAKkD,KAAgBq6C,GACrBv9C,KAAImD,IACVq6C,OACmBntD,GAAW,WAAU,SAAQ,OAAUstD,EAAOz6C,MAC3DlD,KAAKkD,KAAWy6C,EAAMz6C,KAED3S,EAAW,WAAW,UAAO,MAAUotD,EAAMx6C,KAClEnD,KAAImD,IAAW/U,EAAmBuvD,EAAIx6C,IAC5Cq6C,GACmBjsD,GAAW,WAAUosD,GAAS,OAAO,MAAkB,gBAEjDptD,EACb,WACF,SACK,cACLotD,EACR3hD,aACEgE,KAAYhE,YAAW2hD,EAC7B3hD,YASF,MAPE0hD,GAAA7vD,UAAMqE,OAAN,SAA+BkQ,GACtB,MACDpC,MAAKkD,OAAUd,EAAKc,MACpBlD,KAAImD,MAAUf,EAAIe,KAClBnD,KAAYhE,cAAUoG,EAE9BpG,aACD0hD,KAEDE,GAAA,mBAAAA,MAOA,MAACA,MAKDt+C,GAAA,WAgBE,QAAAu+C,GAAiEC,GAAjE,GAAAp9C,GA2BCV,IAkJDA,MAAQpL,UACAmK,OAAE,WACH,MAAK2B,GAAkBq9C,EACbr9C,EAAiBq9C,EAC9BnY,WACgBphB,GAAA,EAChBlqB,WAlLF,IAAY0jD,GAAG,GAAsBJ,GAClC,IAAmE,WAAlEP,GAA4CS,EAAQtsD,SAAgB,CAGtE,GAAS6N,GAAuCy+C,CAC1CE,GAAYC,YAAO5+C,EACnB2+C,EAAWh7C,WAAY66C,EAAkBK,kBAAM7+C,GAC/C2+C,EAAe/6C,eAAS+6C,EAAYC,YAAMtuD,KAC1CquD,EAAYhiD,YAAG,GAA+Bo9C,IACtD/5C,OAAQ,CACN,GAAc8+C,GAAwCL,CACnD,KAAUK,EAAW56C,UACtB,KAAM,IAAkB7V,IAClBC,GAAiBC,iBAGzB,yBAEMowD,GAAWh7C,WAAG,GAAcK,IAAS86C,EAAU56C,UAAU46C,EAAW36C,UAEpEw6C,EAAe/6C,eAAe,YAC9B+6C,EAAYhiD,YAAG,GACvBC,IAEM+hD,EAASL,SAAG,GAAqBF,QACnCz9C,KAAQo+C,EACdJ,EA0OF,MAzQE9vD,QAAAwR,eAAWm+C,EAAAhwD,UAAW,e5Bk+bhBgK,I4Bl+bN,WACQ,MAAKmI,MAAQo+C,EACrBp7C,Y5Bm+bMH,YAAY,EACZC,c4Bp+bL,IA+BD+6C,EAAAhwD,UAAQ8vD,SAAR,SAA4CU,GAIvC,GAHsBnvD,EAAqB,qBAAW1D,UAAK,GAC/CsE,EAAqB,qBAAU,SAAG,EAAmBuuD,GAG1DrwD,EAA8CqwD,EACvD,eACC,KAAM,IAAkB3wD,IAClBC,GAAiBC,iBACoC,wFAK7D,IAAiB0wD,GAAG,GAAqBb,IAAkBY,EACxD,IAAKr+C,KAAiB+9C,IAAS/9C,KAAQo+C,EAAST,SAAOzrD,OAAcosD,GACtE,KAAM,IAAkB5wD,IAClBC,GAAoBuH,oBAC4C,qKAMpE8K,MAAQo+C,EAAST,SAAeW,MACM/vD,KAA3B+vD,EAAYtiD,cACrBgE,KAAQo+C,EAAYpiD,YAA0BD,GACrCuiD,EAEftiD,eAGF6hD,EAAAhwD,UAAiB0wD,kBAAjB,WACK,GAAKv+C,KAAkB+9C,EACxB,KAAM,IAAkBrwD,IAClBC,GAAoBuH,oBAC2C,6KAMjE,OAAK8K,MAAgBw+C,iBAC7B,IAEAX,EAAAhwD,UAAsB4wD,uBAAtB,WAIQ,MAHGz+C,MAAkB+9C,GACrB/9C,KAAgBw+C,iBACtB,GACWx+C,KACb+9C,GAEQF,EAAAhwD,UAAe2wD,gBAAvB,SAA4CvV,GAA5C,GAAAvoC,GAyCCV,IAxCO/S,KACE+S,KAAQo+C,EAAST,SAAKz6C,KAE5B,2CAEIjW,GAAM+S,KAAiB+9C,EAA6C,0CAE1E,IAAkBn0B,GAAG,GAAgB7mB,IAC/B/C,KAAQo+C,EAAWp7C,WACnBhD,KAAQo+C,EAAen7C,eACvBjD,KAAQo+C,EAAST,SAAKz6C,KACtBlD,KAAQo+C,EAAST,SACrBx6C,KAEgB44C,EAAG,SAAa1tD,GAC7B,GAAMA,YAA8B2P,IAAE,CACvC,GAAY0gD,GAAOh+C,EAAQ09C,EAAYp7C,WAC1B27C,EAAQtwD,EAAU0P,UAAQqgD,EAAYp7C,UAChD,KAAS27C,EAAOzsD,OAASwsD,GAC1B,KAAM,IAAkBhxD,IAClBC,GAAiBC,iBACgB,sCACzB+wD,EAAUp7C,UAAA,IAAWo7C,EAASn7C,SAAiB,+BACnCk7C,EAAUn7C,UAAA,IAAUm7C,EAEhDl7C,SACM,OAAC,IAAwBvG,IAAKyD,EAAQ09C,EAAWp7C,WAAO3U,EAChEuwD,GACQ,MACRvwD,GAUI,OARF2R,MAAe6+C,EAAG,GAAqBhD,IAAeE,GAEtD/7C,KAAiB+9C,EAAG,GAAmBvH,IAC1BppD,GAAcC,cACjBu8B,EACR5pB,KAAQo+C,EAAYpiD,YACxB,GACAi8C,KACSj4C,KAAiB+9C,EAAMplD,MACpCswC,IAEe4U,EAAiBK,kBAAhC,SAAsD7+C,GACpD,GAAa7N,GAAM6N,EAA8B7N,OAC9C,KAAUxD,EAAiBwD,EAAe,aAAE,CAG1C,GAASxD,EAAiBwD,EAAiB,eAC5C,KAAM,IAAkB9D,IAClBC,GAAiBC,iBAC8B,2EAIvD,MAAM,IAAkBF,IAClBC,GAAiBC,iBAGzB,uDAEG,GAASI,EAAiBwD,EAAsB,oBAGjD,KAAM,IAAkB9D,IAClBC,GAAiBC,iBAC8B,wEAKvD,IAAe2V,GAAU/R,EAAc,SACpC,KAAW+R,GAAkC,gBAAdA,GAChC,KAAM,IAAkB7V,IAClBC,GAAiBC,iBAGzB,yDACM,OAAC,IAAcyV,IACvBE,IAEArV,OAAAwR,eAAIm+C,EAAAhwD,UAAG,O5Bw4bDgK,I4Bx4bN,WACK,IAAMmI,KAAQo+C,EAAaH,YAC5B,KAAM,IAAkBvwD,IAClBC,GAAoBuH,oBACyC,+EAI/D,OAAK8K,MAAQo+C,EACrBH,a5Bq4bMp7C,YAAY,EACZC,c4Bt4bL,IAYD+6C,EAAAhwD,UAAUixD,WAAV,SAA6BC,GAGxB,GAFsB7vD,EAAuB,uBAAW1D,UAAK,GACjDsE,EAAuB,uBAAU,SAAG,EAAcivD,IACjDA,EACd,KAAM,IAAkBrxD,IAClBC,GAAiBC,iBAGzB,2DAGM,OADFoS,MAA0By+C,yBACvB,GAAuBO,IAAa1mD,GAAW4M,WAAY65C,GACpE/+C,OAEA69C,EAAAhwD,UAAG0Q,IAAH,SAAsBwgD,GAGjB,GAFsB7vD,EAAgB,gBAAW1D,UAAK,GAC1CsE,EAAgB,gBAAU,SAAG,EAAcivD,IAC1CA,EACd,KAAM,IAAkBrxD,IAClBC,GAAiBC,iBAGzB,kDAEM,OADFoS,MAA0By+C,yBACNzgD,GAAQihD,QAAa3mD,GAAW4M,WAAY65C,GACtE/+C,OAEA69C,EAAAhwD,UAAc2pC,eAAd,SACoEC,GADpE,GAAA/2B,GAUCV,IALO,OAFmB9Q,GAA2B,2BAAW1D,UAAK,GACrDsE,EAA2B,2BAAY,WAAG,EAAkB2nC,GACrEz3B,KAA8By+C,yBAAY9mB,YAC9C,SAAiCA,GACzB,MAAeF,GAAC,GAAeynB,IAAKx+C,EAC5Ci3B,OAIJkmB,EAAAhwD,UAAKmpC,MAAL,WAGQ,MAFFh3B,MAA0By+C,yBAEvB,GAAcU,IACvBn/C,OAEA9R,OAAAwR,eAAWm+C,EAAQ,Y5B82bbhmD,I4B92bN,WACS,OAAI9M,KACT,IAAaW,IAAMC,MACX,MAAS,OACjB,KAAaD,IAAMc,MACX,MAAS,OACjB,KAAad,IAAO0zD,OACZ,MAAU,QAClB,SACQ,MAAKvyD,GAAsB,sBAAM9B,O5Bi3bvC8X,YAAY,EACZC,c4Bh3bL,IAEM+6C,EAAW5yD,YAAlB,SAA4Co0D,GAGnC,OAFkBnwD,EAAwB,wBAAW1D,UAAK,GAClDsE,EAAwB,wBAAU,SAAG,EAASuvD,GAC7CA,GACd,IAAY,QACPp0D,EAAgBS,GAAiBC,MAC9B,MACR,KAAY,QACPV,EAAgBS,GAAiBc,MAC9B,MACR,KAAa,SACRvB,EAAgBS,GAAkB0zD,OAC/B,MACR,SACE,KAAM,IAAkB1xD,IAClBC,GAAiBC,iBACA,sBAG7ByxD,KACDxB,KAKDqB,GAAA,WACE,QAAAlM,GAC+BsM,EACYC,GADjCv/C,KAAUs/C,EAAWA,EACrBt/C,KAAYu/C,GACnBA,EA4GL,MA1GEvM,GAAAnlD,UAAGgK,IAAH,SAC0CiG,GAD1C,GAAA4C,GAqBCV,IAlB0B9Q,GAAkB,kBAAW1D,UAAK,EAC3D,IAASomC,GAAoB/zB,GACV,kBACNC,EACPkC,KACJs/C,EACI,OAAAt/C,MAAkBu/C,GACfzM,QAAKlhB,EAAOgtB,IACdxxB,KAAC,SAAsB/T,GACvB,IAAMA,GAAsB,IAAdA,EAAO5tB,OAChB,MAAKoB,GACb,kDACA,IAAS0R,GAAO8a,EAAI,EACjB,OAAI9a,aAAuB8I,IACrB,GAAoB7I,IAAKkC,EAAW4+C,EAAK1tB,EAAKgtB,EAAM,MAC7D,GACO,GAAoBpgD,IAAKkC,EAAW4+C,EAAK1tB,EAAKgtB,EAAKrgD,GAC5D,MAGJy0C,EAAAnlD,UAAGof,IAAH,SAC0CnP,EACXzP,EACCmD,GAEHhC,EAAkB,kBAAWhE,UAAG,EAAK,EAChE,IAASomC,GAAoB/zB,GACV,kBACNC,EACPkC,KACJs/C,EACK9tD,GAAqBmM,GAAkB,kBAAWnM,EACzD,IAAYqrD,GAAO78C,KAAWs/C,EAAeT,EAAa7C,aACvC,kBACZ3tD,EAELmD,EAEI,OADFwO,MAAau/C,GAAItyC,IAAI2kB,EAAKgtB,EAAU/B,GAE1C78C,MAYAgzC,EAAAnlD,UAAMomB,OAAN,SAC0CnW,EAC4B0hD,EACvDnxD,G5B60bT,I4B50bJ,GAAAouD,MAAAlxD,EAA+B,EAA/BA,EAAAC,UAA+BC,OAAAF,IAA/BkxD,EAAAlxD,EAAA,GAAAC,UAA+BD,EAE/B,IAAQqmC,GACGirB,CAgCL,OA7BiC,gBAAb2C,IACPA,YAClB1oD,KAC4BxH,EAAqB,qBAAW9D,UAAK,GAC7DomC,EAAoB/zB,GACD,qBACTC,EACPkC,KACJs/C,GACIzC,EAAO78C,KAAWs/C,EAAeT,EAAmBrC,mBACpC,qBACHgD,EACZnxD,EAGTouD,KAC2BvtD,EAAqB,qBAAW1D,UAAK,GAC3DomC,EAAoB/zB,GACD,qBACTC,EACPkC,KACJs/C,GACIzC,EAAO78C,KAAWs/C,EAAeT,EAAgBxC,gBACjC,qBAGxBmD,IAEIx/C,KAAau/C,GAAOtrC,OAAI2d,EAAKgtB,EAAU/B,GAE7C78C,MAEAgzC,EAAAnlD,UAAMkR,OAAN,SAA+CjB,GACpB5O,EAAqB,qBAAW1D,UAAK,EAC9D,IAASomC,GAAoB/zB,GACP,qBACTC,EACPkC,KACJs/C,EAEI,OADFt/C,MAAau/C,GAAOxgD,OAAI6yB,EAAOgtB,GAErC5+C,MACDgzC,KAEDmM,GAAA,WAIE,QAAAM,GAAyCH,GAArBt/C,KAAUs/C,EAAWA,EAHjCt/C,KAAU0/C,MACV1/C,KAAU2/C,IAE0B,EAmH9C,MAjHEF,GAAA5xD,UAAGof,IAAH,SAC0CnP,EACXzP,EACCmD,GAEHhC,EAAiB,iBAAWhE,UAAG,EAAK,GAC3DwU,KAAsB4/C,oBAC1B,IAAShuB,GAAoB/zB,GACX,iBACLC,EACPkC,KACJs/C,EACK9tD,GAAqBmM,GAAiB,iBAAWnM,EACxD,IAAYqrD,GAAO78C,KAAWs/C,EAAeT,EAAa7C,aACxC,iBACX3tD,EAELmD,EAII,OAHFwO,MAAW0/C,GAAO1/C,KAAW0/C,GAAOpzD,OAChCuwD,EAAYrJ,YAAI5hB,EAAKgtB,EAAchqC,GACzCO,OAEJnV,MAYAy/C,EAAA5xD,UAAMomB,OAAN,SAC0CnW,EAC4B0hD,EACvDnxD,G5B0xbT,I4BzxbJ,GAAAouD,MAAAlxD,EAA+B,EAA/BA,EAAAC,UAA+BC,OAAAF,IAA/BkxD,EAAAlxD,EAAA,GAAAC,UAA+BD,EAE3ByU,MAAsB4/C,oBAE1B,IAAQhuB,GACGirB,CAkCL,OA/BiC,gBAAb2C,IACPA,YAClB1oD,KAC4BxH,EAAoB,oBAAW9D,UAAK,GAC5DomC,EAAoB/zB,GACF,oBACRC,EACPkC,KACJs/C,GACIzC,EAAO78C,KAAWs/C,EAAeT,EAAmBrC,mBACrC,oBACFgD,EACZnxD,EAGTouD,KAC2BvtD,EAAoB,oBAAW1D,UAAK,GAC1DomC,EAAoB/zB,GACF,oBACRC,EACPkC,KACJs/C,GACIzC,EAAO78C,KAAWs/C,EAAeT,EAAgBxC,gBAClC,oBAGvBmD,IAEIx/C,KAAW0/C,GAAO1/C,KAAW0/C,GAAOpzD,OAChCuwD,EAAYrJ,YAAI5hB,EAAKgtB,EAAchqC,GAAOG,QAChD,KAEJ/U,MAEAy/C,EAAA5xD,UAAMkR,OAAN,SAA+CjB,GACpB5O,EAAoB,oBAAW1D,UAAK,GACzDwU,KAAsB4/C,oBAC1B,IAAShuB,GAAoB/zB,GACR,oBACRC,EACPkC,KACJs/C,EAII,OAHFt/C,MAAW0/C,GAAO1/C,KAAW0/C,GAAOpzD,OACtC,GAAkB0qB,IAAI4a,EAAKgtB,EAAchqC,GACzCO,OAEJnV,MAEAy/C,EAAA5xD,UAAMiqC,OAAN,WAGK,MAFC93B,MAAsB4/C,qBACtB5/C,KAAW2/C,IAAQ,EACf3/C,KAAW0/C,GAAOj0D,OAAK,EAClBuU,KAAWs/C,EAAyBb,yBAAM1nB,MAAK/2B,KAC5D0/C,IACgBl7B,GAAA,EAChBlqB,WAGMmlD,EAAA5xD,UAAkB+xD,mBAA1B,WACK,GAAK5/C,KAAY2/C,GAClB,KAAM,IAAkBjyD,IAClBC,GAAoBuH,oBAC6B,wEAK5DuqD,KAKDzhD,GAAA,WAGE,QAAA6hD,GAAoCjB,EAA+B7gD,GAAhDiC,KAAI4+C,EAAaA,EAAW5+C,KAASjC,UAAWA,EAC7DiC,KAAiB+9C,EAAO/9C,KAAUjC,UACxC0gD,yBA2QF,MAzQSoB,GAAOZ,QAAd,SAAiCtoD,EAAsBoH,GAClD,GAAKpH,EAAOlL,OAAI,GAAO,EACxB,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACkB,6FAE9B+I,EAAkBsO,kBAAA,QAAYtO,EAE3ClL,OACM,OAAC,IAAqBo0D,GAAC,GAAe55C,IAAMtP,GACpDoH,IAEA7P,OAAAwR,eAAImgD,EAAAhyD,UAAE,M5BgvbAgK,I4BhvbN,WACQ,MAAKmI,MAAK4+C,EAAKjoD,KACvB+N,e5BivbM7B,YAAY,EACZC,c4BlvbL,IAED5U,OAAAwR,eAAImgD,EAAAhyD,UAAM,U5BmvbJgK,I4BnvbN,WACQ,MAAC,IAAuBmnD,IAAKh/C,KAAK4+C,EAAKjoD,KAAU6N,UAAMxE,KAC/DjC,Y5BovbM8E,YAAY,EACZC,c4BrvbL,IAED5U,OAAAwR,eAAImgD,EAAAhyD,UAAI,Q5BsvbFgK,I4BtvbN,WACQ,MAAKmI,MAAK4+C,EAAKjoD,KACvBsO,mB5BuvbMpC,YAAY,EACZC,c4BxvbL,IAED+8C,EAAAhyD,UAAUixD,WAAV,SAA6BC,GAGxB,GAFsB7vD,EAA+B,+BAAW1D,UAAK,GACzDsE,EAA+B,+BAAU,SAAG,EAAcivD,IACzDA,EACd,KAAM,IAAkBrxD,IAClBC,GAAiBC,iBAGzB,2DACA,IAAU+I,GAAe2B,GAAW4M,WAAa65C,EAC3C,OAAC,IAAuBC,IAAKh/C,KAAK4+C,EAAKjoD,KAAMuN,MAAMvN,GAAMqJ,KACjEjC,YAEA8hD,EAAAhyD,UAAGof,IAAH,SAC+B5e,EACCmD,GAEHhC,EAAwB,wBAAWhE,UAAG,EAAK,GAC/DgG,EAAqBmM,GAAwB,wBAAWnM,EAE/D,IAAYqrD,GAAO78C,KAAUjC,UAAe8gD,EAAa7C,aAChC,wBAClB3tD,EAELmD,EACI,OAAKwO,MAAiB+9C,EAAMhnB,MAC1B8lB,EAAYrJ,YAAKxzC,KAAK4+C,EAAchqC,GAE9CO,QAQA0qC,EAAAhyD,UAAMomB,OAAN,SACsEurC,EACvDnxD,G5BmubT,I4BlubJ,GAAAouD,MAAAlxD,EAA+B,EAA/BA,EAAAC,UAA+BC,OAAAF,IAA/BkxD,EAAAlxD,EAAA,GAAAC,UAA+BD,EAE/B,IAAWsxD,EAqBL,OAlBiC,gBAAb2C,IACPA,YAClB1oD,KAC4BxH,EAA2B,2BAAW9D,UAAK,GAChEqxD,EAAO78C,KAAUjC,UAAe8gD,EAAmBrC,mBAC7B,2BACTgD,EACZnxD,EAGTouD,KAC2BvtD,EAA2B,2BAAW1D,UAAK,GAC9DqxD,EAAO78C,KAAUjC,UAAe8gD,EAAgBxC,gBAC1B,2BAG9BmD,IAEWx/C,KAAiB+9C,EAAMhnB,MAC1B8lB,EAAYrJ,YAAKxzC,KAAK4+C,EAAchqC,GAAOG,QAErD,MAEA8qC,EAAAhyD,UAAMkR,OAAN,WAEQ,MADmB7P,GAA2B,2BAAW1D,UAAK,GACzDwU,KAAiB+9C,EAAMhnB,OAChC,GAAkB/f,IAAKhX,KAAK4+C,EAAchqC,GAE9CO,SAqBA0qC,EAAAhyD,UAAUiyD,WAAV,W5B+rbM,I4B/rbK,GAAA/zD,MAAAR,EAAgB,EAAhBA,EAAAC,UAAgBC,OAAAF,IAAhBQ,EAAAR,GAAAC,UAAgBD,EACEiE,GACK,+BACrBhE,UACR,EAED,EACF,IAG0DksD,GAH/ClmD,GACauuD,wBACtB,GAESC,EAAK,CAEmB,YAAjC3C,GAAWtxD,EAASi0D,KACF1jD,GAAKvQ,EACxBi0D,MACQxuD,EAAOzF,EAA6Ci0D,GACxCzuD,EAA+B,+BAASC,GAExD,2BACsBjB,EACO,+BACrB,UACe,yBACjBiB,EACPuuD,wBAEJC,IAEA,IAAqBC,IACWlyB,+BAASv8B,EAAuBuuD,uBACnCvxB,4BAASh9B,EACpCuuD,uBA6BI,OA3BezjD,IAAKvQ,EAAWi0D,IAC3BtI,EAAO3rD,EACjBi0D,IACiBlwD,EACiB,+BACpB,WACHkwD,EACHj0D,EACJi0D,IACqB5vD,EACS,+BACpB,WACH4vD,EAAI,EACPj0D,EAAQi0D,EACZ,IACqB5vD,EACS,+BACpB,WACH4vD,EAAI,EACPj0D,EAAQi0D,EACZ,IACMtI,GACF1xC,KAAMja,EAA+Ci0D,GACpDvzD,MAAMV,EAAQi0D,EAAgB,GAC3BE,SAAMn0D,EAAQi0D,EAE1B,KACWhgD,KAAmBmgD,mBAAgBF,EAChDvI,IAEQmI,EAAAhyD,UAAkBsyD,mBAA1B,SACwB3uD,EAC+BkmD,GAFvD,GAAAh3C,GA0CCV,KAtCeogD,EAAG,SAAW36B,GACnBv5B,QAAMO,MAAgC,gCAC/Cg5B,GACYiyB,GAAOjrD,QACP2zD,EAAW1I,EAAMjrD,MAAKsK,KAClC2gD,GAEA,IAAmB2I,GAAA,GAAoBzI,KACjC5xC,KAAE,SAAQ9H,GACT,GAASw5C,EAAM1xC,KAAE,CACZ/Y,EACIiR,EAAKmb,KAAK9U,MAAK,EAEvB,kDACF,IAAShG,GAAWL,EAAKmb,KAAIxhB,IAAK6I,EAAOk+C,EAEjClH,GAAK1xC,KACX,GAAoBxH,IACdkC,EAAU3C,UACV2C,EAAKk+C,EACNrgD,EACKL,EAGdO,cAEGhS,MACJ2zD,IACmBE,EAAOtgD,KAAiB+9C,EAAOh1B,OACtCnb,GAAOS,OAAKrO,KAAK4+C,EAAMjoD,MACvB0pD,EAEb7uD,EAEI,OAAC,YACQ6uD,EAAQtI,OACjBr3C,EAAiBq9C,EAAS1wB,SAChCizB,KAGFT,EAAAhyD,UAAGgK,IAAH,cAAA6I,GAuCCV,IArCO,OADmB9Q,GAAwB,wBAAW1D,UAAK,GAC3D,GAAYg5B,IAAA,EAChB,SAA8ClqB,EAAkBC,GAC9D,GAAc8yB,GAAA3sB,EAA0By/C,oBAET3xB,6BAAM,EACHT,gCAAM,EACfO,uBACtB,IAEKtoB,KAAE,SAAiC6nB,GAG1BR,KAEFQ,EAAO9Y,QAAQ8Y,EAAS6R,SAAWjhC,UAQpClE,EACJ,GAAkB7M,IACZC,GAAQwH,QACmC,0DAI5CmF,EACTuzB,IAEGphC,MAGX8N,OAGLslD,KAEDrhD,GAAA,WACE,QAAA+hD,GAC+BjB,EACJV,EACQ4B,EACNC,GAHnBzgD,KAAUs/C,EAAWA,EACrBt/C,KAAI4+C,EAAaA,EAClB5+C,KAASwgD,GAAiBA,EACzBxgD,KAAUygD,GACjBA,EAwFL,MAtFEF,GAAA1yD,UAAI+Y,KAAJ,WAEK,GADsB1X,EAAwB,wBAAW1D,UAAK,IACxDwU,KAAWwgD,GAClB,KAAM,IAAkB9yD,IAClBC,GAAUoH,UAC+C,4GAI3D,OAAKiL,MAAc0gD,cAAK1gD,KAAUwgD,GAC1C55C,OAEA25C,EAAA1yD,UAAGgK,IAAH,SAAyCye,GAEpC,GADsBpnB,EAAuB,uBAAW1D,UAAK,IACvDwU,KAAWwgD,GAClB,KAAM,IAAkB9yD,IAClBC,GAAUoH,UAC+C,2GAIjE,IAAW1G,GAAO2R,KAAUwgD,GAAK55C,KAAMlT,MAChB4J,GAAuB,uBAC5CgZ,GACI,YAAoB/nB,KAAdF,MAA0BE,GAAOyR,KAAa2gD,aAC5DtyD,IAEAH,OAAAwR,eAAI6gD,EAAA1yD,UAAE,M5BunbAgK,I4BvnbN,WACQ,MAAKmI,MAAK4+C,EAAKjoD,KACvB+N,e5BwnbM7B,YAAY,EACZC,c4BznbL,IAED5U,OAAAwR,eAAI6gD,EAAA1yD,UAAG,O5B0nbDgK,I4B1nbN,WACQ,MAAC,IAAqBmG,IAAKgC,KAAK4+C,EAAM5+C,KAC9Cs/C,I5B2nbMz8C,YAAY,EACZC,c4B5nbL,IAED5U,OAAAwR,eAAI6gD,EAAA1yD,UAAM,U5B6nbJgK,I4B7nbN,WACQ,MACR,QADamI,KAAUwgD,I5B+nbjB39C,YAAY,EACZC,c4B/nbL,IAED5U,OAAAwR,eAAI6gD,EAAA1yD,UAAQ,Y5BgobNgK,I4BhobN,WACQ,OACYm2B,iBACS,OAAnBhuB,KAAUwgD,IAAiBxgD,KAAUwgD,GAAkB35C,kBACpDpI,UAAMuB,KAEnBygD,K5BgobM59C,YAAY,EACZC,c4BjobL,IAEOy9C,EAAA1yD,UAAa6yD,cAArB,SAAuC95C,GAAvC,GAAAlG,GAMCV,KALa/Q,IAIN,OAHF2X,GAAQ/X,QAAC,SAAIZ,EAAOI,GAChBY,EAAKhB,GAAOyS,EAAaigD,aACjCtyD,KAEFY,GAEQsxD,EAAA1yD,UAAY8yD,aAApB,SAAsCtyD,GACjC,GAAMA,YAAwBse,IACzB,MAAK3M,MAAc0gD,cAC3BryD,EAAM,IAAUA,YAAuBkf,IAC/B,MAAKvN,MAAa4gD,aAC1BvyD,EAFU,IAEMA,YAAqBme,IAAE,CACrC,GAASve,GAAQI,EAASA,QACZmV,EAAOxD,KAAWs/C,EAAyBb,yBAAcz7C,YAajE,OAZI3U,GAAW2U,WAAO9Q,OAAWsR,IAElCjX,EACD,YAAgByT,KAAK4+C,EAAKjoD,KAAuB,+DAEvCtI,EAAW2U,WAAUO,UAAA,IAASlV,EAAW2U,WACtCQ,SAAiB,wFAEPA,EAAUD,UAAA,IAAYC,EAASA,SAAI,cAIvD,GAAqBxF,IAAI/P,EAAM+R,KACxCs/C,GACQ,MAAMjxD,GACdA,SAGMkyD,EAAA1yD,UAAY+yD,aAApB,SAAqCh6C,GAArC,GAAAlG,GAICV,IAHO,OAAA4G,GAAmByE,cAAIrf,IAAC,SAAKqC,GAC3B,MAAKqS,GAAaigD,aAC1BtyD,MAEHkyD,KAEDM,GAAA,WACE,QAAAhzC,GAAwCizC,EAA+B/iD,GAApDiC,KAAM8gD,GAAeA,EAAW9gD,KAASjC,UAAcA,EAud5E,MArdE8P,GAAAhgB,UAAK+zB,MAAL,SACmCluB,EACHqtD,EAClB1yD,GAEaa,EAAc,cAAW1D,UAAK,GACxCsE,EAAc,cAAU,SAAG,EAASixD,GACpCzvD,EAAc,cAAG,EAASjD,EACzC,IAAeyY,GACAwP,EAAwBhZ,GAAc,cAAS5J,EAC3D,IAAU4iB,EAAc5Q,aACtB,GAA2B,gBAAdrX,GAAgB,CAC3B,IAA2B,IAArBA,EAAQsD,QAAK,KAEpB,KAAM,IAAkBjE,IAClBC,GAAiBC,iBACyC,2JAK/D,IAAc,KAARS,EACP,KAAM,IAAkBX,IAClBC,GAAiBC,iBACyC,8JAKlE,IAAU+I,GAAOqJ,KAAO8gD,GAAKnqD,KAAMuN,MAAC,GAAgB5L,KAAWjK,IACzDpB,GAAK0J,EAAOlL,OAAI,GAAM,EAAmC,iCACrDqb,EAAG,GAAY0F,IACnBxM,KAAUjC,UAAYijD,GAC1B,GAAe/6C,IAEnBtP,QAAM,MAAUtI,YAA8B2P,KAI5C,KAAM,IAAkBtQ,IAClBC,GAAiBC,iBACyC,2JAGzCiD,EAAOxC,GAEhC,IAVE,IAASujC,GAA8BvjC,CAC7ByY,GAAG,GAAY0F,IAAKxM,KAAUjC,UAAYijD,GAAKpvB,EAC3DgtB,OAUU93C,GAAO9G,KAAUjC,UAAe8gD,EAAgBlC,gBAC3C,cAGjBtuD,EACA,IAAY8W,GAAc1R,EACf6iB,EACCxiB,GAAWoR,WAAO67C,GAE5Bj6C,EAEI,OADF9G,MAAkBihD,kBAAS97C,GACxB,GAAS0I,GAAK7N,KAAO8gD,GAAU1xC,UAAQjK,GAAMnF,KACtDjC,YAEA8P,EAAAhgB,UAAOihB,QAAP,SACmCpb,EACQwtD,GAEd1xD,EAAgB,gBAAWhE,UAAG,EAAK,GACvC4E,EAAgB,gBAAU,SAAG,EAAgB8wD,EACpE,IAAyB/8B,EACtB,QAA2B51B,KAAd2yD,GAAyC,QAAXA,EACnC/8B,EAAYlV,GACvBC,cAAM,IAA6B,SAAZgyC,EAGrB,KAAM,IAAkBxzD,IAClBC,GAAiBC,iBACrB,mDAA+DszD,EAAK,+BAJ7D/8B,GAAYlV,GACvBoC,WAOG,GAA8B,OAAzBrR,KAAO8gD,GAAQ9yC,QACrB,KAAM,IAAkBtgB,IAClBC,GAAiBC,iBACiC,yGAIvD,IAA4B,OAAvBoS,KAAO8gD,GAAM7yC,MACnB,KAAM,IAAkBvgB,IAClBC,GAAiBC,iBAC+B,sGAIxD,IAAe0oB,GAAwBhZ,GAAgB,gBAAS5J,GACnDob,EAAG,GAAWH,IAAU2H,EAAa6N,EAE5C,OADFnkB,MAAmBmhD,mBAAUryC,GAC1B,GAASjB,GAAK7N,KAAO8gD,GAAWvxC,WAAST,GAAM9O,KACxDjC,YAEA8P,EAAAhgB,UAAKwW,MAAL,SAAeuF,GAGV,GAFsB1a,EAAc,cAAW1D,UAAK,GACxCsE,EAAc,cAAU,SAAG,EAAK8Z,GAC1CA,GAAM,EACT,KAAM,IAAkBlc,IAClBC,GAAiBC,iBACrB,+BAAgCgc,EAA8B,wCAI5D,OAAC,IAASiE,GAAK7N,KAAO8gD,GAAUrxC,UAAG7F,GAAM5J,KACjDjC,YAEA8P,EAAAhgB,UAAOmgB,QAAP,SACgDozC,G5Bykb1C,I4BxkbJ,GAAA9sC,MAAA/oB,EAAkB,EAAlBA,EAAAC,UAAkBC,OAAAF,IAAlB+oB,EAAA/oB,EAAA,GAAAC,UAAkBD,EAES+D,GAAgB,gBAAW9D,UAAK,EAC3D,IAAWmkB,GAAO3P,KAAqBqhD,qBACtB,gBACLD,EACJ9sC,GAEN,EACI,OAAC,IAASzG,GAAK7N,KAAO8gD,GAAYpxC,YAAOC,GAAM3P,KACvDjC,YAEA8P,EAAAhgB,UAAUyzD,WAAV,SACgDF,G5Bqkb1C,I4BpkbJ,GAAA9sC,MAAA/oB,EAAkB,EAAlBA,EAAAC,UAAkBC,OAAAF,IAAlB+oB,EAAA/oB,EAAA,GAAAC,UAAkBD,EAES+D,GAAmB,mBAAW9D,UAAK,EAC9D,IAAWmkB,GAAO3P,KAAqBqhD,qBACnB,mBACRD,EACJ9sC,GAEN,EACI,OAAC,IAASzG,GAAK7N,KAAO8gD,GAAYpxC,YAAOC,GAAM3P,KACvDjC,YAEA8P,EAAAhgB,UAAS0zD,UAAT,SACgDH,G5Bikb1C,I4BhkbJ,GAAA9sC,MAAA/oB,EAAkB,EAAlBA,EAAAC,UAAkBC,OAAAF,IAAlB+oB,EAAA/oB,EAAA,GAAAC,UAAkBD,EAES+D,GAAkB,kBAAW9D,UAAK,EAC7D,IAAWmkB,GAAO3P,KAAqBqhD,qBACpB,kBACPD,EACJ9sC,GAEN,EACI,OAAC,IAASzG,GAAK7N,KAAO8gD,GAAUlxC,UAAOD,GAAM3P,KACrDjC,YAEA8P,EAAAhgB,UAAKogB,MAAL,SACgDmzC,G5B6jb1C,I4B5jbJ,GAAA9sC,MAAA/oB,EAAkB,EAAlBA,EAAAC,UAAkBC,OAAAF,IAAlB+oB,EAAA/oB,EAAA,GAAAC,UAAkBD,EAES+D,GAAc,cAAW9D,UAAK,EACzD,IAAWmkB,GAAO3P,KAAqBqhD,qBACxB,cACHD,EACJ9sC,GAEN,EACI,OAAC,IAASzG,GAAK7N,KAAO8gD,GAAUlxC,UAAOD,GAAM3P,KACrDjC,YAGQ8P,EAAAhgB,UAAoBwzD,qBAA5B,SACoB9jD,EAC4B6jD,EAC/B9sC,EACA9C,GAGZ,GADYlgB,EAAWiM,EAAG,EAAc6jD,GAC7BA,YAA6B5iD,IAAE,CACxC,GAAO8V,EAAO7oB,OAAK,EACpB,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACrB,kCAA4C2P,EAEhD,MACA,IAAUswB,GAAcuzB,CACrB,KAAMvzB,EAAQ9Y,OACf,KAAM,IAAkBrnB,IAClBC,GAAUoH,UACwC,uDACvCwI,EAEnB,MACM,OAAKyC,MAAkBwhD,kBAAWjkD,EAAMswB,EAAW2yB,GAC3DhvC,GACE,GAAeiwC,IAAeL,GAAO90D,OAASgoB,EACxC,OAAKtU,MAAgB0hD,gBAAWnkD,EAAWkkD,EACnDjwC,IAaM3D,EAAAhgB,UAAiB2zD,kBAAzB,SACoBjkD,EACLgB,EACEiT,GAWX,IAAkB,GATNmwC,MASMp2D,EAAmB,EAAnBsjB,EAAI7O,KAAO8gD,GAAQhyC,QAAnBvjB,EAAAsjB,EAAmBpjB,OAAAF,IAAA,CAApC,GAAaujB,GAAAD,EAAAtjB,EACb,IAAQujB,EAAMpb,MAAcgS,aACnBi8C,EAAK7oD,KAAC,GAAY0T,IAAKxM,KAAUjC,UAAYijD,GAAKziD,EAC9DtQ,UAAQ,CACN,GAAWI,GAAMkQ,EAAM7K,MAAQob,EAAQpb,MACpC,QAAqBnF,KAAfF,EAED,CACN,GAAWqF,GAAUob,EAAMpb,MAAmBuR,iBAC9C,MAAM,IAAkBvX,IAClBC,GAAiBC,iBAC2C,+FACxB8F,EAAiB,2CANjDiuD,EAAK7oD,KACjBzK,IAWE,MAAC,IAASijB,IAAWqwC,EAC7BnwC,IAKQ3D,EAAAhgB,UAAe6zD,gBAAvB,SACoBnkD,EACHmhB,EACAlN,GAGf,GAAa1C,GAAO9O,KAAO8gD,GAAiBhzC,eACzC,IAAO4Q,EAAOjzB,OAAUqjB,EAAQrjB,OACjC,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACrB,kCAA4C2P,EAAM,kGAOlD,KAAC,GADWokD,MACNvvD,EAAI,EAAGA,EAASssB,EAAOjzB,OAAK2G,IAAG,CACvC,GAAcwvD,GAASljC,EAAItsB,EAExB,IAD6B0c,EAAI1c,GACVsB,MAAcgS,aAAE,CACrC,GAA8B,gBAAdk8C,GACjB,KAAM,IAAkBl0D,IAClBC,GAAiBC,iBACiC,uDACvC2P,EAAiB,sBAEpC,KAAAqkD,EAAA,YAAAvE,GAAAuE,IACG,KAA8B,IAArBA,EAAQjwD,QAAK,KACvB,KAAM,IAAkBjE,IAClBC,GAAiBC,iBACrB,+BAAuCg0D,EAAwB,yBAChDrkD,EAEnB,KACA,IAAStP,GAAG,GAAegY,IAAKjG,KAAO8gD,GAAKnqD,KAAMuN,MAAY09C,GACpDD,GAAK7oD,KAAC,GAAY0T,IAAKxM,KAAUjC,UAAYijD,GACzD/yD,QAAQ,CACN,GAAa4zD,GAAO7hD,KAAUjC,UAAe8gD,EAAgBlC,gBACjDp/C,EAEVqkD,EACQD,GAAK7oD,KACjB+oD,IAGI,MAAC,IAASvwC,IAAWqwC,EAC7BnwC,IAmBA3D,EAAAhgB,UAAUiyD,WAAV,W5B2/aM,I4B3/aK,GAAA/zD,MAAAR,EAAgB,EAAhBA,EAAAC,UAAgBC,OAAAF,IAAhBQ,EAAAR,GAAAC,UAAgBD,EACEiE,GAAmB,mBAAWhE,UAAG,EAAK,EACjE,IACuDksD,GAD5ClmD,KAEAwuD,EAAK,CA+CV,OA7C6B,WAAjC3C,GAAWtxD,EAASi0D,KACF1jD,GAAKvQ,EACxBi0D,MACQxuD,EAAOzF,EAA0Ci0D,GACrCzuD,EAAmB,mBAASC,GAChB,8BAE5B,mCACsBjB,EACL,mBACT,UACuB,iCACzBiB,EACPu8B,gCACuBx9B,EACL,mBACT,UACoB,8BACtBiB,EACPg9B,6BAEJwxB,KAEqB1jD,GAAKvQ,EAAWi0D,IAC3BtI,EAAO3rD,EACjBi0D,IACiBlwD,EAAmB,mBAAY,WAASkwD,EAAMj0D,EAAWi0D,IACjD5vD,EACH,mBACR,WACH4vD,EAAI,EACPj0D,EAAQi0D,EACZ,IACqB5vD,EACH,mBACR,WACH4vD,EAAI,EACPj0D,EAAQi0D,EACZ,IACMtI,GACF1xC,KAAMja,EAA4Ci0D,GACjDvzD,MAAMV,EAAQi0D,EAAgB,GAC3BE,SAAMn0D,EAAQi0D,EAE1B,KACWhgD,KAAmBmgD,mBAAQ3uD,EACxCkmD,IAEQ7pC,EAAAhgB,UAAkBsyD,mBAA1B,SACwB3uD,EAC4BkmD,GAFpD,GAAAh3C,GA8BCV,KA1BeogD,EAAG,SAAW36B,GACnBv5B,QAAMO,MAAgC,gCAC/Cg5B,GACYiyB,GAAOjrD,QACP2zD,EAAW1I,EAAMjrD,MAAKsK,KAClC2gD,GAEA,IAAmB2I,GAAA,GAAoBzI,KACjC5xC,KAAE,SAAqB/W,GACbyoD,EAAM1xC,MACR0xC,EAAK1xC,KAAC,GAAiB87C,IAAKphD,EAAU3C,UAAM2C,EAAOogD,GAC7D7xD,KAEGxC,MACJ2zD,IAEkB2B,EAAO/hD,KAAUjC,UAA0B0gD,yBAC1C6B,EAAkByB,EAAOh5B,OACzC/oB,KAAO8gD,GACET,EAEb7uD,EACI,OAAC,YACQ6uD,EAAQtI,OACNgK,EAAS10B,SAC1BizB,KAGFzyC,EAAAhgB,UAAGgK,IAAH,cAAA6I,GAuBCV,IArBO,OADmB9Q,GAAY,YAAW1D,UAAK,GAC/C,GAAYg5B,IAAA,EAChB,SAA2ClqB,EAAkBC,GAC3D,GAAc8yB,GAAA3sB,EAA0By/C,oBAENpyB,gCAAO,EACVS,6BAAM,EACZF,uBACtB,IAEKtoB,KAAE,SAAgC/W,GAGzBo+B,IAEJ/yB,EACTrL,IACKxC,MAGX8N,OAIIsT,EAAAhgB,UAAiBozD,kBAAzB,SAAwC97C,GACnC,GAAOA,YAA0B/Q,KAAU+Q,EAAgBkK,eAAE,CAC9D,GAAmB2yC,GAAOhiD,KAAO8gD,GAA4BvyC,0BAC1D,IAAuB,OAATyzC,IAA2BA,EAAO9vD,OAAOiT,EAAQzR,OAChE,KAAM,IAAkBhG,IAClBC,GAAiBC,iBACgC,wIAEXo0D,EAAc,UACvC78C,EAAMzR,MAE3B,IAEA,IAAuB8a,GAAOxO,KAAO8gD,GAAwBryC,sBAC9B,QAAVD,GACfxO,KAAkCiiD,kCAAO98C,EAAMzR,MACrD8a,KAIIX,EAAAhgB,UAAkBszD,mBAA1B,SAA2CryC,GACtC,GAA6C,OAAxC9O,KAAO8gD,GAAuBryC,uBAAY,CAEhD,GAAqBH,GAAOtO,KAAO8gD,GAA4BvyC,0BAClC,QAAVD,GACbtO,KAAkCiiD,kCAAgB3zC,EAASQ,EACjEpb,SAIIma,EAAAhgB,UAAiCo0D,kCAAzC,SACuBC,EACHpzC,GAEf,IAASA,EAAO5c,OAAagwD,GAC9B,KAAM,IAAkBx0D,IAClBC,GAAiBC,iBACuC,yFACjBs0D,EAAe,+BACjBA,EAAe,gFAE/BpzC,EAE7B,eAEHjB,KAEDi0C,GAAA,WAKE,QAAAK,GAC+B7C,EACQ8C,EACNC,GAFvBriD,KAAUs/C,EAAWA,EACrBt/C,KAAcoiD,GAAeA,EAC7BpiD,KAASqiD,GAAcA,EAPzBriD,KAAcsiD,GAA2C,KAS3DtiD,KAAS0/B,UACFjhC,UAAW4jD,EAAU5jD,UACduvB,iBAAWq0B,EAE/Br0B,kBAiDF,MA/CE9/B,QAAAwR,eAAIyiD,EAAAt0D,UAAI,Q5B47aFgK,I4B57aN,WACE,GAAY5I,KAEN,OADF+Q,MAAQnR,QAAC,SAAG0P,GAAI,MAAMtP,GAAK6J,KAAKyF,KAEtCtP,G5B+7aM4T,YAAY,EACZC,c4Bh8aL,IAED5U,OAAAwR,eAAIyiD,EAAAt0D,UAAK,S5Bi8aHgK,I4Bj8aN,WACQ,MAAKmI,MAAUqiD,GAAKhpC,KAC5BvqB,W5Bk8aM+T,YAAY,EACZC,c4Bn8aL,IAED5U,OAAAwR,eAAIyiD,EAAAt0D,UAAI,Q5Bo8aFgK,I4Bp8aN,WACQ,MAAKmI,MAAUqiD,GAAKhpC,KAC5B9U,M5Bq8aM1B,YAAY,EACZC,c4Bt8aL,IAEDq/C,EAAAt0D,UAAOgB,QAAP,SACwDq2B,EACvCq9B,GAFjB,GAAA7hD,GASCV,IAL4BxQ,GAAwB,wBAAWhE,UAAG,EAAK,GACvDsE,EAAwB,wBAAY,WAAG,EAAYo1B,GAC9DllB,KAAUqiD,GAAKhpC,KAAQxqB,QAAC,SAAG0P,GACrB2mB,EAAK/2B,KAAQo0D,EAAM7hD,EAAsB8hD,sBACnDjkD,OAGFrQ,OAAAwR,eAAIyiD,EAAAt0D,UAAK,S5Bo8aHgK,I4Bp8aN,WACQ,MAAC,IAASgpD,IAAK7gD,KAAeoiD,GAAMpiD,KAC5Cs/C,I5Bq8aMz8C,YAAY,EACZC,c4Bt8aL,IAED5U,OAAAwR,eAAIyiD,EAAAt0D,UAAU,c5Bu8aRgK,I4Bv8aN,WAOQ,MANGmI,MAAgBsiD,KACnBtiD,KAAesiD,GAAsBrkD,GACnC+B,KAAWs/C,EACXt/C,KAERqiD,KACWriD,KACbsiD,I5Bq8aMz/C,YAAY,EACZC,c4Bt8aL,IAEOq/C,EAAAt0D,UAAqB20D,sBAA7B,SAA2CjkD,GACnC,MAAC,IAAoBC,IACrBwB,KAAWs/C,EACZ/gD,EAAItQ,IACJsQ,EACCyB,KAAS0/B,SAEjBjhC,YACD0jD,KAEDnD,GAAA,SAAAv+C,GAEE,QAAAgiD,GAA8B9rD,EAAsBoH,GAApD,GAAA2C,GACED,EAAAtS,KAAA6R,KAAmB4N,GAAOS,OAAM1X,GAAYoH,IAS7CiC,IARI,IAAKrJ,EAAOlL,OAAI,GAAO,EACxB,KAAM,IAAkBiC,IAClBC,GAAiBC,iBACsB,gGAElC+I,EAAkBsO,kBAAA,QAAYtO,EAE3ClL,O5B87aI,O4B77aNiV,GA4CF,MAxDyC48C,IAAAmF,EAAKhiD,GAc5CvS,OAAAwR,eAAI+iD,EAAA50D,UAAE,M5B87aAgK,I4B97aN,WACQ,MAAKmI,MAAO8gD,GAAKnqD,KACzB+N,e5B+7aM7B,YAAY,EACZC,c4Bh8aL,IAED5U,OAAAwR,eAAI+iD,EAAA50D,UAAM,U5Bi8aJgK,I4Bj8aN,WACE,GAAgB6qD,GAAO1iD,KAAO8gD,GAAKnqD,KAAW6N,SAC3C,OAAWk+C,GAAW5zD,UAEzB,KACS,GAAqBkP,IAAC,GAAeiI,IAAYy8C,GAAM1iD,KAChEjC,Y5Bm8aI8E,YAAY,EACZC,c4Bn8aL,IAED5U,OAAAwR,eAAI+iD,EAAA50D,UAAI,Q5Bo8aFgK,I4Bp8aN,WACQ,MAAKmI,MAAO8gD,GAAKnqD,KACzBsO,mB5Bq8aMpC,YAAY,EACZC,c4Bt8aL,IAED2/C,EAAA50D,UAAG0Q,IAAH,SAAuBwgD,GAMlB,GALwBvvD,EAA0B,0BAAWhE,UAAG,EAAK,GACjD4E,EAA0B,0BAAU,SAAG,EAAc2uD,OAC/CxwD,KAAfwwD,IACFA,EAASj+C,GACrBE,SACkC,gBAAb+9C,IAAmC,KAARA,EAC9C,KAAM,IAAkBrxD,IAClBC,GAAiBC,iBAGzB,2CACA,IAAU+I,GAAe2B,GAAW4M,WAAa65C,EAC3C,OAAkB/gD,IAAQihD,QAC1Bj/C,KAAO8gD,GAAKnqD,KAAMuN,MAAMvN,GACxBqJ,KAERjC,YAEA0kD,EAAA50D,UAAGmR,IAAH,SAAiC3Q,GACNa,EAA0B,0BAAW1D,UAAK,GACpDsE,EAA0B,0BAAU,SAAG,EAASzB,EAC/D,IAAYs0D,GAAO3iD,KAAOzB,KACpB,OAAAokD,GAAW11C,IAAO5e,GAAK++B,KAAC,WAAM,MAAMu1B,MAE7CF,GAAA5B,IAsH2B+B,GAAyBt1D,EAC1CgS,GAET,qCAC4BujD,GAAyBv1D,EAC1C4xD,GAEX,sDAC2B4D,GAAyBx1D,EAC1C6xD,GAEV,6CACkC4D,GAAyBz1D,EAC1C0Q,GAEjB,2CACiCglD,GAAyB11D,EAAmBkR,IACvDykD,GAAyB31D,EAAQuzD,IACzBqC,GAAyB51D,EAAgBw0D,IACnCqB,GAAyB71D,EAC1C0xD,GAEnB,kDCzuDsBz/C,IACbs+C,UAAiB+E,GAClBrgD,SAAUxF,GACduE,KAAYgB,GACL0wC,YAAmB6P,GACpBpD,WAAkBqD,GACXjD,kBAAyBkD,GAC1BxC,iBAAwByC,GACnCn1C,MAAao1C,GACLd,cAAqBe,GACfT,oBAA2BU,GACrC79C,UAAWxO,GACVmU,WAAkB4vC,GACjB5vD,YAAWqU,GACtBrU,YCnCAJ,GAAA,kBAAA2U,GAWeA,GAAWG,GAAA,U9BytetByjD,GACA,SAAUx4D,OAAQy4D,QAASv4D,sBkFnvejC,WAAwC,QAAAw4D,GAAAC,GAAc,sBAAAA,GAAyB,QAAAC,OAC/E,QAAAC,IAAAF,GAAe,GAAAljD,SAAAkjD,EAAe,cAAAljD,EAAA,KAAAkjD,EAAye,YAApd,IAAAA,YAAA1zD,OAAA,aAAoC,IAAA0zD,YAAAr1D,QAAA,MAAAmS,EAAgC,IAAArI,GAAA9J,OAAAL,UAAA8S,SAAAxS,KAAAo1D,EAAwC,uBAAAvrD,EAAA,cAAuC,sBAAAA,GAAA,gBAAAurD,GAAA93D,YAAA,KAAA83D,EAAAx3B,YAAA,KAAAw3B,EAAAG,uBAAAH,EAAAG,qBAAA,uBAA6K,yBAAA1rD,OAAA,KAAAurD,EAAAp1D,UAAA,KAAAo1D,EAAAG,uBAAAH,EAAAG,qBAAA,6BACnX,gBAAArjD,OAAA,KAAAkjD,EAAAp1D,KAAA,cAAiE,OAAAkS,GAAS,QAAAuJ,GAAA25C,GAAc,eAAAE,GAAAF,GAAqB,QAAAI,IAAAJ,GAAe,GAAAljD,GAAAojD,GAAAF,EAAY,gBAAAljD,GAAA,UAAAA,GAAA,gBAAAkjD,GAAA93D,OAAyD,QAAAm4D,IAAAL,GAAe,kBAAAE,GAAAF,GAAwB,QAAAjjD,GAAAijD,GAAc,GAAAljD,SAAAkjD,EAAe,iBAAAljD,GAAA,MAAAkjD,GAAA,YAAAljD,EAA4F,QAAAwjD,IAAAN,EAAAljD,EAAArI,GAAmB,MAAAurD,GAAAp1D,KAAA/B,MAAAm3D,EAAAxsD,KAAAvL,WACpX,QAAAs4D,IAAAP,EAAAljD,EAAArI,GAAmB,IAAAurD,EAAA,KAAAv2D,QAAoB,MAAAxB,UAAAC,OAAA,CAAuB,GAAA2U,GAAAvQ,MAAAhC,UAAAuW,MAAAjW,KAAA3C,UAAA,EAA8C,mBAAkB,GAAAwM,GAAAnI,MAAAhC,UAAAuW,MAAAjW,KAAA3C,UAA+E,OAAnCqE,OAAAhC,UAAAk2D,QAAA33D,MAAA4L,EAAAoI,GAAmCmjD,EAAAn3D,MAAAiU,EAAArI,IAAqB,kBAAkB,MAAAurD,GAAAn3D,MAAAiU,EAAA7U,YAA6B,QAAAw4D,GAAAT,EAAAljD,EAAArI,GAAmH,MAAjGgsD,GAAAC,SAAAp2D,UAAAkJ,OAAA,IAAAktD,YAAAp2D,UAAAkJ,MAAApF,QAAA,eAAAkyD,GAAAC,GAAiGE,EAAA53D,MAAA,KAAAZ,WACpY,QAAA04D,IAAAX,EAAAljD,GAAiB,GAAArI,GAAAnI,MAAAhC,UAAAuW,MAAAjW,KAAA3C,UAAA,EAA8C,mBAAkB,GAAA6U,GAAArI,EAAAoM,OAA0C,OAA1B/D,GAAAvH,KAAA1M,MAAAiU,EAAA7U,WAA0B+3D,EAAAn3D,MAAA4T,KAAAK,IAAoE,QAAA8jD,GAAAZ,EAAAljD,GAAgB,QAAArI,MAAcA,EAAAnK,UAAAwS,EAAAxS,UAAwB01D,EAAAa,EAAA/jD,EAAAxS,UAAgB01D,EAAA11D,UAAA,GAAAmK,GAAkBurD,EAAA11D,UAAAqD,YAAAqyD,EAA0BA,EAAAc,GAAA,SAAAd,EAAAvrD,EAAAqrB,GAAqB,OAAAjjB,GAAAvQ,MAAArE,UAAAC,OAAA,GAAAmB,EAAA,EAAwCA,EAAApB,UAAAC,OAAmBmB,IAAAwT,EAAAxT,EAAA,GAAApB,UAAAoB,EAAwB,OAAAyT,GAAAxS,UAAAmK,GAAA5L,MAAAm3D,EAAAnjD,IAAmC,QAAAkkD,IAAAf,GAAe,GAAAv2D,MAAAu3D,kBAAAv3D,MAAAu3D,kBAAAvkD,KAAAskD,QAA4D,CAAK,GAAAjkD,GAAArT,QAAAyrD,KAAoBp4C,KAAAL,KAAAy4C,MAAAp4C,GAAkBkjD,IAAAvjD,KAAAjT,QAAAw2D,EAAA9wD,IAAwE,QAAA+xD,IAAAjB,EAAAljD,GAAiB,OAAArI,GAAAurD,EAAAvsD,MAAA,MAAAoJ,EAAA,GAAAxT,EAAAiD,MAAAhC,UAAAuW,MAAAjW,KAAA3C,UAAA,GAAuEoB,EAAAnB,QAAA,EAAAuM,EAAAvM,QAAqB2U,GAAApI,EAAAm+C,QAAAvpD,EAAAupD,OAAwB,OAAA/1C,GAAApI,EAAApG,KAAA,MAA2I,QAAA6yD,IAAAlB,EAAAljD,GAAiB,MAAAkjD,GAAAljD,GAAA,EAAAkjD,EAAAljD,EAAA,IAAuB,QAAAqkD,IAAAnB,EAAAljD,GAAiBA,EAAA0jD,QAAAR,GAAae,GAAAn2D,KAAA6R,KAAAwkD,GAAAp4D,MAAA,KAAAiU,IAA+BA,EAAA81C,QAAsD,QAAAwO,IAAApB,EAAAljD,GAAiB,SAAAqkD,IAAA,WAAAnB,EAAA,KAAAA,EAAA,IAAA1zD,MAAAhC,UAAAuW,MAAAjW,KAAA3C,UAAA,IAAgF,QAAAo5D,KAAa,GAAAC,KAAAC,GAAA9kD,KAAAwsB,KAAAxsB,KAAAwsB,KAAAu4B,KAAA/kD,MAA0CA,KAAA5N,EAAA4N,KAAA5N,EAAc4N,KAAAyI,EAAAzI,KAAAyI,EAC3sC,QAAA6zB,IAAAinB,GAAeA,EAAA,CAAY,OAATljD,GAAA2kD,GAAShtD,EAAAurD,EAAA93D,OAAA2U,EAAAkjD,EAAAC,KAAAvsD,MAAA,IAAAusD,EAAA32D,EAAA,EAA4CA,EAAAoL,EAAIpL,IAAA,GAAAA,IAAAwT,IAAAC,EAAAlS,SAAA,GAAAiS,EAAAxT,KAAA22D,GAAA,CAAwCljD,EAAAzT,CAAI,MAAA22D,GAAQljD,GAAA,EAAK,SAAAA,EAAA,KAAAijD,EAAAC,KAAA/wD,OAAA6N,GAAAkjD,EAAAljD,GAAsC,QAAA4kD,IAAA1B,GAAe,IAAA35C,EAAA25C,GAAA,OAAAljD,GAAAkjD,EAAA93D,OAAA,EAA8B,GAAA4U,EAAKA,UAAAkjD,GAAAljD,EAAgBkjD,GAAA93D,OAAA,EAAW,QAAAy5D,IAAA3B,GAAe,MAAA1zD,OAAAhC,UAAAvB,OAAAF,SAAAZ,WAAkD,QAAA25D,IAAA5B,GAAe,GAAAljD,GAAAkjD,EAAA93D,MAAe,MAAA4U,EAAA,CAAQ,OAAArI,GAAAnI,MAAAwQ,GAAAD,EAAA,EAAuBA,EAAAC,EAAID,IAAApI,EAAAoI,GAAAmjD,EAAAnjD,EAAc,OAAApI,GAAS,SAA2F,QAAAotD,GAAA7B,GAAc,UAAA8B,EAAA1zD,QAAA4xD,GAAwB,QAAA+B,IAAA/B,EAAAljD,EAAArI,GAAmB,OAAAoI,KAAAmjD,GAAAljD,EAAAlS,KAAA6J,EAAAurD,EAAAnjD,KAAAmjD,GAAkC,QAAAgC,IAAAhC,GAAe,GAAAnjD,GAAAC,KAAArI,EAAA,CAAe,KAAAoI,IAAAmjD,GAAAljD,EAAArI,KAAAurD,EAAAnjD,EAAuB,OAAAC,GAAS,QAAAmlD,IAAAjC,GAAe,GAAAnjD,GAAAC,KAAArI,EAAA,CAAe,KAAAoI,IAAAmjD,GAAAljD,EAAArI,KAAAoI,CAAoB,OAAAC,GAAS,QAAAolD,IAAAlC,GAAe,GAAQvrD,GAARqI,IAAW,KAAArI,IAAAurD,GAAAljD,EAAArI,GAAAurD,EAAAvrD,EAAqB,OAAAqI,GAC9uB,QAAAqlD,IAAAnC,EAAAljD,GAAiB,OAAArI,GAAAoI,EAAAxT,EAAA,EAAgBA,EAAApB,UAAAC,OAAmBmB,IAAA,CAAKwT,EAAA5U,UAAAoB,EAAe,KAAAoL,IAAAoI,GAAAmjD,EAAAvrD,GAAAoI,EAAApI,EAAqB,QAAAqrB,GAAA,EAAYA,EAAAsiC,GAAAl6D,OAAY43B,IAAArrB,EAAA2tD,GAAAtiC,GAAAn1B,OAAAL,UAAAE,eAAAI,KAAAiS,EAAApI,KAAAurD,EAAAvrD,GAAAoI,EAAApI,KAAqE,QAAA4tD,IAAArC,GAA0B,MAAXqC,IAAA,KAAArC,GAAWA,EAAoB,QAAAsC,IAAAtC,EAAAljD,GAAiB,GAAArI,GAAA8tD,EAAS,OAAA53D,QAAAL,UAAAE,eAAAI,KAAA6J,EAAAurD,GAAAvrD,EAAAurD,GAAAvrD,EAAAurD,GAAAljD,EAAAkjD,GAA2R,QAAAwC,MAAc,GAAAxC,GAAA/6C,EAAAuW,QAAiB,OAAAwkC,KAAAyC,iBAAA,GAE5jB,QAAAC,IAAA1C,GAAe,MAAAsC,IAAAtC,EAAA,WAAuB,OAAAljD,GAAA,EAAArI,EAAAkuD,GAAAC,GAAA1zD,IAAAuE,MAAA,KAAAoJ,EAAA8lD,GAAA3C,EAAA9wD,IAAAuE,MAAA,KAAApK,EAAAuU,KAAA2rC,IAAA90C,EAAAvM,OAAA2U,EAAA3U,QAAA43B,EAAA,EAAqG,GAAAhjB,GAAAgjB,EAAAz2B,EAAUy2B,IAAA,CAAK,GAAA+iC,GAAApuD,EAAAqrB,IAAA,GAAAqhB,EAAAtkC,EAAAijB,IAAA,EAA0B,IAAuF,GAApF+iC,EAAA,iBAAA/0D,KAAA+0D,KAAA,aAA0C1hB,EAAA,iBAAArzC,KAAAqzC,KAAA,aAA0C,GAAA0hB,EAAA,GAAA36D,QAAA,GAAAi5C,EAAA,GAAAj5C,OAAA,KAAwC4U,GAAAokD,GAAA,GAAA2B,EAAA,GAAA36D,OAAA,EAAAkD,SAAAy3D,EAAA,UAAA1hB,EAAA,GAAAj5C,OAAA,EAAAkD,SAAA+1C,EAAA,SAAA+f,GAAA,GAAA2B,EAAA,GAAA36D,OAAA,GAAAi5C,EAAA,GAAAj5C,SAAAg5D,GAAA2B,EAAA,GAAA1hB,EAAA,IAA8H0hB,IAAA,GAAO1hB,IAAA,SAAO,GAAArkC,GAAY,UAAAA,IACtF,QAAAgmD,GAAA9C,EAAAljD,GAAgBL,KAAAjQ,KAAAwzD,EAAYvjD,KAAAujD,EAAAvjD,KAAAtF,OAAA2F,EAAqBL,KAAAsmD,IAAA,EAAgD,QAAAC,IAAAhD,EAAAljD,GAA2Q,GAA1PgmD,EAAAl4D,KAAA6R,KAAAujD,IAAAxzD,KAAA,IAAyBiQ,KAAAwmD,cAAAxmD,KAAAujD,EAAAvjD,KAAAtF,OAAA,KAA2CsF,KAAAymD,OAAAzmD,KAAA0mD,QAAA1mD,KAAA2mD,QAAA3mD,KAAA4mD,QAAA5mD,KAAA6mD,QAAA,EAAkE7mD,KAAA/R,IAAA,GAAY+R,KAAA8mD,QAAA9mD,KAAA+mD,SAAA/mD,KAAAgnD,OAAAhnD,KAAAinD,SAAA,EAAuDjnD,KAAAknD,UAAA,EAAiBlnD,KAAAmnD,YAAA,GAAoBnnD,KAAAhI,EAAA,KAAYurD,EAAA,CAAM,GAAAvrD,GAAAgI,KAAAjQ,KAAAwzD,EAAAxzD,KAAAqQ,EAAAmjD,EAAA6D,eAAA7D,EAAA6D,eAAA,OAA+G,IAA5CpnD,KAAAtF,OAAA6oD,EAAA7oD,QAAA6oD,EAAA8D,WAAmCrnD,KAAAujD,EAAAljD,EAASA,EAAAkjD,EAAAiD,eAAsB,GAAAc,GAAA,CAAO/D,EAAA,CAAG,IAAIqC,GAAAvlD,EAAAknD,SAAe,IAAA36D,IAAA,CAAS,MAAA22D,GAAQ,MAAAlgC,IAAUz2B,GAAA,EAAKA,IAAAyT,EAAA,WAAa,aAAArI,EAAAqI,EACt7BkjD,EAAAiE,YAAA,YAAAxvD,IAAAqI,EAAAkjD,EAAAkE,UAA6CznD,MAAAwmD,cAAAnmD,EAAqB,OAAAD,GAAAJ,KAAA6mD,YAAA,KAAAtD,EAAAsD,QAAAtD,EAAAsD,QAAAtD,EAAAmE,MAAA1nD,KAAA4mD,YAAA,KAAArD,EAAAqD,QAAArD,EAAAqD,QAAArD,EAAAoE,MAAA3nD,KAAA2mD,QAAApD,EAAAoD,SAAA,EAAA3mD,KAAA0mD,QAAAnD,EAAAmD,SAAA,IAAA1mD,KAAA6mD,YAAA,KAAAzmD,EAAAymD,QAAAzmD,EAAAymD,QAAAzmD,EAAAsnD,MAAA1nD,KAAA4mD,YAAA,KAAAxmD,EAAAwmD,QAAAxmD,EAAAwmD,QAAAxmD,EAAAunD,MAAA3nD,KAAA2mD,QAAAvmD,EAAAumD,SAAA,EAAA3mD,KAAA0mD,QAAAtmD,EAAAsmD,SAAA,GAA6T1mD,KAAAymD,OAAAlD,EAAAkD,OAAqBzmD,KAAA/R,IAAAs1D,EAAAt1D,KAAA,GAAmB+R,KAAAinD,QAAA1D,EAAA0D,QAAuBjnD,KAAAgnD,OAAAzD,EAAAyD,OAAqBhnD,KAAA+mD,SAAAxD,EAAAwD,SAAyB/mD,KAAA8mD,QAC5evD,EAAAuD,QAAU9mD,KAAAknD,UAAA3D,EAAA2D,WAAA,EAA8BlnD,KAAAmnD,YAAA7D,EAAAC,EAAA4D,aAAA5D,EAAA4D,YAAAS,GAAArE,EAAA4D,cAAA,GAAsEnnD,KAAAhI,EAAAurD,EAASA,EAAAsE,kBAAA7nD,KAAAK,KAAwU,QAAArH,IAAAuqD,GAAe,SAAAA,MAAAzrC,KAA6B,QAAAgwC,IAAAvE,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuBoT,KAAA8sB,SAAAy2B,EAAgBvjD,KAAAujD,EAAA,KAAYvjD,KAAA+nD,IAAA1nD,EAAWL,KAAAjQ,KAAAiI,EAAYgI,KAAAgoD,UAAA5nD,EAAiBJ,KAAA4jD,GAAAh3D,EAAUoT,KAAA/R,MAAAg6D,GAAcjoD,KAAAkoD,EAAAloD,KAAAyjD,IAAA,EAAkB,QAAA0E,IAAA5E,GAAeA,EAAA2E,GAAA,EAAO3E,EAAAz2B,SAAA,KAAgBy2B,IAAA,KAASA,EAAAwE,IAAA,KAAWxE,EAAAK,GAAA,KAAW,QAAAwE,IAAA7E,GAAevjD,KAAA+nD,IAAAxE,EAAWvjD,KAAAujD,KAAUvjD,KAAAK,EAAA,EAAS,QAAAgoD,IAAA9E,EAAAljD,EAAArI,EAAAoI,EAAAxT,EAAAy2B,GAAyB,GAAA+iC,GAAA/lD,MAAmBA,EAAAkjD,IAAA6C,MAAS/lD,EAAAkjD,IAAA6C,MAAA7C,EAAAljD,IAAuB,IAAAqkC,GAAA4jB,GAAAjoD,EAAArI,EAAApL,EAAAy2B,EAA0F,QAAxE,EAAAqhB,GAAA6e,EAAAljD,EAAAqkC,GAAAtkC,IAAAmjD,EAAAE,IAAA,KAAAF,EAAA,GAAAuE,IAAA9vD,EAAAurD,EAAAwE,IAAA3B,IAAAx5D,EAAAy2B,GAAAkgC,EAAAE,GAAArjD,EAAAC,EAAAvH,KAAAyqD,IAAwEA,EAAS,QAAAgF,IAAAhF,EAAAljD,GAAiB,GAAArI,GAAAqI,EAAAtQ,IAAa,IAAAiI,IAAAurD,KAAA,CAAa,GAAAlgC,GAAAjjB,EAAAmjD,IAAAvrD,GAAApL,EAAA47D,GAAApoD,EAAAC,IAAyBgjB,EAAA,GAAAz2B,IAAAiD,MAAAhC,UAAAk+B,OAAA59B,KAAAiS,EAAAxT,EAAA,GAA6Cy2B,IAAA8kC,GAAA9nD,GAAA,GAAAkjD,IAAAvrD,GAAAvM,eAAA83D,KAAAvrD,GAAAurD,EAAAljD,OAAoD,QAAAooD,IAAAlF,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAmE,MAA5C22D,OAAAljD,MAAoBA,GAAA,EAAKkjD,IAAAljD,EAAAioD,GAAA/E,EAAAvrD,EAAAoI,EAAAxT,KAAmB,EAAAyT,EAAAkjD,EAAAljD,GAAA,KACznC,QAAAioD,IAAA/E,EAAAljD,EAAArI,EAAAoI,GAAqB,OAAAxT,GAAA,EAAYA,EAAA22D,EAAA93D,SAAWmB,EAAA,CAAK,GAAAy2B,GAAAkgC,EAAA32D,EAAW,KAAAy2B,EAAA6kC,GAAA7kC,EAAAyJ,UAAAzsB,GAAAgjB,EAAA2kC,WAAAhwD,GAAAqrB,EAAAugC,IAAAxjD,EAAA,MAAAxT,GAAyD,SAAgE,QAAA87D,IAAAnF,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuB,GAAAwT,KAAAuoD,KAAA,MAAAC,IAAArF,EAAAljD,EAAArI,EAAAoI,EAAAxT,EAAkC,IAAAgd,EAAAvJ,GAAA,CAAS,OAAAgjB,GAAA,EAAYA,EAAAhjB,EAAA5U,OAAW43B,IAAAqlC,GAAAnF,EAAAljD,EAAAgjB,GAAArrB,EAAAoI,EAAAxT,EAAqB,aAAoB,MAARoL,GAAA6wD,GAAA7wD,GAAQgB,GAAAuqD,KAAAuF,EAAAzoD,EAAArI,EAAAsI,EAAAF,OAAA4nD,UAAA5nD,EAAAxT,GAAAm8D,GAAAxF,EAAAljD,EAAArI,GAAA,EAAAoI,EAAAxT,GACvT,QAAAm8D,IAAAxF,EAAAljD,EAAArI,EAAAoI,EAAAxT,EAAAy2B,GAAyB,IAAAhjB,EAAA,KAAArT,OAAA,qBAAwC,IAAAo5D,GAAA9lD,EAAA1T,OAAAo7D,UAAAp7D,EAAA83C,EAAAskB,GAAAzF,EAA4E,IAAzC7e,IAAA6e,EAAA0F,IAAAvkB,EAAA,GAAA0jB,IAAA7E,IAAuBvrD,EAAAqwD,GAAA3jB,EAAArkC,EAAArI,EAAAoI,EAAAgmD,EAAA/iC,GAAkBrrB,EAAAurD,EAAA,MAAAvrD,EAAkD,IAAlCoI,EAAA8oD,KAAOlxD,EAAAurD,EAAAnjD,EAAMA,EAAA2nD,IAAAxE,EAAQnjD,EAAA0sB,SAAA90B,EAAaurD,EAAApc,iBAAAgiB,KAAAv8D,EAAAw5D,OAAA,KAAAx5D,OAAA,GAAA22D,EAAApc,iBAAA9mC,KAAAD,EAAAxT,OAAwF,KAAA22D,EAAA6F,YAAwD,KAAAp8D,OAAA,oDAAxDu2D,GAAA6F,YAAAC,GAAAhpD,MAAAD,GAAmI,MAALkpD,MAAKtxD,EAC1Z,QAAAkxD,MAAc,GAAA3F,GAAAgG,GAAAlpD,EAAAmpD,GAAA,SAAAxxD,GAA0B,MAAAurD,GAAAp1D,KAAAkS,EAAA0nD,IAAA1nD,EAAAysB,SAAA90B,IAAkC,SAAAA,GAA0C,KAA7BA,EAAAurD,EAAAp1D,KAAAkS,EAAA0nD,IAAA1nD,EAAAysB,SAAA90B,IAA6B,MAAAA,GAAgB,OAAAqI,GAAS,QAAAuoD,IAAArF,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuB,GAAAgd,EAAAvJ,GAAA,CAAS,OAAAgjB,GAAA,EAAYA,EAAAhjB,EAAA5U,OAAW43B,IAAAulC,GAAArF,EAAAljD,EAAAgjB,GAAArrB,EAAAoI,EAAAxT,EAAqB,aAAoB,MAARoL,GAAA6wD,GAAA7wD,GAAQgB,GAAAuqD,KAAAsC,GAAAxlD,EAAArI,EAAAsI,EAAAF,OAAA4nD,UAAA5nD,EAAAxT,GAAAm8D,GAAAxF,EAAAljD,EAAArI,GAAA,EAAAoI,EAAAxT,GAA+D,QAAA68D,IAAAlG,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuB,GAAAgd,EAAAvJ,GAAA,OAAAgjB,GAAA,EAAoBA,EAAAhjB,EAAA5U,OAAW43B,IAAAomC,GAAAlG,EAAAljD,EAAAgjB,GAAArrB,EAAAoI,EAAAxT,OAAqBwT,GAAAE,EAAAF,OAAA4nD,UAAA5nD,EAAApI,EAAA6wD,GAAA7wD,GAAAgB,GAAAuqD,KAAA2B,GAAA7kD,EAAArI,EAAAoI,EAAAxT,GAAA22D,MAAAyF,GAAAzF,MAAAljD,EAAAooD,GAAAlF,EAAAljD,EAAArI,EAAAoI,EAAAxT,KAAA88D,GAAArpD,GACvX,QAAAqpD,IAAAnG,GAAe,mBAAAA,UAAA2E,EAAA,CAAgC,GAAA7nD,GAAAkjD,EAAAwE,GAAY,IAAA/uD,GAAAqH,GAAAkoD,GAAAloD,EAAArI,EAAAurD,OAAmB,CAAK,GAAAvrD,GAAAurD,EAAAxzD,KAAAqQ,EAAAmjD,GAAmBljD,GAAA+mC,oBAAA/mC,EAAA+mC,oBAAApvC,EAAAoI,EAAAmjD,EAAAyE,SAAA3nD,EAAAspD,aAAAtpD,EAAAspD,YAAAN,GAAArxD,GAAAoI,GAAiGkpD,MAAKtxD,EAAAgxD,GAAA3oD,KAAAkoD,GAAAvwD,EAAAurD,GAAA,GAAAvrD,EAAAqI,IAAArI,EAAA+vD,IAAA,KAAA1nD,EAAA4oD,IAAA,OAAAd,GAAA5E,KAA4D,QAAA8F,IAAA9F,GAAe,MAAAA,KAAAqG,OAAArG,GAAAqG,GAAArG,GAAA,KAAAA,EAAkC,QAAAsG,IAAAtG,EAAAljD,EAAArI,EAAAoI,GAAqB,GAAAxT,IAAA,CAAS,KAAA22D,EAAAyF,GAAAzF,MAAAljD,EAAAkjD,IAAAljD,OAAA,IAAAA,IAAA/T,SAAAi3D,EAAA,EAAuDA,EAAAljD,EAAA5U,OAAW83D,IAAA,CAAK,GAAAlgC,GAAAhjB,EAAAkjD,EAAWlgC,MAAA2kC,SAAAhwD,IAAAqrB,EAAA6kC,IAAA7kC,EAAAymC,GAAAzmC,EAAAjjB,GAAAxT,MAAA,IAAAy2B,GAA+C,MAAAz2B,GACxd,QAAAk9D,IAAAvG,EAAAljD,GAAiB,GAAArI,GAAAurD,EAAAz2B,SAAA1sB,EAAAmjD,EAAAK,IAAAL,EAAAwE,GAA2C,OAAZxE,GAAAE,IAAAiG,GAAAnG,GAAYvrD,EAAA7J,KAAAiS,EAAAC,GAC5D,QAAAkpD,IAAAhG,EAAAljD,GAAiB,GAAAkjD,EAAA2E,EAAA,QAAgB,KAAAsB,GAAA,CAAQ,IAAAnpD,EAAAkjD,EAAA,CAASljD,GAAA,iBAAqB,QAAArI,GAAAwQ,EAAApI,EAAA,EAAgBA,EAAAC,EAAA5U,OAAW2U,IAAA,UAAApI,IAAAqI,EAAAD,KAAA,CAA0BC,EAAA,IAAO,MAAAkjD,GAAQljD,EAAArI,EAA8B,GAA1BoI,EAAAC,EAAIA,EAAA,GAAAkmD,IAAAnmD,EAAAJ,MAAiBhI,GAAA,IAAK,EAAAoI,EAAA2pD,aAAA,IAAA3pD,EAAA4pD,aAAA,CAA0CzG,EAAA,CAAG,GAAA32D,IAAA,CAAS,OAAAwT,EAAA2pD,QAAA,IAAoB3pD,EAAA2pD,SAAA,CAAa,MAAAxG,GAAQ,MAAA6C,GAASx5D,GAAA,GAAKA,OAAA,IAAAwT,EAAA4pD,eAAA5pD,EAAA4pD,aAAA,GAAkD,IAAL5pD,KAAKxT,EAAAyT,EAAAkjD,EAAU32D,EAAEA,IAAAq9D,WAAA7pD,EAAAtH,KAAAlM,EAAkC,KAAT22D,IAAAxzD,KAASnD,EAAAwT,EAAA3U,OAAA,EAAiB,GAAAmB,EAAKA,IAAA,CAAKyT,EAAAkjD,EAAAnjD,EAAAxT,EAAS,IAAAy2B,GAAAwmC,GAAAzpD,EAAAxT,GAAA22D,GAAA,EAAAljD,EAAsBrI,MAAAqrB,EAAO,IAAAz2B,EAAA,EAAQA,EAAAwT,EAAA3U,OAAWmB,IAAAyT,EAAAkjD,EAAAnjD,EAAAxT,GAAAy2B,EAAAwmC,GAAAzpD,EAAAxT,GAAA22D,GAAA,EAAAljD,GAAArI,KAAAqrB,EAAsC,MAAArrB,GAAS,MAAA8xD,IAAAvG,EACzf,GAAAgD,IAAAlmD,EAAAL,OAAgB,QAAAgpD,IAAAzF,GAAuB,MAARA,KAAA0F,IAAQ1F,YAAA6E,IAAA7E,EAAA,KAAoF,QAAAsF,IAAAtF,GAAe,MAAAK,IAAAL,MAAkBA,EAAAc,MAAAd,EAAAc,IAAA,SAAAhkD,GAA0B,MAAAkjD,GAAA2G,YAAA7pD,KAA0BkjD,EAAAc,KAAc,QAAA8F,KAAavF,EAAAz2D,KAAA6R,MAAaA,KAAAhI,EAAA,GAAAowD,IAAApoD,MAAoBA,KAAAoqD,EAAApqD,KAAYA,KAAAqqD,EAAA,KAGxR,QAAAC,IAAA/G,EAAAljD,EAAArI,EAAAoI,GAAwC,KAAnBC,EAAAkjD,EAAAvrD,EAAAurD,EAAAljD,EAAA5N,KAAmB,QAAe4N,KAAA/T,QAAa,QAAAM,IAAA,EAAAy2B,EAAA,EAAiBA,EAAAhjB,EAAA5U,SAAW43B,EAAA,CAAK,GAAA+iC,GAAA/lD,EAAAgjB,EAAW,IAAA+iC,MAAA8B,GAAA9B,EAAA4B,SAAAhwD,EAAA,CAA0B,GAAA0sC,GAAA0hB,EAAAt5B,SAAArkB,EAAA29C,EAAAxC,IAAAwC,EAAA2B,GAA+B3B,GAAA3C,IAAA8E,GAAAhF,EAAAvrD,EAAAouD,GAAgBx5D,GAAA,IAAA83C,EAAAv2C,KAAAsa,EAAArI,IAAAxT,GAAuB,MAAAA,IAAA,GAAAwT,EAAAkmD,GAAmB,QAAAiE,IAAAhH,GAAe,eAAA/9C,KAAA+9C,IAAA,4BAAkC/9C,KAAA+9C,EAAA99C,QAAA,wBAAAA,QAAA,mIAA+L,KAAAA,QAAA,0CAA6D,QAAA+kD,IAAAjH,GAA2B,GAAZA,GAAA9wD,GAAY83D,GAAAhH,GAAA,IAAa,MAAAkH,MAAA,IAAAlH,EAAA,KAAuB,MAAAljD,IAAU,KAAArT,OAAA,wBAAAu2D,GAAwC,QAAAmH,IAAAnH,GAAe,GAAAljD,KAAwB,OAAfsqD,IAAA,GAAAC,IAAArH,EAAAljD,GAAeA,EAAAzO,KAAA,IAAkB,QAAAg5D,OAC1rB,QAAAD,IAAApH,EAAAljD,EAAArI,GAAmB,SAAAqI,EAAArI,EAAAc,KAAA,YAA0B,CAAK,mBAAAuH,GAAA,CAAuB,GAAAuJ,EAAAvJ,GAAA,CAAS,GAAAD,GAAAC,CAAQA,GAAAD,EAAA3U,OAAWuM,EAAAc,KAAA,IAAY,QAAAlM,GAAA,GAAAy2B,EAAA,EAAiBA,EAAAhjB,EAAIgjB,IAAArrB,EAAAc,KAAAlM,GAAA+9D,GAAApH,EAAAnjD,EAAAijB,GAAArrB,GAAApL,EAAA,GAA6C,YAAZoL,GAAAc,KAAA,KAAmB,KAAAuH,YAAA5N,SAAA4N,YAAAsN,SAAAtN,YAAAwqD,UAAgF,CAAK7yD,EAAAc,KAAA,KAAYlM,EAAA,EAAK,KAAAwT,IAAAC,GAAAnS,OAAAL,UAAAE,eAAAI,KAAAkS,EAAAD,IAAA,mBAAAijB,EAAAhjB,EAAAD,MAAApI,EAAAc,KAAAlM,GAAAk+D,GAAA1qD,EAAApI,KAAAc,KAAA,KAAA6xD,GAAApH,EAAAlgC,EAAArrB,GAAApL,EAAA,IAAiJ,YAAZoL,GAAAc,KAAA,KAA3OuH,IAAA0qD,UAA+P,aAAA1qD,IAAiB,aAAAyqD,GAAAzqD,EAAArI,EAAsB,MAAM,cAAAA,EAAAc,KAAA4J,SAAArC,KACtezR,MAAAyR,KAAA5N,GAAA,OAA4B,MAAM,eAAAuF,EAAAc,KAAAuH,EAAA5N,GAAiC,MAAM,gBAAAuF,EAAAc,KAAA,OAA+B,MAAM,cAAA9L,OAAA,uBAAAqT,MAC9G,QAAAyqD,IAAAvH,EAAAljD,GAAiBA,EAAAvH,KAAA,IAAAyqD,EAAA99C,QAAAulD,GAAA,SAAAzH,GAAoC,GAAAljD,GAAA4qD,GAAA1H,EAAgF,OAApEljD,OAAA,aAAAkjD,EAAA5wD,WAAA,IAAAgO,SAAA,IAAAqS,OAAA,GAAAi4C,GAAA1H,GAAAljD,GAAoEA,IAAS,KAAQ,QAAA6qD,IAAA3H,EAAAljD,EAAArI,GAAmBgI,KAAAqjB,EAAArrB,EAASgI,KAAAhI,EAAAurD,EAASvjD,KAAAmrD,EAAA9qD,EAASL,KAAAK,EAAA,EAASL,KAAAujD,EAAA,KAAkM,QAAA6H,MAAc,GAAA7H,GAAA8H,GAAAhrD,EAAA,IAAsE,OAAtDkjD,OAAAljD,EAAAkjD,YAAAv9C,KAAAu9C,QAAAljD,EAAA,MAAAA,EAAA2F,KAAA,MAAsD3F,EAAS,QAAAirD,MAActrD,KAAAgG,KAAAhG,KAAAK,EAAAL,KAAAujD,EAAA,KAA0J,QAAAgI,IAAAhI,GAAe/6C,EAAAygB,WAAA,WAAwB,KAAAs6B,IAAS,GACpsB,QAAAiI,MAAc,GAAAjI,GAAA/6C,EAAAijD,cAC6H,QADtG,KAAAlI,GAAA,mBAAArnB,gBAAAwvB,aAAAxvB,OAAAiL,mBAAAie,EAAA,YAAA7B,EAAA,WAA8H,GAAAA,GAAAxkC,SAAA4sC,cAAA,SAAuCpI,GAAAqI,MAAAC,QAAA,OAAuBtI,EAAAwE,IAAA,GAAShpC,SAAA+sC,gBAAAC,YAAAxI,EAAwC,IAAAljD,GAAAkjD,EAAAyI,aAAsBzI,GAAAljD,EAAA0e,SAAawkC,EAAA16B,OAAS06B,EAAAxsB,MAAA,IAAYwsB,EAAAl+B,OAAU,IAAArtB,GAAA,gBAAAmJ,KAAAE,SAAAjB,EAAA,SAAAC,EAAA4rD,SAAAC,SAAA,IAAA7rD,EAAA4rD,SAAAC,SAAA,KAAA7rD,EAAA4rD,SAAA/oD,IAAgHqgD,GAAAS,EAAA,SAAAT,GAAgB,KAAAnjD,GAAAmjD,EAAA4I,QAAA/rD,GAAAmjD,EAAA38C,MACpd5O,GAAAgI,KAAAosD,MAAAC,aAAyBrsD,MAAOK,EAAA8mC,iBAAA,UAAAoc,GAAA,GAAmCvjD,KAAAosD,SAAcpsD,KAAAssD,OAAYZ,YAAA,WAAuBrrD,EAAAqrD,YAAA1zD,EAAAoI,WAAuB,KAAAmjD,IAAA6B,EAAA,aAAAA,EAAA,SAAsD,GAAA/kD,GAAA,GAAAkjD,GAAAvrD,KAAgBoI,EAAApI,CAA0F,OAArFqI,GAAA+rD,MAAAC,UAAA,WAA6B,YAAAr0D,EAAAgO,KAAA,CAAoBhO,IAAAgO,IAAS,IAAAu9C,GAAAvrD,EAAAutD,EAAWvtD,GAAAutD,GAAA,KAAUhC,MAAM,SAAAA,GAAmBnjD,EAAA4F,MAAQu/C,GAAAhC,GAAMnjD,IAAA4F,KAAS3F,EAAAisD,MAAAZ,YAAA,IAAwB,yBAAA3sC,WAAA,sBAAAA,UAAA4sC,cAAA,mBAAApI,GAAyG,GAAAljD,GAAA0e,SAAA4sC,cAAA,SACtdtrD,GAAAksD,mBAAA,WAAgClsD,EAAAksD,mBAAA,KAA0BlsD,EAAA4pD,WAAAuC,YAAAnsD,GAA4BA,EAAA,KAAOkjD,IAAIA,EAAA,MAAQxkC,SAAA+sC,gBAAAC,YAAA1rD,IAAwC,SAAAkjD,GAAa/6C,EAAAygB,WAAAs6B,EAAA,IAA2B,QAAAkJ,MAAc,QAAAjkD,EAAAkkD,QAAAj6D,IAAAd,QAAA,kBAAmD,GAAA4xD,GAAA/6C,EAAAkkD,QAAApyD,YAAA,GAAgCqyD,IAAA,WAAcpJ,EAAAn2B,KAAAw/B,SAAYD,IAAA,WAAmB,GAAApJ,GAAAqJ,IAAShJ,GAAAp7C,EAAAqkD,eAAArkD,EAAAskD,QAAAtkD,EAAAskD,OAAAj/D,YAAAu3D,EAAA,SAAA58C,EAAAskD,OAAAj/D,UAAAg/D,cAAArkD,EAAAqkD,cAAAE,QAAAvB,MAAAuB,GAAAxJ,IAAA/6C,EAAAqkD,aAAAtJ,IAAwM,QAAAqJ,MAAc,OAAArJ,GAAUA,EAAA6H,MAAO,CAAE,IAAI7H,IAAAp1D,KAAAo1D,EAAAljD,GAAc,MAAAA,GAASkrD,GAAAlrD,GAAM2sD,EAAA7B,EAAA5H,GAAOyJ,EAAA3sD,EAAA2sD,EAAA3pC,IAAA2pC,EAAA3sD,IAAAkjD,EAAAv9C,KAAAgnD,EAAAzJ,EAAAyJ,EAAAzJ,KAAkC0J,IAAA,EAAO,QAAAC,IAAA3J,EAAAljD,GAAiB8pD,EAAAh8D,KAAA6R,MAAaA,KAAAK,EAAAkjD,GAAA,EAAYvjD,KAAAujD,EAAAljD,GAAAmI,EAAYxI,KAAAqjB,EAAA2gC,EAAAhkD,KAAAsoD,GAAAtoD,MAAuBA,KAAAmrD,EAAAgC,IACvtB,QAAAC,IAAA7J,GAAeA,EAAA8J,GAAA,EAAO9J,EAAA+J,IAAA/J,IAAAgK,aAAAhK,EAAA+J,GAAA/J,EAAA+J,EAAA,MAA+F,QAAAE,IAAAjK,EAAAljD,EAAArI,GAAmB,GAAA4rD,GAAAL,GAAAvrD,IAAAurD,EAAAS,EAAAT,EAAAvrD,QAAuB,KAAAurD,GAAA,kBAAAA,GAAA2G,YAAiE,KAAAl9D,OAAA,4BAAjEu2D,GAAAS,EAAAT,EAAA2G,YAAA3G,GAA+G,mBAAAljD,GAAA,EAAAmI,EAAAygB,WAAAs6B,EAAAljD,GAAA,GAAqD,QAAAotD,IAAAlK,EAAAljD,EAAArI,GAAmB4sD,EAAAz2D,KAAA6R,MAAaA,KAAAqjB,EAAA,MAAArrB,EAAAgsD,EAAAT,EAAAvrD,GAAAurD,EAAwBvjD,KAAAhI,EAAAqI,EAASL,KAAAK,EAAA2jD,EAAAhkD,KAAA8X,GAAA9X,MAAuBA,KAAAujD,KAAgR,QAAAmK,IAAAnK,GAAeA,EAAAoK,EAAAH,GAAAjK,EAAAljD,EAAAkjD,EAAAvrD,GAAgBurD,EAAAlgC,EAAAj3B,MAAA,KAAAm3D,KAAqB,QAAAqK,GAAArK,GAAcqB,EAAAz2D,KAAA6R,MAAaA,KAAAK,EAAAkjD,EAASvjD,KAAAujD,KACpe,QAAAsK,IAAAtK,GAAe+B,GAAA/B,IAAA,SAAAA,EAAAvrD,GAAqBgI,KAAAujD,EAAAx1D,eAAAiK,IAAA0xD,GAAAnG,IAAgCA,GAAIA,OAC1Q,QAAAuK,IAAAvK,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuBoT,KAAA+uC,MAAAwU,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAkJ,QAAAmhE,IAAAxK,GAAevjD,KAAAqjB,EAAAkgC,EAASvjD,KAAAK,EAAAL,KAAAhI,EAAAgI,KAAAujD,EAAA,KAA0B,QAAAyK,GAAAzK,EAAAljD,GAAgBL,KAAArQ,KAAA4zD,EAAYvjD,KAAA3R,MAAAgS,EAAmL,QAAA4tD,IAAA1K,GAAe,MAAAA,GAAAvrD,EAAAurD,EAAAvrD,EAAkBurD,IAAA0K,GAAA1K,MAAsBoB,GAAA,iCAAoC,MAClY,QAAAuJ,GAAA3K,EAAAljD,GAAgBkjD,EAAAp3D,IAAAs2C,GAAApiC,MAAA,IAAmB,QAAA8tD,GAAA5K,EAAAljD,GAAgBkjD,EAAAp3D,IAAAiiE,GAAA/tD,MAAA,IACnR,QAAAguD,IAAA9K,GAAe+K,QAAA,GAAAP,IAAA,IAAAQ,GAAA,IAAAD,MAAAt2D,EAAAw2D,GAAsC,IAAAnuD,EAAM,MAAAA,EAAAkuD,GAAAhL,IAAA,CAAeljD,EAAA,GAAA0tD,IAAAxK,EAAY,IAAAvrD,GAAAurD,EAAAkL,YAAA,KAAAruD,EAAAmjD,EAAAvwC,OAAAhb,EAAA,EAAyCA,GAAAq2D,GAAA9K,EAAAvwC,OAAA,EAAAhb,IAAoBA,EAAAqI,IAAArI,EAAAqI,MAAcrI,EAAAqI,EAAAD,GAAAC,EAASA,EAAAkjD,EAAAvrD,EAAMu2D,GAAAhL,GAAAljD,EAAQ,MAAAA,GAAU,QAAAquD,IAAAnL,EAAAljD,GAAiBkjD,KAAAp3D,IAAAwiE,GAAAtuD,MAAA,IAAsB,QAAAuuD,GAAArL,EAAAljD,GAAgBkjD,KAAAp3D,IAAA0iE,GAAAxuD,MAAA,IAAuB,QAAAyuD,MAAc9uD,KAAAujD,EAAA8K,GAAA,4CAAsD,QAAAU,IAAAxL,EAAAljD,EAAArI,EAAAoI,GAAqB,GAAApI,EAAA,IAAS,GAAApL,GAAAF,KAAAsiE,MAAAh3D,EAAoB,IAAApL,EAAA,OAAAy2B,GAAA,EAAiBA,EAAAz2B,EAAAnB,OAAW43B,IAAA,GAAAzZ,EAAAhd,EAAAy2B,IAAA,CAAgB,GAAA+iC,GAAAx5D,EAAAy2B,EAAW,QAAA+iC,EAAA36D,QAAA,CAAkB,GAAAi5C,GAAA0hB,EAAA,EAAW,IAAAx8C,EAAA86B,MAAA,EAAAA,EAAAj5C,QAAA,CAAwB,GAAAgd,GAAAi8B,EAAA,EAAW,YAAAj8B,GAAA,QAAAA,GAAA,SAAAA,EAAA,OAAAwmD,GAAA,EAAiDA,EAAAvqB,EAAAj5C,OAAYwjE,IAAAvqB,EAAAuqB,GAAA,KAAgB,GAAAC,GAAAxE,GAAA99D,GAAa,MAAAuiE,GAAUC,EAAA7L,EAAA,6DAAA2L,EAAAl3D,MAAsEk3D,GAAA,IAAaE,GAAA7L,EAAA,iBAAAljD,EAAA,MAAA6uD,GAAA9uD,EAAA,IAAAA,EAAA,KACprB,QAAAivD,IAAA9L,EAAAljD,EAAArI,IAAmBurD,QAAA2K,EAAA3K,GAAAvrD,GAAA,aAAAqI,GAAiC,QAAA+uD,GAAA7L,EAAAljD,GAAgBquD,GAAAnL,IAAAljD,GAAuB,QAAAivD,IAAA/L,GAAe8C,EAAAl4D,KAAA6R,KAAA,qBAAAujD,GAA4C,QAAAgM,MAAclF,EAAAmF,cAAA,GAAAF,IAAAjF,IAA2B,QAAAoF,IAAAlM,GAAe8C,EAAAl4D,KAAA6R,KAAA,YAAAujD,GAAmC,QAAA+J,KAAajD,EAAAmF,cAAA,GAAAC,IAAApF,IAA2B,QAAAqF,IAAAnM,GAAe8C,EAAAl4D,KAAA6R,KAAA,cAAAujD,GAAqC,QAAAoM,IAAApM,EAAAljD,GAAiB,IAAAujD,GAAAL,GAAA,KAAAv2D,OAAA,6CAAoE,OAAAwb,GAAAygB,WAAA,WAA+Bs6B,KAAIljD,GAAqQ,QAAAuvD,OAAmC,QAAAC,IAAAtM,GAAe,GAAAljD,EAAuD,QAAjDA,EAAAkjD,OAAAljD,KAAcyvD,GAAAvM,KAAAljD,EAAA,MAAAA,EAAA,OAAAA,EAAAkjD,IAAAljD,GAAmCA,EAAiB,QAAA0vD,OAAwB,QAAAC,IAAAzM,GAAe,OAAAA,EAAAuM,GAAAvM,IAAA,GAAA0M,eAAA1M,GAAA,GAAA2M,gBAAwD,QAAAJ,IAAAvM,GAAe,IAAAA,EAAAljD,GAAA,mBAAA6vD,iBAAA,mBAAAD,eAAA,CAAgF,OAAA5vD,IAAA,gFAAArI,EAAA,EAA+FA,EAAAqI,EAAWrI,IAAA,CAAK,GAAAoI,GAAAC,EAAArI,EAAW,KAAI,UAAAi4D,eAAA7vD,GAAAmjD,EAAAljD,EAAAD,EAAkC,MAAAxT,KAAW,KAAAI,OAAA,8FAA2G,MAAAu2D,GAAAljD,EAAqB,QAAA+jD,GAAAb,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAsBoT,KAAA0kC,EAAA6e,EAASvjD,KAAAK,IAASL,KAAAqjB,EAAAjjB,EAASJ,KAAAmwD,EAAAvjE,GAAA,EAAYoT,KAAAowD,EAAA,GAAAxC,GAAA5tD,MAAmBA,KAAAoqD,EAAAiG,GAAU9M,EAAAvjD,KAAAkuD,EAAA,GAAAhB,IAAgB3J,EAAAljD,EAAAiwD,GAAO/M,EAAA+J,GAAA/J,EAAA8J,GAAAD,GAAA7J,KAAA5qD,SAAA4qD,EAAA+J,GAAAF,GAAA7J,GAAsCvjD,KAAAomD,EAAA,KAAYpmD,KAAAhI,GAAA,EAAUgI,KAAAujD,EAAAvjD,KAAAmqD,EAAAnqD,KAAAmrD,EAAAnrD,KAAAsjD,EAAAtjD,KAAAovD,EAAApvD,KAAA4uD,EAAA5uD,KAAAuwD,EAAAvwD,KAAAwwD,EAAA,KAA6DxwD,KAAAgtD,EAAA,EAAShtD,KAAA5N,EAAA4N,KAAAywD,EAAA,KAAmBzwD,KAAAyI,GAAA,EAAUzI,KAAA1N,GAAA,EAAU0N,KAAA0wD,EAAA,EAAS1wD,KAAAmuD,EAAA,KAAYnuD,KAAAqqD,GAAA,EAC5lD,QAAAsG,IAAApN,EAAAljD,GAAiB,OAAAkjD,GAAU,qCAAAljD,EAAA,GAA2C,yCAAyC,sCAAsC,gCAAgG,QAAAuwD,IAAArN,EAAAljD,EAAArI,GAAmBurD,EAAA6L,EAAA,EAAM7L,EAAAD,EAAAuN,GAAAT,EAAA/vD,IAAakjD,EAAA4G,EAAAnyD,EAAMurD,EAAA8G,GAAA,EAAOyG,GAAAvN,EAAA,MAAW,QAAAwN,IAAAxN,EAAAljD,EAAArI,EAAAoI,GAAqBmjD,EAAA6L,EAAA,EAAM7L,EAAAD,EAAAuN,GAAAT,EAAA/vD,IAAakjD,EAAA4G,EAAA,KAAS5G,EAAA8G,EAAAryD,EAAM84D,GAAAvN,EAAAnjD,GAC1W,QAAA0wD,IAAAvN,EAAAljD,GAAiBkjD,EAAAqL,EAAAzB,IAAQ6D,GAAAzN,GAAMA,EAAA4H,EAAAiF,EAAA7M,EAAAD,GAAW2N,GAAA1N,EAAA4H,EAAA,IAAA5H,EAAA4M,GAAgB5M,EAAAyJ,EAAA,EAAMzJ,MAAA7e,EAAAogB,GAAAvB,EAAA7e,EAAAmf,KAAAxjD,EAAA,MAA4B,EAAAkjD,EAAAmN,IAAAnN,EAAA4K,EAAA,GAAAV,IAAAzJ,EAAAT,EAAA0L,GAAA1L,SAAAmN,IAAuCnN,EAAA6M,EAAAtH,EAAAvF,IAAA,mBAAAA,EAAA4E,IAAmC9nD,EAAAkjD,EAAA6C,EAAAX,GAAAlC,EAAA6C,MAAiB7C,EAAA4G,GAAA5G,EAAAkN,IAAAlN,EAAAkN,EAAA,QAAApwD,EAAA,oDAAAkjD,IAAA2N,GAAA3N,EAAA4H,EAAA5H,EAAAkN,EAAAlN,EAAA4G,EAAA9pD,KAAAkjD,EAAAkN,EAAA,MAAAlN,IAAA2N,GAAA3N,EAAA4H,EAAA5H,EAAAkN,EAAA,KAAApwD,IAAuIkvD,IAAK,IAAAv3D,GAAAurD,EAAA4G,CAAU,IAAAnyD,EAAA,CAAMqI,EAAA,GAAKrI,IAAAhB,MAAA,IAAe,QAAAoJ,GAAA,EAAYA,EAAApI,EAAAvM,OAAW2U,IAAA,CAAK,GAAAxT,GAAAoL,EAAAoI,GAAApJ,MAAA,IAAsB,MAAApK,EAAAnB,OAAA,CAAe,GAAA43B,GAAAz2B,EAAA,EAAWA,KAAA,EAAO,IAAAw5D,GAAA/iC,EAAArsB,MAAA,IAAmBqJ,GAAA,GAAA+lD,EAAA36D,QAAA,QAAA26D,EAAA,GAAA/lD,GAAAgjB,EAAA,KAAAz2B,EAAA,IAC7cyT,GAAAgjB,EAAA,oBAAqBhjB,GAAA,IAAY+uD,GAAA7L,EAAAljD,EAAA,gBAAAkjD,EAAAlgC,EAAA,cAAAkgC,EAAA4M,EAAA,MAAA5M,EAAAkN,EAAA,KAAAlN,EAAA4H,EAAA,KAAA9qD,GAGjC,QAAA8wD,IAAA5N,EAAAljD,EAAArI,GAAmB,OAAAoI,IAAA,GAAamjD,EAAAjxD,GAAAixD,EAAAyJ,EAAAh1D,EAAAvM,QAAmB,CAAE,GAAAmB,GAAAwkE,GAAA7N,EAAAvrD,EAAc,IAAApL,GAAAykE,GAAA,CAAU,GAAAhxD,IAAAkjD,EAAAnxD,EAAA,EAAAk7D,IAAAltD,GAAA,GAAuB2uD,GAAAxL,EAAAljD,EAAAkjD,EAAAlgC,EAAA,6BAAyC,OAAM,GAAAz2B,GAAA0kE,GAAA,CAAe/N,EAAAnxD,EAAA,EAAMk7D,IAAIyB,GAAAxL,EAAAljD,EAAAkjD,EAAAlgC,EAAArrB,EAAA,mBAAgCoI,GAAA,CAAK,OAAM2uD,GAAAxL,EAAAljD,EAAAkjD,EAAAlgC,EAAAz2B,EAAA,MAAA2kE,GAAAhO,EAAA32D,GAAgC,GAAAyT,GAAA,GAAArI,EAAAvM,SAAA83D,EAAAnxD,EAAA,EAAAk7D,IAAAltD,GAAA,GAAoCmjD,EAAAvrD,EAAAurD,EAAAvrD,GAAAoI,EAAWA,IAAA2uD,GAAAxL,EAAAljD,EAAAkjD,EAAAlgC,EAAArrB,EAAA,8BAAAw5D,GAAAjO,GAAAkO,GAAAlO,IACtS,QAAA6N,IAAA7N,EAAAljD,GAAiB,GAAArI,GAAAurD,EAAAyJ,EAAA5sD,EAAAC,EAAA1O,QAAA,KAAAqG,EAA8B,WAAAoI,EAAAixD,IAAmBr5D,GAAAqI,EAAAtP,UAAAiH,EAAAoI,GAA2BxR,MAAAoJ,GAAAs5D,IAAsBlxD,GAAA,GAAKpI,EAAAqI,EAAA5U,OAAA4lE,IAA0BhxD,IAAA2S,OAAA5S,EAAApI,GAAgBurD,EAAAyJ,EAAA5sD,EAAApI,EAAQqI,IAAiD,QAAA2wD,IAAAzN,GAAeA,EAAAgN,EAAApD,IAAA5J,EAAA6G,EAAYsH,GAAAnO,IAAA6G,GAAU,QAAAsH,IAAAnO,EAAAljD,GAAiB,SAAAkjD,EAAAiN,EAAA,KAAAxjE,OAAA,0BAAoDu2D,GAAAiN,EAAAb,GAAA3L,EAAAT,EAAA0E,GAAA1E,GAAAljD,GAAoB,QAAAsxD,IAAApO,GAAeA,EAAAiN,IAAAhoD,EAAA+kD,aAAAhK,EAAAiN,GAAAjN,EAAAiN,EAAA,MACpD,QAAAiB,IAAAlO,GAAeA,EAAA7e,EAAAktB,MAAArO,EAAAjxD,GAAAixD,EAAA7e,EAAAugB,GAAA1B,GAAyB,QAAAiO,IAAAjO,GAAeoO,GAAApO,EAAM,IAAAljD,GAAAkjD,EAAA4K,CAAU9tD,IAAA,kBAAAA,GAAAwxD,GAAAxxD,EAAAwxD,IAAiCtO,EAAA4K,EAAA,KAASf,GAAA7J,EAAA2K,GAAQL,GAAAtK,EAAA6M,GAAQ7M,MAAAljD,EAAAkjD,QAAA,KAAAljD,EAAAw8B,QAAAx8B,EAAAwxD,KACrb,QAAAN,IAAAhO,EAAAljD,GAAiB,IAAIkjD,EAAA7e,EAAAotB,GAAAvO,EAAAljD,GAAAkvD,KAAiB,MAAAv3D,GAASq3D,GAAA9L,EAAAljD,EAAArI,EAAA,kCAA4C,QAAA+5D,IAAAxO,GAAe,GAAAA,EAAA8C,GAAA,kBAAA9C,GAAA8C,EAAA,MAAA9C,GAAA8C,GAA4C,IAAA/C,EAAAC,GAAA,MAAAA,GAAAvsD,MAAA,GAA2B,IAAA2sD,GAAAJ,GAAA,CAAU,OAAAljD,MAAArI,EAAAurD,EAAA93D,OAAA2U,EAAA,EAA4BA,EAAApI,EAAIoI,IAAAC,EAAAvH,KAAAyqD,EAAAnjD,GAAiB,OAAAC,GAAS,MAAAklD,IAAAhC,GACrP,QAAAyO,IAAAzO,EAAAljD,GAAiB,GAAAkjD,EAAA10D,SAAA,kBAAA00D,GAAA10D,QAAA00D,EAAA10D,QAAAwR,MAAA,QAA+D,IAAAsjD,GAAAJ,IAAAD,EAAAC,GAAA2N,GAAA3N,EAAAljD,MAAA,QAAmC,CAAK,GAAAkjD,EAAA0O,GAAA,kBAAA1O,GAAA0O,EAAA,GAAAj6D,GAAAurD,EAAA0O,QAA2C,IAAA1O,EAAA8C,GAAA,kBAAA9C,GAAA8C,EAAAruD,MAAA,OAA6C,IAAA2rD,GAAAJ,IAAAD,EAAAC,GAAA,CAAqBvrD,IAAK,QAAAoI,GAAAmjD,EAAA93D,OAAAmB,EAAA,EAAuBA,EAAAwT,EAAIxT,IAAAoL,EAAAc,KAAAlM,OAAcoL,GAAAwtD,GAAAjC,EAAanjD,GAAA2xD,GAAAxO,GAAQ32D,EAAAwT,EAAA3U,MAAW,QAAA43B,GAAA,EAAYA,EAAAz2B,EAAIy2B,IAAAhjB,EAAAlS,SAAA,GAAAiS,EAAAijB,GAAArrB,KAAAqrB,GAAAkgC,IAAoC,QAAA0O,GAAA1O,EAAAljD,GAAgBL,KAAAK,KAAUL,KAAAujD,KAAUvjD,KAAAhI,EAAA,CAAS,IAAAA,GAAAxM,UAAAC,MAAuB,MAAAuM,EAAA,CAAQ,GAAAA,EAAA,OAAAhL,OAAA,6BAAiD,QAAAoT,GAAA,EAAYA,EAAApI,EAAIoI,GAAA,EAAAJ,KAAAiN,IAAAzhB,UAAA4U,GAAA5U,UAAA4U,EAAA,QAA2C,IAAAmjD,EAAA,CAAWA,YAAA0O,IAAAj6D,EAAAurD,EAAA0O,IAAA7xD,EAAAmjD,EAAA8C,MAAAruD,EAAAwtD,GAAAjC,GAAAnjD,EAAAmlD,GAAAhC,GAAmD,QAAA32D,GAAA,EAAYA,EAAAoL,EAAAvM,OAAWmB,IAAAoT,KAAAiN,IAAAjV,EAAApL,GAAAwT,EAAAxT,KACpnB,QAAAslE,IAAA3O,GAAeA,EAAAljD,KAAOkjD,IAAA93D,OAAA,EAAa83D,EAAAvrD,EAAA,EAAM,QAAAm6D,IAAA5O,EAAAljD,GAAiB,QAAA+pD,EAAA7G,EAAAljD,aAAAkjD,GAAAljD,KAAAkjD,EAAAvrD,IAAAurD,IAAA93D,OAAA,EAAA83D,EAAAvrD,GAAAo6D,GAAA7O,IAAA,GAAoE,QAAA6O,IAAA7O,GAAe,GAAAA,EAAAvrD,GAAAurD,IAAA93D,OAAA,CAAoB,OAAA4U,GAAA,EAAArI,EAAA,EAAgBqI,EAAAkjD,IAAA93D,QAAa,CAAE,GAAA2U,GAAAmjD,IAAAljD,EAAa+pD,GAAA7G,EAAAljD,EAAAD,KAAAmjD,IAAAvrD,KAAAoI,GAAuBC,IAAIkjD,IAAA93D,OAAAuM,EAAa,GAAAurD,EAAAvrD,GAAAurD,IAAA93D,OAAA,CAAoB,GAAAmB,KAAS,KAAAoL,EAAAqI,EAAA,EAAUA,EAAAkjD,IAAA93D,QAAa2U,EAAAmjD,IAAAljD,GAAA+pD,EAAAx9D,EAAAwT,KAAAmjD,IAAAvrD,KAAAoI,EAAAxT,EAAAwT,GAAA,GAAAC,GAA0CkjD,KAAA93D,OAAAuM,GACtO,QAAAoyD,GAAA7G,EAAAljD,GAAgB,MAAAnS,QAAAL,UAAAE,eAAAI,KAAAo1D,EAAAljD,GAAgL,QAAAgyD,IAAA9O,EAAAljD,GAAiB,GAAAkjD,EAAA,CAAMA,IAAAvsD,MAAA,IAAe,QAAAgB,GAAA,EAAYA,EAAAurD,EAAA93D,OAAWuM,IAAA,CAAK,GAAAoI,GAAAmjD,EAAAvrD,GAAArG,QAAA,KAAA/E,EAAA,IAA+B,OAAAwT,EAAA,CAAS,GAAAijB,GAAAkgC,EAAAvrD,GAAAjH,UAAA,EAAAqP,EAA0BxT,GAAA22D,EAAAvrD,GAAAjH,UAAAqP,EAAA,OAAsBijB,GAAAkgC,EAAAvrD,EAAYqI,GAAAgjB,EAAAz2B,EAAA0lE,mBAAA1lE,EAAA6Y,QAAA,kBAAsD,QAAA8sD,GAAAhP,EAAAljD,GAAgBL,KAAAK,EAAAL,KAAAywD,EAAAzwD,KAAAqjB,EAAA,GAAwBrjB,KAAA5N,EAAA,KAAY4N,KAAAmrD,EAAAnrD,KAAAujD,EAAA,GAAiBvjD,KAAAomD,GAAA,CAAU,IAAApuD,EAAMurD,aAAAgP,IAAAvyD,KAAAomD,MAAA,KAAA/lD,IAAAkjD,EAAA6C,EAAAoM,GAAAxyD,KAAAujD,EAAAlgC,GAAArjB,KAAAywD,EAAAlN,EAAAkN,EAAAgC,GAAAzyD,KAAAujD,EAAAljD,GAAAqyD,GAAA1yD,KAAAujD,EAAAnxD,GAAA4N,KAAAujD,MAAAoP,GAAA3yD,KAAA4rB,GAAA23B,EAAAvrD,IAAAgI,KAAAmrD,EAAA5H,EAAA4H,GAAA5H,IAAAvrD,GAAAurD,EAAA9wD,IAAAmgE,MAAAC,MAAA7yD,KAAAomD,IAAA/lD,EAAAmyD,GAAAxyD,KAAAhI,EAAA,WAAAgI,KAAAywD,EAAAqC,GAAA96D,EAAA,QAAAy6D,GAAAzyD,KAAAhI,EAAA,WAAA06D,GAAA1yD,KAAAhI,EAAA,IAAAgI,KAAAujD,EAAAuP,GAAA96D,EAAA,WAAA26D,GAAA3yD,KAAAhI,EAAA,WAAAgI,KAAAmrD,EAAA2H,GAAA96D,EAAA,UAAAgI,KAAAomD,IAAA/lD,EAAAL,KAAAhI,EAAA,GAAA+6D,IAAA,OAAA/yD,KAAAomD,IAG9b,QAAAgK,GAAA7M,GAAc,UAAAgP,GAAAhP,GAAgB,QAAAiP,IAAAjP,EAAAljD,EAAArI,GAAmBurD,EAAAlgC,EAAArrB,EAAA86D,GAAAzyD,GAAA,GAAAA,EAAiBkjD,EAAAlgC,IAAAkgC,EAAAlgC,EAAAkgC,EAAAlgC,EAAA5d,QAAA,UAAgC,QAAAgtD,IAAAlP,EAAAljD,EAAArI,GAAmBurD,EAAAljD,EAAArI,EAAA86D,GAAAzyD,GAAA,GAAAA,EAAiB,QAAAqyD,IAAAnP,EAAAljD,GAAiB,GAAAA,EAAA,CAAkB,GAAZA,KAAYzR,MAAAyR,IAAA,EAAAA,EAAA,KAAArT,OAAA,mBAAAqT,EAAmDkjD,GAAAnxD,EAAAiO,MAAMkjD,GAAAnxD,EAAA,KAAc,QAAAugE,IAAApP,EAAAljD,EAAArI,GAAmBqI,YAAA0yD,KAAAxP,EAAAvrD,EAAAqI,EAAA2yD,GAAAzP,EAAAvrD,EAAAurD,EAAA6C,KAAApuD,IAAAqI,EAAA4yD,GAAA5yD,EAAA6yD,KAAA3P,EAAAvrD,EAAA,GAAA+6D,IAAA1yD,EAAA,EAAAkjD,EAAA6C,IACna,QAAA+M,GAAA5P,EAAAljD,EAAArI,GAAkBurD,EAAAvrD,EAAAiV,IAAA5M,EAAArI,GAAa,QAAAi5D,IAAA1N,EAAAljD,EAAArI,GAAmB4R,EAAA5R,UAAAvF,KAAsB2gE,GAAA7P,EAAAvrD,EAAAqI,EAAArI,GAAY,QAAA64D,IAAAtN,GAA2I,MAA5H4P,GAAA5P,EAAA,KAAApiD,KAAAC,MAAA,WAAAD,KAAAE,UAAAV,SAAA,IAAAQ,KAAAkyD,IAAAlyD,KAAAC,MAAA,WAAAD,KAAAE,UAAA8rD,KAAAxsD,SAAA,KAA4H4iD,EAAS,QAAA+P,IAAA/P,GAAe,MAAAA,aAAAgP,GAAAnC,EAAA7M,GAAA,GAAAgP,GAAAhP,MAAA,IAA2C,QAAAgQ,IAAAhQ,EAAAljD,EAAArI,EAAAoI,GAAqB,GAAAxT,GAAA,GAAA2lE,GAAA,YAAqE,OAA5ChP,IAAAiP,GAAA5lE,EAAA22D,GAAWljD,GAAAoyD,GAAA7lE,EAAAyT,GAAWrI,GAAA06D,GAAA9lE,EAAAoL,GAAWoI,IAAAxT,EAAA22D,EAAAnjD,GAAWxT,EAAS,QAAAkmE,IAAAvP,EAAAljD,GAAiB,MAAAkjD,GAAAljD,EAAAmzD,UAAAjQ,EAAA99C,QAAA,iBAAA6sD,mBAAA/O,GAAA,GACtZ,QAAA0P,IAAA1P,EAAAljD,EAAArI,GAAmB,MAAAsrD,GAAAC,MAAAkQ,UAAAlQ,GAAA99C,QAAApF,EAAAqzD,IAAA17D,IAAAurD,IAAA99C,QAAA,uBAA6E,QAAA89C,GAAA,KAAoB,QAAAmQ,IAAAnQ,GAAiC,MAAlBA,KAAA5wD,WAAA,GAAkB,KAAA4wD,GAAA,MAAA5iD,SAAA,QAAA4iD,GAAA5iD,SAAA,IAAyH,QAAAoyD,IAAAxP,EAAAljD,EAAArI,GAAmBgI,KAAAK,EAAAL,KAAAujD,EAAA,KAAmBvjD,KAAAhI,EAAAurD,GAAA,KAAevjD,KAAAqjB,IAAArrB,EACnU,QAAAm4D,GAAA5M,GAAcA,UAAA,GAAA0O,GAAA1O,EAAAljD,EAAA,EAAAkjD,EAAAvrD,GAAAq6D,GAAA9O,EAAAvrD,EAAA,SAAAqI,EAAArI,GAAgDqI,EAAAiyD,mBAAAjyD,EAAAoF,QAAA,YAA2C0qD,EAAA5M,GAAKA,EAAAvrD,EAAA,KAASqI,EAAAszD,GAAApQ,EAAAljD,EAAU,IAAAD,GAAAmjD,IAAA1rD,IAAAwI,EAAiBD,IAAAmjD,IAAAt2C,IAAA5M,EAAAD,MAAmBA,EAAAtH,KAAAd,GAAUurD,EAAAljD,GAAA,KAA+D,QAAAuzD,IAAArQ,EAAAljD,GAAiB8vD,EAAA5M,GAAKljD,EAAAszD,GAAApQ,EAAAljD,GAAU+pD,EAAA7G,IAAAljD,OAAAkjD,EAAAvrD,EAAA,KAAAurD,EAAAljD,GAAAkjD,IAAA1rD,IAAAwI,GAAA5U,OAAA0mE,GAAA5O,IAAAljD,IAAwD,QAAAwzD,IAAAtQ,EAAAljD,GAAgC,MAAf8vD,GAAA5M,GAAKljD,EAAAszD,GAAApQ,EAAAljD,GAAU+pD,EAAA7G,IAAAljD,KAEtW,QAAA+yD,IAAA7P,EAAAljD,EAAArI,GAAmB47D,GAAArQ,EAAAljD,GAAQ,EAAArI,EAAAvM,SAAA83D,EAAAvrD,EAAA,KAAAurD,IAAAt2C,IAAA0mD,GAAApQ,EAAAljD,GAAA8kD,GAAAntD,IAAAurD,EAAAljD,GAAArI,EAAAvM,QAAkW,QAAAmgC,IAAA23B,GAAe,GAAAljD,GAAA,GAAA0yD,GAAmD,OAAtC1yD,GAAArI,EAAAurD,EAAAvrD,EAAQurD,MAAAljD,EAAAkjD,EAAA,GAAA0O,GAAA1O,KAAAljD,IAAAkjD,EAAAljD,GAA8BA,EAC/b,QAAAszD,IAAApQ,EAAAljD,GAAsD,MAArCA,IAAA5N,GAAY8wD,EAAAlgC,IAAAhjB,IAAAyzD,eAAyBzzD,EAAS,QAAA2yD,IAAAzP,EAAAljD,GAAiBA,IAAAkjD,EAAAlgC,IAAA8sC,EAAA5M,KAAAvrD,EAAA,KAAAurD,IAAA10D,QAAA,SAAA00D,EAAAljD,GAAkD,GAAArI,GAAAqI,EAAAyzD,aAAsBzzD,IAAArI,IAAA47D,GAAA5zD,KAAAK,GAAA+yD,GAAApzD,KAAAhI,EAAAurD,KAAgCA,IAAKA,EAAAlgC,EAAAhjB,EAAO,QAAA0zD,MAAc/zD,KAAAujD,EAAA4J,IAAsJ,QAAA6G,MAAcC,QAAA,GAAAF,KAAgB,QAAAG,MAAcD,QAAA,GAAAF,KAAyB,QAAAI,OAAsD,QAAAC,MAAc/N,EAAAl4D,KAAA6R,KAAA,KAAyB,QAAAq0D,MAAchO,EAAAl4D,KAAA6R,KAAA,KAAyB,QAAAs0D,IAAA/Q,EAAAljD,GAAiBL,KAAAujD,IAASvjD,KAAAK,IAASL,KAAAhI,EAAAgI,KAAA5N,EAAA,KAAmB4N,KAAAomD,GAAA,EAAUpmD,KAAAsjD,EAAA,KAAYtjD,KAAAqjB,GAAA,EAAUrjB,KAAA0kC,EAAA1kC,KAAAmrD,EAAA,KAA2C,QAAAoJ,IAAAhR,GAAe6L,EAAA7L,EAAAljD,EAAA,mCAA0C,IAAAA,GAAAkjD,IAAA8G,EAAA9G,CAAc,UAAAljD,EAAA+uD,EAAA7L,EAAAljD,EAAA,YAAAitD,IAAAjtD,GAAAitD,IAAAkH,GAAAjR,OAAA,KAAA+J,IAAAkH,GAAAjR,OAAA,QAAmJ,CAAKA,EAAAvrD,EAAA,GAAAosD,GAAAb,IAAAljD,EAAA,iBAAiCkjD,EAAAvrD,EAAAouD,EAAA7C,EAAAnxD,EAAUiO,EAAAo0D,GAAAlR,MAAA4H,EAAA5H,EAAAD,GAAkBgK,IAAI2D,GAAA5wD,EAAA,iBAAuB,IAAArI,GAAAurD,IAAAkN,EAAArwD,EAAAmjD,IAAAmN,CAAoB14D,IAAAoI,GAAA+yD,EAAA9yD,EAAArI,EAAAoI,GAAe2wD,GAAAxN,EAAAvrD,EAAAqI,GAAA,EAAAkjD,EAAA4H,IAKx+B,QAAAuJ,MAAc10D,KAAAujD,EAAAvjD,KAAAK,EAAA,KAAoB,QAAAs0D,IAAApR,GAA4B,GAAbvjD,KAAAujD,EAAA,GAAA0O,GAAa1O,EAAA,CAAMA,EAAAwO,GAAAxO,EAAQ,QAAAljD,GAAAkjD,EAAA93D,OAAAuM,EAAA,EAAuBA,EAAAqI,EAAIrI,IAAA,CAAK,GAAAoI,GAAAmjD,EAAAvrD,EAAWgI,MAAAujD,EAAAt2C,IAAAsjD,EAAAnwD,QAAqB,QAAAmwD,GAAAhN,GAAc,GAAAljD,SAAAkjD,EAAe,iBAAAljD,GAAAkjD,GAAA,YAAAljD,EAAA,KAAAkjD,EAAA/2B,KAAA+2B,EAAA/2B,KAAAu4B,KAAA1kD,EAAA7N,OAAA,GAAA+wD,EAAmO,QAAAqR,IAAArR,GAAevjD,KAAAqjB,EAAAkgC,GAAAsR,GAAa70D,KAAAhI,EAAAwQ,EAAAssD,IAAAtsD,EAAAssD,GAAAC,IAAAvsD,EAAAssD,GAAAC,MAAAvsD,EAAAssD,GAAAC,KAAAzK,GAAAtqD,KAAAqjB,EAAA,EAAuDrjB,KAAAujD,EAAA,KAAY,EAAAvjD,KAAAhI,IAAAgI,KAAAujD,EAAA,GAAAoR,KAA0B30D,KAAAK,EAAA,KAAsB,QAAA20D,IAAAzR,EAAAljD,GAAiBkjD,MAAA,GAAAljD,EAAA1O,QAAA,aAAA0O,EAAA1O,QAAA,aAAA0O,EAAA1O,QAAA,QAAA4xD,EAAAvrD,EAAAurD,EAAAlgC,EAAAkgC,IAAA,GAAAoR,IAAApR,EAAAljD,IAAA40D,GAAA1R,IAAAljD,GAAAkjD,EAAAljD,EAAA,OAAuH,QAAA60D,IAAA3R,GAAe,QAAAA,EAAAljD,KAAAkjD,SAAAY,KAAAZ,EAAAvrD,EAAkC,QAAAm9D,IAAA5R,EAAAljD,GAAiB,MAAAkjD,GAAAljD,EAAAkjD,EAAAljD,OAAAkjD,SAAAv1D,SAAAqS,GAAyC,QAAA40D,IAAA1R,EAAAljD,GAAiBkjD,UAAAt2C,IAAAsjD,EAAAlwD,MAAAkjD,EAAAljD,IACjrB,QAAA+0D,IAAA7R,EAAAljD,GAAiBL,KAAAujD,IAASvjD,KAAAK,IAAU,QAAAg1D,IAAA9R,EAAAljD,GAAiBL,KAAAujD,IAASvjD,KAAAK,IAA6I,QAAAi1D,MAAct1D,KAAAujD,EAAA,GAAA8R,IAAc,QAAAE,IAAAhS,EAAAljD,EAAArI,GAAmB,GAAAoI,GAAApI,GAAA,EAAY,KAAIg6D,GAAAzO,EAAA,SAAAA,EAAAvrD,GAAmB,GAAApL,GAAA22D,CAAQjjD,GAAAijD,KAAA32D,EAAA89D,GAAAnH,IAAgBljD,EAAAvH,KAAAsH,EAAApI,EAAA,IAAAw9D,mBAAA5oE,MAAwC,MAAAA,GAAS,KAAAyT,GAAAvH,KAAAsH,EAAA,QAAAo1D,mBAAA,YAAA5oE,GAA2D,QAAA6oE,IAAAlS,EAAAljD,GAAiB,GAAArI,GAAA,GAAA82D,GAAaM,GAAAp3D,EAAA,0BAAAurD,EAAiC,IAAAnjD,GAAA,GAAAs1D,MAAgBt1D,GAAAu1D,OAAAzR,GAAA0R,GAAA59D,EAAAoI,EAAA,2BAAAC,GAAiDD,EAAAzF,QAAAupD,GAAA0R,GAAA59D,EAAAoI,EAAA,0BAAAC,GAAiDD,EAAAo9B,QAAA0mB,GAAA0R,GAAA59D,EAAAoI,EAAA,0BAAAC,GAAiDD,EAAAy1D,UAAA3R,GAAA0R,GAAA59D,EAAAoI,EAAA,4BAAAC,GAAqDmI,EAAAygB,WAAA,WAAwB7oB,EAAAy1D,WAAAz1D,EAAAy1D,aAA6B,KAAMz1D,EAAA2nD,IAAAxE,EAAQ,QAAAqS,IAAArS,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuB,IAAIwiE,EAAA7L,EAAAvrD,GAAAqI,EAAAs1D,OAAA,KAAAt1D,EAAA1F,QAAA,KAAA0F,EAAAm9B,QAAA,KAAAn9B,EAAAw1D,UAAA,KAAAjpE,EAAAwT,GAAyE,MAAAijB,GAASgsC,GAAA9L,EAAAlgC,IAAU,QAAAyyC,GAAAvS,GAAc4G,EAAAh8D,KAAA6R,MAAaA,KAAAmmB,QAAA,GAAA8rC,GAAmBjyD,KAAAmuD,EAAA5K,GAAA,KAAevjD,KAAAqjB,GAAA,EAAUrjB,KAAAkuD,EAAAluD,KAAAujD,EAAA,KAAmBvjD,KAAAowD,EAAApwD,KAAA1N,EAAA,GAAiB0N,KAAAywD,EAAA,EAASzwD,KAAAmrD,EAAA,GAAUnrD,KAAAomD,EAAApmD,KAAAovD,EAAApvD,KAAAwwD,EAAAxwD,KAAA4uD,GAAA,EAA+B5uD,KAAAsjD,EAAA,EAAStjD,KAAAmqD,EAAA,KAAYnqD,KAAA0wD,EAAAqF,GAAU/1D,KAAAgtD,EAAAhtD,KAAA0kC,GAAA,EAG/+B,QAAAsxB,IAAAzS,GAAe,MAAA0S,IAAAhQ,GAAA,oBAAA1C,GAAA2S,aAAA,KAAA3S,EAAAsS,UAAkE,QAAA7Q,IAAAzB,GAAe,sBAAAA,EAAAuQ,cAC9H,QAAAqC,IAAA5S,EAAAljD,GAAiBkjD,EAAAlgC,GAAA,EAAOkgC,QAAA6C,GAAA,EAAA7C,IAAA1mB,QAAA0mB,EAAA6C,GAAA,GAAiC7C,EAAA4H,EAAA9qD,EAAMkjD,EAAAkN,EAAA,EAAM2F,GAAA7S,GAAM8S,GAAA9S,GAAM,QAAA6S,IAAA7S,GAAeA,EAAAqL,IAAArL,EAAAqL,GAAA,EAAArL,EAAAiM,cAAA,YAAAjM,EAAAiM,cAAA,UAEnR,QAAA8G,IAAA/S,GAAe,GAAAA,EAAAlgC,OAAA,KAAAkzC,KAAA,GAAAhT,EAAA2K,EAAA,OAAAwC,EAAAnN,IAAA,GAAAA,EAAAiT,IAAA5H,EAAArL,EAAAljD,EAAAm2D,EAAAjT,EAAA,iDAAqH,IAAAA,EAAAiN,GAAA,GAAAE,EAAAnN,GAAAiK,GAAAjK,EAAA+D,GAAA,EAAA/D,OAAkC,IAAAA,EAAAiM,cAAA,uBAAAkB,EAAAnN,GAAA,CAAqDqL,EAAArL,EAAAljD,EAAAm2D,EAAAjT,EAAA,qBAA+BA,EAAAlgC,GAAA,CAAO,KAAI,GAAAhjB,GAAAkjD,EAAAiT,GAAYjT,GAAA,OAAAljD,GAAY,mEAAArI,IAAA,CAAyE,MAAAurD,EAAQ,SAAAvrD,GAAA,EAAa,GAAAoI,EAAM,MAAAA,EAAApI,GAAA,CAAW,GAAApL,EAAM,IAAAA,EAAA,IAAAyT,EAAA,CAAY,GAAAgjB,IAAAkgC,EAAAjxD,EAAAG,IAAAmgE,MAAAC,IAAA,QAAqC,KAAAxvC,GAAA7a,EAAAiuD,MAAAjuD,EAAAiuD,KAAAxK,SAAA,CAAgC,GAAA7F,GAAA59C,EAAAiuD,KAAAxK,SAAAC,QACne7oC,GAAA+iC,EAAApzC,OAAA,EAAAozC,EAAA36D,OAAA,GAAyBmB,GAAA8pE,GAAAlxD,KAAA6d,IAAAywC,cAAA,IAAiC1zD,EAAAxT,EAAIwT,GAAAmjD,EAAAiM,cAAA,YAAAjM,EAAAiM,cAAA,aAAAjM,EAAAkN,EAAA,EAAAlN,EAAA4H,EAAA5H,EAAAqC,KAAA,KAAArC,EAAAiT,IAAA,IAAAJ,GAAA7S,IAAmG,QAAQ8S,GAAA9S,KAAQ,QAAA8S,IAAA9S,EAAAljD,GAAiB,GAAAkjD,IAAA,CAAQoT,GAAApT,EAAM,IAAAvrD,GAAAurD,IAAAnjD,EAAAmjD,EAAA2K,EAAA,GAAA1K,GAAA,IAA2BD,KAAA,KAASA,EAAA2K,EAAA,KAAS7tD,GAAAkjD,EAAAiM,cAAA,QAA4B,KAAIx3D,EAAAu0D,mBAAAnsD,EAAuB,MAAAxT,IAAS22D,IAAAljD,IAAA6tD,EAAA3K,EAAA,qDAAA32D,EAAAG,WAA+E,QAAA4pE,IAAApT,GAAeA,OAAAyJ,IAAAzJ,IAAAsS,UAAA,MAA+B,gBAAAtS,GAAA4G,IAAA3hD,EAAA+kD,aAAAhK,EAAA4G,GAAA5G,EAAA4G,EAAA,MAC1b,QAAAuG,GAAAnN,GAAc,MAAAA,SAAAqT,WAAA,EAC6P,QAAAJ,GAAAjT,EAAAljD,GAAgB,MAAAA,GAAA,KAAAkjD,EAAA6M,EAAA,IAAA7M,EAAAjxD,EAAA,IAAAixD,EAAAiT,IAAA,IAAyC,QAAAK,IAAAtT,GAAe,GAAAljD,GAAA,EAAyD,OAAhDilD,IAAA/B,EAAA,SAAAA,EAAAnjD,GAAmBC,GAAAD,EAAKC,GAAA,IAAOA,GAAAkjD,EAAKljD,GAAA,SAAYA,EAAS,QAAAy2D,IAAAvT,EAAAljD,EAAArI,GAAmBurD,EAAA,CAAG,IAAAnjD,IAAApI,GAAA,CAAY,GAAAoI,IAAA,CAAS,MAAAmjD,GAAQnjD,GAAA,EAAK,GAAAA,EAAA,MAAAmjD,EAAsB,IAARvrD,EAAA6+D,GAAA7+D,GAAQsrD,EAAAC,GAAA,CAAwF,GAA/EljD,EAAAm1D,mBAAAn1D,EAAA5N,IAAgCuF,EAAA,MAAAA,EAAA,IAAAw9D,mBAAAx9D,EAAAvF,IAAA,GAA+C4N,GAAArI,EAAA,CAA6D,GAApDA,EAAAurD,EAAA5xD,QAAA,KAAiB,EAAAqG,MAAAurD,EAAA93D,QAAmC,GAAjB2U,EAAAmjD,EAAA5xD,QAAA,OAAiByO,EAAApI,EAAA,CAAaoI,EAAApI,CAAI,IAAApL,GAAA,OAASA,GAAA22D,EAAAxyD,UAAAqP,EAAA,EAAApI,EAA0BurD,MAAAvwC,OAAA,EAAA5S,GAAAxT,EAAA22D,EAAAvwC,OAAAhb,IAAgCA,EAAAurD,EAAA,GAAOA,EAAA,GAAAljD,EAAArI,IAAA,IAAAqI,IAAArI,EAAqBurD,IAAA,IAAAA,EAAA,OAAAA,EAAA,OAAAA,EAAA,GAA+B,MAAAA,GAAkB,MAAT4P,GAAA5P,EAAAljD,EAAArI,GAASurD,EAAU,QAAAwT,IAAAxT,EAAAljD,EAAArI,GAAmBgI,KAAAg3D,GAAA32D,GAAA,EAAaL,KAAAslD,GAAA,EAAUtlD,KAAAomD,KAAUpmD,KAAAsjD,KAAUtjD,KAAAujD,EAAA,GAAAuL,IAAc9uD,KAAAqqD,EAAAryD,GAAA,GAAA08D,IAAiB10D,KAAAkkD,GAAAlkD,KAAAmlD,GAAAnlD,KAAA4uD,EAAA5uD,KAAAskD,GAAAtkD,KAAAK,EAAAL,KAAA0wD,EAAA1wD,KAAAywD,EAAAzwD,KAAA8jD,GAAA9jD,KAAAqjB,EAAArjB,KAAAoqD,EAAApqD,KAAA5N,EAAA,KAAsF4N,KAAAi3D,GAAAj3D,KAAAovD,EAAA,EAAiBpvD,KAAAwkD,GAAAxkD,KAAAgtD,EAAAhtD,KAAA1N,EAAA0N,KAAA0kC,EAAA1kC,KAAAwwD,EAAAxwD,KAAAhI,EAAA,KAAgDgI,KAAAyI,EAAAzI,KAAAk3D,GAAAl3D,KAAAmwD,GAAA,EAAyBnwD,KAAAm3D,GAAAn3D,KAAAmqD,EAAAnqD,KAAAmuD,EAAA,EAAwBnuD,KAAAuwD,EAAAhN,KAAAh7B,yBAAA,EAAuCvoB,KAAAowD,EAAA,GAAUpwD,KAAAmrD,EAAA,GAAAyJ,IAAArR,KAAA6T,wBAA2Cp3D,KAAAkmD,GAAA,GAAAoP,IAAet1D,KAAAkuD,GAAA3K,OAAA,KAAAA,EAAAp7B,uBAAAo7B,EAAAp7B,sBAAsEnoB,KAAAimD,GAAA1C,KAAA8T,gBAAA,EAC7tC,QAAAC,IAAA/T,GAA2C,GAA5B6L,EAAA7L,IAAA,gBAAsBgU,GAAAhU,GAAM,GAAAA,EAAAqK,EAAA,CAAW,GAAAvtD,GAAAkjD,EAAA6L,IAAAp3D,EAAAo4D,EAAA7M,EAAAqL,EAAqBuE,GAAAn7D,EAAA,MAAAurD,EAAA6M,GAAe+C,EAAAn7D,EAAA,MAAAqI,GAAa8yD,EAAAn7D,EAAA,oBAAwBw/D,GAAAjU,EAAAvrD,GAAQqI,EAAA,GAAA+jD,GAAAb,MAAA,EAAAljD,MAAA,IAA0BA,EAAA+uD,EAAA,EAAM/uD,EAAAijD,EAAAuN,GAAAT,EAAAp4D,IAAaA,GAAA,EAAKwQ,EAAA+zB,WAAA/zB,EAAA+zB,UAAAk7B,aAAAz/D,EAAAwQ,EAAA+zB,UAAAk7B,WAAAp3D,KAAAijD,EAAA,KAAmFtrD,KAAA,GAAA09D,QAAA3N,IAAA1nD,EAAAijD,GAAyBjjD,EAAAuuD,EAAAzB,IAAQ6D,GAAA3wD,GAAMq3D,GAAAnU,GAC/U,QAAAgU,IAAAhU,GAAeA,EAAAyJ,IAAAzJ,EAAAyJ,EAAAnwB,QAAA0mB,EAAAyJ,EAAA,MAA4BzJ,EAAAljD,IAAAkjD,EAAAljD,EAAAs3D,SAAApU,EAAAljD,EAAA,MAA6BkjD,EAAA7e,IAAAl8B,EAAA+kD,aAAAhK,EAAA7e,GAAA6e,EAAA7e,EAAA,MAAoCkzB,GAAArU,GAAMA,EAAA4H,EAAAwM,SAAapU,EAAAiN,IAAAhoD,EAAA+kD,aAAAhK,EAAAiN,GAAAjN,EAAAiN,EAAA,MAAoC,QAAAqH,IAAAtU,EAAAljD,GAAiB,QAAAkjD,EAAA6C,EAAA36D,OAAA,CAAoB,GAAAuM,GAAA,+CAAA0yD,GAAArqD,GAAAD,EAAAmjD,KAAmEnjD,IAAA8tD,EAAA9tD,EAAApI,GAAUurD,EAAA6C,EAAAttD,KAAA,GAAAs8D,IAAA7R,EAAA0T,KAAA52D,IAA2B,GAAAkjD,EAAAqK,GAAAkK,GAAAvU,GAAgD,QAAAuU,IAAAvU,GAAe2R,GAAA3R,EAAA4H,IAAA5H,EAAAiN,IAAAjN,EAAAiN,EAAAb,GAAA3L,EAAAT,EAAA4C,GAAA5C,GAAA,GAAAA,EAAA4K,EAAA,GAG/W,QAAA4J,IAAAxU,EAAAljD,GAAiB,GAAAA,EAAA,CAAMkjD,EAAA6C,EAAA7C,EAAAD,EAAAh3D,OAAAi3D,EAAA6C,GAAoB7C,EAAAD,EAAA73D,OAAA,CAAa,IAAAuM,GAAAurD,EAAA6L,EAAA,MAAYp3D,GAAAurD,EAAA6L,GAAa/uD,GAAA23D,GAAAzU,EAAQ,IAAAnjD,GAAAgwD,EAAA7M,EAAAqL,EAAauE,GAAA/yD,EAAA,MAAAmjD,EAAA6M,GAAe+C,EAAA/yD,EAAA,MAAApI,GAAam7D,EAAA/yD,EAAA,MAAAmjD,EAAA4M,GAAeqH,GAAAjU,EAAAnjD,GAAQmjD,EAAAlgC,GAAAkgC,EAAAnxD,GAAA0kE,GAAA12D,EAAAmjD,EAAAlgC,EAAAkgC,EAAAnxD,GAAwB4F,EAAA,GAAAosD,GAAAb,MAAA,EAAAvrD,EAAAurD,EAAA4K,EAAA,GAAyB,OAAA5K,EAAAlgC,IAAArrB,EAAAouD,EAAA7C,EAAAnxD,GAAsB4F,EAAAixB,WAAA9nB,KAAA82D,MAAA,KAAA92D,KAAA82D,MAAA,IAAA92D,KAAAE,WAA4D4zD,GAAA1R,EAAA4H,EAAAnzD,GAAU44D,GAAA54D,EAAAoI,EAAAC,GAAU,QAAAm3D,IAAAjU,EAAAljD,GAAiBkjD,EAAAvrD,GAAAg6D,MAAU,SAAAzO,EAAAnjD,GAAe+yD,EAAA9yD,EAAAD,EAAAmjD,KAC1V,QAAAyU,IAAAzU,GAAe,GAAAljD,GAAAc,KAAA4D,IAAAw+C,EAAA6C,EAAA36D,OAAA,KAAAuM,EAAAurD,EAAAvrD,EAAAgsD,EAAAT,EAAAvrD,EAAAkgE,GAAA3U,EAAAvrD,EAAAurD,GAAA,KAAAnjD,EAAAmjD,EAAA6C,EAAAx5D,GAAA,SAAAyT,EAA+E,MAAAA,EAAA,CAAQ,GAAAgjB,GAAAjjB,EAAA,GAAAmjD,CAAa32D,GAAAkM,KAAA,OAAAuqB,OAAiBA,GAAA,CAAS,QAAA+iC,GAAA,EAAYA,EAAA/lD,EAAI+lD,IAAA,CAAK,GAAA1hB,GAAAtkC,EAAAgmD,GAAA7C,EAAA96C,EAAArI,EAAAgmD,GAAA/lD,CAAsBqkC,IAAArhB,CAAK,KAAIkyC,GAAA9sD,EAAA7b,EAAA,MAAA83C,EAAA,KAAoB,MAAAuqB,GAAUj3D,KAAAyQ,IAAuD,MAA9CzQ,GAAApL,EAAAgF,KAAA,KAAc2xD,EAAAD,EAAAC,EAAAD,EAAAh3D,OAAAi3D,EAAA6C,EAAAr6B,OAAA,EAAA1rB,IAAgCrI,EAAS,QAAAmgE,IAAA5U,GAAe,IAAAA,EAAAljD,IAAAkjD,EAAA7e,EAAA,CAAe6e,EAAA4T,GAAA,CAAO,IAAA92D,GAAAkjD,EAAAwC,EAAW4G,KAAAF,KAASQ,KAAAN,KAAAM,IAAA,EAAiB,IAAAj1D,GAAAqzD,GAAAjrD,EAAA4sD,EAAAn1D,KAAmBuI,GAAA6M,IAAA5M,EAAAkjD,GAAWvrD,EAAAqI,EAAArI,EAAAqI,EAAA2F,KAAA5F,EAAApI,EAAAurD,EAAAnjD,EAAqBpI,EAAAqI,EAAAD,EAAMmjD,EAAA4G,EAAA,GACla,QAAAiO,IAAA7U,GAAe,MAAAA,GAAAljD,GAAAkjD,EAAA7e,IAAA6e,UAAA2K,EAAA3K,EAAA,qCAAmE,GAAAA,EAAA4G,IAAmBiF,EAAA7L,IAAA,sBAA4BA,EAAA4T,KAAO5T,EAAA7e,EAAAirB,GAAA3L,EAAAT,EAAAwC,GAAAxC,GAAA8U,GAAA9U,IAAA4G,IAA4B5G,EAAA4G,IAAM,IAE1K,QAAAqK,IAAAjR,EAAAljD,EAAArI,GAAmBo3D,EAAA7L,IAAA,2BAAkC,IAAAnjD,GAAAC,EAAAqkC,CAAUtkC,IAAA40D,GAAAzR,EAAA4H,EAAA/qD,GAAamjD,EAAAiB,GAAAxsD,EAAOurD,EAAA96C,EAAApI,EAAAgjB,EAAQ+rC,EAAA7L,IAAA,qBAA2BA,EAAAqL,EAAA0J,GAAA/U,IAAAe,IAAewT,GAAAvU,GAAM,QAAAgV,IAAAhV,EAAAljD,GAAiB+uD,EAAA7L,IAAA,0BAAgCA,EAAA96C,EAAApI,EAAAgjB,EAAQsqC,EAAApK,EAAA,GAIzG,QAAAqU,IAAArU,GAAe,MAAAA,EAAAjxD,IAAAkW,EAAA+kD,aAAAhK,EAAAjxD,GAAAixD,EAAAjxD,EAAA,MAEiP,QAAA+lE,IAAA9U,EAAAljD,GAAiB,GAAArI,GAAA,IAAAmJ,KAAAC,MAAA,IAAAD,KAAAE,SAAiF,OAAzCkiD,GAAAiF,OAAA4G,EAAA7L,IAAA,oBAAAvrD,GAAA,GAAyCA,EAAAqI,EAC7b,QAAAstD,GAAApK,EAAAljD,GAAuC,GAAvB+uD,EAAA7L,IAAA,cAAAljD,GAAuB,GAAAA,EAAA,CAAS,GAAArI,GAAA,IAAWurD,GAAAvrD,MAAA,KAAc,IAAAoI,GAAA4jD,EAAAT,EAAA8E,GAAA9E,EAAgBvrD,OAAA,GAAAu6D,GAAA,wCAAA/pD,EAAAyjD,UAAA,QAAAzjD,EAAAyjD,SAAAC,UAAAsG,GAAAx6D,EAAA,SAAA64D,GAAA74D,IAAkHy9D,GAAAz9D,KAAAoI,OAAmBktD,IAAS8B,GAAA7L,IAAA,wBAAAljD,GAAiCkjD,EAAAqK,EAAA,EAAMrK,EAAAvrD,GAAAurD,EAAAvrD,EAAAwtD,GAAAjC,EAAAljD,GAAiBq3D,GAAAnU,GAAMgU,GAAAhU,GACrS,QAAAmU,IAAAnU,GAA4B,GAAbA,EAAAqK,EAAA,EAAMrK,EAAA96C,GAAA,EAAO86C,EAAAvrD,EAAA,MAAAurD,EAAAD,EAAA73D,QAAA,GAAA83D,EAAA6C,EAAA36D,OAAA83D,EAAAvrD,EAAA0sD,GAAAnB,OAAiD,CAAK6L,EAAA7L,IAAA,wCAAAA,EAAAD,EAAA73D,OAAA,eAAA83D,EAAA6C,EAAA36D,OAAoF,IAAA4U,GAAA8kD,GAAA5B,EAAAD,GAAAtrD,EAAAmtD,GAAA5B,EAAA6C,EAAwB7C,GAAAD,EAAA73D,OAAA,EAAa83D,EAAA6C,EAAA36D,OAAA,EAAa83D,EAAAvrD,EAAA0sD,GAAAnB,EAAAljD,EAAArI,IAAe,QAAAsgE,IAAA/U,EAAAljD,GAAkE,MAAjDA,GAAAm4D,GAAAjV,EAAA,KAAAljD,GAAe+uD,EAAA7L,IAAA,yBAAAljD,GAAkCA,EAAS,QAAAo0D,IAAAlR,EAAAljD,EAAArI,GAA0E,MAAvDqI,GAAAm4D,GAAAjV,IAAAM,KAAAxjD,EAAA,KAAArI,GAAwBo3D,EAAA7L,IAAA,sBAAAljD,GAA+BA,EAC5X,QAAAm4D,IAAAjV,EAAAljD,EAAArI,GAAmB,GAAAoI,GAAAkzD,GAAAt7D,EAAY,QAAAoI,EAAAC,KAAAoyD,GAAAryD,EAAAC,EAAA,IAAAD,EAAAC,GAAAqyD,GAAAtyD,IAAAhO,OAAwC,CAAK,GAAAixB,GAAAz2B,EAAA4b,EAAAyjD,QAAmB5oC,GAAAhjB,IAAA,IAAAzT,EAAA6rE,SAAA7rE,EAAA6rE,SAAkCr4D,EAAAmzD,GAAA3mE,EAAAs/D,SAAA7oC,EAAAz2B,EAAA8rE,KAAA1gE,GAAsH,MAA1FurD,GAAAO,IAAAwB,GAAA/B,EAAAO,GAAA,SAAAP,EAAAljD,GAA4B8yD,EAAA/yD,EAAAC,EAAAkjD,KAAWljD,EAAAkjD,EAAAkN,EAAMz4D,EAAAurD,EAAAmN,EAAMrwD,GAAArI,GAAAm7D,EAAA/yD,EAAAC,EAAArI,GAAem7D,EAAA/yD,EAAA,MAAAmjD,EAAAoB,IAAgB6S,GAAAjU,EAAAnjD,GAAQA,EAAkN,QAAAu4D,OACjY,QAAAC,IAAArV,GAAe,OAAAljD,GAAA7U,UAAA,GAAAwM,EAAA,EAA2BA,EAAAxM,UAAAC,OAAmBuM,IAAA,CAAK,GAAAoI,GAAA5U,UAAAwM,EAAmB,OAAAoI,EAAAquD,YAAA,OAAApuD,EAAAD,MAA+B,CAAK,GAAAxT,IAAMA,EAAA,IAAAyT,KAAAzT,EAAAyT,EAAA5U,OAAA,EAAAmB,EAAA,GAAAA,GAAAyT,EAAA1O,QAAA,IAAA/E,OAAsDyT,GAAAzT,EAAAwT,EAAA,IAAAA,GAAiB,MAAAC,GAAU,QAAAw4D,MAAc,GAAA5C,KAAA,KAAAgB,IAAA,KAAAjqE,OAAA,gDACtS,QAAAk7D,GAAA3E,EAAAljD,GAAgB8pD,EAAAh8D,KAAA6R,MAAaA,KAAAujD,EAAA,GAAAwT,IAAA12D,EAAA,IAAoBL,KAAAK,EAAAkjD,EAASvjD,KAAA1N,EAAA+N,KAAAy4D,QAAAz4D,EAAAy4D,QAAAF,GAAA54D,KAAAK,EAAA,QAAgDL,KAAAqjB,EAAAgrC,GAAA,oDAA8DruD,KAAAmrD,EAAA9qD,KAAA04D,kBAAA,KAAmCxV,EAAAljD,KAAA24D,gBAAA,KAA4B34D,KAAA44D,+BAAA1V,IAAA,kCAAAA,GAA6E2V,oBAAA,eAAmCl5D,KAAAujD,EAAAnxD,EAAAmxD,EAAWvjD,KAAAujD,EAAA6G,EAAA/pD,KAAAgoB,oBAAA,MAAuCk7B,EAAAljD,KAAA84D,6BAAA,cAAA3zD,KAAA+9C,KAAAvjD,KAAAujD,EAAAlgC,EAAAkgC,GAAyEvjD,KAAAwwD,EAAAnwD,KAAAkoB,yBACld,EAAGvoB,KAAA0kC,EAAArkC,KAAAioB,cAAA,GAA4BjoB,OAAA+nB,sBAAA,cAAA5iB,KAAAnF,KAAAL,KAAAujD,EAAAkN,EAAApwD,EAAA,QAAAkjD,EAAAvjD,KAAAmrD,IAAA9qD,IAAAkjD,OAAAvjD,KAAAmrD,EAAA9qD,IAAAkjD,aAAAljD,IAAAkjD,EAAAvjD,KAAAqjB,IAAA8qC,EAAA5K,EAAA,mEAAAljD,KAAkNL,KAAAomD,EAAA,GAAAgT,IAAAp5D,MAEQ,QAAAq5D,IAAA9V,GAAe6Q,GAAAjmE,KAAA6R,MAAcA,KAAA4G,KAAA28C,EAAqB,QAAA+V,MAAcjF,GAAAlmE,KAAA6R,MAAcA,KAAAzK,OAAA,EAAuB,QAAA6jE,IAAA7V,GAAevjD,KAAAujD,IACwE,QAAAgW,MAAcv5D,KAAAK,KAAUL,KAAAujD,KAAU,QAAAiW,IAAAjW,GAA6D,MAA9C,IAAAA,EAAAljD,EAAA5U,SAAA83D,EAAAljD,EAAAkjD,MAAAljD,EAAA0+B,UAAAwkB,QAA8CA,EAAAljD,EAAAiJ,MAA8S,QAAAmwD,IAAAlW,EAAAljD,GAAuD,GAAtCukD,EAAAz2D,KAAA6R,MAAaA,KAAAomD,EAAA7C,GAAA,EAAYvjD,KAAAhI,EAAAqI,GAAA,GAAaL,KAAAomD,EAAApmD,KAAAhI,EAAA,KAAAhL,OAAA0sE,GAAiC15D,MAAAujD,EAAA,GAAAgW,IAAcv5D,KAAAK,EAAA,GAAAs0D,IAAc30D,KAAAmrD,EAAA,KAAYnrD,KAAAwjD,KACntB,QAAAmW,IAAApW,GAAe,qBAAAA,GAAAsO,EAAAtO,EAAAsO,QAAgC,QAAAxxD,KAAAkjD,KAAAljD,GAAA,KAC/F,QAAAu5D,IAAArW,EAAAljD,GAAiBL,KAAAujD,IAASvjD,KAAAK,IAAU,QAAAw5D,IAAAtW,GAAyB,GAAVvjD,KAAAujD,KAAUA,IAAA,CAAQ,GAAAA,YAAAsW,IAAA,CAAoB,GAAAx5D,GAAAkjD,EAAA0O,GAAoB,IAAR1O,IAAA8C,IAAQ,GAAArmD,KAAAmkD,IAAA,CAAgB,OAAAnsD,GAAAgI,KAAAujD,EAAAnjD,EAAA,EAAqBA,EAAAC,EAAA5U,OAAW2U,IAAApI,EAAAc,KAAA,GAAA8gE,IAAAv5D,EAAAD,GAAAmjD,EAAAnjD,IAA8B,MAAAmjD,QAASljD,GAAAmlD,GAAAjC,KAAAgC,GAAAhC,EAAqB,KAAAnjD,EAAA,EAAQA,EAAAC,EAAA5U,OAAW2U,IAAA05D,GAAA95D,KAAAK,EAAAD,GAAAmjD,EAAAnjD,KAAwB,QAAA05D,IAAAvW,EAAAljD,EAAArI,GAAmB,GAAAoI,GAAAmjD,GAAiD,KAAvCnjD,EAAAtH,KAAA,GAAA8gE,IAAAv5D,EAAArI,IAAoBqI,EAAAD,EAAA3U,OAAA,EAAa83D,MAAMvrD,EAAAurD,EAAAljD,GAAW,EAAAA,IAAID,EAAAC,EAAA,KAAAkjD,EAAAnjD,GAAAmjD,EAAAvrD,EAAAurD,MAAAljD,GAAAkjD,EAAAnjD,GAAAC,EAAAD,CAAiDmjD,GAAAljD,GAAArI,EACvb,QAAA+hE,MAAcF,GAAA1rE,KAAA6R,MAAuB,QAAA6xD,GAAAtO,EAAAljD,GAAgBL,KAAAqjB,EAAA,GAAA02C,IAAcN,GAAAtrE,KAAA6R,KAAAujD,EAAAljD,GACrC,QAAAgtD,GAAA9J,EAAAljD,EAAArI,EAAAoI,GAAoBJ,KAAAsjD,EAAAC,EAASvjD,KAAAywD,IAAArwD,EAAWyxD,EAAA1jE,KAAA6R,KAAAK,EAAArI,GAjGzM,GAAAmzD,GAAAoL,cAAmB/tD,EAAAxI,KAE+QwsB,EAAA,oBAAArrB,KAAAE,WAAA,GAAA0jD,GAAA,EAE5JoI,EAAAthE,KAAAymB,KAAA,WAA2B,UAAAzmB,MAAgas4D,GAAAG,GAAAt3D,OAAYs3D,GAAAz2D,UAAA8B,KAAA,aAA2L,IAAAu2D,IAAAzzD,OAAA5E,UAAAmsE,KAAA,SAAAzW,GAAyC,MAAAA,GAAAyW,QAAgB,SAAAzW,GAAa,MAAAA,GAAA99C,QAAA,6BAA8J0+C,GAAAO,GAAAJ,IAASI,GAAA72D,UAAA8B,KAAA,gBAAuN,IAAAk1D,IAAA,EAAAC,KAAeF,GAAA/2D,UAAAuE,GAAA,EAAiBwyD,EAAA/2D,UAAAgkE,EAAA,WAAyB,IAAA7xD,KAAA5N,IAAA4N,KAAA5N,GAAA,EAAA4N,KAAA4kD,IAAA,GAAAC,IAAA,CAAwC,GAAAtB,GAAAvjD,KAAAwsB,KAAAxsB,KAAAwsB,KAAAu4B,UAA8BD,IAAAvB,KAAeqB,EAAA/2D,UAAA+2D,EAAA,WAAyB,GAAA5kD,KAAAyI,EAAA,KAAezI,KAAAyI,EAAAhd,QAAcuU,KAAAyI,EAAA0tC,UAAmB,IAAAqS,IAAA34D,MAAAhC,UAAA8D,QAAA,SAAA4xD,EAAAljD,EAAArI,GAA+C,MAAAnI,OAAAhC,UAAA8D,QAAAxD,KAAAo1D,EAAAljD,EAAArI,IAA2C,SAAAurD,EAAAljD,EAAArI,GAA0D,GAAzCA,EAAA,MAAAA,EAAA,IAAAA,EAAAmJ,KAAA2rC,IAAA,EAAAyW,EAAA93D,OAAAuM,KAAyCsrD,EAAAC,GAAA,MAAAD,GAAAjjD,IAAA,GAAAA,EAAA5U,OAAA83D,EAAA5xD,QAAA0O,EAAArI,IAAA,CAAmD,MAAKA,EAAAurD,EAAA93D,OAAWuM,IAAA,GAAAA,IAAAurD,MAAAvrD,KAAAqI,EAAA,MAAArI,EAAiC,WAASk5D,GAAArhE,MAAAhC,UAAAgB,QAAA,SAAA00D,EAAAljD,EAAArI,GAA4CnI,MAAAhC,UAAAgB,QAAAV,KAAAo1D,EAAAljD,EAAArI,IAAoC,SAAAurD,EAAAljD,EAAArI,GAAiB,OAAAoI,GAAAmjD,EAAA93D,OAAAmB,EAAA02D,EAAAC,KAAAvsD,MAAA,IAAAusD,EAAAlgC,EAAA,EAA4CA,EAAAjjB,EAAIijB,QAAAz2B,IAAAyT,EAAAlS,KAAA6J,EAAApL,EAAAy2B,KAAAkgC,IACx6C8B,CAAM9B,GAAA,CAAG,GAAAyT,IAAAxuD,EAAA+zB,SAAmB,IAAAy6B,GAAA,CAAO,GAAAE,IAAAF,GAAAx6B,SAAoB,IAAA06B,GAAA,CAAO7R,EAAA6R,EAAK,MAAA3T,IAAS8B,EAAA,GAAiR,GAAAM,IAAA,gGAAA3uD,MAAA,IAC1hB4uD,IAAA,KAAApC,EAAsG,IAAAoO,IAAAxM,EAAA,SAAA6Q,EAAA7Q,EAAA,YAAAA,EAAA,QAAA2P,GAAA3P,EAAA,QAAAkC,GAAAlC,EAAA,gBAAAC,EAAAyO,cAAAniE,QAAA,YAAAyzD,EAAA,YAAAA,EAAA,YAAAA,EAAA,WAAAA,EAAA,QAAA0M,IAAA,GAAAzM,EAAAyO,cAAAniE,QAAA,YAAAyzD,EAAA,QAAwRe,EAC3lB5C,GAAA,CAAG,GAAA+C,IAAA,GAAA2T,GAAA,WAAwB,GAAA1W,GAAA8B,CAAQ,OAAAiC,IAAA,sBAA+Bj2D,KAAAkyD,GAAWwR,GAAA,kBAAA1jE,KAAAkyD,GAAsC0S,EAAA,mCAA2C5kE,KAAAkyD,GAAWuO,GAAA,gBAAAzgE,KAAAkyD,GAAoCqO,GAAA,yBAAAvgE,KAAAkyD,OAAA,KAAqE,IAArB0W,KAAA3T,GAAA2T,MAAA,OAAqBhE,EAAA,CAAM,GAAAiE,IAAAnU,IAAY,UAAAmU,OAAAC,WAAA7T,IAAA,CAAgCH,GAAA+T,GAAAznE,EAAc,MAAA8wD,IAAS4C,GAAAG,GAAM,GAAAR,OACwHmR,GAAOiB,GAAA1vD,EAAAuW,QAChek4C,IAAAiB,IAAAjC,EAAAlQ,OAAA,cAAAmS,GAAAkC,WAAAzrE,SAAAw3D,GAAA,aAAsE,IAAAkU,IAAAnsE,OAAAosE,QAAA,SAAA/W,GAAkC,MAAAA,IAAUiG,IAAAyM,GAAA,IAAAgB,GAAAsD,GAAAtE,IAAAhQ,GAAA,KAAAkD,GAAA,WAAsD,IAAA3gD,EAAA2+B,mBAAAj5C,OAAAwR,eAAA,QAAwD,IAAA6jD,IAAA,EAAAljD,EAAAnS,OAAAwR,kBAAmC,WAAY7H,IAAA,WAAe0rD,GAAA,IAA2E,OAAnE/6C,GAAA2+B,iBAAA,OAAAqc,GAAAnjD,GAAgCmI,EAAA4+B,oBAAA,OAAAoc,GAAAnjD,GAAmCkjD,IAAwE8C,GAAAx4D,UAAAwS,EAAA,WAAyBL,KAAAsmD,IAAA,GAErTnC,EAAAoC,GAAAF,EAAQ,IAAAuB,IAAAyS,IAAWG,EAAA,QAAAC,EAAA,MAAAC,EAAA,SAA8BnU,IAAA14D,UAAAwS,EAAA,WAA0BkmD,GAAAnC,EAAA/jD,EAAAlS,KAAA6R,KAAkB,IAAAujD,GAAAvjD,KAAAhI,CAAa,IAAAurD,EAAAoX,eAAApX,EAAAoX,qBAAuC,IAAApX,EAAAyG,aAAA,EAAAuQ,GAAA,KAAgChX,EAAA0D,SAAA,KAAA1D,EAAAwG,SAAA,KAAAxG,EAAAwG,WAAAxG,EAAAwG,SAAA,GAA0D,MAAA1pD,KAAY,IAAAyX,IAAA,2BAAA3W,KAAAE,SAAA,GAAsF4mD,GAAA,EACnWgB,GAAA,mBAAA9nD,KAAAE,SAAA,GAAAuoD,MAAgDN,GAAA,EAM1GjF,GAAA,4BAAAljD,KAAAE,WAAA,EAA+N8iD,GAAAgG,EAAAvF,GAAOuF,EAAAt8D,UAAAiqB,KAAA,EAAmBqzC,EAAAhB,EAAAt8D,UAAcs9D,EAAAhkB,iBAAA,SAAAoc,EAAAljD,EAAArI,EAAAoI,GAAqCsoD,GAAA1oD,KAAAujD,EAAAljD,EAAArI,EAAAoI,IAAkB+qD,EAAA/jB,oBAAA,SAAAmc,EAAAljD,EAAArI,EAAAoI,GAAwCqpD,GAAAzpD,KAAAujD,EAAAljD,EAAArI,EAAAoI,IAC3a+qD,EAAAqE,cAAA,SAAAjM,GAA4B,GAAAljD,GAAArI,EAAAgI,KAAAqqD,CAAe,IAAAryD,EAAA,IAAAqI,KAAcrI,EAAEA,IAAAqyD,EAAAhqD,EAAAvH,KAAAd,EAAgBA,GAAAgI,KAAAoqD,CAAS,IAAAhqD,GAAAmjD,EAAAxzD,MAAAwzD,CAAgB,IAAAD,EAAAC,KAAA,GAAA8C,GAAA9C,EAAAvrD,OAAqB,IAAAurD,YAAA8C,GAAA9C,EAAA7oD,OAAA6oD,EAAA7oD,QAAA1C,MAA4C,CAAK,GAAApL,GAAA22D,CAAQA,GAAA,GAAA8C,GAAAjmD,EAAApI,GAAa0tD,GAAAnC,EAAA32D,GAAa,GAALA,GAAA,EAAKyT,EAAA,OAAAgjB,GAAAhjB,EAAA5U,OAAA,EAA0B,GAAA43B,EAAKA,IAAA,CAAK,GAAA+iC,GAAA7C,IAAAljD,EAAAgjB,EAAez2B,GAAA09D,GAAAlE,EAAAhmD,GAAA,EAAAmjD,IAAA32D,EAA8D,GAA5Cw5D,EAAA7C,IAAAvrD,EAAQpL,EAAA09D,GAAAlE,EAAAhmD,GAAA,EAAAmjD,IAAA32D,EAAkBA,EAAA09D,GAAAlE,EAAAhmD,GAAA,EAAAmjD,IAAA32D,EAAkByT,EAAA,IAAAgjB,EAAA,EAAaA,EAAAhjB,EAAA5U,OAAW43B,IAAA+iC,EAAA7C,IAAAljD,EAAAgjB,GAAAz2B,EAAA09D,GAAAlE,EAAAhmD,GAAA,EAAAmjD,IAAA32D,CAAiC,OAAAA,IACtXu+D,EAAAvG,EAAA,WAAgC,GAAjBuF,EAAA/F,EAAAQ,EAAAz2D,KAAA6R,MAAiBA,KAAAhI,EAAA,CAAW,GAAAA,GAAAurD,EAAAvjD,KAAAhI,EAAAqI,EAAA,CAAmB,KAAArI,IAAAurD,KAAA,CAAc,OAAAnjD,GAAAmjD,IAAAvrD,GAAApL,EAAA,EAAqBA,EAAAwT,EAAA3U,OAAWmB,MAAAyT,EAAA8nD,GAAA/nD,EAAAxT,UAAiB22D,KAAAvrD,GAAcurD,EAAAljD,KAAOL,KAAAqqD,EAAA,MAAac,EAAArC,EAAA,SAAAvF,EAAAljD,EAAArI,EAAAoI,GAAsB,MAAAioD,IAAAroD,KAAAhI,EAAAurD,EAAA9wD,GAAA4N,GAAA,EAAArI,EAAAoI,IAAsC+qD,EAAAtF,GAAA,SAAAtC,EAAAljD,EAAArI,EAAAoI,GAAuB,MAAAioD,IAAAroD,KAAAhI,EAAAurD,EAAA9wD,GAAA4N,GAAA,EAAArI,EAAAoI,IAAsC+qD,EAAAjG,GAAA,SAAA3B,EAAAljD,EAAArI,EAAAoI,GAAuB,GAAAxT,GAAAoT,KAAAhI,CAAoC,KAAvBurD,GAAA9wD,KAAuB7F,GAAA22D,EAAA,CAAa,GAAAlgC,GAAAz2B,EAAA22D,IAAaljD,GAAAioD,GAAAjlC,EAAAhjB,EAAArI,EAAAoI,IAAc,EAAAC,GAAA8nD,GAAA9kC,EAAAhjB,IAAAxQ,MAAAhC,UAAAk+B,OAAA59B,KAAAk1B,EAAAhjB,EAAA,MAAAgjB,EAAA53B,eAAAmB,GAAA22D,KAAA32D,EAAAyT,KAAAzT,GAAA,GAAAA,GAAA,MAAgGA,IAAA,CAAU,OAAAA,GAGrU,IAAAq+D,KAAQ2P,IAAA,MAAAC,KAAA,OAAAC,IAAA,MAAAC,KAAA,MAAAC,KAAA,MAAAC,KAAA,MAAAC,KAAA,MAAAC,KAAA,MAAAC,KAAA,WAAwGpQ,GAAA,SAAAxlD,KAAA,8DACvD0lD,IAAAr9D,UAAAgK,IAAA,WAA4B,KAAAmI,KAAAK,EAAA,CAAaL,KAAAK,GAAS,IAAAkjD,GAAAvjD,KAAAujD,CAAavjD,MAAAujD,IAAAv9C,KAAcu9C,EAAAv9C,KAAA,SAAYu9C,GAAAvjD,KAAAhI,GAAgB,OAAAurD,GAAU,IAAAyJ,GAAA,GAAA9B,IAAA,WAAwB,UAAAI,KAAc,SAAA/H,GAAaA,EAAAxU,SAAU,IAA8Iuc,IAAAz9D,UAAAof,IAAA,SAAAs2C,EAAAljD,GAA+BL,KAAAujD,IAASvjD,KAAAK,IAASL,KAAAgG,KAAA,MAAgBslD,GAAAz9D,UAAAkhD,MAAA,WAA8B/uC,KAAAgG,KAAAhG,KAAAK,EAAAL,KAAAujD,EAAA,KAAkF,IAAAwJ,IAGthBJ,GAAsTM,IAAA,EAAA5B,GAAA,eAA4BrrD,KAAAK,EAAAL,KAAAujD,EAAA,KAA8NY,GAAA+I,GAAA/C,GAAQgB,EAAA+B,GAAAr/D,UAAes9D,EAAAkC,GAAA,EAAOlC,EAAAmC,EAAA,KAASnC,EAAA7C,GAAA,WAAgB,GAAAtoD,KAAAqtD,EAAA,CAAW,GAAA9J,GAAA4J,IAAAntD,KAAAmrD,CAAiB,GAAA5H,KAAA,GAAAvjD,KAAAK,EAAAL,KAAAstD,EAAAttD,KAAAujD,EAAAt6B,WAAAjpB,KAAAqjB,EAAArjB,KAAAK,EAAAkjD,IAAAvjD,KAAAstD,IAAAttD,KAAAujD,EAAAgK,aAAAvtD,KAAAstD,GAAAttD,KAAAstD,EAAA,MAAAttD,KAAAwvD,cAAA,QAAAxvD,KAAAqtD,IAAArtD,KAAAstD,EAAAttD,KAAAujD,EAAAt6B,WAAAjpB,KAAAqjB,EAAArjB,KAAAK,GAAAL,KAAAmrD,EAAAgC,QAAyMhC,EAAAxyD,MAAA,WAAmBqH,KAAAqtD,GAAA,EAAUrtD,KAAAstD,IAAAttD,KAAAstD,EAAAttD,KAAAujD,EAAAt6B,WAAAjpB,KAAAqjB,EAAArjB,KAAAK,GAAAL,KAAAmrD,EAAAgC,MAC/9BhC,EAAAvG,EAAA,WAAesI,GAAA9I,EAAAQ,EAAAz2D,KAAA6R,MAAkBotD,GAAAptD,YAASA,MAAAujD,GAA+TY,EAAAsJ,GAAA7I,GAAQuG,EAAAsC,GAAA5/D,UAAes9D,EAAApG,IAAA,EAAQoG,EAAAwC,EAAA,KAASxC,EAAA3B,GAAA,SAAAjG,GAAiBvjD,KAAAujD,EAAA/3D,UAAiBwU,KAAA2tD,EAAA3tD,KAAA+kD,IAAA,EAAA2I,GAAA1tD,OAA4BmrD,EAAAvG,EAAA,WAAe6I,GAAArJ,EAAAQ,EAAAz2D,KAAA6R,MAAkBA,KAAA2tD,IAAAnlD,EAAA+kD,aAAAvtD,KAAA2tD,GAAA3tD,KAAA2tD,EAAA,KAAA3tD,KAAA+kD,IAAA,EAAA/kD,KAAAujD,OAAmE4H,EAAArzC,GAAA,WAAgB9X,KAAA2tD,EAAA,KAAY3tD,KAAA+kD,KAAA/kD,KAAA+kD,IAAA,EAAA2I,GAAA1tD,QAAkImkD,EAAAyJ,EAAAhJ,EAAO,IAAAyW,MAAUzN,GAAA//D,UAAAi7D,EAAA,SAAAvF,EAAAljD,EAAArI,EAAAoI,GAAgCwJ,EAAAvJ,SAAAg7D,GAAA,GAAAh7D,QAAAg7D,GAAqC,QAAAzuE,GAAA,EAAYA,EAAAyT,EAAA5U,OAAWmB,IAAA,CAAK,GAAAy2B,GAAAqlC,GAAAnF,EAAAljD,EAAAzT,GAAAoL,GAAAgI,KAAAkqD,YAAA9pD,IAAA,EAAAJ,KAAAK,GAAAL,KAAwD,KAAAqjB,EAAA,KAAYrjB,MAAAujD,EAAAlgC,EAAAp1B,KAAAo1B,EAAgB,MAAArjB,OACn9B4tD,EAAA//D,UAAAq3D,GAAA,SAAA3B,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAmC,GAAAgd,EAAAvJ,GAAA,OAAAgjB,GAAA,EAAoBA,EAAAhjB,EAAA5U,OAAW43B,IAAArjB,KAAAklD,GAAA3B,EAAAljD,EAAAgjB,GAAArrB,EAAAoI,EAAAxT,OAA0BoL,MAAAgI,KAAAkqD,YAAA9pD,EAAAE,EAAAF,OAAA4nD,UAAA5nD,EAAAxT,KAAAoT,KAAAK,GAAAL,KAAAhI,EAAA6wD,GAAA7wD,GAAAoI,OAAAC,EAAArH,GAAAuqD,GAAAkF,GAAAlF,EAAAvrD,EAAAqI,EAAA5N,GAAAuF,EAAAoI,EAAAxT,GAAA22D,MAAAyF,GAAAzF,IAAAkF,GAAAlF,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAA,QAAA88D,GAAArpD,SAAAL,MAAAujD,EAAAljD,EAAApS,KAAsL,OAAA+R,OAA4F4tD,EAAA//D,UAAA+2D,EAAA,WAAyBgJ,EAAAxJ,EAAAQ,EAAAz2D,KAAA6R,MAAiB6tD,GAAA7tD,OACxZ4tD,EAAA//D,UAAAq8D,YAAA,WAAmC,KAAAl9D,OAAA,6CAAuG8gE,GAAAjgE,UAAA01D,EAAA,IAAoB,IAAA+X,IAAA,CAASxN,IAAAjgE,UAAAkhD,MAAA,SAAAwU,EAAAljD,EAAArI,EAAAoI,EAAAxT,GAAuC,gBAAAA,IAAA0uE,KAAyBl7D,GAAA+sD,IAAOntD,KAAAK,UAASL,MAAAujD,GAA0GyK,EAAAngE,UAAA8S,SAAA,WAAgC,MAAAX,MAAArQ,KAAkB,IAAA8yC,IAAA,GAAAurB,GAAA,cAAAI,GAAA,GAAAJ,GAAA,eAAAW,GAAA,GAAAX,GAAA,YAAAQ,GAAA,GAAAR,GAAA,cAAAa,GAAA,GAAAb,GAAA,WACnZD,IAAAlgE,UAAA1B,IAAA,SAAAo3D,EAAAljD,EAAArI,GAAiC,GAAAurD,EAAAl1D,OAAA4/D,GAAAjuD,MAAA3R,MAAA,IAAAu1D,GAAAvjD,YAAAkjD,EAAA,GAAAuK,IAAAvK,EAAAljD,EAAA5N,GAAAuN,KAAAqjB,GAAArrB,IAAAurD,IAAAvrD,KAAA,OAAAurD,EAAAljD,GAAAkjD,EAAA/6C,EAAAtc,UAAAq3D,EAAAgY,WAAAhY,EAAAgY,UAAAvjE,IAAAurD,EAAA/6C,EAAAgzD,sBAAAjY,EAAAvrD,KAAAgI,KAAqLhI,GAAEA,IAAAurD,EAA8E,IAAAgL,OAASD,GAAA,KAEhOjE,EAAA,GAAAF,EAA+DhG,GAAAmL,GAAAjJ,GAA2FlC,EAAAsL,GAAApJ,GAA4FlC,EAAAuL,GAAArJ,EAAqI,IAAAoV,KAAQ10C,SAAA,EAAAwhC,GAAA,EAAAM,GAAA,EAAAD,GAAA,EAAAgB,GAAA,EAAAlB,GAAA,EAAAK,GAAA,EAAAkR,GAAA,EAAA/yC,QAAA,EAAAmiC,GAAA,GAA8DqS,IAAQzS,GAAA,WAAAY,GAAA,UAAAqQ,GAAA,QAAAD,GAAA,QAAAxQ,GAAA,QAAAC,GAAA,mBAAAxiC,QAAA,UAAA8hC,GAAA,kBAAAO,GAAA,WAAAD,GAAA,mBAAAQ,GAAA,iBAAiM8F,IAAA/hE,UAAA01D,EAAA,IAAoG,IAAAoY,GAAsBxX,GAAA4L,GAAAH,IAAgd+L,GAAA,GAAA5L,GAAmU,IAAAM,IAAA,KAAAC,GAAA,IACl7CgB,MAASD,KAAOlG,GAAA/G,EAAAv2D,UAAcs9D,EAAAliC,WAAA,SAAAs6B,GAAyBvjD,KAAAoqD,EAAA7G,GAEnI4H,EAAAhD,GAAA,SAAA5E,GAAiBA,IAAA7oD,MAAW,IAAA2F,GAAAL,KAAAmuD,CAAa9tD,IAAA,GAAAqwD,EAAAnN,IAAA6L,EAAApvD,KAAAK,EAAA,gCAAAA,EAAAmpD,MAAAxpD,KAAAivD,GAAA1L,IACjJ4H,EAAA8D,GAAA,SAAA1L,GAAiB,IAAI,GAAAA,GAAAvjD,KAAAujD,EAAA,CAAc,GAAAljD,GAAAqwD,EAAA1wD,KAAAujD,GAAAvrD,EAAAgI,KAAAujD,EAAAmC,IAA8B,QAAArlD,GAAA,GAAAA,IAAAuxD,KAAA5xD,KAAAujD,EAAAuS,KAAA,CAAmC91D,KAAA1N,GAAA,GAAA+N,GAAA,GAAArI,GAAAu3D,KAAyBoC,GAAA3xD,KAAS,IAAAI,GAAAJ,KAAAujD,EAAAiT,GAAiBx2D,MAAAyI,EAAArI,CAAS,IAAAxT,GAAAoT,KAAAujD,EAAAuS,GAA0L,IAAzKlpE,GAAAwiE,EAAApvD,KAAAK,EAAA,4BAAAL,KAAAmrD,EAAA,WAAA/qD,GAA6DJ,KAAAhI,EAAA,KAAAoI,EAAcgvD,EAAApvD,KAAAK,EAAA,iBAAAL,KAAAqjB,EAAA,eAAArjB,KAAAmwD,EAAA,MAAAnwD,KAAAywD,EAAA,KAAAzwD,KAAAmrD,EAAA,KAAA9qD,EAAA,IAAAD,GAA8FJ,KAAAhI,EAAAgI,KAAAqqD,GAAA8G,GAAAnxD,KAAAK,EAAAzT,GAAAglE,IAAA5xD,KAAAhI,GAAA,GAAAqI,IAAAL,KAAAowD,EAAAtH,EAAA9oD,KAAAkuD,EAAA,OAAAluD,KAAA8nD,IAAA9nD,KAAAkuD,EAAAv1D,WAAAo2D,GAAA/uD,KAAAK,EAAAL,KAAAqjB,EAAAz2B,EAAA,MAAA2kE,GAAAvxD,KAAApT,IAAA,GAAAyT,GAAAmxD,GAAAxxD,WAAAhI,IAC1VgI,KAAA1N,IAAA,GAAA+N,EAAAL,KAAA0kC,EAAAugB,GAAAjlD,YAAAhI,GAAA,EAAAg5D,GAAAhxD,YAAqD,CAAK,QAAAI,GAAA,EAAAxT,EAAA+E,QAAA,gBAAuCqO,KAAA5N,EAAA,EAASk7D,GAAI,IAAAjqC,GAAArjB,KAAAK,EAAAkjD,CAAelgC,IAAA8qC,EAAA9qC,EAAA,wBAAArjB,KAAAqjB,EAAA,SAA2C,CAAKrjB,KAAA5N,EAAA,EAASk7D,GAAI,IAAAlH,GAAApmD,KAAAK,EAAAkjD,CAAe6C,IAAA+H,EAAA/H,EAAA,sBAAAhmD,EAAA,KAAAJ,KAAAqjB,EAAA,KAAgDmuC,GAAAxxD,MAASyxD,GAAAzxD,YAAW,CAAK,GAAA0kC,GAAA1kC,KAAAK,EAAAkjD,CAAe7e,IAAAypB,EAAAzpB,EAAA,2CAAkD,MAAAj8B,GAAS2mD,EAAApvD,KAAAK,EAAA,8CAAAL,KAAAujD,GAAAvjD,KAAAujD,EAAAuS,IAAAzG,GAAArvD,KAAAK,EAAAoI,EAAA,iBAAAzI,KAAAujD,EAAAuS,KAAAzG,GAAArvD,KAAAK,EAAAoI,EAAA,sBACM0iD,EAAArD,GAAA,WAAgB,GAAAvE,GAAAmN,EAAA1wD,KAAAujD,GAAAljD,EAAAL,KAAAujD,EAAAuS,GAA6B91D,MAAAgtD,EAAA3sD,EAAA5U,SAAAkmE,GAAA3xD,MAAAmxD,GAAAnxD,KAAAujD,EAAAljD,GAAAL,KAAAhI,GAAA,GAAAurD,GAAAyN,GAAAhxD,QAC5NmrD,EAAAwM,OAAA,WAAoB33D,KAAA1N,GAAA,EAAUk/D,GAAAxxD,OACjNmrD,EAAAlD,GAAA,WAAgBjoD,KAAAwwD,EAAA,IAAY,IAAAjN,GAAA4J,GAAU,OAAA5J,EAAAvjD,KAAAuwD,EAAAvwD,KAAAhI,IAAAurD,EAAAvjD,KAAAK,EAAAkjD,IAAA2K,EAAA3K,EAAA,qEAAA6L,EAAApvD,KAAAK,EAAA,YAAAL,KAAAmrD,GAAA,GAAAnrD,KAAAovD,IAAAG,KAAAjC,KAAAkE,GAAAxxD,WAAA5N,EAAA,EAAAq/D,GAAAzxD,UAA4L,CAAK,GAAAK,GAAAL,KAAAK,EAAAkjD,CAAeljD,IAAA8tD,EAAA9tD,EAAA,mCAA0CqxD,GAAA1xD,UAAAuwD,EAAAhN,KAE6W4H,EAAA8G,EAAApkE,UAAcs9D,EAAAhH,EAAA,WAAe,MAAAnkD,MAAAhI,GAAemzD,EAAA9E,EAAA,WAAe+L,GAAApyD,KAAS,QAAAujD,MAAAljD,EAAA,EAAiBA,EAAAL,KAAAujD,EAAA93D,OAAgB4U,IAAAkjD,EAAAzqD,KAAAkH,KAAAK,EAAAL,KAAAujD,EAAAljD,IAA8B,OAAAkjD,IAAU4H,EAAA8G,EAAA,WAAwB,MAATG,IAAApyD,MAASA,KAAAujD,EAAAj3D,UACjd6+D,EAAAtzD,IAAA,SAAA0rD,EAAAljD,GAAoB,MAAA+pD,GAAApqD,KAAAK,EAAAkjD,GAAAvjD,KAAAK,EAAAkjD,GAAAljD,GAAgC8qD,EAAAl+C,IAAA,SAAAs2C,EAAAljD,GAAoB+pD,EAAApqD,KAAAK,EAAAkjD,KAAAvjD,KAAAhI,IAAAgI,KAAAujD,EAAAzqD,KAAAyqD,IAAuCvjD,KAAAK,EAAAkjD,GAAAljD,GAChd8qD,EAAAt8D,QAAA,SAAA00D,EAAAljD,GAAwB,OAAArI,GAAAgI,KAAAiyD,IAAA7xD,EAAA,EAAuBA,EAAApI,EAAAvM,OAAW2U,IAAA,CAAK,GAAAxT,GAAAoL,EAAAoI,GAAAijB,EAAArjB,KAAAnI,IAAAjL,EAAyB22D,GAAAp1D,KAAAkS,EAAAgjB,EAAAz2B,EAAAoT,OAAuF,IAAA6yD,IAAA,0HAC/KN,GAAA1kE,UAAA8S,SAAA,WAAgC,GAAA4iD,MAAAljD,EAAAL,KAAAqjB,CAAkBhjB,IAAAkjD,EAAAzqD,KAAAm6D,GAAA5yD,EAAAu7D,IAAA,OAA2B,IAAA5jE,GAAAgI,KAAAK,CAAkW,QAArVrI,GAAA,QAAAqI,KAAAkjD,EAAAzqD,KAAA,OAAAuH,EAAAL,KAAAywD,IAAAlN,EAAAzqD,KAAAm6D,GAAA5yD,EAAAu7D,IAAA,QAAArY,EAAAzqD,KAAA08D,mBAAAx9D,EAAAvF,IAAAgT,QAAA,uBAAiI,eAAAzN,EAAAgI,KAAA5N,IAAAmxD,EAAAzqD,KAAA,IAAAd,EAAAvF,MAAoDuF,EAAAgI,KAAAujD,KAAAvjD,KAAAK,GAAA,KAAArI,EAAAxF,OAAA,IAAA+wD,EAAAzqD,KAAA,KAAAyqD,EAAAzqD,KAAAm6D,GAAAj7D,EAAA,KAAAA,EAAAxF,OAAA,GAAAqpE,GAAAC,IAAA,MAA0F9jE,EAAAgI,QAAAhI,IAAAurD,EAAAzqD,KAAA,IAAAd,IAAqCA,EAAAgI,KAAAmrD,IAAA5H,EAAAzqD,KAAA,IAAAm6D,GAAAj7D,EAAA+jE,KAAiCxY,EAAA3xD,KAAA,KAC/a2gE,EAAA1kE,UAAAyM,QAAA,SAAAipD,GAAgC,GAAAljD,GAAA+vD,EAAApwD,MAAAhI,IAAAurD,EAAAlgC,CAAsBrrB,GAAAw6D,GAAAnyD,EAAAkjD,EAAAlgC,GAAArrB,IAAAurD,EAAAkN,EAAoBz4D,EAAAqI,EAAAowD,EAAAlN,EAAAkN,EAAAz4D,IAAAurD,EAAAljD,EAAkBrI,EAAAy6D,GAAApyD,EAAAkjD,EAAAljD,GAAArI,EAAA,MAAAurD,EAAAnxD,CAAwB,IAAAgO,GAAAmjD,GAAU,IAAAvrD,EAAA06D,GAAAryD,EAAAkjD,EAAAnxD,OAAe,IAAA4F,IAAAurD,IAAA,CAAiB,QAAAnjD,EAAA5N,OAAA,MAAAwN,KAAAK,IAAAL,KAAAujD,EAAAnjD,EAAA,IAAAA,MAA+C,CAAK,GAAAxT,GAAAyT,EAAAkjD,EAAAkL,YAAA,MAA2B,GAAA7hE,IAAAwT,EAAAC,EAAAkjD,EAAAvwC,OAAA,EAAApmB,EAAA,GAAAwT,GAAmC,UAAJxT,EAAAwT,IAAI,KAAAxT,EAAAwT,EAAA,OAAwB,QAAAxT,EAAA+E,QAAA,WAAA/E,EAAA+E,QAAA,OAAkDyO,EAAA,GAAAxT,EAAA6hE,YAAA,OAA0B7hE,IAAAoK,MAAA,IAAe,QAAAqsB,MAAA+iC,EAAA,EAAiBA,EAAAx5D,EAAAnB,QAAW,CAAE,GAAAi5C,GAAA93C,EAAAw5D,IAAa,MAAA1hB,EAAAtkC,GAAAgmD,GAAAx5D,EAAAnB,QAAA43B,EAAAvqB,KAAA,UAAA4rC,IAAA,EAAArhB,EAAA53B,QAAA,GAAA43B,EAAA53B,QAAA,IAC9a43B,EAAA,KAAAA,EAAA/Z,MAAAlJ,GAAAgmD,GAAAx5D,EAAAnB,QAAA43B,EAAAvqB,KAAA,MAAAuqB,EAAAvqB,KAAA4rC,GAAAtkC,GAAA,GAA4DA,EAAAijB,EAAAzxB,KAAA,SAAcwO,GAAAxT,EAA4E,MAAnEoL,GAAAqI,EAAAkjD,EAAAnjD,EAAApI,EAAA,IAAAurD,KAAAvrD,EAA8BA,EAAA26D,GAAAtyD,EAAAurB,GAAA23B,EAAAvrD,QAAAurD,EAAA4H,EAAwBnzD,IAAAqI,EAAA8qD,EAAA5H,EAAA4H,GAAa9qD,EAEoD,IAAAu7D,IAAA,YAAAE,GAAA,WAAAD,GAAA,UAAA3I,GAAA,WAAA6I,GAAA,IACjB5Q,GAAA4H,GAAAllE,UAAes9D,EAAAhH,EAAA,WAAuB,MAARgM,GAAAnwD,MAAQA,KAAAK,GAAyJ8qD,EAAAt8D,QAAA,SAAA00D,EAAAljD,GAAwB8vD,EAAAnwD,MAAQA,KAAAujD,EAAA10D,QAAA,SAAAmJ,EAAAoI,GAA6B8wD,GAAAl5D,EAAA,SAAAA,GAAiBurD,EAAAp1D,KAAAkS,EAAArI,EAAAoI,EAAAJ,OAAmBA,OAAOA,OAChemrD,EAAA8G,EAAA,WAAe9B,EAAAnwD,KAAQ,QAAAujD,GAAAvjD,KAAAujD,EAAA8C,IAAAhmD,EAAAL,KAAAujD,EAAA0O,IAAAj6D,KAAAoI,EAAA,EAA2CA,EAAAC,EAAA5U,OAAW2U,IAAA,OAAAxT,GAAA22D,EAAAnjD,GAAAijB,EAAA,EAAuBA,EAAAz2B,EAAAnB,OAAW43B,IAAArrB,EAAAc,KAAAuH,EAAAD,GAAiB,OAAApI,IAAUmzD,EAAA9E,EAAA,SAAA9C,GAAgB4M,EAAAnwD,KAAQ,IAAAK,KAAS,IAAAijD,EAAAC,GAAAsQ,GAAA7zD,KAAAujD,KAAAljD,EAAA6kD,GAAA7kD,EAAAL,KAAAujD,EAAA1rD,IAAA87D,GAAA3zD,KAAAujD,UAAqD,CAAKA,EAAAvjD,KAAAujD,EAAA8C,GAAa,QAAAruD,GAAA,EAAYA,EAAAurD,EAAA93D,OAAWuM,IAAAqI,EAAA6kD,GAAA7kD,EAAAkjD,EAAAvrD,IAAiB,MAAAqI,IAAU8qD,EAAAl+C,IAAA,SAAAs2C,EAAAljD,GAA4H,MAAxG8vD,GAAAnwD,MAAQA,KAAAhI,EAAA,KAAYurD,EAAAoQ,GAAA3zD,KAAAujD,GAAasQ,GAAA7zD,KAAAujD,KAAAvjD,KAAAK,GAAAL,KAAAujD,EAAA1rD,IAAA0rD,GAAA93D,QAA2CuU,KAAAujD,EAAAt2C,IAAAs2C,GAAAljD,IAAkBL,KAAAK,GAAA,EAAUL,MAAamrD,EAAAtzD,IAAA,SAAA0rD,EAAAljD,GAAqC,MAAjBkjD,KAAAvjD,KAAAqmD,EAAA9C,MAAiB,EAAAA,EAAA93D,OAAA83D,EAAA,GAAA9wD,GAAA4N,GAC3X8qD,EAAAxqD,SAAA,WAAsB,GAAAX,KAAAhI,EAAA,MAAAgI,MAAAhI,CAAwB,KAAAgI,KAAAujD,EAAA,QAAoB,QAAAA,MAAAljD,EAAAL,KAAAujD,EAAA0O,IAAAj6D,EAAA,EAA8BA,EAAAqI,EAAA5U,OAAWuM,IAAA,CAAK,GAAAoI,GAAAC,EAAArI,GAAApL,EAAA4oE,mBAAAp1D,EAAA3N,GAA2C2N,GAAAJ,KAAAqmD,EAAAjmD,EAAY,QAAAijB,GAAA,EAAYA,EAAAjjB,EAAA3U,OAAW43B,IAAA,CAAK,GAAA+iC,GAAAx5D,CAAQ,MAAAwT,EAAAijB,KAAA+iC,GAAA,IAAAoP,mBAAAp1D,EAAAijB,GAAA5wB,KAAqD8wD,EAAAzqD,KAAAstD,IAAW,MAAApmD,MAAAhI,EAAAurD,EAAA3xD,KAAA,KACrI,IAAAqiE,IAAA,IAAYF,IAAAlmE,UAAAof,IAAA,SAAAs2C,GAA6BvjD,KAAAujD,KAAUwQ,GAAAlmE,UAAAkhD,MAAA,WAA8B/uC,KAAAiN,IAAAkgD,MAAe4G,GAAAlmE,UAAAgK,IAAA,WAA4B,MAAAmI,MAAAujD,GAA2EY,EAAA+P,GAAAF,GAAwB,IAAAgI,KAAQ7yC,KAAA,IAAAs/B,GAAA,IAAAyR,GAAA,IAAAhR,GAAA,IAA8D/E,GAAAiQ,GAAA/N,GAAuClC,EAAAkQ,GAAAhO,GAAiH8E,EAAAmJ,GAAAzmE,UAAes9D,EAAAgI,EAAA,KAAqXhI,EAAArG,GAAA,SAAAvB,GAAiB,MAAAvjD,MAAAujD,EAAAuB,GAAAvB,IAC/iC4H,EAAAtuB,MAAA,WAAmB78B,KAAAhI,IAAAgI,KAAAhI,EAAA2/D,SAAA33D,KAAAhI,EAAA,MAAsCgI,KAAAqjB,GAAA,GAAW8nC,EAAAyG,GAAA,WAAgB,UACpFzG,EAAA2G,GAAA,SAAAvO,EAAAljD,GAA8B,GAAXL,KAAAqjB,EAAAkgC,EAAA96C,EAAW,GAAAzI,KAAAmzD,EAAA,CAA+D,GAAjD/D,EAAApvD,KAAAK,EAAA,yCAAiDL,KAAAujD,EAAA2K,IAAA3K,OAAA,CAAuB,GAAAvrD,GAAAurD,QAAA0Y,kBAAA,8BAA+Dj8D,MAAA0kC,EAAA1sC,GAAA,KAAgBgI,KAAAujD,EAAAkN,KAAAlN,UAAA0Y,kBAAA,2BAAAj8D,KAAAujD,EAAAmN,EAAAnN,KAAAvjD,KAAAK,EAAAkjD,IAAA4K,EAAA5K,EAAA,wDAAwJ,GAAAljD,EAAA,CAAM,IAAI,GAAAD,GAAAJ,KAAAujD,EAAA2C,GAAA3C,EAAAyL,MAAA3uD,GAA2B,MAAAzT,GAAsC,MAA7ByiE,IAAArvD,KAAAK,EAAAzT,OAAa2rE,IAAAv4D,KAAAujD,EAAAvjD,MAAuBA,KAAAmrD,EAAA/qD,EAAA,OAAYgvD,GAAApvD,KAAAK,EAAA,qCAAAk4D,GAAAv4D,KAAAujD,EACzbvjD,UAAM,IAAAA,KAAAmzD,IAAAnzD,KAAAomD,EAAAkH,IAAgC,SAAAjtD,GAAoBitD,IAAAttD,KAAAomD,GAAA,IAAA6P,GAAA,KAAAgB,MAAAj3D,KAAAqjB,EAAA,IAAArjB,KAAAhI,EAAA2/D,SAAAvI,EAAApvD,KAAAK,EAAA,yDAAmGitD,IAAAkH,GAAAx0D,KAAAujD,EAAAvjD,MAAA,MAAqDstD,IAAAttD,KAAAomD,GAAA,KAClN+E,EAAAlG,GAAA,WAAgBjlD,KAAAqjB,EAAArjB,KAAAhI,EAAAyQ,EAAgBzI,KAAAhI,IAAA,GAAAgI,KAAAmzD,GAAAnzD,KAAAmzD,EAAA,EAAA/D,EAAApvD,KAAAK,EAAA,sDAAAk0D,GAAAv0D,OAAA,GAAAA,KAAAmzD,IAAA/D,EAAApvD,KAAAK,EAAA,gDAAAL,KAAAomD,GAAAgJ,EAAApvD,KAAAK,EAAA,yDAAuNitD,IAAAkH,GAAAx0D,KAAAujD,EAAAvjD,MAAA,KAAAovD,EAAApvD,KAAAK,EAAA,+CAAwFitD,IAAAkH,GAAAx0D,KAAAujD,EAAAvjD,MAAA,MAAAovD,EAAApvD,KAAAK,EAAA,4CAAAL,KAAAmzD,GAAA,GAAAnzD,KAAAmzD,EAAA7F,IAAA,GAAAttD,KAAAmzD,GAAA7F,IAAAiL,GAAAv4D,KAAAujD,EAAAvjD,QAA6JmrD,EAAAtH,GAAA,WAAgB,MAAA7jD,MAAAujD,EAAAM,MAC5fsH,EAAA3C,GAAA,WAAgB,MAAAxoD,MAAAujD,EAAAiF,MAAuQmM,GAAA9mE,UAAAs2D,EAAA,WAA0B,MAAAnkD,MAAAujD,EAAAY,KAAmBwQ,GAAA9mE,UAAAG,SAAA,SAAAu1D,GAAyC,MAAPA,GAAAgN,EAAAhN,GAAO6G,EAAApqD,KAAAujD,EAAAljD,EAAAkjD,IAAsBoR,GAAA9mE,UAAAw4D,EAAA,WAA0B,MAAArmD,MAAAujD,EAAA8C,IAAwJ,IAAAwO,IAAA,EACrjBD,IAAA/mE,UAAA8pE,OAAA,WAA+B33D,KAAAK,GAAAL,KAAAK,EAAAs3D,SAAA33D,KAAAK,EAAA,MAAAL,KAAAujD,GAAA,GAAAvjD,KAAAujD,IAAAvrD,IAAAk5D,GAAAlxD,KAAAujD,EAAA8C,IAAA,SAAA9C,GAAuFA,EAAAoU,WAAWzF,GAAAlyD,KAAAujD,OAAwF8R,GAAAxnE,UAAAlB,UAAA,SAAA42D,GAAmC,MAAA/6C,GAAA9b,KAAAC,UAAA42D,EAAAvjD,KAAAujD,IAAmC8R,GAAAxnE,UAAAmhE,MAAA,SAAAzL,GAA+B,MAAA/6C,GAAA9b,KAAAsiE,MAAAzL,EAAAvjD,KAAAK,IAAm5B8jD,EAAA2R,EAAA3L,EAAO,IAAA4L,IAAA,EAAUD,GAAAjoE,UAAAwS,EAAAguD,GAAA,iBAAmC,IAAAqI,IAAA,YAAAwF,IAAA,aAAqC/Q,GAAA2K,EAAAjoE,UAC1yCs9D,EAAA+F,GAAA,SAAA3N,EAAAljD,EAAArI,EAAAoI,GAAuB,GAAAJ,KAAAujD,EAAA,KAAAv2D,OAAA,0DAAAgT,KAAA1N,EAAA,YAAyFixD,EAAaljD,OAAA87D,cAAA,MAA0Bn8D,KAAA1N,EAAAixD,EAASvjD,KAAAmrD,EAAA,GAAUnrD,KAAAywD,EAAA,EAASzwD,KAAAowD,EAAA/vD,EAASL,KAAA4uD,GAAA,EAAU5uD,KAAAqjB,GAAA,EAAUrjB,KAAAujD,EAAAyM,GAAAhwD,KAAAmuD,EAAAnuD,KAAAmuD,EAAAwN,IAAgC37D,KAAAkuD,EAAA2B,GAAA7vD,KAAAmuD,EAAAnuD,KAAAmuD,EAAAwN,IAAgC37D,KAAAujD,EAAAgJ,mBAAAvI,EAAAhkD,KAAAsnD,GAAAtnD,KAA0C,KAAI4uD,EAAA5uD,KAAAK,EAAAm2D,EAAAx2D,KAAA,gBAAAA,KAAAovD,GAAA,EAAApvD,KAAAujD,EAAA16B,KAAAxoB,EAAAkjD,EAAA9wD,IAAA,GAAAuN,KAAAovD,GAAA,EAAgF,MAAA/rC,GAAsE,MAA7DurC,GAAA5uD,KAAAK,EAAAm2D,EAAAx2D,KAAA,sBAAAqjB,EAAAt2B,cAAkDopE,IAAAn2D,KAAAqjB,GAAkBkgC,EAAAvrD,GAAA,EAAQ,IAAApL,GAAA,GAAAqlE,GAAAjyD,KAAAmmB,QACne/lB,IAAA4xD,GAAA5xD,EAAA,SAAAmjD,EAAAljD,GAAsBzT,EAAAqgB,IAAA5M,EAAAkjD,KAAanjD,EAAAk8B,GAAA1vC,EAAAqlE,KAAYj6D,EAAAwQ,EAAA4zD,UAAA7Y,YAAA/6C,GAAA4zD,WAAsC,GAAA5T,GAAA0T,GAAA77D,KAAAD,GAAApI,GAAApL,EAAAqgB,IAAA,kEAA8FrgB,EAAAiC,QAAA,SAAA00D,EAAAljD,GAAwBL,KAAAujD,EAAA8Y,iBAAAh8D,EAAAkjD,IAA6BvjD,MAAOA,KAAA0wD,IAAA1wD,KAAAujD,EAAA+Y,aAAAt8D,KAAA0wD,GAAqC,mBAAA1wD,MAAAujD,GAAAvjD,KAAAujD,EAAAgZ,kBAAAv8D,KAAA0kC,IAAA1kC,KAAAujD,EAAAgZ,gBAAAv8D,KAAA0kC,EAA6F,KAAIiyB,GAAA32D,MAAA,EAAAA,KAAAsjD,IAAAtjD,KAAAgtD,EAAAgJ,GAAAh2D,KAAAujD,GAAAqL,EAAA5uD,KAAAK,EAAAm2D,EAAAx2D,KAAA,oBAAAA,KAAAsjD,EAAA,0BAAAtjD,KAAAgtD,IAAAhtD,KAAAgtD,GAAAhtD,KAAAujD,EAAA2S,QACrXl2D,KAAAsjD,EAAAtjD,KAAAujD,EAAAsS,UAAA7R,EAAAhkD,KAAA8lD,GAAA9lD,YAAAmqD,EAAAqD,GAAAxtD,KAAA8lD,GAAA9lD,KAAAsjD,EAAAtjD,OAAA4uD,EAAA5uD,KAAAK,EAAAm2D,EAAAx2D,KAAA,oBAAAA,KAAAwwD,GAAA,EAAAxwD,KAAAujD,EAAAj+B,KAAAi+B,GAAAvjD,KAAAwwD,GAAA,EAAgJ,MAAAntC,GAASurC,EAAA5uD,KAAAK,EAAAm2D,EAAAx2D,KAAA,eAAAqjB,EAAAt2B,UAAAopE,GAAAn2D,KAAAqjB,KACzJ8nC,EAAArF,GAAA,eAAgB,KAAAyQ,MAAAv2D,KAAAujD,IAAAvjD,KAAAmrD,EAAA,mBAAAnrD,KAAAsjD,EAAA,eAAAtjD,KAAAywD,EAAA,EAAA7B,EAAA5uD,KAAAK,EAAAm2D,EAAAx2D,UAAAmrD,IAAAnrD,KAAAwvD,cAAA,WAAAxvD,KAAA68B,MAAA,KAChBsuB,EAAAtuB,MAAA,SAAA0mB,GAAoBvjD,KAAAujD,GAAAvjD,KAAAqjB,IAAAurC,EAAA5uD,KAAAK,EAAAm2D,EAAAx2D,KAAA,aAAAA,KAAAqjB,GAAA,EAAArjB,KAAAomD,GAAA,EAAApmD,KAAAujD,EAAA1mB,QAAA78B,KAAAomD,GAAA,EAAApmD,KAAAywD,EAAAlN,GAAA,EAAAvjD,KAAAwvD,cAAA,YAAAxvD,KAAAwvD,cAAA,SAAA6G,GAAAr2D,QAA6KmrD,EAAAvG,EAAA,WAAe5kD,KAAAujD,IAAAvjD,KAAAqjB,IAAArjB,KAAAqjB,GAAA,EAAArjB,KAAAomD,GAAA,EAAApmD,KAAAujD,EAAA1mB,QAAA78B,KAAAomD,GAAA,GAAAiQ,GAAAr2D,MAAA,IAA6E81D,EAAA1R,EAAAQ,EAAAz2D,KAAA6R,OAAkBmrD,EAAA7D,GAAA,WAAgBtnD,KAAA5N,IAAA4N,KAAAovD,GAAApvD,KAAAwwD,GAAAxwD,KAAAomD,EAAAkQ,GAAAt2D,WAAA4nD,OAAqDuD,EAAAvD,GAAA,WAAgB0O,GAAAt2D,OAG1VmrD,EAAAqL,EAAA,WAAe,IAAI,SAAA9F,EAAA1wD,WAAAujD,EAAAhuD,QAAA,EAAkC,MAAAguD,GAAS,WAAW4H,EAAAvF,GAAA,WAAgB,IAAI,SAAA8K,EAAA1wD,WAAAujD,EAAAiZ,WAAA,GAAsC,MAAAjZ,GAAS,MAAAqL,GAAA5uD,KAAAK,EAAA,uBAAAkjD,EAAAx2D,SAAA,KAAuDo+D,EAAA2K,EAAA,WAAe,IAAI,MAAA91D,MAAAujD,EAAAvjD,KAAAujD,EAAAkZ,aAAA,GAAqC,MAAAlZ,GAAS,MAAAqL,GAAA5uD,KAAAK,EAAA,6BAAAkjD,EAAAx2D,SAAA,KAC9So+D,EAAAoP,GAAA,SAAAhX,GAAiB,GAAAvjD,KAAAujD,EAAA,CAAW,GAAAljD,GAAAL,KAAAujD,EAAAkZ,YAA0BlZ,IAAA,GAAAljD,EAAA1O,QAAA4xD,KAAAljD,IAAAtP,UAAAwyD,EAAA93D,QAA8C83D,GAAA,CAAO,GAAJA,EAAAljD,EAAImI,EAAA9b,KAAA,IAAc,GAAAsL,GAAAwQ,EAAA9b,KAAAsiE,MAAAzL,EAAsB,MAAAA,GAAQ,MAAAnjD,IAAUpI,EAAAwyD,GAAAjH,GAAQ,MAAAvrD,KAAWmzD,EAAAzF,GAAA,WAAgB,MAAA1lD,MAAAywD,GAAetF,EAAAhC,GAAA,WAAgB,MAAA7F,GAAAtjD,KAAAmrD,GAAAnrD,KAAAmrD,EAAAnrD,KAAAmrD,EAAA14D,IACnO04D,EAAA4L,GAAAlpE,UAAes9D,EAAAxG,GAAA,EAAOwG,EAAAyC,EAAA,EACwSzC,EAAAyG,GAAA,WAAgB,UAAA5xD,KAAA4tD,GAC9UzC,EAAAhF,GAAA,SAAA5C,GAA8D,GAA7CvjD,KAAAwwD,EAAA,KAAYpB,EAAApvD,KAAAujD,EAAA,wBAAiC,GAAAvjD,KAAA4tD,EAAA,GAAArK,KAAAvjD,KAAAujD,MAAA2K,EAAA3K,EAAA,sCAAsE,CAAK6L,EAAApvD,KAAAujD,EAAA,WAAoBvjD,KAAAovD,EAAAjuD,KAAAC,MAAA,IAAAD,KAAAE,UAAqCkiD,EAAAvjD,KAAAovD,GAAW,IAAA/uD,GAAA,GAAA+jD,GAAApkD,UAAAujD,EAAA,EAAAA,MAAA,IAAAvrD,EAAAgI,KAAA5N,CAA6C4N,MAAAoqD,IAAApyD,KAAAytD,GAAAztD,GAAA0tD,GAAA1tD,EAAAgI,KAAAoqD,IAAApyD,EAAAgI,KAAAoqD,GAA4C,OAAApqD,KAAAqjB,IAAAhjB,EAAA+lD,EAAApuD,EAAuB,IAAAoI,GAAA43D,GAAAh4D,MAAApT,EAAAwjE,EAAApwD,KAAA4uD,EAA2BuE,GAAAvmE,EAAA,MAAA22D,GAAa,EAAAvjD,KAAAg3D,IAAA7D,EAAAvmE,EAAA,OAAAoT,KAAAg3D,IAA+Bh3D,KAAAkuD,GAAAluD,KAAAywD,GAAA0C,EAAAvmE,EAAA,oBAAAoT,KAAAywD,GAAgD+G,GAAAx3D,KAAApT,GAAWoT,KAAAqjB,GAAArrB,GAAA8+D,GAAAlqE,EAAAoT,KAAAqjB,EAAArrB,GAA0Bi9D,GAAAj1D,KAAAmrD,EAAA9qD,GAAaL,KAAAimD,IAAAkN,EAAAvmE,EAAA,OACtewT,GAAAwwD,GAAAvwD,EAAAzT,EAAA,OAAAgkE,GAAAvwD,EAAAzT,EAAAwT,GAA2BJ,KAAA4tD,EAAA,MAAS,IAAA5tD,KAAA4tD,IAAArK,EAAAwU,GAAA/3D,KAAAujD,GAAA,GAAAvjD,KAAAomD,EAAA36D,OAAA2jE,EAAApvD,KAAAujD,EAAA,kDAAA2R,GAAAl1D,KAAAmrD,IAAA5H,EAAAvjD,KAAAujD,MAAA2K,EAAA3K,EAAA,kEAAAwU,GAAA/3D,MAAAovD,EAAApvD,KAAAujD,EAAA,kDAIpC4H,EAAApF,GAAA,WAAgB/lD,KAAA0kC,EAAA,KAAY0qB,EAAApvD,KAAAujD,EAAA,4BAAqCvjD,KAAAK,EAAA,GAAA+jD,GAAApkD,UAAAujD,EAAA,QAAAvjD,KAAAm3D,IAA0C,OAAAn3D,KAAAqjB,IAAArjB,KAAAK,EAAA+lD,EAAApmD,KAAA5N,GAAiC4N,KAAAK,EAAAqwD,EAAA,CAAW,IAAAnN,GAAA6M,EAAApwD,KAAAmlD,GAAiBgO,GAAA5P,EAAA,aAAiB4P,EAAA5P,EAAA,MAAAvjD,KAAAowD,GAAkB+C,EAAA5P,EAAA,KAAAvjD,KAAAwkD,GAAA,SAA0B2O,EAAA5P,EAAA,MAAAvjD,KAAAmwD,GAAkBqH,GAAAx3D,KAAAujD,GAAW4P,EAAA5P,EAAA,kBAAsBvjD,KAAAqjB,GAAArjB,KAAA5N,GAAA0kE,GAAAvT,EAAAvjD,KAAAqjB,EAAArjB,KAAA5N,GAAoC2+D,GAAA/wD,KAAAK,EAAAkjD,GAAA,EAAAvjD,KAAAkkD,IAAwBkL,EAAApvD,KAAAujD,EAAA,wBAEpV4H,EAAA2G,GAAA,SAAAvO,EAAAljD,GAAmB,MAAAL,KAAA4tD,IAAA5tD,KAAAK,GAAAkjD,GAAA4R,GAAAn1D,KAAAmrD,EAAA5H,IAAA,GAAAvjD,KAAAyI,EAAA86C,EAAA96C,EAAA0sD,GAAAn1D,KAAAmrD,EAAA5H,IAAA,GAAAvjD,KAAA4tD,EAAA,CAA+E,IAAI,GAAA51D,GAAAgI,KAAAkmD,GAAA3C,EAAAyL,MAAA3uD,GAAyB,MAAAgjB,GAASrrB,EAAA,KAAO,GAAA4R,EAAA5R,IAAA,GAAAA,EAAAvM,OAAA,GAAA4U,EAAArI,EAAA,GAAAqI,EAAA,GAAAkjD,EAAA,GAAA6L,EAAApvD,KAAAujD,EAAA,6CAAAvjD,KAAA0kC,EAAA0qB,EAAApvD,KAAAujD,EAAA,kDAA6J,CAAK,GAAAvjD,KAAAK,EAAA,MAAAL,KAAAK,EAAAuuD,EAAA,IAAArL,EAAAqL,GAAmE,KAAArL,EAAnEqU,IAAA53D,WAAAK,EAAAs3D,SAAA33D,KAAAK,EAAA,UAAgFkjD,EAAAvjD,KAAAujD,MAAA4K,EAAA5K,EAAA,2CAAkE6U,IAAAp4D,MAASstD,QAAIttD,MAAAk3D,GAAA72D,EAAA,MAAAkjD,EAAAvjD,KAAAk3D,GAAAl3D,KAAAmwD,KAChd9vD,IAAA,GAAA+uD,EAAApvD,KAAAujD,EAAAljD,EAAA,cAAAkjD,EAAA,qDAAAljD,GAAAL,KAAAwkD,IAAA,GAAAxkD,KAAAmqD,IAAAnqD,KAAA1N,IAAA0N,KAAA1N,EAAAq9D,GAAA3L,EAAAhkD,KAAAumD,GAAAvmD,MAAA,WAA6JovD,GAAApvD,KAAAujD,EAAA,mCAAAoK,EAAA3tD,KAAA,QAA4D,IAAAA,KAAAK,GAAAkjD,GAAAqU,GAAA53D,OAAA,cAAAwF,KAAAnF,GAAA,IAAAA,EAAArI,EAAAgI,KAAAkmD,GAAA3C,EAAAyL,MAAA3uD,GAAArI,EAAA,EAAkFA,EAAAqI,EAAA5U,OAAWuM,IAAA,CAAK,GAAAoI,GAAAC,EAAArI,EAA8B,IAAnBgI,KAAAmwD,EAAA/vD,EAAA,GAAYA,IAAA,GAAO,GAAAJ,KAAA4tD,EAAA,QAAAxtD,EAAA,IAA2BJ,KAAAowD,EAAAhwD,EAAA,GAAYJ,KAAAkkD,GAAA9jD,EAAA,EAAa,IAAAxT,GAAAwT,EAAA,EAAW,OAAAxT,IAAAoT,KAAA2kD,GAAA/3D,EAAAwiE,EAAApvD,KAAAujD,EAAA,OAAAvjD,KAAA2kD,KAA8CvkD,IAAA,GAAO,MAAAA,IAAAJ,KAAAslD,GAAAllD,EAAAgvD,EAAApvD,KAAAujD,EAAA,QAAAvjD,KAAAslD,KAC7ctlD,KAAAkuD,IAAA9tD,EAAAmjD,QAAA32D,EAAAwT,EAAAmjD,EAAAnjD,EAAAmjD,EAAA0Y,kBAAA,iCAAAjH,GAAAh1D,KAAAmrD,EAAAv+D,GAAAoT,KAAAywD,KAAArwD,IAAAmjD,EAAAnjD,EAAAmjD,EAAA0Y,kBAAA,4BAAAj8D,KAAA0wD,EAAAtwD,EAAA+yD,EAAAnzD,KAAA4uD,EAAA5uD,KAAAywD,EAAArwD,OAAAJ,KAAAujD,MAAA4K,EAAA/tD,EAAA,yDAAuQJ,KAAA4tD,EAAA,EAAS5tD,KAAAhI,GAAAgI,KAAAhI,EAAA2tD,GAAA3lD,MAAwBA,KAAAmlD,GAAAsP,GAAAz0D,UAAAkkD,GAAAlkD,KAAAskD,IAAiC6T,GAAAn4D,UAAS,QAAAI,EAAA,aAAAA,EAAA,IAAAutD,EAAA3tD,KAAA,OAA2C,IAAAA,KAAA4tD,IAAA,QAAAxtD,EAAA,aAAAA,EAAA,WAAAA,EAAA,GAAAutD,EAAA3tD,KAAA,GAAAs3D,GAAAt3D,MAAA,QAAAI,EAAA,IAAAJ,KAAAhI,GAAAgI,KAAAhI,EAAAytD,GAAAzlD,KAAAI,GAAAJ,KAAAmqD,EAC7X,KAAKgB,EAAA5E,GAAA,WAAgB,MAAAvmD,KAAA1N,IAAA0N,KAAA1N,EAAA,KAAA0N,KAAAK,EAAAs3D,SAAA33D,KAAAK,EAAA,KAAA+3D,GAAAp4D,MAAAstD,MACrBnC,EAAAlG,GAAA,SAAA1B,GAA8C,GAA7B6L,EAAApvD,KAAAujD,EAAA,oBAA6BvjD,KAAAK,GAAAkjD,EAAA,CAAcqU,GAAA53D,MAASA,KAAAK,EAAA,IAAY,IAAAA,GAAA,MAAQ,KAAA80D,GAAAn1D,KAAAmrD,EAAA5H,GAA4F,MAA5FljD,GAAAL,KAAAmrD,EAAA9qD,UAAAkjD,EAAAljD,IAAA,KAAAA,EAAAkjD,GAAAljD,EAAAkjD,EAAAv1D,SAAAu1D,IAAA4O,GAAA9xD,EAAAkjD,IAAAgN,EAAAhN,IAAAljD,EAAA,EAAmH,GAAXL,KAAAyI,EAAA86C,EAAA96C,EAAW,GAAAzI,KAAA4tD,EAAA,GAAArK,EAAAvrD,EAAA,GAAAqI,GAAA8sD,IAAA9C,EAAAmF,cAAA,GAAAE,IAAArF,IAAAyN,GAAA93D,WAAAsjD,EAAA73D,OAAA,GAAA0sE,GAAAn4D,UAA4F,CAAK,GAAAhI,GAAAurD,EAAAnxD,CAAU,OAAA4F,GAAA,GAAAA,GAAA,EAAAgI,KAAAyI,EAAA2mD,EAAApvD,KAAAujD,EAAA,sCAAmE,CAAK6L,EAAApvD,KAAAujD,EAAA,+BAAAoN,GAAA34D,EAAAgI,KAAAyI,GAAsD,IAAArI,EAC7S,KADmTA,EAAA,GAAAC,KAAA60D,GAAAl1D,KAAAmrD,IAAAnrD,KAAAwwD,IAAAjN,EAAAvjD,KAAAujD,MAAA2K,EAAA3K,EAAA,+BAC3bnjD,GAAA,MAAAJ,KAAA4tD,GAAA,GAAA5tD,KAAA4tD,GAAA,GAAA5tD,KAAAmuD,EAAA/tD,GAAA,GAAAgvD,EAAApvD,KAAAujD,EAAA,uBAAAvjD,KAAAwwD,EAAAb,GAAA3L,EAAAhkD,KAAAmmD,GAAAnmD,KAAAujD,GAAA8U,GAAAr4D,UAAAmuD,IAAAnuD,KAAAmuD,IAAA/tD,GAAA,IAAwIA,GAAA,GAAAC,GAAA+3D,GAAAp4D,MAAA,MAA4BovD,GAAApvD,KAAAujD,EAAA,kCAAkF,OAAvC6L,EAAApvD,KAAAujD,EAAA,8BAAuCvrD,GAAU,OAAA21D,EAAA3tD,KAAA,EAAiB,MAAM,QAAA2tD,EAAA3tD,KAAA,GAAkB,MAAM,QAAA2tD,EAAA3tD,KAAA,EAAiB,MAAM,SAAA2tD,EAAA3tD,KAAA,MAC3BmrD,EAAA9C,GAAA,SAAA9E,GAAiBA,EAAA6L,EAAApvD,KAAAujD,EAAA,kCAAA6L,EAAApvD,KAAAujD,EAAA,6BAAmF+J,KAE/InC,EAAArG,GAAA,SAAAvB,GAAiB,GAAAA,IAAAvjD,KAAAuwD,EAAA,KAAAvjE,OAAA,sDAAoG,OAAnBu2D,GAAA,GAAAuS,GAAQvS,EAAA7e,EAAA1kC,KAAAuwD,EAAWhN,GAAU4H,EAAA3C,GAAA,WAAgB,QAAAxoD,KAAAhI,IAAA,GAAoBmzD,EAAAtH,GAAA,WAAgB,MAAA7jD,MAAAuwD,GAAe,GAAA2D,IAAsB/I,EAAAwN,GAAA9qE,UAAes9D,EAAAxF,GAAA,aACvewF,EAAA1F,GAAA,aAAkB0F,EAAA3F,GAAA,aAAkB2F,EAAAzG,GAAA,aAAkByG,EAAA+M,GAAA,aAAqUW,GAAAhrE,UAAA01D,EAAA,SAAAA,EAAAljD,GAA6B,UAAA6nD,GAAA3E,EAAAljD,IAEnJ8jD,EAAA+D,EAAAiC,GACrQjC,EAAAr6D,UAAA4iE,EAAA,WAAyBzwD,KAAAujD,EAAAvrD,EAAAgI,KAAAomD,EAAgBpmD,KAAAwwD,IAAAxwD,KAAAujD,EAAAgN,GAAA,EAAsB,IAAAhN,GAAAvjD,KAAAujD,EAAAljD,EAAAL,KAAA1N,EAAA0F,EAAAgI,KAAAK,EAAAD,EAAAJ,KAAAmrD,OAAA,EAAgDiE,GAAA7L,IAAA,aAAmB+J,IAAI/J,EAAAe,GAAAtsD,EAAOurD,EAAAO,GAAA1jD,MAAWmjD,EAAA2K,IAAAkB,EAAA7L,IAAA,oCAAAA,EAAA8G,EAAAhqD,KAAAkjD,EAAA8G,EAAA9G,GAAA,GAAmE6L,EAAA7L,IAAA,kBAAwBA,EAAAyJ,EAAA,GAAAsH,IAAA/Q,OAAkB,OAAAA,EAAAlgC,IAAAkgC,EAAAyJ,EAAA56D,EAAAmxD,EAAAnxD,GAAwB4F,EAAAqI,EAAIkjD,EAAAlgC,GAAAkgC,EAAAnxD,IAAA4F,EAAA8+D,GAAAz2D,EAAAkjD,EAAAlgC,EAAAkgC,EAAAnxD,IAA4BmxD,IAAAyJ,EAAMzJ,EAAAD,EAAAtrD,EAAMqI,EAAAi4D,GAAA/U,MAAAD,GAAcgK,KAAIt1D,EAAAurD,IAAA8G,EAAAhqD,IAAAkjD,EAAA4H,EAAAnzD,EAAA,GAAAurD,EAAA4P,EAAA,EAAAoB,GAAAhR,KAAA0N,GAAA5wD,EAAA,gBAAAkjD,IAAA2K,GAAA3K,IAAAkN,GAAAQ,GAAA5wD,EAAA,oBAAAkjD,IAAAkN,GAAAlN,EAAAvrD,EAAA,GAAAosD,GAAAb,IAAAljD,EAAA,iBAAAkjD,EAAAvrD,EAAAouD,EAAA7C,EAAAnxD,EAAA2+D,GAAAxN,EAAAvrD,EAAAqI,GAC3V,QAAAkjD,EAAA4P,EAAA,IAAiBjL,EAAAr6D,UAAAw3B,MAAA,WAA6BiyC,GAAAt3D,KAAAujD,IAAY2E,EAAAr6D,UAAAy1D,EAAA,SAAAC,GAA0B,GAAAvjD,KAAA0kC,EAAA,CAAW,GAAArkC,KAASA,GAAAq8D,SAAAhS,GAAAnH,GAAiBsU,GAAA73D,KAAAujD,EAAAljD,OAAaw3D,IAAA73D,KAAAujD,MAAmB2E,EAAAr6D,UAAA+2D,EAAA,WAAyB5kD,KAAAujD,EAAAvrD,EAAA,WAAcgI,MAAAomD,EAAckR,GAAAt3D,KAAAujD,SAAWvjD,MAAAujD,EAAc2E,EAAA9D,EAAAQ,EAAAz2D,KAAA6R,OAA2DmkD,EAAAkV,GAAAjF,IAAmDjQ,EAAAmV,GAAAjF,IAAiClQ,EAAAiV,GAAAT,IAASS,GAAAvrE,UAAA83D,GAAA,WAA2B+I,GAAA1uD,KAAAujD,EAAAlgC,EAAA,wBAAArjB,KAAAujD,EAAAljD,GAA8CL,KAAAujD,EAAAiM,cAAA,MACxc4J,GAAAvrE,UAAA43D,GAAA,SAAAlC,EAAAljD,GAA8BL,KAAAujD,EAAAiM,cAAA,GAAA6J,IAAAh5D,KAAiC+4D,GAAAvrE,UAAA23D,GAAA,SAAAjC,EAAAljD,GAA8BquD,GAAA1uD,KAAAujD,EAAAlgC,EAAA,yBAAArjB,KAAAujD,EAAAljD,EAAA,0BAAAA,GAA2EL,KAAAujD,EAAAiM,cAAA,GAAA8J,MAA8BF,GAAAvrE,UAAA62D,GAAA,WAA2BgK,GAAA1uD,KAAAujD,EAAAlgC,EAAA,wBAAArjB,KAAAujD,EAAAljD,GAA8CL,KAAAujD,EAAAiM,cAAA,KAA2B,IAAAmN,IAAAzY,GAAA,SAAAX,EAAAljD,GAAwB,QAAArI,MAAcA,EAAAnK,UAAA01D,EAAA11D,SAAwB,IAAAuS,GAAA,GAAApI,EAA+D,OAAnDurD,GAAAn3D,MAAAgU,EAAAvQ,MAAAhC,UAAAuW,MAAAjW,KAAA3C,UAAA,IAAmD4U,GAASy4D,GAAqHU,IAAA1rE,UAAAs2D,EAAA,WAA0B,MAAAnkD,MAAAK,EAAA5U,OAAAuU,KAAAujD,EAAA93D,QAAoC8tE,GAAA1rE,UAAAG,SAAA,SAAAu1D,GAAkC,UAAAiF,GAAAxoD,KAAAK,EAAAkjD,IAAA,GAAAiF,GAAAxoD,KAAAujD,MAAyCgW,GAAA1rE,UAAAw4D,EAAA,WAA0B,OAAA9C,MAAAljD,EAAAL,KAAAK,EAAA5U,OAAA,EAA+B,GAAA4U,IAAKA,EAAAkjD,EAAAzqD,KAAAkH,KAAAK,KAAsB,IAAArI,GAAAgI,KAAAujD,EAAA93D,MAAoB,KAAA4U,EAAA,EAAQA,EAAArI,IAAIqI,EAAAkjD,EAAAzqD,KAAAkH,KAAAujD,EAAAljD,GAAsB,OAAAkjD,IAAoJY,EAAAsV,GAAA7U,EAAQ,IAAA8U,IAAA,qDAA6DvO,GAAAsO,GAAA5rE,UAAes9D,EAAAxH,GAAA,WAAgB,GAAAJ,GAAA4J,GAAU,YAAAntD,KAAAmrD,GAAA,EAAA5H,EAAAvjD,KAAAmrD,GAAA,CAAgC,OAAA9qD,GAAU,EAAAL,KAAAujD,EAAAY,MAAA9jD,EAAAm5D,GAAAx5D,KAAAujD,IAAAvjD,KAAAglD,GAAA3kD,KAAyCL,KAAAwjD,IAAiF,QAAtEnjD,GAAAL,KAAAmkD,IAAAnkD,KAAAhI,IAAAqI,EAAAL,KAAA6kD,MAAmCxkD,IAAAL,KAAAmrD,EAAA5H,EAAAvjD,KAAAK,EAAAkjD,EAAAt2C,IAAAsjD,EAAAlwD,OAAmCA,IAAW8qD,EAAA/C,GAAA,SAAA7E,GAAiB,QAAA4O,GAAAnyD,KAAAK,EAAAkjD,EAAAgN,EAAAhN,MAAAvjD,KAAAykD,GAAAlB,IAAA,IAC1vC4H,EAAA1G,GAAA,SAAAlB,GAAiB4O,GAAAnyD,KAAAK,EAAAkjD,EAAAgN,EAAAhN,IAAkBvjD,KAAAglD,GAAAzB,IAAAvjD,KAAAmkD,IAAAnkD,KAAAhI,EAAAgI,KAAAujD,IAAAzqD,KAAAyqD,GAAAoW,GAAApW,IAAoD4H,EAAA3H,GAAA,WAAgB,OAAAD,GAAAvjD,KAAAujD,EAAiBvjD,KAAAmkD,IAAAnkD,KAAAomD,GAAgB,CAAE,GAAA/lD,GAAAL,KAAA6kD,IAAgBtB,KAAAzqD,KAAAuH,GAAY,KAAKL,KAAAmkD,IAAAnkD,KAAAhI,GAAA,EAAAgI,KAAAujD,EAAAY,KAA8BwV,GAAAH,GAAAjW,KAAY4H,EAAAtG,GAAA,WAAgB,UAAuFsG,EAAAnG,GAAA,SAAAzB,GAAiB,wBAAAA,GAAA8W,IAAA9W,EAAA8W,MAAyClP,EAAAn9D,SAAA,SAAAu1D,GAAuB,MAAAvjD,MAAAujD,EAAAv1D,SAAAu1D,IAAAvjD,KAAAK,EAAArS,SAAAu1D,IAA+C4H,EAAAhH,EAAA,WAAe,MAAAnkD,MAAAujD,EAAAY,IAAAnkD,KAAAK,EAAA8jD,KAC3cgH,EAAAvG,EAAA,WAAiC,GAAlB6U,GAAArV,EAAAQ,EAAAz2D,KAAA6R,MAAkB,EAAAA,KAAAK,EAAA8jD,IAAA,KAAAn3D,OAAA,kDAAwEgT,MAAAK,CAAc,QAAAkjD,GAAAvjD,KAAAujD,EAAiB,GAAAA,EAAAljD,EAAA5U,QAAA,GAAA83D,IAAA93D,QAA6BkuE,GAAAH,GAAAjW,UAAWvjD,MAAAujD,GAA8ZsW,GAAAhsE,UAAAw4D,EAAA,WAA0B,OAAA9C,GAAAvjD,KAAAujD,EAAAljD,KAAArI,EAAAurD,EAAA93D,OAAA2U,EAAA,EAAqCA,EAAApI,EAAIoI,IAAAC,EAAAvH,KAAAyqD,EAAAnjD,GAAAC,EAAmB,OAAAA,IACpqBw5D,GAAAhsE,UAAAokE,EAAA,WAA0B,OAAA1O,GAAAvjD,KAAAujD,EAAAljD,KAAArI,EAAAurD,EAAA93D,OAAA2U,EAAA,EAAqCA,EAAApI,EAAIoI,IAAAC,EAAAvH,KAAAyqD,EAAAnjD,GAAAmjD,EAAmB,OAAAljD,IAAUw5D,GAAAhsE,UAAAs2D,EAAA,WAA0B,MAAAnkD,MAAAujD,EAAA93D,QAAkD04D,EAAA4V,GAAAF,IAAyD1V,EAAA0N,EAAA4H,IAAQtO,EAAA0G,EAAAhkE,UAAcs9D,EAAAxH,GAAA,SAAAJ,EAAAljD,GAAmB,IAAAkjD,EAAA,MAAAsO,GAAAzN,EAAAT,GAAAx1D,KAAA6R,KAA+B85D,IAAA95D,KAAAqjB,MAAA,KAAAhjB,IAAA,IAAAkjD,GAA8BvjD,KAAAs8B,MAAW6uB,EAAA7uB,GAAA,WAAgB,OAAAinB,GAAAvjD,KAAAqjB,EAAiB,EAAAkgC,EAAAY,KAAQ,CAAE,GAAA9jD,GAAAL,KAAA2jD,IAAgB,KAAAtjD,EAA2P,KAArP,IAAArI,GAAAurD,EAAAnjD,EAAApI,EAAAurD,EAAA32D,EAAAwT,EAAA3U,OAAyB43B,EAAAjjB,EAAA,EAAW,OAAAxT,EAAAy2B,MAAA,OAAiB,CAAK,MAAAz2B,EAAAq4D,GAAA7kD,OAAc,CAAKA,EAAA,GAAAA,EAAAkJ,MAAalJ,EAAA,EAAIpI,IAAAurD,EAAM32D,EAAAoL,EAAAvM,MAAW,QAAA26D,GAAApuD,EAAAoI,GAAeA,EAAAxT,GAAA,GAAO,CAAE,GAAA83C,GAAA,EAAAtkC,EAAA,EAAAqI,EAAA,EAAArI,EAAA,CAA6C,IAAzBskC,EAAAj8B,EAAA7b,GAAAoL,EAAAyQ,GAAA86C,EAAAvrD,EAAA0sC,GAAA6e,EAAA96C,EAAAi8B,EAAyB1sC,EAAA0sC,GAAA6e,EAAA6C,EAAA7C,EAAA,KAAoBvrD,GAAAoI,GAAApI,EAAA0sC,GAAUtkC,EAAAskC,EAAI1sC,EAAAoI,GAAAgmD,EAAO/iC,IAAAhjB,EAAMgjB,EAAAj3B,MAAA4T,MAAAK,MAC1nB8qD,EAAA1G,GAAA,SAAAlB,GAAiBsO,EAAAzN,EAAAK,GAAAt2D,KAAA6R,KAAAujD,GAAoBvjD,KAAAs8B,MAAW6uB,EAAA3H,GAAA,WAAgBqO,EAAAzN,EAAAZ,GAAAr1D,KAAA6R,MAAkBA,KAAAs8B,MAAW6uB,EAAAvG,EAAA,WAAeiN,EAAAzN,EAAAQ,EAAAz2D,KAAA6R,MAAiBwI,EAAA+kD,iBAAA,IAAuBtI,GAAAjlD,KAAAqjB,EAAAkgC,GAAavjD,KAAAqjB,EAAA,MAAsE8gC,EAAAkJ,EAAAwE,GAAOxE,EAAAx/D,UAAAg3D,GAAA,WAA0B,GAAAtB,GAAA,GAAAuS,GAAAz1D,EAAAL,KAAAsjD,CAAsF,OAAjEjjD,MAAAxR,QAAA,SAAAwR,EAAAD,GAA2BmjD,EAAAp9B,QAAAlZ,IAAA7M,EAAAC,KAAqBL,KAAAywD,IAAAlN,EAAA7e,GAAA,GAAiB6e,GAAU8J,EAAAx/D,UAAAm3D,GAAA,SAAAzB,GAA2B,OAAAA,EAAAnxD,IAAAmxD,KAAkBsV,GAAAhrE,UAAA46B,iBAAAowC,GAAAhrE,UAAA01D,EAA6C2E,EAAAr6D,UAAAy3B,KAAA4iC,EAAAr6D,UAAAy1D,EAA+B4E,EAAAr6D,UAAAg7B,KAAAq/B,EAAAr6D,UAAA4iE,EAA+BvI,EAAAr6D,UAAAw3B,MAAA6iC,EAAAr6D,UAAAw3B,MAAoCo2C,GAAA10C,SAAA,EAAc00C,GAAAv0C,QAAA,EAAau0C,GAAAt0C,WAAA,EAAgBu0C,GAAA70C,SAAA,WAAuBstC,GAAAjrC,UAAA8yC,GAAgBA,GAAA7yC,KAAA,IAAY6yC,GAAA5yC,MAAA,IAAa4yC,GAAAxvE,MAAA,IAAawvE,GAAA3yC,QAAA,IAAe8gC,EAAAt8D,UAAAk7B,OAAAohC,EAAAt8D,UAAAi7D,EAAiCuE,EAAAx/D,UAAA64B,UAAA2mC,EAAAx/D,UAAA81D,GAAqC0J,EAAAx/D,UAAA45B,cAAA4lC,EAAAx/D,UAAAu6D,GAAyC0N,EAAAjoE,UAAA+4B,WAAAkvC,EAAAjoE,UAAAg4D,GAAsCiQ,EAAAjoE,UAAA25B,aAAAsuC,EAAAjoE,UAAAs7D,GAAwC2M,EAAAjoE,UAAAi5B,iBAAAgvC,EAAAjoE,UAAA63D,GACx2BoQ,EAAAjoE,UAAAw5B,UAAAyuC,EAAAjoE,UAAA2oE,EAAoCV,EAAAjoE,UAAA05B,cAAAuuC,EAAAjoE,UAAA+3D,GAAyCkQ,EAAAjoE,UAAAo5B,gBAAA6uC,EAAAjoE,UAAA0sE,GAA2CzE,EAAAjoE,UAAAy5B,gBAAAwuC,EAAAjoE,UAAAioE,EAA0CA,EAAAjoE,UAAAy5B,gBAAAwuC,EAAAjoE,UAAAioE,EAA0CA,EAAAjoE,UAAAy3B,KAAAwwC,EAAAjoE,UAAAqjE,GAAgCtmE,OAAAy4D,SAAgBuZ,0BAAAD,GAAAE,UAAApB,GAAAvyC,UAAAwyC,GAAAoB,WAAA3I,GAAA4I,UAAA1P,KAAmFl/D,KAAA,mBAAA+tC,eAAAl8B,SlF0ve5U,KACS,MAAMvT,GACN,KAAUO,OACR","file":"firebase-firestore.js","sourcesContent":["try {\n webpackJsonpFirebase([1],{\n\n/***/ 66:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n\n// EXTERNAL MODULE: ./src/app.ts + 1 modules\nvar src_app = __webpack_require__(9);\n\n// CONCATENATED MODULE: ./src/firestore/core/version.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n/** The semver (www.semver.org) version of the SDK. */\nvar SDK_VERSION = src_app[\"default\"].SDK_VERSION;\n// CONCATENATED MODULE: ./src/firestore/util/log.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n/* tslint:disable:no-console */\n\nvar LogLevel;\n(function (LogLevel) {\n LogLevel[LogLevel[\"DEBUG\"] = 0] = \"DEBUG\";\n LogLevel[LogLevel[\"ERROR\"] = 1] = \"ERROR\";\n LogLevel[LogLevel[\"SILENT\"] = 2] = \"SILENT\";\n})(LogLevel || (LogLevel = {}));\nvar logLevel = LogLevel.ERROR;\n// Helper methods are needed because variables can't be exported as read/write\nfunction getLogLevel() {\n return logLevel;\n}\nfunction setLogLevel(newLevel) {\n logLevel = newLevel;\n}\nfunction debug(tag, msg) {\n var obj = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n obj[_i - 2] = arguments[_i];\n }\n if (logLevel <= LogLevel.DEBUG) {\n var time = new Date().toISOString();\n var args = obj.map(argToString);\n console.log.apply(console, [\"Firestore (\" + SDK_VERSION + \") \" + time + \" [\" + tag + \"]: \" + msg].concat(args));\n }\n}\nfunction log_error(msg) {\n var obj = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n obj[_i - 1] = arguments[_i];\n }\n if (logLevel <= LogLevel.ERROR) {\n var time = new Date().toISOString();\n var args = obj.map(argToString);\n console.error.apply(console, [\"Firestore (\" + SDK_VERSION + \") \" + time + \": \" + msg].concat(args));\n }\n}\n/**\r\n * Converts an additional log parameter to a string representation.\r\n */\nfunction argToString(obj) {\n if (typeof obj === 'string') {\n return obj;\n } else {\n try {\n return JSON.stringify(obj);\n } catch (e) {\n // Converting to JSON failed, just log the object directly\n return obj;\n }\n }\n}\n// CONCATENATED MODULE: ./src/firestore/util/assert.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * Unconditionally fails, throwing an Error with the given message.\r\n *\r\n * Returns any so it can be used in expressions:\r\n * @example\r\n * let futureVar = fail('not implemented yet');\r\n */\nfunction fail(failure) {\n // Log the failure in addition to throw an exception, just in case the\n // exception is swallowed.\n var message = \"FIRESTORE (\" + SDK_VERSION + \") INTERNAL ASSERTION FAILED: \" + failure;\n log_error(message);\n // NOTE: We don't use FirestoreError here because these are internal failures\n // that cannot be handled by the user. (Also it would create a circular\n // dependency between the error and assert modules which doesn't work.)\n throw new Error(message);\n}\n/**\r\n * Fails if the given assertion condition is false, throwing an Error with the\r\n * given message if it did.\r\n */\nfunction assert(assertion, message) {\n if (!assertion) {\n fail(message);\n }\n}\n// CONCATENATED MODULE: ./src/firestore/platform/platform.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n/**\r\n * Provides singleton helpers where setup code can inject a platform at runtime.\r\n * setPlatform needs to be set before Firestore is used and must be set exactly\r\n * once.\r\n */\nvar platform_PlatformSupport = /** @class */function () {\n function PlatformSupport() {}\n PlatformSupport.setPlatform = function (platform) {\n if (PlatformSupport.platform) {\n fail('Platform already defined');\n }\n PlatformSupport.platform = platform;\n };\n PlatformSupport.getPlatform = function () {\n if (!PlatformSupport.platform) {\n fail('Platform not set');\n }\n return PlatformSupport.platform;\n };\n return PlatformSupport;\n}();\n\n/**\r\n * Returns the representation of an empty \"proto\" byte string for the\r\n * platform.\r\n */\nfunction emptyByteString() {\n return platform_PlatformSupport.getPlatform().emptyByteString;\n}\n// CONCATENATED MODULE: ./src/firestore/util/error.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar __extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n// TODO(mcg): Change to a string enum once we've upgraded to typescript 2.4.\n// tslint:disable-next-line:variable-name Intended to look like a TS 2.4 enum\nvar Code = {\n // Causes are copied from:\n // https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h\n /** Not an error; returned on success. */\n OK: 'ok',\n /** The operation was cancelled (typically by the caller). */\n CANCELLED: 'cancelled',\n /** Unknown error or an error from a different error domain. */\n UNKNOWN: 'unknown',\n /**\r\n * Client specified an invalid argument. Note that this differs from\r\n * FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are\r\n * problematic regardless of the state of the system (e.g., a malformed file\r\n * name).\r\n */\n INVALID_ARGUMENT: 'invalid-argument',\n /**\r\n * Deadline expired before operation could complete. For operations that\r\n * change the state of the system, this error may be returned even if the\r\n * operation has completed successfully. For example, a successful response\r\n * from a server could have been delayed long enough for the deadline to\r\n * expire.\r\n */\n DEADLINE_EXCEEDED: 'deadline-exceeded',\n /** Some requested entity (e.g., file or directory) was not found. */\n NOT_FOUND: 'not-found',\n /**\r\n * Some entity that we attempted to create (e.g., file or directory) already\r\n * exists.\r\n */\n ALREADY_EXISTS: 'already-exists',\n /**\r\n * The caller does not have permission to execute the specified operation.\r\n * PERMISSION_DENIED must not be used for rejections caused by exhausting\r\n * some resource (use RESOURCE_EXHAUSTED instead for those errors).\r\n * PERMISSION_DENIED must not be used if the caller can not be identified\r\n * (use UNAUTHENTICATED instead for those errors).\r\n */\n PERMISSION_DENIED: 'permission-denied',\n /**\r\n * The request does not have valid authentication credentials for the\r\n * operation.\r\n */\n UNAUTHENTICATED: 'unauthenticated',\n /**\r\n * Some resource has been exhausted, perhaps a per-user quota, or perhaps the\r\n * entire file system is out of space.\r\n */\n RESOURCE_EXHAUSTED: 'resource-exhausted',\n /**\r\n * Operation was rejected because the system is not in a state required for\r\n * the operation's execution. For example, directory to be deleted may be\r\n * non-empty, an rmdir operation is applied to a non-directory, etc.\r\n *\r\n * A litmus test that may help a service implementor in deciding\r\n * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:\r\n * (a) Use UNAVAILABLE if the client can retry just the failing call.\r\n * (b) Use ABORTED if the client should retry at a higher-level\r\n * (e.g., restarting a read-modify-write sequence).\r\n * (c) Use FAILED_PRECONDITION if the client should not retry until\r\n * the system state has been explicitly fixed. E.g., if an \"rmdir\"\r\n * fails because the directory is non-empty, FAILED_PRECONDITION\r\n * should be returned since the client should not retry unless\r\n * they have first fixed up the directory by deleting files from it.\r\n * (d) Use FAILED_PRECONDITION if the client performs conditional\r\n * REST Get/Update/Delete on a resource and the resource on the\r\n * server does not match the condition. E.g., conflicting\r\n * read-modify-write on the same resource.\r\n */\n FAILED_PRECONDITION: 'failed-precondition',\n /**\r\n * The operation was aborted, typically due to a concurrency issue like\r\n * sequencer check failures, transaction aborts, etc.\r\n *\r\n * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,\r\n * and UNAVAILABLE.\r\n */\n ABORTED: 'aborted',\n /**\r\n * Operation was attempted past the valid range. E.g., seeking or reading\r\n * past end of file.\r\n *\r\n * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed\r\n * if the system state changes. For example, a 32-bit file system will\r\n * generate INVALID_ARGUMENT if asked to read at an offset that is not in the\r\n * range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from\r\n * an offset past the current file size.\r\n *\r\n * There is a fair bit of overlap between FAILED_PRECONDITION and\r\n * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)\r\n * when it applies so that callers who are iterating through a space can\r\n * easily look for an OUT_OF_RANGE error to detect when they are done.\r\n */\n OUT_OF_RANGE: 'out-of-range',\n /** Operation is not implemented or not supported/enabled in this service. */\n UNIMPLEMENTED: 'unimplemented',\n /**\r\n * Internal errors. Means some invariants expected by underlying System has\r\n * been broken. If you see one of these errors, Something is very broken.\r\n */\n INTERNAL: 'internal',\n /**\r\n * The service is currently unavailable. This is a most likely a transient\r\n * condition and may be corrected by retrying with a backoff.\r\n *\r\n * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,\r\n * and UNAVAILABLE.\r\n */\n UNAVAILABLE: 'unavailable',\n /** Unrecoverable data loss or corruption. */\n DATA_LOSS: 'data-loss'\n};\n/**\r\n * An error class used for Firestore-generated errors. Ideally we should be\r\n * using FirebaseError, but integrating with it is overly arduous at the moment,\r\n * so we define our own compatible error class (with a `name` of 'FirebaseError'\r\n * and compatible `code` and `message` fields.)\r\n */\nvar FirestoreError = /** @class */function (_super) {\n __extends(FirestoreError, _super);\n function FirestoreError(code, message) {\n var _this = _super.call(this, message) || this;\n _this.code = code;\n _this.message = message;\n _this.name = 'FirebaseError';\n // HACK: We write a toString property directly because Error is not a real\n // class and so inheritance does not work correctly. We could alternatively\n // do the same \"back-door inheritance\" trick that FirebaseError does.\n _this.toString = function () {\n return _this.name + \": [code=\" + _this.code + \"]: \" + _this.message;\n };\n return _this;\n }\n return FirestoreError;\n}(Error);\n\n// CONCATENATED MODULE: ./src/firestore/util/api.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n// We are doing some heavy reflective stuff, lots of any casting necessary\n/* tslint:disable:no-any */\n\n/**\r\n * Helper function to prevent instantiation through the constructor.\r\n *\r\n * This method creates a new constructor that throws when it's invoked.\r\n * The prototype of that constructor is then set to the prototype of the hidden\r\n * \"class\" to expose all the prototype methods and allow for instanceof\r\n * checks.\r\n *\r\n * To also make all the static methods available, all properties of the\r\n * original constructor are copied to the new constructor.\r\n */\nfunction makeConstructorPrivate(cls, optionalMessage) {\n function PublicConstructor() {\n var error = 'This constructor is private.';\n if (optionalMessage) {\n error += ' ';\n error += optionalMessage;\n }\n throw new FirestoreError(Code.INVALID_ARGUMENT, error);\n }\n // Make sure instanceof checks work and all methods are exposed on the public\n // constructor\n PublicConstructor.prototype = cls.prototype;\n // Copy any static methods/members\n for (var staticProperty in cls) {\n if (cls.hasOwnProperty(staticProperty)) {\n PublicConstructor[staticProperty] = cls[staticProperty];\n }\n }\n return PublicConstructor;\n}\n// CONCATENATED MODULE: ./src/firestore/util/obj.ts\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\nfunction contains(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\nfunction obj_get(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : null;\n}\nfunction obj_size(obj) {\n var count = 0;\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n count++;\n }\n }\n return count;\n}\n/** Returns the given value if it's defined or the defaultValue otherwise. */\nfunction defaulted(value, defaultValue) {\n return value !== undefined ? value : defaultValue;\n}\nfunction forEachNumber(obj, fn) {\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n var num = parseInt(key, 10);\n if (!isNaN(num)) {\n fn(num, obj[key]);\n }\n }\n }\n}\nfunction forEach(obj, fn) {\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn(key, obj[key]);\n }\n }\n}\nfunction lookupOrInsert(obj, key, valFn) {\n if (!contains(obj, key)) {\n obj[key] = valFn();\n }\n return obj[key];\n}\nfunction isEmpty(obj) {\n assert(obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object', 'isEmpty() expects object parameter.');\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return false;\n }\n }\n return true;\n}\nfunction shallowCopy(obj) {\n assert(obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object', 'shallowCopy() expects object parameter.');\n var result = {};\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n// CONCATENATED MODULE: ./src/firestore/util/input_validation.ts\nvar input_validation__typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n/**\r\n * Validates the invocation of functionName has the exact number of arguments.\r\n *\r\n * Forward the magic \"arguments\" variable as second parameter on which the\r\n * parameter validation is performed:\r\n * validateExactNumberOfArgs('myFunction', arguments, 2);\r\n */\nfunction validateExactNumberOfArgs(functionName, args, numberOfArgs) {\n if (args.length !== numberOfArgs) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires \" + formatPlural(numberOfArgs, 'argument') + ', but was called with ' + formatPlural(args.length, 'argument') + '.');\n }\n}\n/**\r\n * Validates the invocation of functionName has at least the provided number of\r\n * arguments (but can have many more).\r\n *\r\n * Forward the magic \"arguments\" variable as second parameter on which the\r\n * parameter validation is performed:\r\n * validateAtLeastNumberOfArgs('myFunction', arguments, 2);\r\n */\nfunction validateAtLeastNumberOfArgs(functionName, args, minNumberOfArgs) {\n if (args.length < minNumberOfArgs) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires at least \" + formatPlural(minNumberOfArgs, 'argument') + ', but was called with ' + formatPlural(args.length, 'argument') + '.');\n }\n}\n/**\r\n * Validates the invocation of functionName has number of arguments between\r\n * the values provided.\r\n *\r\n * Forward the magic \"arguments\" variable as second parameter on which the\r\n * parameter validation is performed:\r\n * validateBetweenNumberOfArgs('myFunction', arguments, 2, 3);\r\n */\nfunction validateBetweenNumberOfArgs(functionName, args, minNumberOfArgs, maxNumberOfArgs) {\n if (args.length < minNumberOfArgs || args.length > maxNumberOfArgs) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires between \" + minNumberOfArgs + \" and \" + (maxNumberOfArgs + \" arguments, but was called with \") + formatPlural(args.length, 'argument') + '.');\n }\n}\n/**\r\n * Validates the provided argument is an array and has as least the expected\r\n * number of elements.\r\n */\nfunction validateNamedArrayAtLeastNumberOfElements(functionName, value, name, minNumberOfElements) {\n if (!(value instanceof Array) || value.length < minNumberOfElements) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires its \" + name + \" argument to be an \" + 'array with at least ' + (formatPlural(minNumberOfElements, 'element') + \".\"));\n }\n}\n/**\r\n * Validates the provided positional argument has the native JavaScript type\r\n * using typeof checks.\r\n */\nfunction validateArgType(functionName, type, position, argument) {\n validateType(functionName, type, ordinal(position) + \" argument\", argument);\n}\n/**\r\n * Validates the provided argument has the native JavaScript type using\r\n * typeof checks or is undefined.\r\n */\nfunction validateOptionalArgType(functionName, type, position, argument) {\n if (argument !== undefined) {\n validateArgType(functionName, type, position, argument);\n }\n}\n/**\r\n * Validates the provided named option has the native JavaScript type using\r\n * typeof checks.\r\n */\nfunction validateNamedType(functionName, type, optionName, argument) {\n validateType(functionName, type, optionName + \" option\", argument);\n}\n/**\r\n * Validates the provided named option has the native JavaScript type using\r\n * typeof checks or is undefined.\r\n */\nfunction validateNamedOptionalType(functionName, type, optionName, argument) {\n if (argument !== undefined) {\n validateNamedType(functionName, type, optionName, argument);\n }\n}\n/** Helper to validate the type of a provided input. */\nfunction validateType(functionName, type, inputName, input) {\n if ((typeof input === 'undefined' ? 'undefined' : input_validation__typeof(input)) !== type || type === 'object' && !isPlainObject(input)) {\n var description = valueDescription(input);\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires its \" + inputName + \" \" + (\"to be of type \" + type + \", but it was: \" + description));\n }\n}\n/**\r\n * Returns true iff it's a non-null object without a custom prototype\r\n * (i.e. excludes Array, Date, etc.).\r\n */\nfunction isPlainObject(input) {\n return (typeof input === 'undefined' ? 'undefined' : input_validation__typeof(input)) === 'object' && input !== null && Object.getPrototypeOf(input) === Object.prototype;\n}\n/** Returns a string describing the type / value of the provided input. */\nfunction valueDescription(input) {\n if (input === undefined) {\n return 'undefined';\n } else if (input === null) {\n return 'null';\n } else if (typeof input === 'string') {\n if (input.length > 20) {\n input = input.substring(0, 20) + \"...\";\n }\n return JSON.stringify(input);\n } else if (typeof input === 'number' || typeof input === 'boolean') {\n return '' + input;\n } else if ((typeof input === 'undefined' ? 'undefined' : input_validation__typeof(input)) === 'object') {\n if (input instanceof Array) {\n return 'an array';\n } else {\n var customObjectName = tryGetCustomObjectType(input);\n if (customObjectName) {\n return \"a custom \" + customObjectName + \" object\";\n } else {\n return 'an object';\n }\n }\n } else if (typeof input === 'function') {\n return 'a function';\n } else {\n return fail('Unknown wrong type: ' + (typeof input === 'undefined' ? 'undefined' : input_validation__typeof(input)));\n }\n}\n/** Hacky method to try to get the constructor name for an object. */\nfunction tryGetCustomObjectType(input) {\n if (input.constructor) {\n var funcNameRegex = /function\\s+([^\\s(]+)\\s*\\(/;\n var results = funcNameRegex.exec(input.constructor.toString());\n if (results && results.length > 1) {\n return results[1];\n }\n }\n return null;\n}\n/** Validates the provided argument is defined. */\nfunction validateDefined(functionName, position, argument) {\n if (argument === undefined) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires a valid \" + ordinal(position) + \" \" + \"argument, but it was undefined.\");\n }\n}\n/**\r\n * Validates the provided positional argument is an object, and its keys and\r\n * values match the expected keys and types provided in optionTypes.\r\n */\nfunction validateOptionNames(functionName, options, optionNames) {\n forEach(options, function (key, _) {\n if (optionNames.indexOf(key) < 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Unknown option '\" + key + \"' passed to function \" + functionName + \"(). \" + 'Available options: ' + optionNames.join(', '));\n }\n });\n}\n/**\r\n * Helper method to throw an error that the provided argument did not pass\r\n * an instanceof check.\r\n */\nfunction invalidClassError(functionName, type, position, argument) {\n var description = valueDescription(argument);\n return new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + functionName + \"() requires its \" + ordinal(position) + \" \" + (\"argument to be a \" + type + \", but it was: \" + description));\n}\n/** Converts a number to its english word representation */\nfunction ordinal(num) {\n switch (num) {\n case 1:\n return 'first';\n case 2:\n return 'second';\n case 3:\n return 'third';\n default:\n return num + 'th';\n }\n}\n/**\r\n * Formats the given word as plural conditionally given the preceding number.\r\n */\nfunction formatPlural(num, str) {\n return num + \" \" + str + (num === 1 ? '' : 's');\n}\n// CONCATENATED MODULE: ./src/firestore/util/misc.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n// tslint:disable-next-line:class-as-namespace\nvar misc_AutoId = /** @class */function () {\n function AutoId() {}\n AutoId.newId = function () {\n // Alphanumeric characters\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n var autoId = '';\n for (var i = 0; i < 20; i++) {\n autoId += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n assert(autoId.length === 20, 'Invalid auto ID: ' + autoId);\n return autoId;\n };\n return AutoId;\n}();\n\nfunction primitiveComparator(left, right) {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n/** Helper to compare nullable (or undefined-able) objects using equals(). */\nfunction equals(left, right) {\n if (left !== null && left !== undefined) {\n return !!(right && left.equals(right));\n } else {\n // HACK: Explicitly cast since TypeScript's type narrowing apparently isn't\n // smart enough.\n return left === right;\n }\n}\n/** Helper to compare arrays using equals(). */\nfunction arrayEquals(left, right) {\n if (left.length !== right.length) {\n return false;\n }\n for (var i = 0; i < left.length; i++) {\n if (!left[i].equals(right[i])) {\n return false;\n }\n }\n return true;\n}\n/**\r\n * Returns the largest lexicographically smaller string of equal or smaller\r\n * length. Returns an empty string if there is no such predecessor (if the input\r\n * is empty).\r\n *\r\n * Strings returned from this method can be invalid UTF-16 but this is sufficent\r\n * in use for indexeddb because that depends on lexicographical ordering but\r\n * shouldn't be used elsewhere.\r\n */\nfunction immediatePredecessor(s) {\n // We can decrement the last character in the string and be done\n // unless that character is 0 (0x0000), in which case we have to erase the\n // last character.\n var lastIndex = s.length - 1;\n if (s.length === 0) {\n // Special case the empty string.\n return '';\n } else if (s.charAt(lastIndex) === '\\0') {\n return s.substring(0, lastIndex);\n } else {\n return s.substring(0, lastIndex) + String.fromCharCode(s.charCodeAt(lastIndex) - 1);\n }\n}\n/**\r\n * Returns the immediate lexicographically-following string. This is useful to\r\n * construct an inclusive range for indexeddb iterators.\r\n */\nfunction immediateSuccessor(s) {\n // Return the input string, with an additional NUL byte appended.\n return s + '\\0';\n}\n// CONCATENATED MODULE: ./src/firestore/api/blob.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n/** Helper function to assert Uint8Array is available at runtime. */\nfunction assertUint8ArrayAvailable() {\n if (typeof Uint8Array === 'undefined') {\n throw new FirestoreError(Code.UNIMPLEMENTED, 'Uint8Arrays are not available in this environment.');\n }\n}\n/** Helper function to assert Base64 functions are available at runtime. */\nfunction assertBase64Available() {\n if (!platform_PlatformSupport.getPlatform().base64Available) {\n throw new FirestoreError(Code.UNIMPLEMENTED, 'Blobs are unavailable in Firestore in this environment.');\n }\n}\n/**\r\n * Immutable class holding a blob (binary data).\r\n * This class is directly exposed in the public API.\r\n *\r\n * Note that while you can't hide the constructor in JavaScript code, we are\r\n * using the hack above to make sure no-one outside this module can call it.\r\n */\nvar blob_Blob = /** @class */function () {\n function Blob(binaryString) {\n assertBase64Available();\n this._binaryString = binaryString;\n }\n Blob.fromBase64String = function (base64) {\n validateExactNumberOfArgs('Blob.fromBase64String', arguments, 1);\n validateArgType('Blob.fromBase64String', 'string', 1, base64);\n assertBase64Available();\n try {\n var binaryString = platform_PlatformSupport.getPlatform().atob(base64);\n return new Blob(binaryString);\n } catch (e) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Failed to construct Blob from Base64 string: ' + e);\n }\n };\n Blob.fromUint8Array = function (array) {\n validateExactNumberOfArgs('Blob.fromUint8Array', arguments, 1);\n assertUint8ArrayAvailable();\n if (!(array instanceof Uint8Array)) {\n throw invalidClassError('Blob.fromUint8Array', 'Uint8Array', 1, array);\n }\n // We can't call array.map directly because it expects the return type to\n // be a Uint8Array, whereas we can convert it to a regular array by invoking\n // map on the Array prototype.\n var binaryString = Array.prototype.map.call(array, function (char) {\n return String.fromCharCode(char);\n }).join('');\n return new Blob(binaryString);\n };\n Blob.prototype.toBase64 = function () {\n validateExactNumberOfArgs('Blob.toBase64', arguments, 0);\n assertBase64Available();\n return platform_PlatformSupport.getPlatform().btoa(this._binaryString);\n };\n Blob.prototype.toUint8Array = function () {\n validateExactNumberOfArgs('Blob.toUint8Array', arguments, 0);\n assertUint8ArrayAvailable();\n var buffer = new Uint8Array(this._binaryString.length);\n for (var i = 0; i < this._binaryString.length; i++) {\n buffer[i] = this._binaryString.charCodeAt(i);\n }\n return buffer;\n };\n Blob.prototype.toString = function () {\n return 'Blob(base64: ' + this.toBase64() + ')';\n };\n /**\r\n * Actually private to JS consumers of our API, so this function is prefixed\r\n * with an underscore.\r\n */\n Blob.prototype._equals = function (other) {\n return this._binaryString === other._binaryString;\n };\n /**\r\n * Actually private to JS consumers of our API, so this function is prefixed\r\n * with an underscore.\r\n */\n Blob.prototype._compareTo = function (other) {\n return primitiveComparator(this._binaryString, other._binaryString);\n };\n return Blob;\n}();\n\n// Public instance that disallows construction at runtime. This constructor is\n// used when exporting Blob on firebase.firestore.Blob and will be called Blob\n// publicly. Internally we still use Blob which has a type checked private\n// constructor. Note that Blob and PublicBlob can be used interchangeably in\n// instanceof checks.\n// For our internal TypeScript code PublicBlob doesn't exist as a type, and so\n// we need to use Blob as type and export it too.\n// tslint:disable-next-line:variable-name We're treating this as a class name.\nvar PublicBlob = makeConstructorPrivate(blob_Blob, 'Use Blob.fromUint8Array() or Blob.fromBase64String() instead.');\n// CONCATENATED MODULE: ./src/firestore/api/geo_point.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n/**\r\n * Immutable class representing a geo point as latitude-longitude pair.\r\n * This class is directly exposed in the public API, including its constructor.\r\n */\nvar geo_point_GeoPoint = /** @class */function () {\n function GeoPoint(latitude, longitude) {\n validateExactNumberOfArgs('GeoPoint', arguments, 2);\n validateArgType('GeoPoint', 'number', 1, latitude);\n validateArgType('GeoPoint', 'number', 2, longitude);\n if (!isFinite(latitude) || latitude < -90 || latitude > 90) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Latitude must be a number between -90 and 90, but was: ' + latitude);\n }\n if (!isFinite(longitude) || longitude < -180 || longitude > 180) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Longitude must be a number between -180 and 180, but was: ' + longitude);\n }\n this._lat = latitude;\n this._long = longitude;\n }\n Object.defineProperty(GeoPoint.prototype, \"latitude\", {\n /**\r\n * Returns the latitude of this geo point, a number between -90 and 90.\r\n */\n get: function get() {\n return this._lat;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(GeoPoint.prototype, \"longitude\", {\n /**\r\n * Returns the longitude of this geo point, a number between -180 and 180.\r\n */\n get: function get() {\n return this._long;\n },\n enumerable: true,\n configurable: true\n });\n /**\r\n * Actually private to JS consumers of our API, so this function is prefixed\r\n * with an underscore.\r\n */\n GeoPoint.prototype._equals = function (other) {\n return this._lat === other._lat && this._long === other._long;\n };\n /**\r\n * Actually private to JS consumers of our API, so this function is prefixed\r\n * with an underscore.\r\n */\n GeoPoint.prototype._compareTo = function (other) {\n return primitiveComparator(this._lat, other._lat) || primitiveComparator(this._long, other._long);\n };\n return GeoPoint;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/database_info.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\nvar DatabaseInfo = /** @class */function () {\n /**\r\n * Constructs a DatabaseInfo using the provided host, databaseId and\r\n * persistenceKey.\r\n *\r\n * @param databaseId The database to use.\r\n * @param persistenceKey A unique identifier for this Firestore's local\r\n * storage (used in conjunction with the databaseId).\r\n * @param host The Firestore backend host to connect to.\r\n * @param ssl Whether to use SSL when connecting.\r\n */\n function DatabaseInfo(databaseId, persistenceKey, host, ssl) {\n this.databaseId = databaseId;\n this.persistenceKey = persistenceKey;\n this.host = host;\n this.ssl = ssl;\n }\n return DatabaseInfo;\n}();\n\n/** The default database name for a project. */\nvar DEFAULT_DATABASE_NAME = '(default)';\n/** Represents the database ID a Firestore client is associated with. */\nvar database_info_DatabaseId = /** @class */function () {\n function DatabaseId(projectId, database) {\n this.projectId = projectId;\n this.database = database ? database : DEFAULT_DATABASE_NAME;\n }\n Object.defineProperty(DatabaseId.prototype, \"isDefaultDatabase\", {\n get: function get() {\n return this.database === DEFAULT_DATABASE_NAME;\n },\n enumerable: true,\n configurable: true\n });\n DatabaseId.prototype.equals = function (other) {\n return other instanceof DatabaseId && other.projectId === this.projectId && other.database === this.database;\n };\n DatabaseId.prototype.compareTo = function (other) {\n return primitiveComparator(this.projectId, other.projectId) || primitiveComparator(this.database, other.database);\n };\n return DatabaseId;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/model/path.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar path___extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\nvar DOCUMENT_KEY_NAME = '__name__';\n/**\r\n * Path represents an ordered sequence of string segments.\r\n */\nvar path_Path = /** @class */function () {\n function Path(segments, offset, length) {\n this.init(segments, offset, length);\n }\n /**\r\n * An initialization method that can be called from outside the constructor.\r\n * We need this so that we can have a non-static construct method that returns\r\n * the polymorphic `this` type.\r\n */\n Path.prototype.init = function (segments, offset, length) {\n if (offset === undefined) {\n offset = 0;\n } else if (offset > segments.length) {\n fail('offset ' + offset + ' out of range ' + segments.length);\n }\n if (length === undefined) {\n length = segments.length - offset;\n } else if (length > segments.length - offset) {\n fail('length ' + length + ' out of range ' + (segments.length - offset));\n }\n this.segments = segments;\n this.offset = offset;\n this.len = length;\n };\n /**\r\n * Constructs a new instance of Path using the same concrete type as `this`.\r\n * We need this instead of using the normal constructor, because polymorphic\r\n * `this` doesn't work on static methods.\r\n */\n Path.prototype.construct = function (segments, offset, length) {\n var path = Object.create(Object.getPrototypeOf(this));\n path.init(segments, offset, length);\n return path;\n };\n Object.defineProperty(Path.prototype, \"length\", {\n get: function get() {\n return this.len;\n },\n enumerable: true,\n configurable: true\n });\n Path.prototype.equals = function (other) {\n return Path.comparator(this, other) === 0;\n };\n Path.prototype.child = function (nameOrPath) {\n var segments = this.segments.slice(this.offset, this.limit());\n if (nameOrPath instanceof Path) {\n nameOrPath.forEach(function (segment) {\n segments.push(segment);\n });\n } else if (typeof nameOrPath === 'string') {\n segments.push(nameOrPath);\n } else {\n fail('Unknown parameter type for Path.child(): ' + nameOrPath);\n }\n return this.construct(segments);\n };\n /** The index of one past the last segment of the path. */\n Path.prototype.limit = function () {\n return this.offset + this.length;\n };\n Path.prototype.popFirst = function (size) {\n size = size === undefined ? 1 : size;\n assert(this.length >= size, \"Can't call popFirst() with less segments\");\n return this.construct(this.segments, this.offset + size, this.length - size);\n };\n Path.prototype.popLast = function () {\n assert(!this.isEmpty(), \"Can't call popLast() on empty path\");\n return this.construct(this.segments, this.offset, this.length - 1);\n };\n Path.prototype.firstSegment = function () {\n assert(!this.isEmpty(), \"Can't call firstSegment() on empty path\");\n return this.segments[this.offset];\n };\n Path.prototype.lastSegment = function () {\n assert(!this.isEmpty(), \"Can't call lastSegment() on empty path\");\n return this.segments[this.limit() - 1];\n };\n Path.prototype.get = function (index) {\n assert(index < this.length, 'Index out of range');\n return this.segments[this.offset + index];\n };\n Path.prototype.isEmpty = function () {\n return this.length === 0;\n };\n Path.prototype.isPrefixOf = function (other) {\n if (other.length < this.length) {\n return false;\n }\n for (var i = 0; i < this.length; i++) {\n if (this.get(i) !== other.get(i)) {\n return false;\n }\n }\n return true;\n };\n Path.prototype.forEach = function (fn) {\n for (var i = this.offset, end = this.limit(); i < end; i++) {\n fn(this.segments[i]);\n }\n };\n Path.prototype.toArray = function () {\n return this.segments.slice(this.offset, this.limit());\n };\n Path.comparator = function (p1, p2) {\n var len = Math.min(p1.length, p2.length);\n for (var i = 0; i < len; i++) {\n var left = p1.get(i);\n var right = p2.get(i);\n if (left < right) return -1;\n if (left > right) return 1;\n }\n if (p1.length < p2.length) return -1;\n if (p1.length > p2.length) return 1;\n return 0;\n };\n return Path;\n}();\n\n/**\r\n * A slash-separated path for navigating resources (documents and collections)\r\n * within Firestore.\r\n */\nvar path_ResourcePath = /** @class */function (_super) {\n path___extends(ResourcePath, _super);\n function ResourcePath() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ResourcePath.prototype.canonicalString = function () {\n // NOTE: The client is ignorant of any path segments containing escape\n // sequences (e.g. __id123__) and just passes them through raw (they exist\n // for legacy reasons and should not be used frequently).\n return this.toArray().join('/');\n };\n ResourcePath.prototype.toString = function () {\n return this.canonicalString();\n };\n /**\r\n * Creates a resource path from the given slash-delimited string.\r\n */\n ResourcePath.fromString = function (path) {\n // NOTE: The client is ignorant of any path segments containing escape\n // sequences (e.g. __id123__) and just passes them through raw (they exist\n // for legacy reasons and should not be used frequently).\n if (path.indexOf('//') >= 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid path (\" + path + \"). Paths must not contain // in them.\");\n }\n // We may still have an empty segment at the beginning or end if they had a\n // leading or trailing slash (which we allow).\n var segments = path.split('/').filter(function (segment) {\n return segment.length > 0;\n });\n return new ResourcePath(segments);\n };\n ResourcePath.EMPTY_PATH = new ResourcePath([]);\n return ResourcePath;\n}(path_Path);\n\nvar identifierRegExp = /^[_a-zA-Z][_a-zA-Z0-9]*$/;\n/** A dot-separated path for navigating sub-objects within a document. */\nvar path_FieldPath = /** @class */function (_super) {\n path___extends(FieldPath, _super);\n function FieldPath() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n /**\r\n * Returns true if the string could be used as a segment in a field path\r\n * without escaping.\r\n */\n FieldPath.isValidIdentifier = function (segment) {\n return identifierRegExp.test(segment);\n };\n FieldPath.prototype.canonicalString = function () {\n return this.toArray().map(function (str) {\n str = str.replace('\\\\', '\\\\\\\\').replace('`', '\\\\`');\n if (!FieldPath.isValidIdentifier(str)) {\n str = '`' + str + '`';\n }\n return str;\n }).join('.');\n };\n FieldPath.prototype.toString = function () {\n return this.canonicalString();\n };\n /**\r\n * Returns true if this field references the key of a document.\r\n */\n FieldPath.prototype.isKeyField = function () {\n return this.length === 1 && this.get(0) === DOCUMENT_KEY_NAME;\n };\n /**\r\n * The field designating the key of a document.\r\n */\n FieldPath.keyField = function () {\n return new FieldPath([DOCUMENT_KEY_NAME]);\n };\n /**\r\n * Parses a field string from the given server-formatted string.\r\n *\r\n * - Splitting the empty string is not allowed (for now at least).\r\n * - Empty segments within the string (e.g. if there are two consecutive\r\n * separators) are not allowed.\r\n *\r\n * TODO(b/37244157): we should make this more strict. Right now, it allows\r\n * non-identifier path components, even if they aren't escaped.\r\n */\n FieldPath.fromServerFormat = function (path) {\n var segments = [];\n var current = '';\n var i = 0;\n var addCurrentSegment = function addCurrentSegment() {\n if (current.length === 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid field path (\" + path + \"). Paths must not be empty, begin \" + \"with '.', end with '.', or contain '..'\");\n }\n segments.push(current);\n current = '';\n };\n var inBackticks = false;\n while (i < path.length) {\n var c = path[i];\n if (c === '\\\\') {\n if (i + 1 === path.length) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Path has trailing escape character: ' + path);\n }\n var next = path[i + 1];\n if (!(next === '\\\\' || next === '.' || next === '`')) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Path has invalid escape sequence: ' + path);\n }\n current += next;\n i += 2;\n } else if (c === '`') {\n inBackticks = !inBackticks;\n i++;\n } else if (c === '.' && !inBackticks) {\n addCurrentSegment();\n i++;\n } else {\n current += c;\n i++;\n }\n }\n addCurrentSegment();\n if (inBackticks) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Unterminated ` in path: ' + path);\n }\n return new FieldPath(segments);\n };\n FieldPath.EMPTY_PATH = new FieldPath([]);\n return FieldPath;\n}(path_Path);\n\n// CONCATENATED MODULE: ./src/firestore/model/document_key.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\nvar document_key_DocumentKey = /** @class */function () {\n function DocumentKey(path) {\n this.path = path;\n assert(DocumentKey.isDocumentKey(path), 'Invalid DocumentKey with an odd number of segments: ' + path.toArray().join('/'));\n }\n DocumentKey.prototype.equals = function (other) {\n return other !== null && path_ResourcePath.comparator(this.path, other.path) === 0;\n };\n DocumentKey.prototype.toString = function () {\n return this.path.toString();\n };\n DocumentKey.comparator = function (k1, k2) {\n return path_ResourcePath.comparator(k1.path, k2.path);\n };\n DocumentKey.isDocumentKey = function (path) {\n return path.length % 2 === 0;\n };\n /**\r\n * Creates and returns a new document key with the given segments.\r\n *\r\n * @param path The segments of the path to the document\r\n * @return A new instance of DocumentKey\r\n */\n DocumentKey.fromSegments = function (segments) {\n return new DocumentKey(new path_ResourcePath(segments.slice()));\n };\n /**\r\n * Creates and returns a new document key using '/' to split the string into\r\n * segments.\r\n *\r\n * @param path The slash-separated path string to the document\r\n * @return A new instance of DocumentKey\r\n */\n DocumentKey.fromPathString = function (path) {\n return new DocumentKey(path_ResourcePath.fromString(path));\n };\n DocumentKey.EMPTY = new DocumentKey(new path_ResourcePath([]));\n return DocumentKey;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/model/document.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\nvar document_Document = /** @class */function () {\n function Document(key, version, data, options) {\n this.key = key;\n this.version = version;\n this.data = data;\n this.hasLocalMutations = options.hasLocalMutations;\n }\n Document.prototype.field = function (path) {\n return this.data.field(path);\n };\n Document.prototype.fieldValue = function (path) {\n var field = this.field(path);\n return field ? field.value() : undefined;\n };\n Document.prototype.value = function () {\n return this.data.value();\n };\n Document.prototype.equals = function (other) {\n return other instanceof Document && this.key.equals(other.key) && this.version.equals(other.version) && this.data.equals(other.data) && this.hasLocalMutations === other.hasLocalMutations;\n };\n Document.prototype.toString = function () {\n return \"Document(\" + this.key + \", \" + this.version + \", \" + this.data.toString() + \", \" + (\"{hasLocalMutations: \" + this.hasLocalMutations + \"})\");\n };\n Document.compareByKey = function (d1, d2) {\n return document_key_DocumentKey.comparator(d1.key, d2.key);\n };\n Document.compareByField = function (field, d1, d2) {\n var v1 = d1.field(field);\n var v2 = d2.field(field);\n if (v1 !== undefined && v2 !== undefined) {\n return v1.compareTo(v2);\n } else {\n return fail(\"Trying to compare documents on fields that don't exist\");\n }\n };\n return Document;\n}();\n\n/**\r\n * A class representing a deleted document.\r\n * Version is set to 0 if we don't point to any specific time, otherwise it\r\n * denotes time we know it didn't exist at.\r\n */\nvar document_NoDocument = /** @class */function () {\n function NoDocument(key, version) {\n this.key = key;\n this.version = version;\n }\n NoDocument.prototype.toString = function () {\n return \"NoDocument(\" + this.key + \", \" + this.version + \")\";\n };\n NoDocument.prototype.equals = function (other) {\n return other && other.version.equals(this.version) && other.key.equals(this.key);\n };\n NoDocument.compareByKey = function (d1, d2) {\n return document_key_DocumentKey.comparator(d1.key, d2.key);\n };\n return NoDocument;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/util/sorted_map.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n// An immutable sorted map implementation, based on a Left-leaning Red-Black\n// tree.\nvar sorted_map_SortedMap = /** @class */function () {\n function SortedMap(comparator, root) {\n this.comparator = comparator;\n this.root = root ? root : sorted_map_LLRBNode.EMPTY;\n }\n // Returns a copy of the map, with the specified key/value added or replaced.\n SortedMap.prototype.insert = function (key, value) {\n return new SortedMap(this.comparator, this.root.insert(key, value, this.comparator).copy(null, null, sorted_map_LLRBNode.BLACK, null, null));\n };\n // Returns a copy of the map, with the specified key removed.\n SortedMap.prototype.remove = function (key) {\n return new SortedMap(this.comparator, this.root.remove(key, this.comparator).copy(null, null, sorted_map_LLRBNode.BLACK, null, null));\n };\n // Returns the value of the node with the given key, or null.\n SortedMap.prototype.get = function (key) {\n var node = this.root;\n while (!node.isEmpty()) {\n var cmp = this.comparator(key, node.key);\n if (cmp === 0) {\n return node.value;\n } else if (cmp < 0) {\n node = node.left;\n } else if (cmp > 0) {\n node = node.right;\n }\n }\n return null;\n };\n // Returns the key of the item *before* the specified key, or null if key is\n // the first item.\n SortedMap.prototype.getPredecessorKey = function (key) {\n var node = this.root;\n var rightParent = null;\n while (!node.isEmpty()) {\n var cmp = this.comparator(key, node.key);\n if (cmp === 0) {\n if (!node.left.isEmpty()) {\n node = node.left;\n while (!node.right.isEmpty()) {\n node = node.right;\n }return node.key;\n } else if (rightParent) {\n return rightParent.key;\n } else {\n return null; // first item.\n }\n } else if (cmp < 0) {\n node = node.left;\n } else if (cmp > 0) {\n rightParent = node;\n node = node.right;\n }\n }\n throw fail('Attempted to find predecessor key for a nonexistent key.' + ' What gives?');\n };\n // Returns the index of the element in this sorted map, or -1 if it doesn't\n // exist.\n SortedMap.prototype.indexOf = function (key) {\n // Number of nodes that were pruned when descending right\n var prunedNodes = 0;\n var node = this.root;\n while (!node.isEmpty()) {\n var cmp = this.comparator(key, node.key);\n if (cmp === 0) {\n return prunedNodes + node.left.size;\n } else if (cmp < 0) {\n node = node.left;\n } else {\n // Count all nodes left of the node plus the node itself\n prunedNodes += node.left.size + 1;\n node = node.right;\n }\n }\n // Node not found\n return -1;\n };\n SortedMap.prototype.isEmpty = function () {\n return this.root.isEmpty();\n };\n Object.defineProperty(SortedMap.prototype, \"size\", {\n // Returns the total number of nodes in the map.\n get: function get() {\n return this.root.size;\n },\n enumerable: true,\n configurable: true\n });\n // Returns the minimum key in the map.\n SortedMap.prototype.minKey = function () {\n return this.root.minKey();\n };\n // Returns the maximum key in the map.\n SortedMap.prototype.maxKey = function () {\n return this.root.maxKey();\n };\n // Traverses the map in key order and calls the specified action function\n // for each key/value pair. If action returns true, traversal is aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n SortedMap.prototype.inorderTraversal = function (action) {\n return this.root.inorderTraversal(action);\n };\n SortedMap.prototype.forEach = function (fn) {\n this.inorderTraversal(function (k, v) {\n fn(k, v);\n return false;\n });\n };\n // Traverses the map in reverse key order and calls the specified action\n // function for each key/value pair. If action returns true, traversal is\n // aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n SortedMap.prototype.reverseTraversal = function (action) {\n return this.root.reverseTraversal(action);\n };\n SortedMap.prototype.getIterator = function (resultGenerator) {\n return new sorted_map_SortedMapIterator(this.root, null, this.comparator, false, resultGenerator);\n };\n SortedMap.prototype.getIteratorFrom = function (key, resultGenerator) {\n return new sorted_map_SortedMapIterator(this.root, key, this.comparator, false, resultGenerator);\n };\n SortedMap.prototype.getReverseIterator = function (resultGenerator) {\n return new sorted_map_SortedMapIterator(this.root, null, this.comparator, true, resultGenerator);\n };\n SortedMap.prototype.getReverseIteratorFrom = function (key, resultGenerator) {\n return new sorted_map_SortedMapIterator(this.root, key, this.comparator, true, resultGenerator);\n };\n return SortedMap;\n}(); // end SortedMap\n\n// An iterator over an LLRBNode.\nvar sorted_map_SortedMapIterator = /** @class */function () {\n function SortedMapIterator(node, startKey, comparator, isReverse, resultGenerator) {\n this.resultGenerator = resultGenerator || null;\n this.isReverse = isReverse;\n this.nodeStack = [];\n var cmp = 1;\n while (!node.isEmpty()) {\n cmp = startKey ? comparator(node.key, startKey) : 1;\n // flip the comparison if we're going in reverse\n if (isReverse) cmp *= -1;\n if (cmp < 0) {\n // This node is less than our start key. ignore it\n if (this.isReverse) {\n node = node.left;\n } else {\n node = node.right;\n }\n } else if (cmp === 0) {\n // This node is exactly equal to our start key. Push it on the stack,\n // but stop iterating;\n this.nodeStack.push(node);\n break;\n } else {\n // This node is greater than our start key, add it to the stack and move\n // to the next one\n this.nodeStack.push(node);\n if (this.isReverse) {\n node = node.right;\n } else {\n node = node.left;\n }\n }\n }\n }\n SortedMapIterator.prototype.getNext = function () {\n assert(this.nodeStack.length > 0, 'getNext() called on iterator when hasNext() is false.');\n var node = this.nodeStack.pop();\n var result;\n if (this.resultGenerator) result = this.resultGenerator(node.key, node.value);else result = { key: node.key, value: node.value };\n if (this.isReverse) {\n node = node.left;\n while (!node.isEmpty()) {\n this.nodeStack.push(node);\n node = node.right;\n }\n } else {\n node = node.right;\n while (!node.isEmpty()) {\n this.nodeStack.push(node);\n node = node.left;\n }\n }\n return result;\n };\n SortedMapIterator.prototype.hasNext = function () {\n return this.nodeStack.length > 0;\n };\n SortedMapIterator.prototype.peek = function () {\n if (this.nodeStack.length === 0) return null;\n var node = this.nodeStack[this.nodeStack.length - 1];\n if (this.resultGenerator) {\n return this.resultGenerator(node.key, node.value);\n } else {\n return { key: node.key, value: node.value };\n }\n };\n return SortedMapIterator;\n}(); // end SortedMapIterator\n\n// Represents a node in a Left-leaning Red-Black tree.\nvar sorted_map_LLRBNode = /** @class */function () {\n function LLRBNode(key, value, color, left, right) {\n this.key = key;\n this.value = value;\n this.color = color != null ? color : LLRBNode.RED;\n this.left = left != null ? left : LLRBNode.EMPTY;\n this.right = right != null ? right : LLRBNode.EMPTY;\n this.size = this.left.size + 1 + this.right.size;\n }\n // Returns a copy of the current node, optionally replacing pieces of it.\n LLRBNode.prototype.copy = function (key, value, color, left, right) {\n return new LLRBNode(key != null ? key : this.key, value != null ? value : this.value, color != null ? color : this.color, left != null ? left : this.left, right != null ? right : this.right);\n };\n LLRBNode.prototype.isEmpty = function () {\n return false;\n };\n // Traverses the tree in key order and calls the specified action function\n // for each node. If action returns true, traversal is aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n LLRBNode.prototype.inorderTraversal = function (action) {\n return this.left.inorderTraversal(action) || action(this.key, this.value) || this.right.inorderTraversal(action);\n };\n // Traverses the tree in reverse key order and calls the specified action\n // function for each node. If action returns true, traversal is aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n LLRBNode.prototype.reverseTraversal = function (action) {\n return this.right.reverseTraversal(action) || action(this.key, this.value) || this.left.reverseTraversal(action);\n };\n // Returns the minimum node in the tree.\n LLRBNode.prototype.min = function () {\n if (this.left.isEmpty()) {\n return this;\n } else {\n return this.left.min();\n }\n };\n // Returns the maximum key in the tree.\n LLRBNode.prototype.minKey = function () {\n return this.min().key;\n };\n // Returns the maximum key in the tree.\n LLRBNode.prototype.maxKey = function () {\n if (this.right.isEmpty()) {\n return this.key;\n } else {\n return this.right.maxKey();\n }\n };\n // Returns new tree, with the key/value added.\n LLRBNode.prototype.insert = function (key, value, comparator) {\n var n = this;\n var cmp = comparator(key, n.key);\n if (cmp < 0) {\n n = n.copy(null, null, null, n.left.insert(key, value, comparator), null);\n } else if (cmp === 0) {\n n = n.copy(null, value, null, null, null);\n } else {\n n = n.copy(null, null, null, null, n.right.insert(key, value, comparator));\n }\n return n.fixUp();\n };\n LLRBNode.prototype.removeMin = function () {\n if (this.left.isEmpty()) {\n return LLRBNode.EMPTY;\n }\n var n = this;\n if (!n.left.isRed() && !n.left.left.isRed()) n = n.moveRedLeft();\n n = n.copy(null, null, null, n.left.removeMin(), null);\n return n.fixUp();\n };\n // Returns new tree, with the specified item removed.\n LLRBNode.prototype.remove = function (key, comparator) {\n var smallest;\n var n = this;\n if (comparator(key, n.key) < 0) {\n if (!n.left.isEmpty() && !n.left.isRed() && !n.left.left.isRed()) {\n n = n.moveRedLeft();\n }\n n = n.copy(null, null, null, n.left.remove(key, comparator), null);\n } else {\n if (n.left.isRed()) n = n.rotateRight();\n if (!n.right.isEmpty() && !n.right.isRed() && !n.right.left.isRed()) {\n n = n.moveRedRight();\n }\n if (comparator(key, n.key) === 0) {\n if (n.right.isEmpty()) {\n return LLRBNode.EMPTY;\n } else {\n smallest = n.right.min();\n n = n.copy(smallest.key, smallest.value, null, null, n.right.removeMin());\n }\n }\n n = n.copy(null, null, null, null, n.right.remove(key, comparator));\n }\n return n.fixUp();\n };\n LLRBNode.prototype.isRed = function () {\n return this.color;\n };\n // Returns new tree after performing any needed rotations.\n LLRBNode.prototype.fixUp = function () {\n var n = this;\n if (n.right.isRed() && !n.left.isRed()) n = n.rotateLeft();\n if (n.left.isRed() && n.left.left.isRed()) n = n.rotateRight();\n if (n.left.isRed() && n.right.isRed()) n = n.colorFlip();\n return n;\n };\n LLRBNode.prototype.moveRedLeft = function () {\n var n = this.colorFlip();\n if (n.right.left.isRed()) {\n n = n.copy(null, null, null, null, n.right.rotateRight());\n n = n.rotateLeft();\n n = n.colorFlip();\n }\n return n;\n };\n LLRBNode.prototype.moveRedRight = function () {\n var n = this.colorFlip();\n if (n.left.left.isRed()) {\n n = n.rotateRight();\n n = n.colorFlip();\n }\n return n;\n };\n LLRBNode.prototype.rotateLeft = function () {\n var nl = this.copy(null, null, LLRBNode.RED, null, this.right.left);\n return this.right.copy(null, null, this.color, nl, null);\n };\n LLRBNode.prototype.rotateRight = function () {\n var nr = this.copy(null, null, LLRBNode.RED, this.left.right, null);\n return this.left.copy(null, null, this.color, null, nr);\n };\n LLRBNode.prototype.colorFlip = function () {\n var left = this.left.copy(null, null, !this.left.color, null, null);\n var right = this.right.copy(null, null, !this.right.color, null, null);\n return this.copy(null, null, !this.color, left, right);\n };\n // For testing.\n LLRBNode.prototype.checkMaxDepth = function () {\n var blackDepth = this.check();\n if (Math.pow(2.0, blackDepth) <= this.size + 1) {\n return true;\n } else {\n return false;\n }\n };\n // In a balanced RB tree, the black-depth (number of black nodes) from root to\n // leaves is equal on both sides. This function verifies that or asserts.\n LLRBNode.prototype.check = function () {\n if (this.isRed() && this.left.isRed()) {\n throw fail('Red node has red child(' + this.key + ',' + this.value + ')');\n }\n if (this.right.isRed()) {\n throw fail('Right child of (' + this.key + ',' + this.value + ') is red');\n }\n var blackDepth = this.left.check();\n if (blackDepth !== this.right.check()) {\n throw fail('Black depths differ');\n } else {\n return blackDepth + (this.isRed() ? 0 : 1);\n }\n };\n LLRBNode.EMPTY = null;\n LLRBNode.RED = true;\n LLRBNode.BLACK = false;\n return LLRBNode;\n}(); // end LLRBNode\n\n// Represents an empty node (a leaf node in the Red-Black Tree).\nvar LLRBEmptyNode = /** @class */function () {\n function LLRBEmptyNode() {\n this.size = 0;\n }\n // Returns a copy of the current node.\n LLRBEmptyNode.prototype.copy = function (key, value, color, left, right) {\n return this;\n };\n // Returns a copy of the tree, with the specified key/value added.\n LLRBEmptyNode.prototype.insert = function (key, value, comparator) {\n return new sorted_map_LLRBNode(key, value);\n };\n // Returns a copy of the tree, with the specified key removed.\n LLRBEmptyNode.prototype.remove = function (key, comparator) {\n return this;\n };\n LLRBEmptyNode.prototype.isEmpty = function () {\n return true;\n };\n LLRBEmptyNode.prototype.inorderTraversal = function (action) {\n return false;\n };\n LLRBEmptyNode.prototype.reverseTraversal = function (action) {\n return false;\n };\n LLRBEmptyNode.prototype.minKey = function () {\n return null;\n };\n LLRBEmptyNode.prototype.maxKey = function () {\n return null;\n };\n LLRBEmptyNode.prototype.isRed = function () {\n return false;\n };\n // For testing.\n LLRBEmptyNode.prototype.checkMaxDepth = function () {\n return true;\n };\n LLRBEmptyNode.prototype.check = function () {\n return 0;\n };\n return LLRBEmptyNode;\n}(); // end LLRBEmptyNode\n\nsorted_map_LLRBNode.EMPTY = new LLRBEmptyNode();\n// CONCATENATED MODULE: ./src/firestore/model/field_value.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar field_value___extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\nvar TypeOrder;\n(function (TypeOrder) {\n // This order is defined by the backend.\n TypeOrder[TypeOrder[\"NullValue\"] = 0] = \"NullValue\";\n TypeOrder[TypeOrder[\"BooleanValue\"] = 1] = \"BooleanValue\";\n TypeOrder[TypeOrder[\"NumberValue\"] = 2] = \"NumberValue\";\n TypeOrder[TypeOrder[\"TimestampValue\"] = 3] = \"TimestampValue\";\n TypeOrder[TypeOrder[\"StringValue\"] = 4] = \"StringValue\";\n TypeOrder[TypeOrder[\"BlobValue\"] = 5] = \"BlobValue\";\n TypeOrder[TypeOrder[\"RefValue\"] = 6] = \"RefValue\";\n TypeOrder[TypeOrder[\"GeoPointValue\"] = 7] = \"GeoPointValue\";\n TypeOrder[TypeOrder[\"ArrayValue\"] = 8] = \"ArrayValue\";\n TypeOrder[TypeOrder[\"ObjectValue\"] = 9] = \"ObjectValue\";\n})(TypeOrder || (TypeOrder = {}));\n/**\r\n * A field value represents a datatype as stored by Firestore.\r\n */\nvar field_value_FieldValue = /** @class */function () {\n function FieldValue() {}\n FieldValue.prototype.toString = function () {\n var val = this.value();\n return val === null ? 'null' : val.toString();\n };\n FieldValue.prototype.defaultCompareTo = function (other) {\n assert(this.typeOrder !== other.typeOrder, 'Default compareTo should not be used for values of same type.');\n var cmp = primitiveComparator(this.typeOrder, other.typeOrder);\n return cmp;\n };\n return FieldValue;\n}();\n\nvar NullValue = /** @class */function (_super) {\n field_value___extends(NullValue, _super);\n function NullValue() {\n var _this = _super.call(this) || this;\n _this.typeOrder = TypeOrder.NullValue;\n // internalValue is unused but we add it to work around\n // https://github.com/Microsoft/TypeScript/issues/15585\n _this.internalValue = null;\n return _this;\n }\n NullValue.prototype.value = function () {\n return null;\n };\n NullValue.prototype.equals = function (other) {\n return other instanceof NullValue;\n };\n NullValue.prototype.compareTo = function (other) {\n if (other instanceof NullValue) {\n return 0;\n }\n return this.defaultCompareTo(other);\n };\n NullValue.INSTANCE = new NullValue();\n return NullValue;\n}(field_value_FieldValue);\n\nvar field_value_BooleanValue = /** @class */function (_super) {\n field_value___extends(BooleanValue, _super);\n function BooleanValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.BooleanValue;\n return _this;\n }\n BooleanValue.prototype.value = function () {\n return this.internalValue;\n };\n BooleanValue.prototype.equals = function (other) {\n return other instanceof BooleanValue && this.internalValue === other.internalValue;\n };\n BooleanValue.prototype.compareTo = function (other) {\n if (other instanceof BooleanValue) {\n return primitiveComparator(this, other);\n }\n return this.defaultCompareTo(other);\n };\n BooleanValue.of = function (value) {\n return value ? BooleanValue.TRUE : BooleanValue.FALSE;\n };\n BooleanValue.TRUE = new BooleanValue(true);\n BooleanValue.FALSE = new BooleanValue(false);\n return BooleanValue;\n}(field_value_FieldValue);\n\n/** Base class for IntegerValue and DoubleValue. */\nvar NumberValue = /** @class */function (_super) {\n field_value___extends(NumberValue, _super);\n function NumberValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.NumberValue;\n return _this;\n }\n NumberValue.prototype.value = function () {\n return this.internalValue;\n };\n NumberValue.prototype.compareTo = function (other) {\n if (other instanceof NumberValue) {\n return numericComparator(this.internalValue, other.internalValue);\n }\n return this.defaultCompareTo(other);\n };\n return NumberValue;\n}(field_value_FieldValue);\n\n/** Utility function to compare doubles (using Firestore semantics for NaN). */\nfunction numericComparator(left, right) {\n if (left < right) {\n return -1;\n } else if (left > right) {\n return 1;\n } else if (left === right) {\n return 0;\n } else {\n // one or both are NaN.\n if (isNaN(left)) {\n return isNaN(right) ? 0 : -1;\n } else {\n return 1;\n }\n }\n}\n/**\r\n * Utility function to check numbers for equality using Firestore semantics\r\n * (NaN === NaN, -0.0 !== 0.0).\r\n */\nfunction numericEquals(left, right) {\n // Implemented based on Object.is() polyfill from\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n if (left === right) {\n // +0 != -0\n return left !== 0 || 1 / left === 1 / right;\n } else {\n // NaN == NaN\n return left !== left && right !== right;\n }\n}\nvar IntegerValue = /** @class */function (_super) {\n field_value___extends(IntegerValue, _super);\n function IntegerValue(internalValue) {\n return _super.call(this, internalValue) || this;\n }\n IntegerValue.prototype.equals = function (other) {\n // NOTE: DoubleValue and IntegerValue instances may compareTo() the same,\n // but that doesn't make them equal via equals().\n if (other instanceof IntegerValue) {\n return numericEquals(this.internalValue, other.internalValue);\n } else {\n return false;\n }\n };\n return IntegerValue;\n}(NumberValue);\n\nvar DoubleValue = /** @class */function (_super) {\n field_value___extends(DoubleValue, _super);\n function DoubleValue(internalValue) {\n var _this = _super.call(this, internalValue) || this;\n _this.internalValue = internalValue;\n return _this;\n }\n DoubleValue.prototype.equals = function (other) {\n // NOTE: DoubleValue and IntegerValue instances may compareTo() the same,\n // but that doesn't make them equal via equals().\n if (other instanceof DoubleValue) {\n return numericEquals(this.internalValue, other.internalValue);\n } else {\n return false;\n }\n };\n DoubleValue.NAN = new DoubleValue(NaN);\n DoubleValue.POSITIVE_INFINITY = new DoubleValue(Infinity);\n DoubleValue.NEGATIVE_INFINITY = new DoubleValue(-Infinity);\n return DoubleValue;\n}(NumberValue);\n\n// TODO(b/37267885): Add truncation support\nvar field_value_StringValue = /** @class */function (_super) {\n field_value___extends(StringValue, _super);\n function StringValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.StringValue;\n return _this;\n }\n StringValue.prototype.value = function () {\n return this.internalValue;\n };\n StringValue.prototype.equals = function (other) {\n return other instanceof StringValue && this.internalValue === other.internalValue;\n };\n StringValue.prototype.compareTo = function (other) {\n if (other instanceof StringValue) {\n return primitiveComparator(this.internalValue, other.internalValue);\n }\n return this.defaultCompareTo(other);\n };\n return StringValue;\n}(field_value_FieldValue);\n\nvar TimestampValue = /** @class */function (_super) {\n field_value___extends(TimestampValue, _super);\n function TimestampValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.TimestampValue;\n return _this;\n }\n TimestampValue.prototype.value = function () {\n return this.internalValue.toDate();\n };\n TimestampValue.prototype.equals = function (other) {\n return other instanceof TimestampValue && this.internalValue.equals(other.internalValue);\n };\n TimestampValue.prototype.compareTo = function (other) {\n if (other instanceof TimestampValue) {\n return this.internalValue.compareTo(other.internalValue);\n } else if (other instanceof ServerTimestampValue) {\n // Concrete timestamps come before server timestamps.\n return -1;\n } else {\n return this.defaultCompareTo(other);\n }\n };\n return TimestampValue;\n}(field_value_FieldValue);\n\n/**\r\n * Represents a locally-applied ServerTimestamp.\r\n *\r\n * Notes:\r\n * - ServerTimestampValue instances are created as the result of applying a\r\n * TransformMutation (see TransformMutation.applyTo()). They can only exist in\r\n * the local view of a document. Therefore they do not need to be parsed or\r\n * serialized.\r\n * - When evaluated locally (e.g. for snapshot.data()), they evaluate to null.\r\n * - With respect to other ServerTimestampValues, they sort by their\r\n * localWriteTime.\r\n */\nvar ServerTimestampValue = /** @class */function (_super) {\n field_value___extends(ServerTimestampValue, _super);\n function ServerTimestampValue(localWriteTime) {\n var _this = _super.call(this) || this;\n _this.localWriteTime = localWriteTime;\n _this.typeOrder = TypeOrder.TimestampValue;\n return _this;\n }\n ServerTimestampValue.prototype.value = function () {\n return null;\n };\n ServerTimestampValue.prototype.equals = function (other) {\n return other instanceof ServerTimestampValue && this.localWriteTime.equals(other.localWriteTime);\n };\n ServerTimestampValue.prototype.compareTo = function (other) {\n if (other instanceof ServerTimestampValue) {\n return this.localWriteTime.compareTo(other.localWriteTime);\n } else if (other instanceof TimestampValue) {\n // Server timestamps come after all concrete timestamps.\n return 1;\n } else {\n return this.defaultCompareTo(other);\n }\n };\n ServerTimestampValue.prototype.toString = function () {\n return '';\n };\n return ServerTimestampValue;\n}(field_value_FieldValue);\n\nvar BlobValue = /** @class */function (_super) {\n field_value___extends(BlobValue, _super);\n function BlobValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.BlobValue;\n return _this;\n }\n BlobValue.prototype.value = function () {\n return this.internalValue;\n };\n BlobValue.prototype.equals = function (other) {\n return other instanceof BlobValue && this.internalValue._equals(other.internalValue);\n };\n BlobValue.prototype.compareTo = function (other) {\n if (other instanceof BlobValue) {\n return this.internalValue._compareTo(other.internalValue);\n }\n return this.defaultCompareTo(other);\n };\n return BlobValue;\n}(field_value_FieldValue);\n\nvar field_value_RefValue = /** @class */function (_super) {\n field_value___extends(RefValue, _super);\n function RefValue(databaseId, key) {\n var _this = _super.call(this) || this;\n _this.databaseId = databaseId;\n _this.key = key;\n _this.typeOrder = TypeOrder.RefValue;\n return _this;\n }\n RefValue.prototype.value = function () {\n return this.key;\n };\n RefValue.prototype.equals = function (other) {\n if (other instanceof RefValue) {\n return this.key.equals(other.key) && this.databaseId.equals(other.databaseId);\n } else {\n return false;\n }\n };\n RefValue.prototype.compareTo = function (other) {\n if (other instanceof RefValue) {\n var cmp = this.databaseId.compareTo(other.databaseId);\n return cmp !== 0 ? cmp : document_key_DocumentKey.comparator(this.key, other.key);\n }\n return this.defaultCompareTo(other);\n };\n return RefValue;\n}(field_value_FieldValue);\n\nvar GeoPointValue = /** @class */function (_super) {\n field_value___extends(GeoPointValue, _super);\n function GeoPointValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.GeoPointValue;\n return _this;\n }\n GeoPointValue.prototype.value = function () {\n return this.internalValue;\n };\n GeoPointValue.prototype.equals = function (other) {\n return other instanceof GeoPointValue && this.internalValue._equals(other.internalValue);\n };\n GeoPointValue.prototype.compareTo = function (other) {\n if (other instanceof GeoPointValue) {\n return this.internalValue._compareTo(other.internalValue);\n }\n return this.defaultCompareTo(other);\n };\n return GeoPointValue;\n}(field_value_FieldValue);\n\nvar field_value_ObjectValue = /** @class */function (_super) {\n field_value___extends(ObjectValue, _super);\n function ObjectValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.ObjectValue;\n return _this;\n }\n ObjectValue.prototype.value = function () {\n var result = {};\n this.internalValue.inorderTraversal(function (key, val) {\n result[key] = val.value();\n });\n return result;\n };\n ObjectValue.prototype.forEach = function (action) {\n this.internalValue.inorderTraversal(action);\n };\n ObjectValue.prototype.equals = function (other) {\n if (other instanceof ObjectValue) {\n var it1 = this.internalValue.getIterator();\n var it2 = other.internalValue.getIterator();\n while (it1.hasNext() && it2.hasNext()) {\n var next1 = it1.getNext();\n var next2 = it2.getNext();\n if (next1.key !== next2.key || !next1.value.equals(next2.value)) {\n return false;\n }\n }\n return !it1.hasNext() && !it2.hasNext();\n }\n return false;\n };\n ObjectValue.prototype.compareTo = function (other) {\n if (other instanceof ObjectValue) {\n var it1 = this.internalValue.getIterator();\n var it2 = other.internalValue.getIterator();\n while (it1.hasNext() && it2.hasNext()) {\n var next1 = it1.getNext();\n var next2 = it2.getNext();\n var cmp = primitiveComparator(next1.key, next2.key) || next1.value.compareTo(next2.value);\n if (cmp) {\n return cmp;\n }\n }\n // Only equal if both iterators are exhausted\n return primitiveComparator(it1.hasNext(), it2.hasNext());\n } else {\n return this.defaultCompareTo(other);\n }\n };\n ObjectValue.prototype.set = function (path, to) {\n assert(!path.isEmpty(), 'Cannot set field for empty path on ObjectValue');\n if (path.length === 1) {\n return this.setChild(path.firstSegment(), to);\n } else {\n var child = this.child(path.firstSegment());\n if (!(child instanceof ObjectValue)) {\n child = ObjectValue.EMPTY;\n }\n var newChild = child.set(path.popFirst(), to);\n return this.setChild(path.firstSegment(), newChild);\n }\n };\n ObjectValue.prototype.delete = function (path) {\n assert(!path.isEmpty(), 'Cannot delete field for empty path on ObjectValue');\n if (path.length === 1) {\n return new ObjectValue(this.internalValue.remove(path.firstSegment()));\n } else {\n // nested field\n var child = this.child(path.firstSegment());\n if (child instanceof ObjectValue) {\n var newChild = child.delete(path.popFirst());\n return new ObjectValue(this.internalValue.insert(path.firstSegment(), newChild));\n } else {\n // Don't actually change a primitive value to an object for a delete\n return this;\n }\n }\n };\n ObjectValue.prototype.contains = function (path) {\n return this.field(path) !== undefined;\n };\n ObjectValue.prototype.field = function (path) {\n assert(!path.isEmpty(), \"Can't get field of empty path\");\n var field = this;\n path.forEach(function (pathSegment) {\n if (field instanceof ObjectValue) {\n field = field.internalValue.get(pathSegment) || undefined;\n } else {\n field = undefined;\n }\n });\n return field;\n };\n ObjectValue.prototype.toString = function () {\n return JSON.stringify(this.value());\n };\n ObjectValue.prototype.child = function (childName) {\n return this.internalValue.get(childName) || undefined;\n };\n ObjectValue.prototype.setChild = function (childName, value) {\n return new ObjectValue(this.internalValue.insert(childName, value));\n };\n ObjectValue.EMPTY = new ObjectValue(new sorted_map_SortedMap(primitiveComparator));\n return ObjectValue;\n}(field_value_FieldValue);\n\nvar field_value_ArrayValue = /** @class */function (_super) {\n field_value___extends(ArrayValue, _super);\n function ArrayValue(internalValue) {\n var _this = _super.call(this) || this;\n _this.internalValue = internalValue;\n _this.typeOrder = TypeOrder.ArrayValue;\n return _this;\n }\n ArrayValue.prototype.value = function () {\n return this.internalValue.map(function (v) {\n return v.value();\n });\n };\n ArrayValue.prototype.forEach = function (action) {\n this.internalValue.forEach(action);\n };\n ArrayValue.prototype.equals = function (other) {\n if (other instanceof ArrayValue) {\n if (this.internalValue.length !== other.internalValue.length) {\n return false;\n }\n for (var i = 0; i < this.internalValue.length; i++) {\n if (!this.internalValue[i].equals(other.internalValue[i])) {\n return false;\n }\n }\n return true;\n }\n return false;\n };\n ArrayValue.prototype.compareTo = function (other) {\n if (other instanceof ArrayValue) {\n var minLength = Math.min(this.internalValue.length, other.internalValue.length);\n for (var i = 0; i < minLength; i++) {\n var cmp = this.internalValue[i].compareTo(other.internalValue[i]);\n if (cmp) {\n return cmp;\n }\n }\n return primitiveComparator(this.internalValue.length, other.internalValue.length);\n } else {\n return this.defaultCompareTo(other);\n }\n };\n ArrayValue.prototype.toString = function () {\n return JSON.stringify(this.value());\n };\n return ArrayValue;\n}(field_value_FieldValue);\n\n// CONCATENATED MODULE: ./src/firestore/util/types.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n// Untyped Number alias we can use to check for ES6 methods / properties.\n// tslint:disable-next-line:no-any variable-name\nvar NumberAsAny = Number;\n/**\r\n * Minimum safe integer in Javascript because of floating point precision.\r\n * Added to not rely on ES6 features.\r\n */\nvar MIN_SAFE_INTEGER = NumberAsAny.MIN_SAFE_INTEGER || -(Math.pow(2, 53) - 1);\n/**\r\n * Maximum safe integer in Javascript because of floating point precision.\r\n * Added to not rely on ES6 features.\r\n */\nvar MAX_SAFE_INTEGER = NumberAsAny.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1;\n/**\r\n * Returns whether an number is an integer, uses native implementation if\r\n * available.\r\n * Added to not rely on ES6 features.\r\n * @param value The value to test for being an integer\r\n */\nvar isInteger = NumberAsAny.isInteger || function (value) {\n return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;\n};\n/**\r\n * Returns whether a variable is either undefined or null.\r\n */\nfunction isNullOrUndefined(value) {\n return value === null || value === undefined;\n}\n/**\r\n * Returns whether a value is an integer and in the safe integer range\r\n * @param value The value to test for being an integer and in the safe range\r\n */\nfunction isSafeInteger(value) {\n return isInteger(value) && value <= MAX_SAFE_INTEGER && value >= MIN_SAFE_INTEGER;\n}\n/**\r\n * Safely checks if the number is NaN.\r\n */\nfunction safeIsNaN(value) {\n if (NumberAsAny.IsNaN) {\n return NumberAsAny.IsNaN(value);\n } else {\n return typeof value === 'number' && isNaN(value);\n }\n}\n// CONCATENATED MODULE: ./src/firestore/core/query.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\nvar query_Query = /** @class */function () {\n function Query(path, explicitOrderBy, filters, limit, startAt, endAt) {\n if (explicitOrderBy === void 0) {\n explicitOrderBy = [];\n }\n if (filters === void 0) {\n filters = [];\n }\n if (limit === void 0) {\n limit = null;\n }\n if (startAt === void 0) {\n startAt = null;\n }\n if (endAt === void 0) {\n endAt = null;\n }\n this.path = path;\n this.explicitOrderBy = explicitOrderBy;\n this.filters = filters;\n this.limit = limit;\n this.startAt = startAt;\n this.endAt = endAt;\n this.memoizedCanonicalId = null;\n this.memoizedOrderBy = null;\n if (this.startAt) {\n this.assertValidBound(this.startAt);\n }\n if (this.endAt) {\n this.assertValidBound(this.endAt);\n }\n }\n Query.atPath = function (path) {\n return new Query(path);\n };\n Object.defineProperty(Query.prototype, \"orderBy\", {\n get: function get() {\n if (this.memoizedOrderBy === null) {\n var inequalityField = this.getInequalityFilterField();\n var firstOrderByField = this.getFirstOrderByField();\n if (inequalityField !== null && firstOrderByField === null) {\n // In order to implicitly add key ordering, we must also add the\n // inequality filter field for it to be a valid query.\n // Note that the default inequality field and key ordering is ascending.\n if (inequalityField.isKeyField()) {\n this.memoizedOrderBy = [KEY_ORDERING_ASC];\n } else {\n this.memoizedOrderBy = [new query_OrderBy(inequalityField), KEY_ORDERING_ASC];\n }\n } else {\n assert(inequalityField === null || firstOrderByField !== null && inequalityField.equals(firstOrderByField), 'First orderBy should match inequality field.');\n this.memoizedOrderBy = [];\n var foundKeyOrdering = false;\n for (var _i = 0, _a = this.explicitOrderBy; _i < _a.length; _i++) {\n var orderBy = _a[_i];\n this.memoizedOrderBy.push(orderBy);\n if (orderBy.field.isKeyField()) {\n foundKeyOrdering = true;\n }\n }\n if (!foundKeyOrdering) {\n // The order of the implicit key ordering always matches the last\n // explicit order by\n var lastDirection = this.explicitOrderBy.length > 0 ? this.explicitOrderBy[this.explicitOrderBy.length - 1].dir : Direction.ASCENDING;\n this.memoizedOrderBy.push(lastDirection === Direction.ASCENDING ? KEY_ORDERING_ASC : KEY_ORDERING_DESC);\n }\n }\n }\n return this.memoizedOrderBy;\n },\n enumerable: true,\n configurable: true\n });\n Query.prototype.addFilter = function (filter) {\n assert(this.getInequalityFilterField() == null || !(filter instanceof query_RelationFilter) || !filter.isInequality() || filter.field.equals(this.getInequalityFilterField()), 'Query must only have one inequality field.');\n assert(!document_key_DocumentKey.isDocumentKey(this.path), 'No filtering allowed for document query');\n var newFilters = this.filters.concat([filter]);\n return new Query(this.path, this.explicitOrderBy.slice(), newFilters, this.limit, this.startAt, this.endAt);\n };\n Query.prototype.addOrderBy = function (orderBy) {\n assert(!document_key_DocumentKey.isDocumentKey(this.path), 'No ordering allowed for document query');\n assert(!this.startAt && !this.endAt, 'Bounds must be set after orderBy');\n // TODO(dimond): validate that orderBy does not list the same key twice.\n var newOrderBy = this.explicitOrderBy.concat([orderBy]);\n return new Query(this.path, newOrderBy, this.filters.slice(), this.limit, this.startAt, this.endAt);\n };\n Query.prototype.withLimit = function (limit) {\n return new Query(this.path, this.explicitOrderBy.slice(), this.filters.slice(), limit, this.startAt, this.endAt);\n };\n Query.prototype.withStartAt = function (bound) {\n return new Query(this.path, this.explicitOrderBy.slice(), this.filters.slice(), this.limit, bound, this.endAt);\n };\n Query.prototype.withEndAt = function (bound) {\n return new Query(this.path, this.explicitOrderBy.slice(), this.filters.slice(), this.limit, this.startAt, bound);\n };\n // TODO(b/29183165): This is used to get a unique string from a query to, for\n // example, use as a dictionary key, but the implementation is subject to\n // collisions. Make it collision-free.\n Query.prototype.canonicalId = function () {\n if (this.memoizedCanonicalId === null) {\n var canonicalId = this.path.canonicalString();\n canonicalId += '|f:';\n for (var _i = 0, _a = this.filters; _i < _a.length; _i++) {\n var filter = _a[_i];\n canonicalId += filter.canonicalId();\n canonicalId += ',';\n }\n canonicalId += '|ob:';\n // TODO(dimond): make this collision resistant\n for (var _b = 0, _c = this.orderBy; _b < _c.length; _b++) {\n var orderBy = _c[_b];\n canonicalId += orderBy.canonicalId();\n canonicalId += ',';\n }\n if (!isNullOrUndefined(this.limit)) {\n canonicalId += '|l:';\n canonicalId += this.limit;\n }\n if (this.startAt) {\n canonicalId += '|lb:';\n canonicalId += this.startAt.canonicalId();\n }\n if (this.endAt) {\n canonicalId += '|ub:';\n canonicalId += this.endAt.canonicalId();\n }\n this.memoizedCanonicalId = canonicalId;\n }\n return this.memoizedCanonicalId;\n };\n Query.prototype.toString = function () {\n var str = 'Query(' + this.path.canonicalString();\n if (this.filters.length > 0) {\n str += \", filters: [\" + this.filters.join(', ') + \"]\";\n }\n if (!isNullOrUndefined(this.limit)) {\n str += ', limit: ' + this.limit;\n }\n if (this.explicitOrderBy.length > 0) {\n str += \", orderBy: [\" + this.explicitOrderBy.join(', ') + \"]\";\n }\n if (this.startAt) {\n str += ', startAt: ' + this.startAt.canonicalId();\n }\n if (this.endAt) {\n str += ', endAt: ' + this.endAt.canonicalId();\n }\n return str + ')';\n };\n Query.prototype.equals = function (other) {\n if (this.limit !== other.limit) {\n return false;\n }\n if (this.orderBy.length !== other.orderBy.length) {\n return false;\n }\n for (var i = 0; i < this.orderBy.length; i++) {\n if (!this.orderBy[i].equals(other.orderBy[i])) {\n return false;\n }\n }\n if (this.filters.length !== other.filters.length) {\n return false;\n }\n for (var i = 0; i < this.filters.length; i++) {\n if (!this.filters[i].equals(other.filters[i])) {\n return false;\n }\n }\n if (!this.path.equals(other.path)) {\n return false;\n }\n if (this.startAt !== null ? !this.startAt.equals(other.startAt) : other.startAt !== null) {\n return false;\n }\n return this.endAt !== null ? this.endAt.equals(other.endAt) : other.endAt === null;\n };\n Query.prototype.docComparator = function (d1, d2) {\n var comparedOnKeyField = false;\n for (var _i = 0, _a = this.orderBy; _i < _a.length; _i++) {\n var orderBy = _a[_i];\n var comp = orderBy.compare(d1, d2);\n if (comp !== 0) return comp;\n comparedOnKeyField = comparedOnKeyField || orderBy.field.isKeyField();\n }\n // Assert that we actually compared by key\n assert(comparedOnKeyField, \"orderBy used that doesn't compare on key field\");\n return 0;\n };\n Query.prototype.matches = function (doc) {\n return this.matchesAncestor(doc) && this.matchesOrderBy(doc) && this.matchesFilters(doc) && this.matchesBounds(doc);\n };\n Query.prototype.hasLimit = function () {\n return !isNullOrUndefined(this.limit);\n };\n Query.prototype.getFirstOrderByField = function () {\n return this.explicitOrderBy.length > 0 ? this.explicitOrderBy[0].field : null;\n };\n Query.prototype.getInequalityFilterField = function () {\n for (var _i = 0, _a = this.filters; _i < _a.length; _i++) {\n var filter = _a[_i];\n if (filter instanceof query_RelationFilter && filter.isInequality()) {\n return filter.field;\n }\n }\n return null;\n };\n Query.prototype.isDocumentQuery = function () {\n return document_key_DocumentKey.isDocumentKey(this.path) && this.filters.length === 0;\n };\n Query.prototype.matchesAncestor = function (doc) {\n var docPath = doc.key.path;\n if (document_key_DocumentKey.isDocumentKey(this.path)) {\n // exact match for document queries\n return this.path.equals(docPath);\n } else {\n // shallow ancestor queries by default\n return this.path.isPrefixOf(docPath) && this.path.length === docPath.length - 1;\n }\n };\n /**\r\n * A document must have a value for every ordering clause in order to show up\r\n * in the results.\r\n */\n Query.prototype.matchesOrderBy = function (doc) {\n for (var _i = 0, _a = this.explicitOrderBy; _i < _a.length; _i++) {\n var orderBy = _a[_i];\n // order by key always matches\n if (!orderBy.field.isKeyField() && doc.field(orderBy.field) === undefined) {\n return false;\n }\n }\n return true;\n };\n Query.prototype.matchesFilters = function (doc) {\n for (var _i = 0, _a = this.filters; _i < _a.length; _i++) {\n var filter = _a[_i];\n if (!filter.matches(doc)) {\n return false;\n }\n }\n return true;\n };\n /**\r\n * Makes sure a document is within the bounds, if provided.\r\n */\n Query.prototype.matchesBounds = function (doc) {\n if (this.startAt && !this.startAt.sortsBeforeDocument(this.orderBy, doc)) {\n return false;\n }\n if (this.endAt && this.endAt.sortsBeforeDocument(this.orderBy, doc)) {\n return false;\n }\n return true;\n };\n Query.prototype.assertValidBound = function (bound) {\n assert(bound.position.length <= this.orderBy.length, 'Bound is longer than orderBy');\n };\n return Query;\n}();\n\nvar query_RelationOp = /** @class */function () {\n function RelationOp(name) {\n this.name = name;\n }\n RelationOp.fromString = function (op) {\n switch (op) {\n case '<':\n return RelationOp.LESS_THAN;\n case '<=':\n return RelationOp.LESS_THAN_OR_EQUAL;\n case '==':\n return RelationOp.EQUAL;\n case '>=':\n return RelationOp.GREATER_THAN_OR_EQUAL;\n case '>':\n return RelationOp.GREATER_THAN;\n default:\n return fail('Unknown relation: ' + op);\n }\n };\n RelationOp.prototype.toString = function () {\n return this.name;\n };\n RelationOp.prototype.equals = function (other) {\n return this.name === other.name;\n };\n RelationOp.LESS_THAN = new RelationOp('<');\n RelationOp.LESS_THAN_OR_EQUAL = new RelationOp('<=');\n RelationOp.EQUAL = new RelationOp('==');\n RelationOp.GREATER_THAN = new RelationOp('>');\n RelationOp.GREATER_THAN_OR_EQUAL = new RelationOp('>=');\n return RelationOp;\n}();\n\nvar query_RelationFilter = /** @class */function () {\n function RelationFilter(field, op, value) {\n this.field = field;\n this.op = op;\n this.value = value;\n }\n RelationFilter.prototype.matches = function (doc) {\n if (this.field.isKeyField()) {\n assert(this.value instanceof field_value_RefValue, 'Comparing on key, but filter value not a RefValue');\n var refValue = this.value;\n var comparison = document_key_DocumentKey.comparator(doc.key, refValue.key);\n return this.matchesComparison(comparison);\n } else {\n var val = doc.field(this.field);\n return val !== undefined && this.matchesValue(val);\n }\n };\n RelationFilter.prototype.matchesValue = function (value) {\n // Only compare types with matching backend order (such as double and int).\n if (this.value.typeOrder !== value.typeOrder) {\n return false;\n }\n return this.matchesComparison(value.compareTo(this.value));\n };\n RelationFilter.prototype.matchesComparison = function (comparison) {\n switch (this.op) {\n case query_RelationOp.LESS_THAN:\n return comparison < 0;\n case query_RelationOp.LESS_THAN_OR_EQUAL:\n return comparison <= 0;\n case query_RelationOp.EQUAL:\n return comparison === 0;\n case query_RelationOp.GREATER_THAN:\n return comparison > 0;\n case query_RelationOp.GREATER_THAN_OR_EQUAL:\n return comparison >= 0;\n default:\n return fail('Unknown relation op' + this.op);\n }\n };\n RelationFilter.prototype.isInequality = function () {\n return this.op !== query_RelationOp.EQUAL;\n };\n RelationFilter.prototype.canonicalId = function () {\n // TODO(b/29183165): Technically, this won't be unique if two values have\n // the same description, such as the int 3 and the string \"3\". So we should\n // add the types in here somehow, too.\n return this.field.canonicalString() + this.op.toString() + this.value.toString();\n };\n RelationFilter.prototype.equals = function (other) {\n if (other instanceof RelationFilter) {\n return this.op.equals(other.op) && this.field.equals(other.field) && this.value.equals(other.value);\n } else {\n return false;\n }\n };\n RelationFilter.prototype.toString = function () {\n return this.field.canonicalString() + \" \" + this.op + \" \" + this.value.value();\n };\n return RelationFilter;\n}();\n\n/**\r\n * Filter that matches 'null' values.\r\n */\nvar NullFilter = /** @class */function () {\n function NullFilter(field) {\n this.field = field;\n }\n NullFilter.prototype.matches = function (doc) {\n var val = doc.field(this.field);\n return val !== undefined && val.value() === null;\n };\n NullFilter.prototype.canonicalId = function () {\n return this.field.canonicalString() + ' IS null';\n };\n NullFilter.prototype.toString = function () {\n return this.field.canonicalString() + \" IS null\";\n };\n NullFilter.prototype.equals = function (other) {\n if (other instanceof NullFilter) {\n return this.field.equals(other.field);\n } else {\n return false;\n }\n };\n return NullFilter;\n}();\n\n/**\r\n * Filter that matches 'NaN' values.\r\n */\nvar NanFilter = /** @class */function () {\n function NanFilter(field) {\n this.field = field;\n }\n NanFilter.prototype.matches = function (doc) {\n var val = doc.field(this.field).value();\n return typeof val === 'number' && isNaN(val);\n };\n NanFilter.prototype.canonicalId = function () {\n return this.field.canonicalString() + ' IS NaN';\n };\n NanFilter.prototype.toString = function () {\n return this.field.canonicalString() + \" IS NaN\";\n };\n NanFilter.prototype.equals = function (other) {\n if (other instanceof NanFilter) {\n return this.field.equals(other.field);\n } else {\n return false;\n }\n };\n return NanFilter;\n}();\n\n/**\r\n * Creates a filter based on the provided arguments.\r\n */\nfunction fieldFilter(field, op, value) {\n if (value.equals(NullValue.INSTANCE)) {\n if (op !== query_RelationOp.EQUAL) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid query. You can only perform equals ' + 'comparisons on null.');\n }\n return new NullFilter(field);\n } else if (value.equals(DoubleValue.NAN)) {\n if (op !== query_RelationOp.EQUAL) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid query. You can only perform equals ' + 'comparisons on NaN.');\n }\n return new NanFilter(field);\n } else {\n return new query_RelationFilter(field, op, value);\n }\n}\n/**\r\n * The direction of sorting in an order by.\r\n */\nvar Direction = /** @class */function () {\n function Direction(name) {\n this.name = name;\n }\n Direction.prototype.toString = function () {\n return this.name;\n };\n Direction.ASCENDING = new Direction('asc');\n Direction.DESCENDING = new Direction('desc');\n return Direction;\n}();\n\n/**\r\n * Represents a bound of a query.\r\n *\r\n * The bound is specified with the given components representing a position and\r\n * whether it's just before or just after the position (relative to whatever the\r\n * query order is).\r\n *\r\n * The position represents a logical index position for a query. It's a prefix\r\n * of values for the (potentially implicit) order by clauses of a query.\r\n *\r\n * Bound provides a function to determine whether a document comes before or\r\n * after a bound. This is influenced by whether the position is just before or\r\n * just after the provided values.\r\n */\nvar query_Bound = /** @class */function () {\n function Bound(position, before) {\n this.position = position;\n this.before = before;\n }\n Bound.prototype.canonicalId = function () {\n // TODO(b/29183165): Make this collision robust.\n var canonicalId = this.before ? 'b:' : 'a:';\n for (var _i = 0, _a = this.position; _i < _a.length; _i++) {\n var component = _a[_i];\n canonicalId += component.toString();\n }\n return canonicalId;\n };\n /**\r\n * Returns true if a document sorts before a bound using the provided sort\r\n * order.\r\n */\n Bound.prototype.sortsBeforeDocument = function (orderBy, doc) {\n assert(this.position.length <= orderBy.length, \"Bound has more components than query's orderBy\");\n var comparison = 0;\n for (var i = 0; i < this.position.length; i++) {\n var orderByComponent = orderBy[i];\n var component = this.position[i];\n if (orderByComponent.field.isKeyField()) {\n assert(component instanceof field_value_RefValue, 'Bound has a non-key value where the key path is being used.');\n comparison = document_key_DocumentKey.comparator(component.key, doc.key);\n } else {\n var docValue = doc.field(orderByComponent.field);\n assert(docValue !== undefined, 'Field should exist since document matched the orderBy already.');\n comparison = component.compareTo(docValue);\n }\n if (orderByComponent.dir === Direction.DESCENDING) {\n comparison = comparison * -1;\n }\n if (comparison !== 0) {\n break;\n }\n }\n return this.before ? comparison <= 0 : comparison < 0;\n };\n Bound.prototype.equals = function (other) {\n if (other === null) {\n return false;\n }\n if (this.before !== other.before || this.position.length !== other.position.length) {\n return false;\n }\n for (var i = 0; i < this.position.length; i++) {\n var thisPosition = this.position[i];\n var otherPosition = other.position[i];\n return thisPosition.equals(otherPosition);\n }\n return true;\n };\n return Bound;\n}();\n\n/**\r\n * An ordering on a field, in some Direction. Direction defaults to ASCENDING.\r\n */\nvar query_OrderBy = /** @class */function () {\n function OrderBy(field, dir) {\n this.field = field;\n if (dir === undefined) {\n dir = Direction.ASCENDING;\n }\n this.dir = dir;\n this.isKeyOrderBy = field.isKeyField();\n }\n OrderBy.prototype.compare = function (d1, d2) {\n var comparison = this.isKeyOrderBy ? document_Document.compareByKey(d1, d2) : document_Document.compareByField(this.field, d1, d2);\n switch (this.dir) {\n case Direction.ASCENDING:\n return comparison;\n case Direction.DESCENDING:\n return -1 * comparison;\n default:\n return fail('Unknown direction: ' + this.dir);\n }\n };\n OrderBy.prototype.canonicalId = function () {\n // TODO(b/29183165): Make this collision robust.\n return this.field.canonicalString() + this.dir.toString();\n };\n OrderBy.prototype.toString = function () {\n return this.field.canonicalString() + \" (\" + this.dir + \")\";\n };\n OrderBy.prototype.equals = function (other) {\n return this.dir === other.dir && this.field.equals(other.field);\n };\n return OrderBy;\n}();\n\nvar KEY_ORDERING_ASC = new query_OrderBy(path_FieldPath.keyField(), Direction.ASCENDING);\nvar KEY_ORDERING_DESC = new query_OrderBy(path_FieldPath.keyField(), Direction.DESCENDING);\n// CONCATENATED MODULE: ./src/firestore/core/timestamp.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n// A RegExp matching ISO 8601 UTC timestamps with optional fraction.\nvar isoRegExp = new RegExp(/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.(\\d+))?Z$/);\nvar timestamp_Timestamp = /** @class */function () {\n function Timestamp(seconds, nanos) {\n this.seconds = seconds;\n this.nanos = nanos;\n assert(nanos >= 0, 'timestamp nanoseconds out of range: ' + nanos);\n assert(nanos < 1e9, 'timestamp nanoseconds out of range' + nanos);\n // Midnight at the beginning of 1/1/1 is the earliest Firestore supports.\n assert(seconds >= -62135596800, 'timestamp seconds out of range: ' + seconds);\n // This will break in the year 10,000.\n assert(seconds < 253402300800, 'timestamp seconds out of range' + seconds);\n }\n Timestamp.now = function () {\n return Timestamp.fromEpochMilliseconds(Date.now());\n };\n Timestamp.fromDate = function (date) {\n return Timestamp.fromEpochMilliseconds(date.getTime());\n };\n Timestamp.fromEpochMilliseconds = function (milliseconds) {\n var seconds = Math.floor(milliseconds / 1000);\n var nanos = (milliseconds - seconds * 1000) * 1e6;\n return new Timestamp(seconds, nanos);\n };\n Timestamp.fromISOString = function (utc) {\n // The date string can have higher precision (nanos) than the Date class\n // (millis), so we do some custom parsing here.\n // Parse the nanos right out of the string.\n var nanos = 0;\n var fraction = isoRegExp.exec(utc);\n assert(!!fraction, 'invalid timestamp: ' + utc);\n if (fraction[1]) {\n // Pad the fraction out to 9 digits (nanos).\n var nanoStr = fraction[1];\n nanoStr = (nanoStr + '000000000').substr(0, 9);\n nanos = parseInt(nanoStr, 10);\n }\n // Parse the date to get the seconds.\n var date = new Date(utc);\n var seconds = Math.floor(date.getTime() / 1000);\n return new Timestamp(seconds, nanos);\n };\n Timestamp.prototype.toDate = function () {\n return new Date(this.toEpochMilliseconds());\n };\n Timestamp.prototype.toEpochMilliseconds = function () {\n return this.seconds * 1000 + this.nanos / 1e6;\n };\n Timestamp.prototype.compareTo = function (other) {\n if (this.seconds === other.seconds) {\n return primitiveComparator(this.nanos, other.nanos);\n }\n return primitiveComparator(this.seconds, other.seconds);\n };\n Timestamp.prototype.equals = function (other) {\n return other.seconds === this.seconds && other.nanos === this.nanos;\n };\n Timestamp.prototype.toString = function () {\n return 'Timestamp(seconds=' + this.seconds + ', nanos=' + this.nanos + ')';\n };\n return Timestamp;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/snapshot_version.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n/**\r\n * A version of a document in Firestore. This corresponds to the version\r\n * timestamp, such as update_time or read_time.\r\n */\nvar snapshot_version_SnapshotVersion = /** @class */function () {\n function SnapshotVersion(timestamp) {\n this.timestamp = timestamp;\n }\n // TODO(b/34176344): Once we no longer need to use the old alpha protos,\n // delete this constructor and use a timestamp-backed version everywhere.\n SnapshotVersion.fromMicroseconds = function (value) {\n var seconds = Math.floor(value / 1e6);\n var nanos = value % 1e6 * 1e3;\n return new SnapshotVersion(new timestamp_Timestamp(seconds, nanos));\n };\n SnapshotVersion.fromTimestamp = function (value) {\n return new SnapshotVersion(value);\n };\n SnapshotVersion.forDeletedDoc = function () {\n return SnapshotVersion.MIN;\n };\n SnapshotVersion.prototype.compareTo = function (other) {\n return this.timestamp.compareTo(other.timestamp);\n };\n SnapshotVersion.prototype.equals = function (other) {\n return this.timestamp.equals(other.timestamp);\n };\n /** Returns a number representation of the version for use in spec tests. */\n SnapshotVersion.prototype.toMicroseconds = function () {\n // Convert to microseconds.\n return this.timestamp.seconds * 1e6 + this.timestamp.nanos / 1000;\n };\n SnapshotVersion.prototype.toString = function () {\n return 'SnapshotVersion(' + this.timestamp.toString() + ')';\n };\n SnapshotVersion.prototype.toTimestamp = function () {\n return this.timestamp;\n };\n SnapshotVersion.MIN = new SnapshotVersion(new timestamp_Timestamp(0, 0));\n return SnapshotVersion;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/query_data.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/** An enumeration of the different purposes we have for queries. */\nvar QueryPurpose;\n(function (QueryPurpose) {\n /** A regular, normal query. */\n QueryPurpose[QueryPurpose[\"Listen\"] = 0] = \"Listen\";\n /**\r\n * The query was used to refill a query after an existence filter mismatch.\r\n */\n QueryPurpose[QueryPurpose[\"ExistenceFilterMismatch\"] = 1] = \"ExistenceFilterMismatch\";\n /** The query was used to resolve a limbo document. */\n QueryPurpose[QueryPurpose[\"LimboResolution\"] = 2] = \"LimboResolution\";\n})(QueryPurpose || (QueryPurpose = {}));\n/**\r\n * An immutable set of metadata that the local store tracks for each query.\r\n */\nvar query_data_QueryData = /** @class */function () {\n function QueryData(\n /** The query being listened to. */\n query,\n /**\r\n * The target ID to which the query corresponds; Assigned by the\r\n * LocalStore for user listens and by the SyncEngine for limbo watches.\r\n */\n targetId,\n /** The purpose of the query. */\n purpose,\n /** The latest snapshot version seen for this target. */\n snapshotVersion,\n /**\r\n * An opaque, server-assigned token that allows watching a query to be\r\n * resumed after disconnecting without retransmitting all the data that\r\n * matches the query. The resume token essentially identifies a point in\r\n * time from which the server should resume sending results.\r\n */\n resumeToken) {\n if (snapshotVersion === void 0) {\n snapshotVersion = snapshot_version_SnapshotVersion.MIN;\n }\n if (resumeToken === void 0) {\n resumeToken = emptyByteString();\n }\n this.query = query;\n this.targetId = targetId;\n this.purpose = purpose;\n this.snapshotVersion = snapshotVersion;\n this.resumeToken = resumeToken;\n }\n /**\r\n * Creates a new query data instance with an updated snapshot version and\r\n * resume token.\r\n */\n QueryData.prototype.update = function (updated) {\n return new QueryData(this.query, this.targetId, this.purpose, updated.snapshotVersion, updated.resumeToken);\n };\n QueryData.prototype.equals = function (other) {\n return this.targetId === other.targetId && this.purpose === other.purpose && this.snapshotVersion.equals(other.snapshotVersion) && this.resumeToken === other.resumeToken && this.query.equals(other.query);\n };\n return QueryData;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/model/mutation.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar mutation___extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n/**\r\n * Provides a set of fields that can be used to partially patch a document.\r\n * FieldMask is used in conjunction with ObjectValue.\r\n * Examples:\r\n * foo - Overwrites foo entirely with the provided value. If foo is not\r\n * present in the companion ObjectValue, the field is deleted.\r\n * foo.bar - Overwrites only the field bar of the object foo.\r\n * If foo is not an object, foo is replaced with an object\r\n * containing foo\r\n */\nvar mutation_FieldMask = /** @class */function () {\n function FieldMask(fields) {\n this.fields = fields;\n // TODO(dimond): validation of FieldMask\n }\n FieldMask.prototype.equals = function (other) {\n return arrayEquals(this.fields, other.fields);\n };\n return FieldMask;\n}();\n\n/** Transforms a value into a server-generated timestamp. */\nvar ServerTimestampTransform = /** @class */function () {\n function ServerTimestampTransform() {}\n ServerTimestampTransform.prototype.equals = function (other) {\n return other instanceof ServerTimestampTransform;\n };\n ServerTimestampTransform.instance = new ServerTimestampTransform();\n return ServerTimestampTransform;\n}();\n\n/** A field path and the TransformOperation to perform upon it. */\nvar FieldTransform = /** @class */function () {\n function FieldTransform(field, transform) {\n this.field = field;\n this.transform = transform;\n }\n FieldTransform.prototype.equals = function (other) {\n return this.field.equals(other.field) && this.transform.equals(other.transform);\n };\n return FieldTransform;\n}();\n\n/** The result of successfully applying a mutation to the backend. */\nvar MutationResult = /** @class */function () {\n function MutationResult(\n /**\r\n * The version at which the mutation was committed or null for a delete.\r\n */\n version,\n /**\r\n * The resulting fields returned from the backend after a\r\n * TransformMutation has been committed. Contains one FieldValue for each\r\n * FieldTransform that was in the mutation.\r\n *\r\n * Will be null if the mutation was not a TransformMutation.\r\n */\n transformResults) {\n this.version = version;\n this.transformResults = transformResults;\n }\n return MutationResult;\n}();\n\nvar MutationType;\n(function (MutationType) {\n MutationType[MutationType[\"Set\"] = 0] = \"Set\";\n MutationType[MutationType[\"Patch\"] = 1] = \"Patch\";\n MutationType[MutationType[\"Transform\"] = 2] = \"Transform\";\n MutationType[MutationType[\"Delete\"] = 3] = \"Delete\";\n})(MutationType || (MutationType = {}));\n/**\r\n * Encodes a precondition for a mutation. This follows the model that the\r\n * backend accepts with the special case of an explicit \"empty\" precondition\r\n * (meaning no precondition).\r\n */\nvar mutation_Precondition = /** @class */function () {\n function Precondition(updateTime, exists) {\n this.updateTime = updateTime;\n this.exists = exists;\n assert(updateTime === undefined || exists === undefined, 'Precondition can specify \"exists\" or \"updateTime\" but not both');\n }\n /** Creates a new Precondition with an exists flag. */\n Precondition.exists = function (exists) {\n return new Precondition(undefined, exists);\n };\n /** Creates a new Precondition based on a version a document exists at. */\n Precondition.updateTime = function (version) {\n return new Precondition(version);\n };\n Object.defineProperty(Precondition.prototype, \"isNone\", {\n /** Returns whether this Precondition is empty. */\n get: function get() {\n return this.updateTime === undefined && this.exists === undefined;\n },\n enumerable: true,\n configurable: true\n });\n /**\r\n * Returns true if the preconditions is valid for the given document\r\n * (or null if no document is available).\r\n */\n Precondition.prototype.isValidFor = function (maybeDoc) {\n if (this.updateTime !== undefined) {\n return maybeDoc instanceof document_Document && maybeDoc.version.equals(this.updateTime);\n } else if (this.exists !== undefined) {\n if (this.exists) {\n return maybeDoc instanceof document_Document;\n } else {\n return maybeDoc === null || maybeDoc instanceof document_NoDocument;\n }\n } else {\n assert(this.isNone, 'Precondition should be empty');\n return true;\n }\n };\n Precondition.prototype.equals = function (other) {\n return equals(this.updateTime, other.updateTime) && this.exists === other.exists;\n };\n Precondition.NONE = new Precondition();\n return Precondition;\n}();\n\n/**\r\n * A mutation describes a self-contained change to a document. Mutations can\r\n * create, replace, delete, and update subsets of documents.\r\n *\r\n * Mutations not only act on the value of the document but also it version.\r\n * In the case of Set, Patch, and Transform mutations we preserve the existing\r\n * version. In the case of Delete mutations, we reset the version to 0.\r\n *\r\n * Here's the expected transition table.\r\n *\r\n * MUTATION APPLIED TO RESULTS IN\r\n *\r\n * SetMutation Document(v3) Document(v3)\r\n * SetMutation NoDocument(v3) Document(v0)\r\n * SetMutation null Document(v0)\r\n * PatchMutation Document(v3) Document(v3)\r\n * PatchMutation NoDocument(v3) NoDocument(v3)\r\n * PatchMutation null null\r\n * TransformMutation Document(v3) Document(v3)\r\n * TransformMutation NoDocument(v3) NoDocument(v3)\r\n * TransformMutation null null\r\n * DeleteMutation Document(v3) NoDocument(v0)\r\n * DeleteMutation NoDocument(v3) NoDocument(v0)\r\n * DeleteMutation null NoDocument(v0)\r\n *\r\n * Note that TransformMutations don't create Documents (in the case of being\r\n * applied to a NoDocument), even though they would on the backend. This is\r\n * because the client always combines the TransformMutation with a SetMutation\r\n * or PatchMutation and we only want to apply the transform if the prior\r\n * mutation resulted in a Document (always true for a SetMutation, but not\r\n * necessarily for a PatchMutation).\r\n *\r\n * ## Subclassing Notes\r\n *\r\n * Subclasses of Mutation need to implement applyToRemoteDocument() and\r\n * applyToLocalView() to implement the actual behavior of applying the mutation\r\n * to some source document.\r\n */\nvar mutation_Mutation = /** @class */function () {\n function Mutation() {}\n Mutation.prototype.verifyKeyMatches = function (maybeDoc) {\n if (maybeDoc != null) {\n assert(maybeDoc.key.equals(this.key), 'Can only apply a mutation to a document with the same key');\n }\n };\n /**\r\n * Returns the version from the given document for use as the result of a\r\n * mutation. Mutations are defined to return the version of the base document\r\n * only if it is an existing document. Deleted and unknown documents have a\r\n * post-mutation version of SnapshotVersion.MIN.\r\n */\n Mutation.getPostMutationVersion = function (maybeDoc) {\n if (maybeDoc instanceof document_Document) {\n return maybeDoc.version;\n } else {\n return snapshot_version_SnapshotVersion.MIN;\n }\n };\n return Mutation;\n}();\n\n/**\r\n * A mutation that creates or replaces the document at the given key with the\r\n * object value contents.\r\n */\nvar mutation_SetMutation = /** @class */function (_super) {\n mutation___extends(SetMutation, _super);\n function SetMutation(key, value, precondition) {\n var _this = _super.call(this) || this;\n _this.key = key;\n _this.value = value;\n _this.precondition = precondition;\n _this.type = MutationType.Set;\n return _this;\n }\n SetMutation.prototype.applyToRemoteDocument = function (maybeDoc, mutationResult) {\n this.verifyKeyMatches(maybeDoc);\n assert(mutationResult.transformResults == null, 'Transform results received by SetMutation.');\n // Unlike applyToLocalView, if we're applying a mutation to a remote\n // document the server has accepted the mutation so the precondition must\n // have held.\n var version = mutation_Mutation.getPostMutationVersion(maybeDoc);\n return new document_Document(this.key, version, this.value, {\n hasLocalMutations: false\n });\n };\n SetMutation.prototype.applyToLocalView = function (maybeDoc, localWriteTime) {\n this.verifyKeyMatches(maybeDoc);\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n var version = mutation_Mutation.getPostMutationVersion(maybeDoc);\n return new document_Document(this.key, version, this.value, {\n hasLocalMutations: true\n });\n };\n SetMutation.prototype.equals = function (other) {\n return other instanceof SetMutation && this.key.equals(other.key) && this.value.equals(other.value) && this.precondition.equals(other.precondition);\n };\n return SetMutation;\n}(mutation_Mutation);\n\n/**\r\n * A mutation that modifies fields of the document at the given key with the\r\n * given values. The values are applied through a field mask:\r\n *\r\n * * When a field is in both the mask and the values, the corresponding field\r\n * is updated.\r\n * * When a field is in neither the mask nor the values, the corresponding\r\n * field is unmodified.\r\n * * When a field is in the mask but not in the values, the corresponding field\r\n * is deleted.\r\n * * When a field is not in the mask but is in the values, the values map is\r\n * ignored.\r\n */\nvar mutation_PatchMutation = /** @class */function (_super) {\n mutation___extends(PatchMutation, _super);\n function PatchMutation(key, data, fieldMask, precondition) {\n var _this = _super.call(this) || this;\n _this.key = key;\n _this.data = data;\n _this.fieldMask = fieldMask;\n _this.precondition = precondition;\n _this.type = MutationType.Patch;\n return _this;\n }\n PatchMutation.prototype.applyToRemoteDocument = function (maybeDoc, mutationResult) {\n this.verifyKeyMatches(maybeDoc);\n assert(mutationResult.transformResults == null, 'Transform results received by PatchMutation.');\n // TODO(mcg): Relax enforcement of this precondition\n //\n // We shouldn't actually enforce the precondition since it already passed on\n // the backend, but we may not have a local version of the document to\n // patch, so we use the precondition to prevent incorrectly putting a\n // partial document into our cache.\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n var version = mutation_Mutation.getPostMutationVersion(maybeDoc);\n var newData = this.patchDocument(maybeDoc);\n return new document_Document(this.key, version, newData, {\n hasLocalMutations: false\n });\n };\n PatchMutation.prototype.applyToLocalView = function (maybeDoc, localWriteTime) {\n this.verifyKeyMatches(maybeDoc);\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n var version = mutation_Mutation.getPostMutationVersion(maybeDoc);\n var newData = this.patchDocument(maybeDoc);\n return new document_Document(this.key, version, newData, {\n hasLocalMutations: true\n });\n };\n PatchMutation.prototype.equals = function (other) {\n return other instanceof PatchMutation && this.key.equals(other.key) && this.fieldMask.equals(other.fieldMask) && this.precondition.equals(other.precondition);\n };\n /**\r\n * Patches the data of document if available or creates a new document. Note\r\n * that this does not check whether or not the precondition of this patch\r\n * holds.\r\n */\n PatchMutation.prototype.patchDocument = function (maybeDoc) {\n var data;\n if (maybeDoc instanceof document_Document) {\n data = maybeDoc.data;\n } else {\n data = field_value_ObjectValue.EMPTY;\n }\n return this.patchObject(data);\n };\n PatchMutation.prototype.patchObject = function (data) {\n for (var _i = 0, _a = this.fieldMask.fields; _i < _a.length; _i++) {\n var fieldPath = _a[_i];\n var newValue = this.data.field(fieldPath);\n if (newValue !== undefined) {\n data = data.set(fieldPath, newValue);\n } else {\n data = data.delete(fieldPath);\n }\n }\n return data;\n };\n return PatchMutation;\n}(mutation_Mutation);\n\n/**\r\n * A mutation that modifies specific fields of the document with transform\r\n * operations. Currently the only supported transform is a server timestamp, but\r\n * IP Address, increment(n), etc. could be supported in the future.\r\n *\r\n * It is somewhat similar to a PatchMutation in that it patches specific fields\r\n * and has no effect when applied to a null or NoDocument (see comment on\r\n * Mutation for rationale).\r\n */\nvar mutation_TransformMutation = /** @class */function (_super) {\n mutation___extends(TransformMutation, _super);\n function TransformMutation(key, fieldTransforms) {\n var _this = _super.call(this) || this;\n _this.key = key;\n _this.fieldTransforms = fieldTransforms;\n _this.type = MutationType.Transform;\n // NOTE: We set a precondition of exists: true as a safety-check, since we\n // always combine TransformMutations with a SetMutation or PatchMutation which\n // (if successful) should end up with an existing document.\n _this.precondition = mutation_Precondition.exists(true);\n return _this;\n }\n TransformMutation.prototype.applyToRemoteDocument = function (maybeDoc, mutationResult) {\n this.verifyKeyMatches(maybeDoc);\n assert(mutationResult.transformResults != null, 'Transform results missing for TransformMutation.');\n var transformResults = mutationResult.transformResults;\n // TODO(mcg): Relax enforcement of this precondition\n //\n // We shouldn't actually enforce the precondition since it already passed on\n // the backend, but we may not have a local version of the document to\n // patch, so we use the precondition to prevent incorrectly putting a\n // partial document into our cache.\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n var doc = this.requireDocument(maybeDoc);\n var newData = this.transformObject(doc.data, transformResults);\n return new document_Document(this.key, doc.version, newData, {\n hasLocalMutations: false\n });\n };\n TransformMutation.prototype.applyToLocalView = function (maybeDoc, localWriteTime) {\n this.verifyKeyMatches(maybeDoc);\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n var doc = this.requireDocument(maybeDoc);\n var transformResults = this.localTransformResults(localWriteTime);\n var newData = this.transformObject(doc.data, transformResults);\n return new document_Document(this.key, doc.version, newData, {\n hasLocalMutations: true\n });\n };\n TransformMutation.prototype.equals = function (other) {\n return other instanceof TransformMutation && this.key.equals(other.key) && arrayEquals(this.fieldTransforms, other.fieldTransforms) && this.precondition.equals(other.precondition);\n };\n /**\r\n * Asserts that the given MaybeDocument is actually a Document and verifies\r\n * that it matches the key for this mutation. Since we only support\r\n * transformations with precondition exists this method is guaranteed to be\r\n * safe.\r\n */\n TransformMutation.prototype.requireDocument = function (maybeDoc) {\n assert(maybeDoc instanceof document_Document, 'Unknown MaybeDocument type ' + maybeDoc);\n var doc = maybeDoc;\n assert(doc.key.equals(this.key), 'Can only transform a document with the same key');\n return doc;\n };\n /**\r\n * Creates a list of \"transform results\" (a transform result is a field value\r\n * representing the result of applying a transform) for use when applying a\r\n * TransformMutation locally.\r\n *\r\n * @param localWriteTime The local time of the transform mutation (used to\r\n * generate ServerTimestampValues).\r\n * @return The transform results list.\r\n */\n TransformMutation.prototype.localTransformResults = function (localWriteTime) {\n var transformResults = [];\n for (var _i = 0, _a = this.fieldTransforms; _i < _a.length; _i++) {\n var fieldTransform = _a[_i];\n var transform = fieldTransform.transform;\n if (transform instanceof ServerTimestampTransform) {\n transformResults.push(new ServerTimestampValue(localWriteTime));\n } else {\n return fail('Encountered unknown transform: ' + transform);\n }\n }\n return transformResults;\n };\n TransformMutation.prototype.transformObject = function (data, transformResults) {\n assert(transformResults.length === this.fieldTransforms.length, 'TransformResults length mismatch.');\n for (var i = 0; i < this.fieldTransforms.length; i++) {\n var fieldTransform = this.fieldTransforms[i];\n var transform = fieldTransform.transform;\n var fieldPath = fieldTransform.field;\n if (transform instanceof ServerTimestampTransform) {\n data = data.set(fieldPath, transformResults[i]);\n } else {\n return fail('Encountered unknown transform: ' + transform);\n }\n }\n return data;\n };\n return TransformMutation;\n}(mutation_Mutation);\n\n/** A mutation that deletes the document at the given key. */\nvar mutation_DeleteMutation = /** @class */function (_super) {\n mutation___extends(DeleteMutation, _super);\n function DeleteMutation(key, precondition) {\n var _this = _super.call(this) || this;\n _this.key = key;\n _this.precondition = precondition;\n _this.type = MutationType.Delete;\n return _this;\n }\n DeleteMutation.prototype.applyToRemoteDocument = function (maybeDoc, mutationResult) {\n this.verifyKeyMatches(maybeDoc);\n assert(mutationResult.transformResults == null, 'Transform results received by DeleteMutation.');\n // Unlike applyToLocalView, if we're applying a mutation to a remote\n // document the server has accepted the mutation so the precondition must\n // have held.\n return new document_NoDocument(this.key, snapshot_version_SnapshotVersion.MIN);\n };\n DeleteMutation.prototype.applyToLocalView = function (maybeDoc, localWriteTime) {\n this.verifyKeyMatches(maybeDoc);\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n if (maybeDoc) {\n assert(maybeDoc.key.equals(this.key), 'Can only apply mutation to document with same key');\n }\n return new document_NoDocument(this.key, snapshot_version_SnapshotVersion.forDeletedDoc());\n };\n DeleteMutation.prototype.equals = function (other) {\n return other instanceof DeleteMutation && this.key.equals(other.key) && this.precondition.equals(other.precondition);\n };\n return DeleteMutation;\n}(mutation_Mutation);\n\n// CONCATENATED MODULE: ./src/firestore/remote/existence_filter.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar ExistenceFilter = /** @class */function () {\n // TODO(b/33078163): just use simplest form of existence filter for now\n function ExistenceFilter(count) {\n this.count = count;\n }\n ExistenceFilter.prototype.equals = function (other) {\n return other && other.count === this.count;\n };\n return ExistenceFilter;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/remote/rpc_error.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * Error Codes describing the different ways GRPC can fail. These are copied\r\n * directly from GRPC's sources here:\r\n *\r\n * https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h\r\n *\r\n * Important! The names of these identifiers matter because the string forms\r\n * are used for reverse lookups from the webchannel stream. Do NOT change the\r\n * names of these identifiers.\r\n */\nvar RpcCode;\n(function (RpcCode) {\n RpcCode[RpcCode[\"OK\"] = 0] = \"OK\";\n RpcCode[RpcCode[\"CANCELLED\"] = 1] = \"CANCELLED\";\n RpcCode[RpcCode[\"UNKNOWN\"] = 2] = \"UNKNOWN\";\n RpcCode[RpcCode[\"INVALID_ARGUMENT\"] = 3] = \"INVALID_ARGUMENT\";\n RpcCode[RpcCode[\"DEADLINE_EXCEEDED\"] = 4] = \"DEADLINE_EXCEEDED\";\n RpcCode[RpcCode[\"NOT_FOUND\"] = 5] = \"NOT_FOUND\";\n RpcCode[RpcCode[\"ALREADY_EXISTS\"] = 6] = \"ALREADY_EXISTS\";\n RpcCode[RpcCode[\"PERMISSION_DENIED\"] = 7] = \"PERMISSION_DENIED\";\n RpcCode[RpcCode[\"UNAUTHENTICATED\"] = 16] = \"UNAUTHENTICATED\";\n RpcCode[RpcCode[\"RESOURCE_EXHAUSTED\"] = 8] = \"RESOURCE_EXHAUSTED\";\n RpcCode[RpcCode[\"FAILED_PRECONDITION\"] = 9] = \"FAILED_PRECONDITION\";\n RpcCode[RpcCode[\"ABORTED\"] = 10] = \"ABORTED\";\n RpcCode[RpcCode[\"OUT_OF_RANGE\"] = 11] = \"OUT_OF_RANGE\";\n RpcCode[RpcCode[\"UNIMPLEMENTED\"] = 12] = \"UNIMPLEMENTED\";\n RpcCode[RpcCode[\"INTERNAL\"] = 13] = \"INTERNAL\";\n RpcCode[RpcCode[\"UNAVAILABLE\"] = 14] = \"UNAVAILABLE\";\n RpcCode[RpcCode[\"DATA_LOSS\"] = 15] = \"DATA_LOSS\";\n})(RpcCode || (RpcCode = {}));\nfunction isPermanentError(code) {\n switch (code) {\n case Code.OK:\n return fail('Treated status OK as error');\n case Code.CANCELLED:\n case Code.UNKNOWN:\n case Code.DEADLINE_EXCEEDED:\n case Code.RESOURCE_EXHAUSTED:\n case Code.INTERNAL:\n case Code.UNAVAILABLE:\n // Unauthenticated means something went wrong with our token and we need\n // to retry with new credentials which will happen automatically.\n // TODO(b/37325376): Give up after second unauthenticated error.\n case Code.UNAUTHENTICATED:\n return false;\n case Code.INVALID_ARGUMENT:\n case Code.NOT_FOUND:\n case Code.ALREADY_EXISTS:\n case Code.PERMISSION_DENIED:\n case Code.FAILED_PRECONDITION:\n // Aborted might be retried in some scenarios, but that is dependant on\n // the context and should handled individually by the calling code.\n // See https://cloud.google.com/apis/design/errors.\n case Code.ABORTED:\n case Code.OUT_OF_RANGE:\n case Code.UNIMPLEMENTED:\n case Code.DATA_LOSS:\n return true;\n default:\n return fail('Unknown status code: ' + code);\n }\n}\n/**\r\n * Maps an error Code from a GRPC status identifier like 'NOT_FOUND'.\r\n *\r\n * @returns The Code equivalent to the given status string or undefined if\r\n * there is no match.\r\n */\nfunction mapCodeFromRpcStatus(status) {\n // tslint:disable-next-line:no-any lookup by string\n var code = RpcCode[status];\n if (code === undefined) {\n return undefined;\n }\n return mapCodeFromRpcCode(code);\n}\n/**\r\n * Maps an error Code from GRPC status code number, like 0, 1, or 14. These\r\n * are not the same as HTTP status codes.\r\n *\r\n * @returns The Code equivalent to the given GRPC status code. Fails if there\r\n * is no match.\r\n */\nfunction mapCodeFromRpcCode(code) {\n switch (code) {\n case RpcCode.OK:\n return Code.OK;\n case RpcCode.CANCELLED:\n return Code.CANCELLED;\n case RpcCode.UNKNOWN:\n return Code.UNKNOWN;\n case RpcCode.DEADLINE_EXCEEDED:\n return Code.DEADLINE_EXCEEDED;\n case RpcCode.RESOURCE_EXHAUSTED:\n return Code.RESOURCE_EXHAUSTED;\n case RpcCode.INTERNAL:\n return Code.INTERNAL;\n case RpcCode.UNAVAILABLE:\n return Code.UNAVAILABLE;\n case RpcCode.UNAUTHENTICATED:\n return Code.UNAUTHENTICATED;\n case RpcCode.INVALID_ARGUMENT:\n return Code.INVALID_ARGUMENT;\n case RpcCode.NOT_FOUND:\n return Code.NOT_FOUND;\n case RpcCode.ALREADY_EXISTS:\n return Code.ALREADY_EXISTS;\n case RpcCode.PERMISSION_DENIED:\n return Code.PERMISSION_DENIED;\n case RpcCode.FAILED_PRECONDITION:\n return Code.FAILED_PRECONDITION;\n case RpcCode.ABORTED:\n return Code.ABORTED;\n case RpcCode.OUT_OF_RANGE:\n return Code.OUT_OF_RANGE;\n case RpcCode.UNIMPLEMENTED:\n return Code.UNIMPLEMENTED;\n case RpcCode.DATA_LOSS:\n return Code.DATA_LOSS;\n default:\n return fail('Unknown status code: ' + code);\n }\n}\n/**\r\n * Maps an RPC code from a Code. This is the reverse operation from\r\n * mapCodeFromRpcCode and should really only be used in tests.\r\n */\nfunction mapRpcCodeFromCode(code) {\n if (code === undefined) {\n return RpcCode.OK;\n }\n switch (code) {\n case Code.OK:\n return RpcCode.OK;\n case Code.CANCELLED:\n return RpcCode.CANCELLED;\n case Code.UNKNOWN:\n return RpcCode.UNKNOWN;\n case Code.DEADLINE_EXCEEDED:\n return RpcCode.DEADLINE_EXCEEDED;\n case Code.RESOURCE_EXHAUSTED:\n return RpcCode.RESOURCE_EXHAUSTED;\n case Code.INTERNAL:\n return RpcCode.INTERNAL;\n case Code.UNAVAILABLE:\n return RpcCode.UNAVAILABLE;\n case Code.UNAUTHENTICATED:\n return RpcCode.UNAUTHENTICATED;\n case Code.INVALID_ARGUMENT:\n return RpcCode.INVALID_ARGUMENT;\n case Code.NOT_FOUND:\n return RpcCode.NOT_FOUND;\n case Code.ALREADY_EXISTS:\n return RpcCode.ALREADY_EXISTS;\n case Code.PERMISSION_DENIED:\n return RpcCode.PERMISSION_DENIED;\n case Code.FAILED_PRECONDITION:\n return RpcCode.FAILED_PRECONDITION;\n case Code.ABORTED:\n return RpcCode.ABORTED;\n case Code.OUT_OF_RANGE:\n return RpcCode.OUT_OF_RANGE;\n case Code.UNIMPLEMENTED:\n return RpcCode.UNIMPLEMENTED;\n case Code.DATA_LOSS:\n return RpcCode.DATA_LOSS;\n default:\n return fail('Unknown status code: ' + code);\n }\n}\n/**\r\n * Converts an HTTP Status Code to the equivalent error code.\r\n *\r\n * @param status An HTTP Status Code, like 200, 404, 503, etc.\r\n * @returns The equivalent Code. Unknown status codes are mapped to\r\n * Code.UNKNOWN.\r\n */\nfunction mapCodeFromHttpStatus(status) {\n // The canonical error codes for Google APIs [1] specify mapping onto HTTP\n // status codes but the mapping is not bijective. In each case of ambiguity\n // this function chooses a primary error.\n //\n // [1]\n // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto\n switch (status) {\n case 200:\n // OK\n return Code.OK;\n case 400:\n // Bad Request\n return Code.INVALID_ARGUMENT;\n // Other possibilities based on the forward mapping\n // return Code.FAILED_PRECONDITION;\n // return Code.OUT_OF_RANGE;\n case 401:\n // Unauthorized\n return Code.UNAUTHENTICATED;\n case 403:\n // Forbidden\n return Code.PERMISSION_DENIED;\n case 404:\n // Not Found\n return Code.NOT_FOUND;\n case 409:\n // Conflict\n return Code.ABORTED;\n // Other possibilities:\n // return Code.ALREADY_EXISTS;\n case 416:\n // Range Not Satisfiable\n return Code.OUT_OF_RANGE;\n case 429:\n // Too Many Requests\n return Code.RESOURCE_EXHAUSTED;\n case 499:\n // Client Closed Request\n return Code.CANCELLED;\n case 500:\n // Internal Server Error\n return Code.UNKNOWN;\n // Other possibilities:\n // return Code.INTERNAL;\n // return Code.DATA_LOSS;\n case 501:\n // Unimplemented\n return Code.UNIMPLEMENTED;\n case 503:\n // Service Unavailable\n return Code.UNAVAILABLE;\n case 504:\n // Gateway Timeout\n return Code.DEADLINE_EXCEEDED;\n default:\n if (status >= 200 && status < 300) return Code.OK;\n if (status >= 400 && status < 500) return Code.FAILED_PRECONDITION;\n if (status >= 500 && status < 600) return Code.INTERNAL;\n return Code.UNKNOWN;\n }\n}\n// CONCATENATED MODULE: ./src/firestore/util/sorted_set.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n/**\r\n * SortedSet is an immutable (copy-on-write) collection that holds elements\r\n * in order specified by the provided comparator.\r\n *\r\n * NOTE: if provided comparator returns 0 for two elements, we consider them to\r\n * be equal!\r\n */\nvar sorted_set_SortedSet = /** @class */function () {\n function SortedSet(comparator) {\n this.comparator = comparator;\n this.data = new sorted_map_SortedMap(this.comparator);\n }\n /**\r\n * Creates a SortedSet from the keys of the map.\r\n * This is currently implemented as an O(n) copy.\r\n */\n SortedSet.fromMapKeys = function (map) {\n var keys = new SortedSet(map.comparator);\n map.forEach(function (key) {\n keys = keys.add(key);\n });\n return keys;\n };\n SortedSet.prototype.has = function (elem) {\n return this.data.get(elem) !== null;\n };\n SortedSet.prototype.first = function () {\n return this.data.minKey();\n };\n SortedSet.prototype.last = function () {\n return this.data.maxKey();\n };\n Object.defineProperty(SortedSet.prototype, \"size\", {\n get: function get() {\n return this.data.size;\n },\n enumerable: true,\n configurable: true\n });\n SortedSet.prototype.indexOf = function (elem) {\n return this.data.indexOf(elem);\n };\n /** Iterates elements in order defined by \"comparator\" */\n SortedSet.prototype.forEach = function (cb) {\n this.data.inorderTraversal(function (k, v) {\n cb(k);\n return false;\n });\n };\n /** Iterates over `elem`s such that: range[0] <= elem < range[1]. */\n SortedSet.prototype.forEachInRange = function (range, cb) {\n var iter = this.data.getIteratorFrom(range[0]);\n while (iter.hasNext()) {\n var elem = iter.getNext();\n if (this.comparator(elem.key, range[1]) >= 0) return;\n cb(elem.key);\n }\n };\n /**\r\n * Iterates over `elem`s such that: start <= elem until false is returned.\r\n */\n SortedSet.prototype.forEachWhile = function (cb, start) {\n var iter;\n if (start !== undefined) {\n iter = this.data.getIteratorFrom(start);\n } else {\n iter = this.data.getIterator();\n }\n while (iter.hasNext()) {\n var elem = iter.getNext();\n var result = cb(elem.key);\n if (!result) return;\n }\n };\n /** Finds the least element greater than or equal to `elem`. */\n SortedSet.prototype.firstAfterOrEqual = function (elem) {\n var iter = this.data.getIteratorFrom(elem);\n return iter.hasNext() ? iter.getNext().key : null;\n };\n /** Inserts or updates an element */\n SortedSet.prototype.add = function (elem) {\n return this.copy(this.data.remove(elem).insert(elem, true));\n };\n /** Deletes an element */\n SortedSet.prototype.delete = function (elem) {\n if (!this.has(elem)) return this;\n return this.copy(this.data.remove(elem));\n };\n SortedSet.prototype.isEmpty = function () {\n return this.data.isEmpty();\n };\n SortedSet.prototype.unionWith = function (other) {\n var result = this;\n other.forEach(function (elem) {\n result = result.add(elem);\n });\n return result;\n };\n SortedSet.prototype.equals = function (other) {\n if (!(other instanceof SortedSet)) return false;\n if (this.size !== other.size) return false;\n var thisIt = this.data.getIterator();\n var otherIt = other.data.getIterator();\n while (thisIt.hasNext()) {\n var thisElem = thisIt.getNext().key;\n var otherElem = otherIt.getNext().key;\n if (this.comparator(thisElem, otherElem) !== 0) return false;\n }\n return true;\n };\n SortedSet.prototype.toString = function () {\n var result = [];\n this.forEach(function (elem) {\n return result.push(elem);\n });\n return 'SortedSet(' + result.toString() + ')';\n };\n SortedSet.prototype.copy = function (data) {\n var result = new SortedSet(this.comparator);\n result.data = data;\n return result;\n };\n return SortedSet;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/model/collections.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\nvar EMPTY_MAYBE_DOCUMENT_MAP = new sorted_map_SortedMap(document_key_DocumentKey.comparator);\nfunction maybeDocumentMap() {\n return EMPTY_MAYBE_DOCUMENT_MAP;\n}\nvar EMPTY_DOCUMENT_MAP = new sorted_map_SortedMap(document_key_DocumentKey.comparator);\nfunction documentMap() {\n return EMPTY_DOCUMENT_MAP;\n}\nvar EMPTY_DOCUMENT_VERSION_MAP = new sorted_map_SortedMap(document_key_DocumentKey.comparator);\nfunction documentVersionMap() {\n return EMPTY_DOCUMENT_VERSION_MAP;\n}\nvar EMPTY_DOCUMENT_KEY_SET = new sorted_set_SortedSet(document_key_DocumentKey.comparator);\nfunction documentKeySet() {\n return EMPTY_DOCUMENT_KEY_SET;\n}\n// CONCATENATED MODULE: ./src/firestore/remote/remote_event.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n/**\r\n * An event from the RemoteStore. It is split into targetChanges (changes to the\r\n * state or the set of documents in our watched targets) and documentUpdates\r\n * (changes to the actual documents).\r\n */\nvar remote_event_RemoteEvent = /** @class */function () {\n function RemoteEvent(\n /**\r\n * The snapshot version this event brings us up to, or MIN if not set.\r\n */\n snapshotVersion,\n /**\r\n * A map from target to changes to the target. See TargetChange.\r\n */\n targetChanges,\n /**\r\n * A set of which documents have changed or been deleted, along with the\r\n * doc's new values (if not deleted).\r\n */\n documentUpdates) {\n this.snapshotVersion = snapshotVersion;\n this.targetChanges = targetChanges;\n this.documentUpdates = documentUpdates;\n }\n RemoteEvent.prototype.addDocumentUpdate = function (doc) {\n this.documentUpdates = this.documentUpdates.insert(doc.key, doc);\n };\n RemoteEvent.prototype.handleExistenceFilterMismatch = function (targetId) {\n /*\r\n * An existence filter mismatch will reset the query and we need to reset\r\n * the mapping to contain no documents and an empty resume token.\r\n *\r\n * Note:\r\n * * The reset mapping is empty, specifically forcing the consumer of the\r\n * change to forget all keys for this targetID;\r\n * * The resume snapshot for this target must be reset\r\n * * The target must be unacked because unwatching and rewatching\r\n * introduces a race for changes.\r\n */\n this.targetChanges[targetId] = {\n mapping: new ResetMapping(),\n snapshotVersion: snapshot_version_SnapshotVersion.MIN,\n currentStatusUpdate: CurrentStatusUpdate.MarkNotCurrent,\n resumeToken: emptyByteString()\n };\n };\n return RemoteEvent;\n}();\n\n/**\r\n * Represents an update to the current status of a target, either explicitly\r\n * having no new state, or the new value to set. Note \"current\" has special\r\n * meaning for in the RPC protocol that implies that a target is both up-to-date\r\n * and consistent with the rest of the watch stream.\r\n */\nvar CurrentStatusUpdate;\n(function (CurrentStatusUpdate) {\n /** The current status is not affected and should not be modified. */\n CurrentStatusUpdate[CurrentStatusUpdate[\"None\"] = 0] = \"None\";\n /** The target must be marked as no longer \"current\". */\n CurrentStatusUpdate[CurrentStatusUpdate[\"MarkNotCurrent\"] = 1] = \"MarkNotCurrent\";\n /** The target must be marked as \"current\". */\n CurrentStatusUpdate[CurrentStatusUpdate[\"MarkCurrent\"] = 2] = \"MarkCurrent\";\n})(CurrentStatusUpdate || (CurrentStatusUpdate = {}));\nvar EMPTY_KEY_SET = documentKeySet();\nvar ResetMapping = /** @class */function () {\n function ResetMapping() {\n this.docs = EMPTY_KEY_SET;\n }\n Object.defineProperty(ResetMapping.prototype, \"documents\", {\n get: function get() {\n return this.docs;\n },\n enumerable: true,\n configurable: true\n });\n ResetMapping.prototype.add = function (key) {\n this.docs = this.docs.add(key);\n };\n ResetMapping.prototype.delete = function (key) {\n this.docs = this.docs.delete(key);\n };\n ResetMapping.prototype.equals = function (other) {\n return other !== null && this.docs.equals(other.docs);\n };\n return ResetMapping;\n}();\n\nvar UpdateMapping = /** @class */function () {\n function UpdateMapping() {\n this.addedDocuments = EMPTY_KEY_SET;\n this.removedDocuments = EMPTY_KEY_SET;\n }\n UpdateMapping.prototype.applyToKeySet = function (keys) {\n var result = keys;\n this.addedDocuments.forEach(function (key) {\n return result = result.add(key);\n });\n this.removedDocuments.forEach(function (key) {\n return result = result.delete(key);\n });\n return result;\n };\n UpdateMapping.prototype.add = function (key) {\n this.addedDocuments = this.addedDocuments.add(key);\n this.removedDocuments = this.removedDocuments.delete(key);\n };\n UpdateMapping.prototype.delete = function (key) {\n this.addedDocuments = this.addedDocuments.delete(key);\n this.removedDocuments = this.removedDocuments.add(key);\n };\n UpdateMapping.prototype.equals = function (other) {\n return other !== null && this.addedDocuments.equals(other.addedDocuments) && this.removedDocuments.equals(other.removedDocuments);\n };\n return UpdateMapping;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/remote/watch_change.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n/**\r\n * Represents a changed document and a list of target ids to which this change\r\n * applies.\r\n *\r\n * If document has been deleted NoDocument will be provided.\r\n */\nvar DocumentWatchChange = /** @class */function () {\n function DocumentWatchChange(\n /** The new document applies to all of these targets. */\n updatedTargetIds,\n /** The new document is removed from all of these targets. */\n removedTargetIds,\n /** The key of the document for this change. */\n key,\n /**\r\n * The new document or NoDocument if it was deleted. Is null if the\r\n * document went out of view without the server sending a new document.\r\n */\n newDoc) {\n this.updatedTargetIds = updatedTargetIds;\n this.removedTargetIds = removedTargetIds;\n this.key = key;\n this.newDoc = newDoc;\n }\n return DocumentWatchChange;\n}();\n\nvar ExistenceFilterChange = /** @class */function () {\n function ExistenceFilterChange(targetId, existenceFilter) {\n this.targetId = targetId;\n this.existenceFilter = existenceFilter;\n }\n return ExistenceFilterChange;\n}();\n\nvar WatchTargetChangeState;\n(function (WatchTargetChangeState) {\n WatchTargetChangeState[WatchTargetChangeState[\"NoChange\"] = 0] = \"NoChange\";\n WatchTargetChangeState[WatchTargetChangeState[\"Added\"] = 1] = \"Added\";\n WatchTargetChangeState[WatchTargetChangeState[\"Removed\"] = 2] = \"Removed\";\n WatchTargetChangeState[WatchTargetChangeState[\"Current\"] = 3] = \"Current\";\n WatchTargetChangeState[WatchTargetChangeState[\"Reset\"] = 4] = \"Reset\";\n})(WatchTargetChangeState || (WatchTargetChangeState = {}));\nvar watch_change_WatchTargetChange = /** @class */function () {\n function WatchTargetChange(\n /** What kind of change occurred to the watch target. */\n state,\n /** The target IDs that were added/removed/set. */\n targetIds,\n /**\r\n * An opaque, server-assigned token that allows watching a query to be\r\n * resumed after disconnecting without retransmitting all the data that\r\n * matches the query. The resume token essentially identifies a point in\r\n * time from which the server should resume sending results.\r\n */\n resumeToken,\n /** An RPC error indicating why the watch failed. */\n cause) {\n if (resumeToken === void 0) {\n resumeToken = emptyByteString();\n }\n if (cause === void 0) {\n cause = null;\n }\n this.state = state;\n this.targetIds = targetIds;\n this.resumeToken = resumeToken;\n this.cause = cause;\n }\n return WatchTargetChange;\n}();\n\n/**\r\n * A helper class to accumulate watch changes into a RemoteEvent and other\r\n * target information.\r\n */\nvar watch_change_WatchChangeAggregator = /** @class */function () {\n function WatchChangeAggregator(snapshotVersion, listenTargets, pendingTargetResponses) {\n this.snapshotVersion = snapshotVersion;\n this.listenTargets = listenTargets;\n /** The existence filter - if any - for the given target IDs. */\n this.existenceFilters = {};\n /** Keeps track of the current target mappings */\n this.targetChanges = {};\n /** Keeps track of document to update */\n this.documentUpdates = maybeDocumentMap();\n /** Whether this aggregator was frozen and can no longer be modified */\n this.frozen = false;\n this.pendingTargetResponses = shallowCopy(pendingTargetResponses);\n }\n /** Aggregates a watch change into the current state */\n WatchChangeAggregator.prototype.add = function (watchChange) {\n assert(!this.frozen, 'Trying to modify frozen WatchChangeAggregator.');\n if (watchChange instanceof DocumentWatchChange) {\n this.addDocumentChange(watchChange);\n } else if (watchChange instanceof watch_change_WatchTargetChange) {\n this.addTargetChange(watchChange);\n } else if (watchChange instanceof ExistenceFilterChange) {\n this.addExistenceFilterChange(watchChange);\n } else {\n fail('Unknown watch change: ' + watchChange);\n }\n };\n /** Aggregates all provided watch changes to the current state in order */\n WatchChangeAggregator.prototype.addChanges = function (watchChanges) {\n var _this = this;\n assert(!this.frozen, 'Trying to modify frozen WatchChangeAggregator.');\n watchChanges.forEach(function (change) {\n return _this.add(change);\n });\n };\n /**\r\n * Converts the current state into a remote event with the snapshot version\r\n * provided via the constructor.\r\n */\n WatchChangeAggregator.prototype.createRemoteEvent = function () {\n var _this = this;\n var targetChanges = this.targetChanges;\n // Remove all the non-active targets from the remote event.\n forEachNumber(this.targetChanges, function (targetId) {\n if (!_this.isActiveTarget(targetId)) {\n delete targetChanges[targetId];\n }\n });\n // Mark this aggregator as frozen so no further modifications are made\n this.frozen = true;\n return new remote_event_RemoteEvent(this.snapshotVersion, targetChanges, this.documentUpdates);\n };\n WatchChangeAggregator.prototype.ensureTargetChange = function (targetId) {\n var change = this.targetChanges[targetId];\n if (!change) {\n // Create an UpdateMapping by default, since resets are always explicit.\n change = {\n currentStatusUpdate: CurrentStatusUpdate.None,\n snapshotVersion: this.snapshotVersion,\n mapping: new UpdateMapping(),\n resumeToken: emptyByteString()\n };\n this.targetChanges[targetId] = change;\n }\n return change;\n };\n /**\r\n * We need to wait for watch to ack targets before we process those events,\r\n * so to know if a target is active, there must be no pending acks we're\r\n * waiting for and it must be in the current list of targets that the client\r\n * cares about.\r\n *\r\n * This method is visible for testing.\r\n */\n WatchChangeAggregator.prototype.isActiveTarget = function (targetId) {\n return !contains(this.pendingTargetResponses, targetId) && contains(this.listenTargets, targetId);\n };\n WatchChangeAggregator.prototype.addDocumentChange = function (docChange) {\n var relevant = false;\n for (var _i = 0, _a = docChange.updatedTargetIds; _i < _a.length; _i++) {\n var targetId = _a[_i];\n if (this.isActiveTarget(targetId)) {\n var change = this.ensureTargetChange(targetId);\n change.mapping.add(docChange.key);\n relevant = true;\n }\n }\n for (var _b = 0, _c = docChange.removedTargetIds; _b < _c.length; _b++) {\n var targetId = _c[_b];\n if (this.isActiveTarget(targetId)) {\n var change = this.ensureTargetChange(targetId);\n change.mapping.delete(docChange.key);\n relevant = true;\n }\n }\n // Only update the document if there is a new document to replace to an\n // active target that is being listened to, this might be just a target\n // update instead.\n if (docChange.newDoc && relevant) {\n this.documentUpdates = this.documentUpdates.insert(docChange.key, docChange.newDoc);\n }\n };\n WatchChangeAggregator.prototype.addTargetChange = function (targetChange) {\n var _this = this;\n targetChange.targetIds.forEach(function (targetId) {\n var change = _this.ensureTargetChange(targetId);\n switch (targetChange.state) {\n case WatchTargetChangeState.NoChange:\n if (_this.isActiveTarget(targetId)) {\n // Creating the change above satisfies the semantics of no-change.\n applyResumeToken(change, targetChange.resumeToken);\n }\n break;\n case WatchTargetChangeState.Added:\n // We need to decrement the number of pending acks needed from watch\n // for this targetId.\n _this.recordTargetResponse(targetId);\n if (!contains(_this.pendingTargetResponses, targetId)) {\n // We have a freshly added target, so we need to reset any state\n // that we had previously This can happen e.g. when remove and add\n // back a target for existence filter mismatches.\n change.mapping = new UpdateMapping();\n change.currentStatusUpdate = CurrentStatusUpdate.None;\n delete _this.existenceFilters[targetId];\n }\n applyResumeToken(change, targetChange.resumeToken);\n break;\n case WatchTargetChangeState.Removed:\n // We need to keep track of removed targets to we can\n // post-filter and remove any target changes.\n // We need to decrement the number of pending acks needed from watch\n // for this targetId.\n _this.recordTargetResponse(targetId);\n assert(!targetChange.cause, 'WatchChangeAggregator does not handle errored targets');\n break;\n case WatchTargetChangeState.Current:\n if (_this.isActiveTarget(targetId)) {\n change.currentStatusUpdate = CurrentStatusUpdate.MarkCurrent;\n applyResumeToken(change, targetChange.resumeToken);\n }\n break;\n case WatchTargetChangeState.Reset:\n if (_this.isActiveTarget(targetId)) {\n // Overwrite any existing target mapping with a reset\n // mapping. Every subsequent update will modify the reset\n // mapping, not an update mapping.\n change.mapping = new ResetMapping();\n applyResumeToken(change, targetChange.resumeToken);\n }\n break;\n default:\n fail('Unknown target watch change state: ' + targetChange.state);\n }\n });\n };\n /**\r\n * Record that we get a watch target add/remove by decrementing the number of\r\n * pending target responses that we have.\r\n */\n WatchChangeAggregator.prototype.recordTargetResponse = function (targetId) {\n var newCount = (this.pendingTargetResponses[targetId] || 0) - 1;\n if (newCount === 0) {\n delete this.pendingTargetResponses[targetId];\n } else {\n this.pendingTargetResponses[targetId] = newCount;\n }\n };\n WatchChangeAggregator.prototype.addExistenceFilterChange = function (change) {\n if (this.isActiveTarget(change.targetId)) {\n this.existenceFilters[change.targetId] = change.existenceFilter;\n }\n };\n return WatchChangeAggregator;\n}();\n\n/**\r\n * Applies the resume token to the TargetChange, but only when it has a new\r\n * value. null and empty resumeTokens are discarded.\r\n */\nfunction applyResumeToken(change, resumeToken) {\n if (resumeToken.length > 0) {\n change.resumeToken = resumeToken;\n }\n}\n// CONCATENATED MODULE: ./src/firestore/remote/serializer.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar DIRECTIONS = function () {\n var dirs = {};\n dirs[Direction.ASCENDING.name] = 'ASCENDING';\n dirs[Direction.DESCENDING.name] = 'DESCENDING';\n return dirs;\n}();\nvar OPERATORS = function () {\n var ops = {};\n ops[query_RelationOp.LESS_THAN.name] = 'LESS_THAN';\n ops[query_RelationOp.LESS_THAN_OR_EQUAL.name] = 'LESS_THAN_OR_EQUAL';\n ops[query_RelationOp.GREATER_THAN.name] = 'GREATER_THAN';\n ops[query_RelationOp.GREATER_THAN_OR_EQUAL.name] = 'GREATER_THAN_OR_EQUAL';\n ops[query_RelationOp.EQUAL.name] = 'EQUAL';\n return ops;\n}();\nfunction assertPresent(value, description) {\n assert(!isNullOrUndefined(value), description + ' is missing');\n}\nfunction parseInt64(value) {\n // TODO(bjornick): Handle int64 greater than 53 bits.\n if (typeof value === 'number') {\n return value;\n } else if (typeof value === 'string') {\n return parseInt(value, 10);\n } else {\n return fail(\"can't parse \" + value);\n }\n}\n/**\r\n * Generates JsonObject values for the Datastore API suitable for sending to\r\n * either GRPC stub methods or via the JSON/HTTP REST API.\r\n * TODO(klimt): We can remove the databaseId argument if we keep the full\r\n * resource name in documents.\r\n */\nvar serializer_JsonProtoSerializer = /** @class */function () {\n function JsonProtoSerializer(databaseId, options) {\n this.databaseId = databaseId;\n this.options = options;\n }\n JsonProtoSerializer.prototype.emptyByteString = function () {\n if (this.options.useProto3Json) {\n return '';\n } else {\n return new Uint8Array(0);\n }\n };\n JsonProtoSerializer.prototype.unsafeCastProtoByteString = function (byteString) {\n // byteStrings can be either string or UInt8Array, but the typings say\n // it's always a string. Cast as string to avoid type check failing\n return byteString;\n };\n JsonProtoSerializer.prototype.fromRpcStatus = function (status) {\n var code = status.code === undefined ? Code.UNKNOWN : mapCodeFromRpcCode(status.code);\n return new FirestoreError(code, status.message || '');\n };\n /**\r\n * Returns a value for a Date that's appropriate to put into a proto.\r\n * DO NOT USE THIS FOR ANYTHING ELSE.\r\n * This method cheats. It's typed as returning \"string\" because that's what\r\n * our generated proto interfaces say dates must be. But it's easier and safer\r\n * to actually return a Timestamp proto.\r\n */\n JsonProtoSerializer.prototype.toTimestamp = function (timestamp) {\n return {\n seconds: timestamp.seconds,\n nanos: timestamp.nanos\n // tslint:disable-next-line:no-any\n };\n };\n JsonProtoSerializer.prototype.fromTimestamp = function (date) {\n // The json interface (for the browser) will return an iso timestamp string,\n // while the proto js library (for node) will return a\n // google.protobuf.Timestamp instance.\n if (typeof date === 'string') {\n // TODO(b/37282237): Use strings for Proto3 timestamps\n // assert(this.options.useProto3Json,\n // 'The timestamp string format requires Proto3.');\n return timestamp_Timestamp.fromISOString(date);\n } else {\n assert(!!date, 'Cannot deserialize null or undefined timestamp.');\n // TODO(b/37282237): Use strings for Proto3 timestamps\n // assert(!this.options.useProto3Json,\n // 'The timestamp instance format requires Proto JS.');\n var seconds = parseInt64(date.seconds || '0');\n var nanos = date.nanos || 0;\n return new timestamp_Timestamp(seconds, nanos);\n }\n };\n /**\r\n * Returns a value for bytes that's appropriate to put in a proto.\r\n * DO NOT USE THIS FOR ANYTHING ELSE.\r\n * This method cheats. It's typed as returning \"string\" because that's what\r\n * our generated proto interfaces say bytes must be. But it should return\r\n * an Uint8Array in Node.\r\n */\n JsonProtoSerializer.prototype.toBytes = function (bytes) {\n if (this.options.useProto3Json) {\n return bytes.toBase64();\n } else {\n // The typings say it's a string, but it needs to be a Uint8Array in Node.\n return this.unsafeCastProtoByteString(bytes.toUint8Array());\n }\n };\n /**\r\n * Parse the blob from the protos into the internal Blob class. Note that the\r\n * typings assume all blobs are strings, but they are actually Uint8Arrays\r\n * on Node.\r\n */\n JsonProtoSerializer.prototype.fromBlob = function (blob) {\n if (typeof blob === 'string') {\n assert(this.options.useProto3Json, 'Expected bytes to be passed in as Uint8Array, but got a string instead.');\n return blob_Blob.fromBase64String(blob);\n } else {\n assert(!this.options.useProto3Json, 'Expected bytes to be passed in as string, but got something else instead.');\n return blob_Blob.fromUint8Array(blob);\n }\n };\n JsonProtoSerializer.prototype.toVersion = function (version) {\n return this.toTimestamp(version.toTimestamp());\n };\n JsonProtoSerializer.prototype.fromVersion = function (version) {\n assert(!!version, \"Trying to deserialize version that isn't set\");\n return snapshot_version_SnapshotVersion.fromTimestamp(this.fromTimestamp(version));\n };\n JsonProtoSerializer.prototype.toResourceName = function (databaseId, path) {\n return this.fullyQualifiedPrefixPath(databaseId).child('documents').child(path).canonicalString();\n };\n JsonProtoSerializer.prototype.fromResourceName = function (name) {\n var resource = path_ResourcePath.fromString(name);\n assert(this.isValidResourceName(resource), 'Tried to deserialize invalid key ' + resource.toString());\n return resource;\n };\n JsonProtoSerializer.prototype.toName = function (key) {\n return this.toResourceName(this.databaseId, key.path);\n };\n JsonProtoSerializer.prototype.fromName = function (name) {\n var resource = this.fromResourceName(name);\n assert(resource.get(1) === this.databaseId.projectId, 'Tried to deserialize key from different project: ' + resource.get(1) + ' vs ' + this.databaseId.projectId);\n assert(!resource.get(3) && !this.databaseId.database || resource.get(3) === this.databaseId.database, 'Tried to deserialize key from different database: ' + resource.get(3) + ' vs ' + this.databaseId.database);\n return new document_key_DocumentKey(this.extractLocalPathFromResourceName(resource));\n };\n JsonProtoSerializer.prototype.toQueryPath = function (path) {\n if (path.length === 0) {\n // If the path is empty, the backend requires we leave off the /documents\n // at the end.\n return this.encodedDatabaseId;\n }\n return this.toResourceName(this.databaseId, path);\n };\n JsonProtoSerializer.prototype.fromQueryPath = function (name) {\n var resourceName = this.fromResourceName(name);\n if (resourceName.length === 4) {\n return path_ResourcePath.EMPTY_PATH;\n }\n return this.extractLocalPathFromResourceName(resourceName);\n };\n Object.defineProperty(JsonProtoSerializer.prototype, \"encodedDatabaseId\", {\n get: function get() {\n var path = new path_ResourcePath(['projects', this.databaseId.projectId, 'databases', this.databaseId.database]);\n return path.canonicalString();\n },\n enumerable: true,\n configurable: true\n });\n JsonProtoSerializer.prototype.fullyQualifiedPrefixPath = function (databaseId) {\n return new path_ResourcePath(['projects', databaseId.projectId, 'databases', databaseId.database]);\n };\n JsonProtoSerializer.prototype.extractLocalPathFromResourceName = function (resourceName) {\n assert(resourceName.length > 4 && resourceName.get(4) === 'documents', 'tried to deserialize invalid key ' + resourceName.toString());\n return resourceName.popFirst(5);\n };\n JsonProtoSerializer.prototype.isValidResourceName = function (path) {\n // Resource names have at least 4 components (project ID, database ID)\n return path.length >= 4 && path.get(0) === 'projects' && path.get(2) === 'databases';\n };\n JsonProtoSerializer.prototype.toValue = function (val) {\n if (val instanceof NullValue) {\n return { nullValue: 'NULL_VALUE' };\n } else if (val instanceof field_value_BooleanValue) {\n return { booleanValue: val.value() };\n } else if (val instanceof IntegerValue) {\n return { integerValue: '' + val.value() };\n } else if (val instanceof DoubleValue) {\n var doubleValue = val.value();\n if (this.options.useProto3Json) {\n // Proto 3 let's us encode NaN and Infinity as string values as\n // expected by the backend. This is currently not checked by our unit\n // tests because they rely on protobuf.js.\n if (isNaN(doubleValue)) {\n return { doubleValue: 'NaN' };\n } else if (doubleValue === Infinity) {\n return { doubleValue: 'Infinity' };\n } else if (doubleValue === -Infinity) {\n return { doubleValue: '-Infinity' };\n }\n }\n return { doubleValue: val.value() };\n } else if (val instanceof field_value_StringValue) {\n return { stringValue: val.value() };\n } else if (val instanceof field_value_ObjectValue) {\n return { mapValue: this.toMapValue(val) };\n } else if (val instanceof field_value_ArrayValue) {\n return { arrayValue: this.toArrayValue(val) };\n } else if (val instanceof TimestampValue) {\n return {\n timestampValue: this.toTimestamp(val.internalValue)\n };\n } else if (val instanceof GeoPointValue) {\n return {\n geoPointValue: {\n latitude: val.value().latitude,\n longitude: val.value().longitude\n }\n };\n } else if (val instanceof BlobValue) {\n return {\n bytesValue: this.toBytes(val.value())\n };\n } else if (val instanceof field_value_RefValue) {\n return {\n referenceValue: this.toResourceName(val.databaseId, val.key.path)\n };\n } else {\n return fail('Unknown FieldValue ' + JSON.stringify(val));\n }\n };\n JsonProtoSerializer.prototype.fromValue = function (obj) {\n var _this = this;\n // tslint:disable-next-line:no-any\n var type = obj['value_type'];\n if (hasTag(obj, type, 'nullValue')) {\n return NullValue.INSTANCE;\n } else if (hasTag(obj, type, 'booleanValue')) {\n return field_value_BooleanValue.of(obj.booleanValue);\n } else if (hasTag(obj, type, 'integerValue')) {\n return new IntegerValue(parseInt64(obj.integerValue));\n } else if (hasTag(obj, type, 'doubleValue')) {\n if (this.options.useProto3Json) {\n // Proto 3 uses the string values 'NaN' and 'Infinity'.\n if (obj.doubleValue === 'NaN') {\n return DoubleValue.NAN;\n } else if (obj.doubleValue === 'Infinity') {\n return DoubleValue.POSITIVE_INFINITY;\n } else if (obj.doubleValue === '-Infinity') {\n return DoubleValue.NEGATIVE_INFINITY;\n }\n }\n return new DoubleValue(obj.doubleValue);\n } else if (hasTag(obj, type, 'stringValue')) {\n return new field_value_StringValue(obj.stringValue);\n } else if (hasTag(obj, type, 'mapValue')) {\n return this.fromFields(obj.mapValue.fields || {});\n } else if (hasTag(obj, type, 'arrayValue')) {\n // \"values\" is not present if the array is empty\n assertPresent(obj.arrayValue, 'arrayValue');\n var values = obj.arrayValue.values || [];\n return new field_value_ArrayValue(values.map(function (v) {\n return _this.fromValue(v);\n }));\n } else if (hasTag(obj, type, 'timestampValue')) {\n assertPresent(obj.timestampValue, 'timestampValue');\n return new TimestampValue(this.fromTimestamp(obj.timestampValue));\n } else if (hasTag(obj, type, 'geoPointValue')) {\n assertPresent(obj.geoPointValue, 'geoPointValue');\n var latitude = obj.geoPointValue.latitude || 0;\n var longitude = obj.geoPointValue.longitude || 0;\n return new GeoPointValue(new geo_point_GeoPoint(latitude, longitude));\n } else if (hasTag(obj, type, 'bytesValue')) {\n assertPresent(obj.bytesValue, 'bytesValue');\n var blob = this.fromBlob(obj.bytesValue);\n return new BlobValue(blob);\n } else if (hasTag(obj, type, 'referenceValue')) {\n assertPresent(obj.referenceValue, 'referenceValue');\n var resourceName = this.fromResourceName(obj.referenceValue);\n var dbId = new database_info_DatabaseId(resourceName.get(1), resourceName.get(3));\n var key = new document_key_DocumentKey(this.extractLocalPathFromResourceName(resourceName));\n return new field_value_RefValue(dbId, key);\n } else {\n return fail('Unknown Value proto ' + JSON.stringify(obj));\n }\n };\n /** Creates an api.Document from key and fields (but no create/update time) */\n JsonProtoSerializer.prototype.toMutationDocument = function (key, fields) {\n return {\n name: this.toName(key),\n fields: this.toFields(fields)\n };\n };\n JsonProtoSerializer.prototype.toDocument = function (document) {\n assert(!document.hasLocalMutations, \"Can't serialize documents with mutations.\");\n return {\n name: this.toName(document.key),\n fields: this.toFields(document.data),\n updateTime: this.toTimestamp(document.version.toTimestamp())\n };\n };\n JsonProtoSerializer.prototype.fromDocument = function (document) {\n return new document_Document(this.fromName(document.name), this.fromVersion(document.updateTime), this.fromFields(document.fields || {}), { hasLocalMutations: false });\n };\n JsonProtoSerializer.prototype.toFields = function (fields) {\n var _this = this;\n var result = {};\n fields.forEach(function (key, value) {\n result[key] = _this.toValue(value);\n });\n return result;\n };\n JsonProtoSerializer.prototype.fromFields = function (object) {\n var _this = this;\n // Proto map gets mapped to Object, so cast it.\n var map = object;\n var result = field_value_ObjectValue.EMPTY;\n forEach(map, function (key, value) {\n result = result.set(new path_FieldPath([key]), _this.fromValue(value));\n });\n return result;\n };\n JsonProtoSerializer.prototype.toMapValue = function (map) {\n return {\n fields: this.toFields(map)\n };\n };\n JsonProtoSerializer.prototype.toArrayValue = function (array) {\n var _this = this;\n var result = [];\n array.forEach(function (value) {\n result.push(_this.toValue(value));\n });\n return { values: result };\n };\n JsonProtoSerializer.prototype.fromFound = function (doc) {\n assert(!!doc.found, 'Tried to deserialize a found document from a missing document.');\n assertPresent(doc.found.name, 'doc.found.name');\n assertPresent(doc.found.updateTime, 'doc.found.updateTime');\n var key = this.fromName(doc.found.name);\n var version = this.fromVersion(doc.found.updateTime);\n var fields = this.fromFields(doc.found.fields || {});\n return new document_Document(key, version, fields, { hasLocalMutations: false });\n };\n JsonProtoSerializer.prototype.fromMissing = function (result) {\n assert(!!result.missing, 'Tried to deserialize a missing document from a found document.');\n assert(!!result.readTime, 'Tried to deserialize a missing document without a read time.');\n var key = this.fromName(result.missing);\n var version = this.fromVersion(result.readTime);\n return new document_NoDocument(key, version);\n };\n JsonProtoSerializer.prototype.fromMaybeDocument = function (result) {\n // tslint:disable-next-line:no-any\n var type = result['result_type'];\n if (hasTag(result, type, 'found')) {\n return this.fromFound(result);\n } else if (hasTag(result, type, 'missing')) {\n return this.fromMissing(result);\n }\n return fail('invalid batch get response: ' + JSON.stringify(result));\n };\n JsonProtoSerializer.prototype.toWatchTargetChangeState = function (state) {\n switch (state) {\n case WatchTargetChangeState.Added:\n return 'ADD';\n case WatchTargetChangeState.Current:\n return 'CURRENT';\n case WatchTargetChangeState.NoChange:\n return 'NO_CHANGE';\n case WatchTargetChangeState.Removed:\n return 'REMOVE';\n case WatchTargetChangeState.Reset:\n return 'RESET';\n default:\n return fail('Unknown WatchTargetChangeState: ' + state);\n }\n };\n JsonProtoSerializer.prototype.toTestWatchChange = function (watchChange) {\n if (watchChange instanceof ExistenceFilterChange) {\n return {\n filter: {\n count: watchChange.existenceFilter.count,\n targetId: watchChange.targetId\n }\n };\n }\n if (watchChange instanceof DocumentWatchChange) {\n if (watchChange.newDoc instanceof document_Document) {\n var doc = watchChange.newDoc;\n return {\n documentChange: {\n document: {\n name: this.toName(doc.key),\n fields: this.toFields(doc.data),\n updateTime: this.toVersion(doc.version)\n },\n targetIds: watchChange.updatedTargetIds,\n removedTargetIds: watchChange.removedTargetIds\n }\n };\n } else if (watchChange.newDoc instanceof document_NoDocument) {\n var doc = watchChange.newDoc;\n return {\n documentDelete: {\n document: this.toName(doc.key),\n readTime: this.toVersion(doc.version),\n removedTargetIds: watchChange.removedTargetIds\n }\n };\n } else if (watchChange.newDoc === null) {\n return {\n documentRemove: {\n document: this.toName(watchChange.key),\n removedTargetIds: watchChange.removedTargetIds\n }\n };\n }\n }\n if (watchChange instanceof watch_change_WatchTargetChange) {\n var cause = undefined;\n if (watchChange.cause) {\n cause = {\n code: mapRpcCodeFromCode(watchChange.cause.code),\n message: watchChange.cause.message\n };\n }\n return {\n targetChange: {\n targetChangeType: this.toWatchTargetChangeState(watchChange.state),\n targetIds: watchChange.targetIds,\n resumeToken: this.unsafeCastProtoByteString(watchChange.resumeToken),\n cause: cause\n }\n };\n }\n return fail('Unrecognized watch change: ' + JSON.stringify(watchChange));\n };\n JsonProtoSerializer.prototype.fromWatchChange = function (change) {\n // tslint:disable-next-line:no-any\n var type = change['change_type'];\n var watchChange;\n if (hasTag(change, type, 'targetChange')) {\n assertPresent(change.targetChange, 'targetChange');\n // proto3 default value is unset in JSON (undefined), so use 'NO_CHANGE'\n // if unset\n var state = this.fromWatchTargetChangeState(change.targetChange.targetChangeType || 'NO_CHANGE');\n var targetIds = change.targetChange.targetIds || [];\n var resumeToken = change.targetChange.resumeToken || this.emptyByteString();\n var causeProto = change.targetChange.cause;\n var cause = causeProto && this.fromRpcStatus(causeProto);\n watchChange = new watch_change_WatchTargetChange(state, targetIds, resumeToken, cause || null);\n } else if (hasTag(change, type, 'documentChange')) {\n assertPresent(change.documentChange, 'documentChange');\n assertPresent(change.documentChange.document, 'documentChange.name');\n assertPresent(change.documentChange.document.name, 'documentChange.document.name');\n assertPresent(change.documentChange.document.updateTime, 'documentChange.document.updateTime');\n var entityChange = change.documentChange;\n var key = this.fromName(entityChange.document.name);\n var version = this.fromVersion(entityChange.document.updateTime);\n var fields = this.fromFields(entityChange.document.fields || {});\n var doc = new document_Document(key, version, fields, {\n hasLocalMutations: false\n });\n var updatedTargetIds = entityChange.targetIds || [];\n var removedTargetIds = entityChange.removedTargetIds || [];\n watchChange = new DocumentWatchChange(updatedTargetIds, removedTargetIds, doc.key, doc);\n } else if (hasTag(change, type, 'documentDelete')) {\n assertPresent(change.documentDelete, 'documentDelete');\n assertPresent(change.documentDelete.document, 'documentDelete.document');\n var docDelete = change.documentDelete;\n var key = this.fromName(docDelete.document);\n var version = docDelete.readTime ? this.fromVersion(docDelete.readTime) : snapshot_version_SnapshotVersion.forDeletedDoc();\n var doc = new document_NoDocument(key, version);\n var removedTargetIds = docDelete.removedTargetIds || [];\n watchChange = new DocumentWatchChange([], removedTargetIds, doc.key, doc);\n } else if (hasTag(change, type, 'documentRemove')) {\n assertPresent(change.documentRemove, 'documentRemove');\n assertPresent(change.documentRemove.document, 'documentRemove');\n var docRemove = change.documentRemove;\n var key = this.fromName(docRemove.document);\n var removedTargetIds = docRemove.removedTargetIds || [];\n watchChange = new DocumentWatchChange([], removedTargetIds, key, null);\n } else if (hasTag(change, type, 'filter')) {\n // TODO(dimond): implement existence filter parsing with strategy.\n assertPresent(change.filter, 'filter');\n assertPresent(change.filter.targetId, 'filter.targetId');\n var filter = change.filter;\n var count = filter.count || 0;\n var existenceFilter = new ExistenceFilter(count);\n var targetId = filter.targetId;\n watchChange = new ExistenceFilterChange(targetId, existenceFilter);\n } else {\n return fail('Unknown change type ' + JSON.stringify(change));\n }\n return watchChange;\n };\n JsonProtoSerializer.prototype.fromWatchTargetChangeState = function (state) {\n if (state === 'NO_CHANGE') {\n return WatchTargetChangeState.NoChange;\n } else if (state === 'ADD') {\n return WatchTargetChangeState.Added;\n } else if (state === 'REMOVE') {\n return WatchTargetChangeState.Removed;\n } else if (state === 'CURRENT') {\n return WatchTargetChangeState.Current;\n } else if (state === 'RESET') {\n return WatchTargetChangeState.Reset;\n } else {\n return fail('Got unexpected TargetChange.state: ' + state);\n }\n };\n JsonProtoSerializer.prototype.versionFromListenResponse = function (change) {\n // We have only reached a consistent snapshot for the entire stream if there\n // is a read_time set and it applies to all targets (i.e. the list of\n // targets is empty). The backend is guaranteed to send such responses.\n // tslint:disable-next-line:no-any\n var type = change['response_type'];\n if (!hasTag(change, type, 'targetChange')) {\n return snapshot_version_SnapshotVersion.MIN;\n }\n var targetChange = change.targetChange;\n if (targetChange.targetIds && targetChange.targetIds.length) {\n return snapshot_version_SnapshotVersion.MIN;\n }\n if (!targetChange.readTime) {\n return snapshot_version_SnapshotVersion.MIN;\n }\n return this.fromVersion(targetChange.readTime);\n };\n JsonProtoSerializer.prototype.toMutation = function (mutation) {\n var _this = this;\n var result;\n if (mutation instanceof mutation_SetMutation) {\n result = {\n update: this.toMutationDocument(mutation.key, mutation.value)\n };\n } else if (mutation instanceof mutation_DeleteMutation) {\n result = { delete: this.toName(mutation.key) };\n } else if (mutation instanceof mutation_PatchMutation) {\n result = {\n update: this.toMutationDocument(mutation.key, mutation.data),\n updateMask: this.toDocumentMask(mutation.fieldMask)\n };\n } else if (mutation instanceof mutation_TransformMutation) {\n result = {\n transform: {\n document: this.toName(mutation.key),\n fieldTransforms: mutation.fieldTransforms.map(function (transform) {\n return _this.toFieldTransform(transform);\n })\n }\n };\n } else {\n return fail('Unknown mutation type ' + mutation.type);\n }\n if (!mutation.precondition.isNone) {\n result.currentDocument = this.toPrecondition(mutation.precondition);\n }\n return result;\n };\n JsonProtoSerializer.prototype.fromMutation = function (proto) {\n var _this = this;\n var precondition = proto.currentDocument ? this.fromPrecondition(proto.currentDocument) : mutation_Precondition.NONE;\n if (proto.update) {\n assertPresent(proto.update.name, 'name');\n var key = this.fromName(proto.update.name);\n var value = this.fromFields(proto.update.fields || {});\n if (proto.updateMask) {\n var fieldMask = this.fromDocumentMask(proto.updateMask);\n return new mutation_PatchMutation(key, value, fieldMask, precondition);\n } else {\n return new mutation_SetMutation(key, value, precondition);\n }\n } else if (proto.delete) {\n var key = this.fromName(proto.delete);\n return new mutation_DeleteMutation(key, precondition);\n } else if (proto.transform) {\n var key = this.fromName(proto.transform.document);\n var fieldTransforms = proto.transform.fieldTransforms.map(function (transform) {\n return _this.fromFieldTransform(transform);\n });\n assert(precondition.exists === true, 'Transforms only support precondition \"exists == true\"');\n return new mutation_TransformMutation(key, fieldTransforms);\n } else {\n return fail('unknown mutation proto: ' + JSON.stringify(proto));\n }\n };\n JsonProtoSerializer.prototype.toPrecondition = function (precondition) {\n assert(!precondition.isNone, \"Can't serialize an empty precondition\");\n if (precondition.updateTime !== undefined) {\n return {\n updateTime: this.toVersion(precondition.updateTime)\n };\n } else if (precondition.exists !== undefined) {\n return { exists: precondition.exists };\n } else {\n return fail('Unknown precondition');\n }\n };\n JsonProtoSerializer.prototype.fromPrecondition = function (precondition) {\n if (precondition.updateTime !== undefined) {\n return mutation_Precondition.updateTime(this.fromVersion(precondition.updateTime));\n } else if (precondition.exists !== undefined) {\n return mutation_Precondition.exists(precondition.exists);\n } else {\n return mutation_Precondition.NONE;\n }\n };\n JsonProtoSerializer.prototype.fromWriteResult = function (proto) {\n var _this = this;\n // NOTE: Deletes don't have an updateTime.\n var version = proto.updateTime ? this.fromVersion(proto.updateTime) : null;\n var transformResults = null;\n if (proto.transformResults) {\n transformResults = proto.transformResults.map(function (result) {\n return _this.fromValue(result);\n });\n }\n return new MutationResult(version, transformResults);\n };\n JsonProtoSerializer.prototype.fromWriteResults = function (protos) {\n var _this = this;\n return (protos || []).map(function (proto) {\n return _this.fromWriteResult(proto);\n });\n };\n JsonProtoSerializer.prototype.toFieldTransform = function (fieldTransform) {\n assert(fieldTransform.transform instanceof ServerTimestampTransform, 'Unknown transform: ' + fieldTransform.transform);\n return {\n fieldPath: fieldTransform.field.canonicalString(),\n setToServerValue: 'REQUEST_TIME'\n };\n };\n JsonProtoSerializer.prototype.fromFieldTransform = function (proto) {\n assert(proto.setToServerValue === 'REQUEST_TIME', 'Unknown transform proto: ' + JSON.stringify(proto));\n var fieldPath = path_FieldPath.fromServerFormat(proto.fieldPath);\n return new FieldTransform(fieldPath, ServerTimestampTransform.instance);\n };\n JsonProtoSerializer.prototype.toDocumentsTarget = function (query) {\n return { documents: [this.toQueryPath(query.path)] };\n };\n JsonProtoSerializer.prototype.fromDocumentsTarget = function (documentsTarget) {\n var count = documentsTarget.documents.length;\n assert(count === 1, 'DocumentsTarget contained other than 1 document: ' + count);\n var name = documentsTarget.documents[0];\n return query_Query.atPath(this.fromQueryPath(name));\n };\n JsonProtoSerializer.prototype.toQueryTarget = function (query) {\n // Dissect the path into parent, collectionId, and optional key filter.\n var result = { structuredQuery: {} };\n if (query.path.isEmpty()) {\n result.parent = this.toQueryPath(path_ResourcePath.EMPTY_PATH);\n } else {\n var path = query.path;\n assert(path.length % 2 !== 0, 'Document queries with filters are not supported.');\n result.parent = this.toQueryPath(path.popLast());\n result.structuredQuery.from = [{ collectionId: path.lastSegment() }];\n }\n var where = this.toFilter(query.filters);\n if (where) {\n result.structuredQuery.where = where;\n }\n var orderBy = this.toOrder(query.orderBy);\n if (orderBy) {\n result.structuredQuery.orderBy = orderBy;\n }\n var limit = this.toLimit(query.limit);\n if (limit !== undefined) {\n result.structuredQuery.limit = limit;\n }\n if (query.startAt) {\n result.structuredQuery.startAt = this.toCursor(query.startAt);\n }\n if (query.endAt) {\n result.structuredQuery.endAt = this.toCursor(query.endAt);\n }\n return result;\n };\n JsonProtoSerializer.prototype.fromQueryTarget = function (target) {\n var path = this.fromQueryPath(target.parent);\n var query = target.structuredQuery;\n var fromCount = query.from ? query.from.length : 0;\n if (fromCount > 0) {\n assert(fromCount === 1, 'StructuredQuery.from with more than one collection is not supported.');\n var from = query.from[0];\n path = path.child(from.collectionId);\n }\n var filterBy = [];\n if (query.where) {\n filterBy = this.fromFilter(query.where);\n }\n var orderBy = [];\n if (query.orderBy) {\n orderBy = this.fromOrder(query.orderBy);\n }\n var limit = null;\n if (query.limit) {\n limit = query.limit;\n }\n var startAt = null;\n if (query.startAt) {\n startAt = this.fromCursor(query.startAt);\n }\n var endAt = null;\n if (query.endAt) {\n endAt = this.fromCursor(query.endAt);\n }\n return new query_Query(path, orderBy, filterBy, limit, startAt, endAt);\n };\n JsonProtoSerializer.prototype.toListenRequestLabels = function (queryData) {\n var value = this.toLabel(queryData.purpose);\n if (value == null) {\n return null;\n } else {\n return {\n 'goog-listen-tags': value\n };\n }\n };\n JsonProtoSerializer.prototype.toLabel = function (purpose) {\n switch (purpose) {\n case QueryPurpose.Listen:\n return null;\n case QueryPurpose.ExistenceFilterMismatch:\n return 'existence-filter-mismatch';\n case QueryPurpose.LimboResolution:\n return 'limbo-document';\n default:\n return fail('Unrecognized query purpose: ' + purpose);\n }\n };\n JsonProtoSerializer.prototype.toTarget = function (queryData) {\n var result;\n var query = queryData.query;\n if (query.isDocumentQuery()) {\n result = { documents: this.toDocumentsTarget(query) };\n } else {\n result = { query: this.toQueryTarget(query) };\n }\n result.targetId = queryData.targetId;\n if (queryData.resumeToken.length > 0) {\n result.resumeToken = this.unsafeCastProtoByteString(queryData.resumeToken);\n }\n return result;\n };\n JsonProtoSerializer.prototype.toFilter = function (filters) {\n var _this = this;\n if (filters.length === 0) return;\n var protos = filters.map(function (filter) {\n return filter instanceof query_RelationFilter ? _this.toRelationFilter(filter) : _this.toUnaryFilter(filter);\n });\n if (protos.length === 1) {\n return protos[0];\n }\n return { compositeFilter: { op: 'AND', filters: protos } };\n };\n JsonProtoSerializer.prototype.fromFilter = function (filter) {\n var _this = this;\n if (!filter) {\n return [];\n } else if (filter.unaryFilter !== undefined) {\n return [this.fromUnaryFilter(filter)];\n } else if (filter.fieldFilter !== undefined) {\n return [this.fromRelationFilter(filter)];\n } else if (filter.compositeFilter !== undefined) {\n return filter.compositeFilter.filters.map(function (f) {\n return _this.fromFilter(f);\n }).reduce(function (accum, current) {\n return accum.concat(current);\n });\n } else {\n return fail('Unknown filter: ' + JSON.stringify(filter));\n }\n };\n JsonProtoSerializer.prototype.toOrder = function (orderBys) {\n var _this = this;\n if (orderBys.length === 0) return;\n return orderBys.map(function (order) {\n return _this.toPropertyOrder(order);\n });\n };\n JsonProtoSerializer.prototype.fromOrder = function (orderBys) {\n var _this = this;\n return orderBys.map(function (order) {\n return _this.fromPropertyOrder(order);\n });\n };\n JsonProtoSerializer.prototype.toLimit = function (limit) {\n if (!isNullOrUndefined(limit)) {\n return limit;\n }\n return;\n };\n JsonProtoSerializer.prototype.toCursor = function (cursor) {\n var _this = this;\n return {\n before: cursor.before,\n values: cursor.position.map(function (component) {\n return _this.toValue(component);\n })\n };\n };\n JsonProtoSerializer.prototype.fromCursor = function (cursor) {\n var _this = this;\n var before = !!cursor.before;\n var position = cursor.values.map(function (component) {\n return _this.fromValue(component);\n });\n return new query_Bound(position, before);\n };\n // visible for testing\n JsonProtoSerializer.prototype.toDirection = function (dir) {\n return DIRECTIONS[dir.name];\n };\n // visible for testing\n JsonProtoSerializer.prototype.fromDirection = function (dir) {\n switch (dir) {\n case 'ASCENDING':\n return Direction.ASCENDING;\n case 'DESCENDING':\n return Direction.DESCENDING;\n default:\n return undefined;\n }\n };\n // visible for testing\n JsonProtoSerializer.prototype.toOperatorName = function (op) {\n return OPERATORS[op.name];\n };\n JsonProtoSerializer.prototype.fromOperatorName = function (op) {\n switch (op) {\n case 'EQUAL':\n return query_RelationOp.EQUAL;\n case 'GREATER_THAN':\n return query_RelationOp.GREATER_THAN;\n case 'GREATER_THAN_OR_EQUAL':\n return query_RelationOp.GREATER_THAN_OR_EQUAL;\n case 'LESS_THAN':\n return query_RelationOp.LESS_THAN;\n case 'LESS_THAN_OR_EQUAL':\n return query_RelationOp.LESS_THAN_OR_EQUAL;\n case 'OPERATOR_UNSPECIFIED':\n return fail('Unspecified relation');\n default:\n return fail('Unknown relation');\n }\n };\n JsonProtoSerializer.prototype.toFieldPathReference = function (path) {\n return { fieldPath: path.canonicalString() };\n };\n JsonProtoSerializer.prototype.fromFieldPathReference = function (fieldReference) {\n return path_FieldPath.fromServerFormat(fieldReference.fieldPath);\n };\n // visible for testing\n JsonProtoSerializer.prototype.toPropertyOrder = function (orderBy) {\n return {\n field: this.toFieldPathReference(orderBy.field),\n direction: this.toDirection(orderBy.dir)\n };\n };\n JsonProtoSerializer.prototype.fromPropertyOrder = function (orderBy) {\n return new query_OrderBy(this.fromFieldPathReference(orderBy.field), this.fromDirection(orderBy.direction));\n };\n // visible for testing\n JsonProtoSerializer.prototype.toRelationFilter = function (filter) {\n if (filter instanceof query_RelationFilter) {\n return {\n fieldFilter: {\n field: this.toFieldPathReference(filter.field),\n op: this.toOperatorName(filter.op),\n value: this.toValue(filter.value)\n }\n };\n } else {\n return fail('Unrecognized filter: ' + JSON.stringify(filter));\n }\n };\n JsonProtoSerializer.prototype.fromRelationFilter = function (filter) {\n return new query_RelationFilter(this.fromFieldPathReference(filter.fieldFilter.field), this.fromOperatorName(filter.fieldFilter.op), this.fromValue(filter.fieldFilter.value));\n };\n // visible for testing\n JsonProtoSerializer.prototype.toUnaryFilter = function (filter) {\n if (filter instanceof NanFilter) {\n return {\n unaryFilter: {\n field: this.toFieldPathReference(filter.field),\n op: 'IS_NAN'\n }\n };\n } else if (filter instanceof NullFilter) {\n return {\n unaryFilter: {\n field: this.toFieldPathReference(filter.field),\n op: 'IS_NULL'\n }\n };\n } else {\n return fail('Unrecognized filter: ' + JSON.stringify(filter));\n }\n };\n JsonProtoSerializer.prototype.fromUnaryFilter = function (filter) {\n switch (filter.unaryFilter.op) {\n case 'IS_NAN':\n var nanField = this.fromFieldPathReference(filter.unaryFilter.field);\n return new NanFilter(nanField);\n case 'IS_NULL':\n var nullField = this.fromFieldPathReference(filter.unaryFilter.field);\n return new NullFilter(nullField);\n case 'OPERATOR_UNSPECIFIED':\n return fail('Unspecified filter');\n default:\n return fail('Unknown filter');\n }\n };\n JsonProtoSerializer.prototype.toDocumentMask = function (fieldMask) {\n return {\n fieldPaths: fieldMask.fields.map(function (field) {\n return field.canonicalString();\n })\n };\n };\n JsonProtoSerializer.prototype.fromDocumentMask = function (proto) {\n var paths = proto.fieldPaths || [];\n var fields = paths.map(function (path) {\n return path_FieldPath.fromServerFormat(path);\n });\n return new mutation_FieldMask(fields);\n };\n return JsonProtoSerializer;\n}();\n\n/**\r\n * Checks for a specific oneof tag in a protocol buffer message.\r\n *\r\n * This intentionally accommodates two distinct cases:\r\n *\r\n * 1) Messages containing a type tag: these are the format produced by GRPC in\r\n * return values. These may contain default-value mappings for all tags in the\r\n * oneof but the type tag specifies which one was actually set.\r\n *\r\n * 2) Messages that don't contain a type tag: these are the format required by\r\n * GRPC as inputs. If we emitted objects with type tags, ProtoBuf.js would\r\n * choke claiming that the tags aren't fields in the Message.\r\n *\r\n * Allowing both formats here makes the serializer able to consume the outputs\r\n * it produces: for all messages it supports, fromX(toX(value)) == value.\r\n *\r\n * Note that case 2 suffers from ambiguity: if multiple tags are present\r\n * without a type tag then the callers are structured in such a way that the\r\n * first invocation will win. Since we only parse in this mode when parsing\r\n * the output of a serialize method this works, but it's not a general\r\n * solution.\r\n *\r\n * Unfortunately there is no general solution here because proto3 makes it\r\n * impossible to distinguish unset from explicitly set fields: both have the\r\n * default value for the type. Without the type tag but multiple value tags\r\n * it's possible to have default values for each tag in the oneof and not be\r\n * able to know which was actually in effect.\r\n */\nfunction hasTag(obj, type, tag) {\n return type === tag || !type && tag in obj;\n}\n// EXTERNAL MODULE: ./src/utils/promise.ts\nvar utils_promise = __webpack_require__(3);\n\n// EXTERNAL MODULE: ./node_modules/@firebase/webchannel-wrapper/dist/index.js\nvar dist = __webpack_require__(67);\nvar dist_default = /*#__PURE__*/__webpack_require__.n(dist);\n\n// CONCATENATED MODULE: ./src/firestore/remote/stream_bridge.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n/**\r\n * Provides a simple helper class that implements the Stream interface to\r\n * bridge to other implementations that are streams but do not implement the\r\n * interface. The stream callbacks are invoked with the callOn... methods.\r\n */\nvar stream_bridge_StreamBridge = /** @class */function () {\n function StreamBridge(args) {\n this.wrappedOnOpen = null;\n this.wrappedOnClose = null;\n this.wrappedOnMessage = null;\n this.sendFn = args.sendFn;\n this.closeFn = args.closeFn;\n }\n StreamBridge.prototype.onOpen = function (callback) {\n assert(!this.wrappedOnOpen, 'Called onOpen on stream twice!');\n this.wrappedOnOpen = callback;\n };\n StreamBridge.prototype.onClose = function (callback) {\n assert(!this.wrappedOnClose, 'Called onClose on stream twice!');\n this.wrappedOnClose = callback;\n };\n StreamBridge.prototype.onMessage = function (callback) {\n assert(!this.wrappedOnMessage, 'Called onMessage on stream twice!');\n this.wrappedOnMessage = callback;\n };\n StreamBridge.prototype.close = function () {\n this.closeFn();\n };\n StreamBridge.prototype.send = function (msg) {\n this.sendFn(msg);\n };\n StreamBridge.prototype.callOnOpen = function () {\n assert(this.wrappedOnOpen !== null, 'Cannot call onOpen because no callback ' + 'was set');\n this.wrappedOnOpen();\n };\n StreamBridge.prototype.callOnClose = function (err) {\n assert(this.wrappedOnClose !== null, 'Cannot call onClose because no ' + 'callback was set');\n this.wrappedOnClose(err);\n };\n StreamBridge.prototype.callOnMessage = function (msg) {\n assert(this.wrappedOnMessage !== null, 'Cannot call onMessage because no ' + 'callback was set');\n this.wrappedOnMessage(msg);\n };\n return StreamBridge;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/platform_browser/webchannel_connection.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\nvar LOG_TAG = 'Connection';\nvar RPC_URL_VERSION = 'v1beta1';\n// TODO(b/38203344): The SDK_VERSION is set independently from Firebase because\n// we are doing out-of-band releases. Once we release as part of Firebase, we\n// should use the Firebase version instead.\nvar X_GOOG_API_CLIENT_VALUE = 'gl-js/ fire/' + SDK_VERSION;\nvar XHR_TIMEOUT_SECS = 15;\nvar webchannel_connection_WebChannelConnection = /** @class */function () {\n function WebChannelConnection(info) {\n this.databaseId = info.databaseId;\n this.pool = new dist[\"XhrIoPool\"]();\n var proto = info.ssl ? 'https' : 'http';\n this.baseUrl = proto + '://' + info.host;\n }\n /**\r\n * Modifies the headers for a request, adding any authorization token if\r\n * present and any additional headers for the request.\r\n */\n WebChannelConnection.prototype.modifyHeadersForRequest = function (headers, token) {\n if (token) {\n for (var header in token.authHeaders) {\n if (token.authHeaders.hasOwnProperty(header)) {\n headers[header] = token.authHeaders[header];\n }\n }\n }\n headers['X-Goog-Api-Client'] = X_GOOG_API_CLIENT_VALUE;\n // This header is used to improve routing and project isolation by the\n // backend.\n headers['google-cloud-resource-prefix'] = \"projects/\" + this.databaseId.projectId + \"/\" + (\"databases/\" + this.databaseId.database);\n };\n WebChannelConnection.prototype.invoke = function (rpcName, request, token) {\n var _this = this;\n var url = this.makeUrl(rpcName);\n return new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n _this.pool.getObject(function (xhr) {\n xhr.listenOnce(dist[\"EventType\"].COMPLETE, function () {\n try {\n switch (xhr.getLastErrorCode()) {\n case dist[\"ErrorCode\"].NO_ERROR:\n var json = xhr.getResponseJson();\n debug(LOG_TAG, 'XHR received:', JSON.stringify(json));\n resolve(json);\n break;\n case dist[\"ErrorCode\"].TIMEOUT:\n log_error('RPC \"' + rpcName + '\" timed out, retrying.');\n reject(new FirestoreError(Code.DEADLINE_EXCEEDED, 'Request time out'));\n break;\n case dist[\"ErrorCode\"].HTTP_ERROR:\n var status_1 = xhr.getStatus();\n log_error('RPC \"' + rpcName + '\" failed with status:', status_1, 'response text:', xhr.getResponseText());\n if (status_1 > 0) {\n reject(new FirestoreError(mapCodeFromHttpStatus(status_1), 'Server responded with status ' + xhr.getStatusText()));\n } else {\n // If we received an HTTP_ERROR but there's no status code,\n // it's most probably a connection issue, let's retry.\n log_error(LOG_TAG, 'RPC \"' + rpcName + '\" failed, retrying.');\n reject(new FirestoreError(Code.UNAVAILABLE, 'Connection failed.'));\n }\n break;\n default:\n fail('RPC \"' + rpcName + '\" failed with unanticipated ' + 'webchannel error ' + xhr.getLastErrorCode() + ': ' + xhr.getLastError() + ', giving up.');\n }\n } finally {\n debug(LOG_TAG, 'RPC \"' + rpcName + '\" completed.');\n _this.pool.releaseObject(xhr);\n }\n });\n var requestString = JSON.stringify(request);\n debug(LOG_TAG, 'XHR sending: ', url + ' ' + requestString);\n // Content-Type: text/plain will avoid preflight requests which might\n // mess with CORS and redirects by proxies. If we add custom headers\n // we will need to change this code to potentially use the\n // $httpOverwrite parameter supported by ESF to avoid\n // triggering preflight requests.\n var headers = { 'Content-Type': 'text/plain' };\n _this.modifyHeadersForRequest(headers, token);\n xhr.send(url, 'POST', requestString, headers, XHR_TIMEOUT_SECS);\n });\n });\n };\n WebChannelConnection.prototype.openStream = function (rpcName, token) {\n var rpcService = WebChannelConnection.RPC_STREAM_SERVICE_MAPPING[rpcName];\n var rpcUrlName = WebChannelConnection.RPC_STREAM_NAME_MAPPING[rpcName];\n if (!rpcService || !rpcUrlName) {\n fail('Unknown RPC name: ' + rpcName);\n }\n var urlParts = [this.baseUrl, '/', rpcService, '/', rpcUrlName, '/channel'];\n var webchannelTransport = Object(dist[\"createWebChannelTransport\"])();\n var request = {\n // Background channel test avoids the initial two test calls and decreases\n // initial cold start time.\n // TODO(dimond): wenboz@ mentioned this might affect use with proxies and\n // we should monitor closely for any reports.\n backgroundChannelTest: true,\n // Required for backend stickiness, routing behavior is based on this\n // parameter.\n httpSessionIdParam: 'gsessionid',\n initMessageHeaders: {},\n sendRawJson: true,\n supportsCrossDomainXhr: true\n };\n this.modifyHeadersForRequest(request.initMessageHeaders, token);\n var url = urlParts.join('');\n debug(LOG_TAG, 'Creating WebChannel: ' + url + ' ' + request);\n // tslint:disable-next-line:no-any Because listen isn't defined on it.\n var channel = webchannelTransport.createWebChannel(url, request);\n // WebChannel supports sending the first message with the handshake - saving\n // a network round trip. However, it will have to call send in the same\n // JS event loop as open. In order to enforce this, we delay actually\n // opening the WebChannel until send is called. Whether we have called\n // open is tracked with this variable.\n var opened = false;\n // A flag to determine whether the stream was closed (by us or through an\n // error/close event) to avoid delivering multiple close events or sending\n // on a closed stream\n var closed = false;\n // tslint:disable-next-line:no-any\n var streamBridge = new stream_bridge_StreamBridge({\n sendFn: function sendFn(msg) {\n if (!closed) {\n if (!opened) {\n debug(LOG_TAG, 'Opening WebChannel transport.');\n channel.open();\n opened = true;\n }\n debug(LOG_TAG, 'WebChannel sending:', msg);\n channel.send(msg);\n } else {\n debug(LOG_TAG, 'Not sending because WebChannel is closed:', msg);\n }\n },\n closeFn: function closeFn() {\n return channel.close();\n }\n });\n // Closure events are guarded and exceptions are swallowed, so catch any\n // exception and rethrow using a setTimeout so they become visible again.\n // Note that eventually this function could go away if we are confident\n // enough the code is exception free.\n var unguardedEventListen = function unguardedEventListen(type, fn) {\n // TODO(dimond): closure typing seems broken because WebChannel does\n // not implement goog.events.Listenable\n channel.listen(type, function (param) {\n try {\n fn(param);\n } catch (e) {\n setTimeout(function () {\n throw e;\n }, 0);\n }\n });\n };\n unguardedEventListen(dist[\"WebChannel\"].EventType.OPEN, function () {\n if (!closed) {\n debug(LOG_TAG, 'WebChannel transport opened.');\n }\n });\n unguardedEventListen(dist[\"WebChannel\"].EventType.CLOSE, function () {\n if (!closed) {\n closed = true;\n debug(LOG_TAG, 'WebChannel transport closed');\n streamBridge.callOnClose();\n }\n });\n unguardedEventListen(dist[\"WebChannel\"].EventType.ERROR, function (err) {\n if (!closed) {\n closed = true;\n debug(LOG_TAG, 'WebChannel transport errored:', err);\n streamBridge.callOnClose(new FirestoreError(Code.UNAVAILABLE, 'The operation could not be completed'));\n }\n });\n unguardedEventListen(dist[\"WebChannel\"].EventType.MESSAGE, function (msg) {\n if (!closed) {\n // WebChannel delivers message events as array. If batching\n // is not enabled (it's off by default) each message will be\n // delivered alone, resulting in a single element array.\n var msgData = msg.data[0];\n assert(!!msgData, 'Got a webchannel message without data.');\n // TODO(b/35143891): There is a bug in One Platform that caused errors\n // (and only errors) to be wrapped in an extra array. To be forward\n // compatible with the bug we need to check either condition. The latter\n // can be removed once the fix has been rolled out.\n var error = msgData.error || msgData[0] && msgData[0].error;\n if (error) {\n debug(LOG_TAG, 'WebChannel received error:', error);\n // error.status will be a string like 'OK' or 'NOT_FOUND'.\n var status_2 = error.status;\n var code = mapCodeFromRpcStatus(status_2);\n var message = error.message;\n if (code === undefined) {\n code = Code.INTERNAL;\n message = 'Unknown error status: ' + status_2 + ' with message ' + error.message;\n }\n // Mark closed so no further events are propagated\n closed = true;\n streamBridge.callOnClose(new FirestoreError(code, message));\n channel.close();\n } else {\n debug(LOG_TAG, 'WebChannel received:', msgData);\n streamBridge.callOnMessage(msgData);\n }\n }\n });\n setTimeout(function () {\n // Technically we could/should wait for the WebChannel opened event,\n // but because we want to send the first message with the WebChannel\n // handshake we pretend the channel opened here (asynchronously), and\n // then delay the actual open until the first message is sent.\n streamBridge.callOnOpen();\n }, 0);\n return streamBridge;\n };\n // visible for testing\n WebChannelConnection.prototype.makeUrl = function (rpcName) {\n var url = [this.baseUrl, '/', RPC_URL_VERSION];\n url.push('/projects/');\n url.push(this.databaseId.projectId);\n url.push('/databases/');\n url.push(this.databaseId.database);\n url.push('/documents');\n url.push(':');\n url.push(rpcName);\n return url.join('');\n };\n /**\r\n * Mapping from RPC name to service providing the RPC.\r\n * For streaming RPCs only.\r\n */\n WebChannelConnection.RPC_STREAM_SERVICE_MAPPING = {\n Write: 'google.firestore.v1beta1.Firestore',\n Listen: 'google.firestore.v1beta1.Firestore'\n };\n /**\r\n * Mapping from RPC name to actual RPC name in URLs.\r\n * For streaming RPCs only.\r\n */\n WebChannelConnection.RPC_STREAM_NAME_MAPPING = {\n Write: 'Write',\n Listen: 'Listen'\n };\n return WebChannelConnection;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/platform_browser/browser_platform.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\nvar browser_platform_BrowserPlatform = /** @class */function () {\n function BrowserPlatform() {\n this.emptyByteString = '';\n this.base64Available = typeof atob !== 'undefined';\n }\n BrowserPlatform.prototype.loadConnection = function (databaseInfo) {\n return utils_promise[\"b\" /* PromiseImpl */].resolve(new webchannel_connection_WebChannelConnection(databaseInfo));\n };\n BrowserPlatform.prototype.newSerializer = function (databaseId) {\n return new serializer_JsonProtoSerializer(databaseId, { useProto3Json: true });\n };\n BrowserPlatform.prototype.atob = function (encoded) {\n return atob(encoded);\n };\n BrowserPlatform.prototype.btoa = function (raw) {\n return btoa(raw);\n };\n return BrowserPlatform;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/platform_browser/browser_init.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * This code needs to run before Firestore is used. This can be achieved in\r\n * several ways:\r\n * 1) Through the JSCompiler compiling this code and then (automatically)\r\n * executing it before exporting the Firestore symbols.\r\n * 2) Through importing this module first in a Firestore main module\r\n */\nplatform_PlatformSupport.setPlatform(new browser_platform_BrowserPlatform());\n// CONCATENATED MODULE: ./src/firestore/api/field_path.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n// The objects that are a part of this API are exposed to third-parties as\n// compiled javascript so we want to flag our private members with a leading\n// underscore to discourage their use.\n// tslint:disable:strip-private-property-underscore\n/**\r\n * A FieldPath refers to a field in a document. The path may consist of a single\r\n * field name (referring to a top-level field in the document), or a list of\r\n * field names (referring to a nested field in the document).\r\n */\nvar field_path_FieldPath = /** @class */function () {\n /**\r\n * Creates a FieldPath from the provided field names. If more than one field\r\n * name is provided, the path will point to a nested field in a document.\r\n *\r\n * @param fieldNames A list of field names.\r\n */\n function FieldPath() {\n var fieldNames = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n fieldNames[_i] = arguments[_i];\n }\n validateNamedArrayAtLeastNumberOfElements('FieldPath', fieldNames, 'fieldNames', 1);\n for (var i = 0; i < fieldNames.length; ++i) {\n validateArgType('FieldPath', 'string', i, fieldNames[i]);\n if (fieldNames[i].length === 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid field name at argument $(i + 1). \" + 'Field names must not be empty.');\n }\n }\n this._internalPath = new path_FieldPath(fieldNames);\n }\n FieldPath.documentId = function () {\n return FieldPath._DOCUMENT_ID;\n };\n /**\r\n * Internal Note: The backend doesn't technically support querying by\r\n * document ID. Instead it queries by the entire document name (full path\r\n * included), but in the cases we currently support documentId(), the net\r\n * effect is the same.\r\n */\n FieldPath._DOCUMENT_ID = new FieldPath(path_FieldPath.keyField().canonicalString());\n return FieldPath;\n}();\n\n/**\r\n * Matches any characters in a field path string that are reserved.\r\n */\nvar RESERVED = new RegExp('[~\\\\*/\\\\[\\\\]]');\n/**\r\n * Parses a field path string into a FieldPath, treating dots as separators.\r\n */\nfunction fromDotSeparatedString(path) {\n var found = path.search(RESERVED);\n if (found >= 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid field path (\" + path + \"). Paths must not contain \" + \"'~', '*', '/', '[', or ']'\");\n }\n try {\n return new (field_path_FieldPath.bind.apply(field_path_FieldPath, [void 0].concat(path.split('.'))))();\n } catch (e) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid field path (\" + path + \"). Paths must not be empty, \" + \"begin with '.', end with '.', or contain '..'\");\n }\n}\n// CONCATENATED MODULE: ./src/firestore/core/types.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n/** Describes the online state of the Firestore client */\nvar OnlineState;\n(function (OnlineState) {\n /**\r\n * The Firestore client is in an unknown online state. This means the client\r\n * is either not actively trying to establish a connection or it was\r\n * previously in an unknown state and is trying to establish a connection.\r\n */\n OnlineState[OnlineState[\"Unknown\"] = 0] = \"Unknown\";\n /**\r\n * The client is connected and the connections are healthy. This state is\r\n * reached after a successful connection and there has been at least one\r\n * succesful message received from the backends.\r\n */\n OnlineState[OnlineState[\"Healthy\"] = 1] = \"Healthy\";\n /**\r\n * The client has tried to establish a connection but has failed.\r\n * This state is reached after either a connection attempt failed or a\r\n * healthy stream was closed for unexpected reasons.\r\n */\n OnlineState[OnlineState[\"Failed\"] = 2] = \"Failed\";\n})(OnlineState || (OnlineState = {}));\n// CONCATENATED MODULE: ./src/firestore/core/view_snapshot.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\nvar ChangeType;\n(function (ChangeType) {\n ChangeType[ChangeType[\"Added\"] = 0] = \"Added\";\n ChangeType[ChangeType[\"Removed\"] = 1] = \"Removed\";\n ChangeType[ChangeType[\"Modified\"] = 2] = \"Modified\";\n ChangeType[ChangeType[\"Metadata\"] = 3] = \"Metadata\";\n})(ChangeType || (ChangeType = {}));\nvar SyncState;\n(function (SyncState) {\n SyncState[SyncState[\"Local\"] = 0] = \"Local\";\n SyncState[SyncState[\"Synced\"] = 1] = \"Synced\";\n})(SyncState || (SyncState = {}));\n/**\r\n * DocumentChangeSet keeps track of a set of changes to docs in a query, merging\r\n * duplicate events for the same doc.\r\n */\nvar view_snapshot_DocumentChangeSet = /** @class */function () {\n function DocumentChangeSet() {\n this.changeMap = new sorted_map_SortedMap(document_key_DocumentKey.comparator);\n }\n DocumentChangeSet.prototype.track = function (change) {\n var key = change.doc.key;\n var oldChange = this.changeMap.get(key);\n if (!oldChange) {\n this.changeMap = this.changeMap.insert(key, change);\n return;\n }\n // Merge the new change with the existing change.\n if (change.type !== ChangeType.Added && oldChange.type === ChangeType.Metadata) {\n this.changeMap = this.changeMap.insert(key, change);\n } else if (change.type === ChangeType.Metadata && oldChange.type !== ChangeType.Removed) {\n this.changeMap = this.changeMap.insert(key, {\n type: oldChange.type,\n doc: change.doc\n });\n } else if (change.type === ChangeType.Modified && oldChange.type === ChangeType.Modified) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Modified,\n doc: change.doc\n });\n } else if (change.type === ChangeType.Modified && oldChange.type === ChangeType.Added) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Added,\n doc: change.doc\n });\n } else if (change.type === ChangeType.Removed && oldChange.type === ChangeType.Added) {\n this.changeMap = this.changeMap.remove(key);\n } else if (change.type === ChangeType.Removed && oldChange.type === ChangeType.Modified) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Removed,\n doc: oldChange.doc\n });\n } else if (change.type === ChangeType.Added && oldChange.type === ChangeType.Removed) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Modified,\n doc: change.doc\n });\n } else {\n // This includes these cases, which don't make sense:\n // Added->Added\n // Removed->Removed\n // Modified->Added\n // Removed->Modified\n // Metadata->Added\n // Removed->Metadata\n fail('unsupported combination of changes: ' + JSON.stringify(change) + ' after ' + JSON.stringify(oldChange));\n }\n };\n DocumentChangeSet.prototype.getChanges = function () {\n var changes = [];\n this.changeMap.inorderTraversal(function (key, change) {\n changes.push(change);\n });\n return changes;\n };\n return DocumentChangeSet;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/model/document_set.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n/**\r\n * DocumentSet is an immutable (copy-on-write) collection that holds documents\r\n * in order specified by the provided comparator. We always add a document key\r\n * comparator on top of what is provided to guarantee document equality based on\r\n * the key.\r\n */\nvar document_set_DocumentSet = /** @class */function () {\n /** The default ordering is by key if the comparator is omitted */\n function DocumentSet(comp) {\n // We are adding document key comparator to the end as it's the only\n // guaranteed unique property of a document.\n if (comp) {\n this.comparator = function (d1, d2) {\n return comp(d1, d2) || document_key_DocumentKey.comparator(d1.key, d2.key);\n };\n } else {\n this.comparator = function (d1, d2) {\n return document_key_DocumentKey.comparator(d1.key, d2.key);\n };\n }\n this.keyedMap = documentMap();\n this.sortedSet = new sorted_map_SortedMap(this.comparator);\n }\n /**\r\n * Returns an empty copy of the existing DocumentSet, using the same\r\n * comparator.\r\n */\n DocumentSet.emptySet = function (oldSet) {\n return new DocumentSet(oldSet.comparator);\n };\n DocumentSet.prototype.has = function (key) {\n return this.keyedMap.get(key) != null;\n };\n DocumentSet.prototype.get = function (key) {\n return this.keyedMap.get(key);\n };\n DocumentSet.prototype.first = function () {\n return this.sortedSet.minKey();\n };\n DocumentSet.prototype.last = function () {\n return this.sortedSet.maxKey();\n };\n DocumentSet.prototype.isEmpty = function () {\n return this.sortedSet.isEmpty();\n };\n /**\r\n * Returns previous document or null if it's a first doc.\r\n *\r\n * @param key A key that MUST be present in the DocumentSet.\r\n */\n DocumentSet.prototype.prevDoc = function (key) {\n assert(this.has(key), 'Trying to get a previous document to non-existing key: ' + key);\n var doc = this.keyedMap.get(key);\n return this.sortedSet.getPredecessorKey(doc);\n };\n /**\r\n * Returns the index of the provided key in the document set, or -1 if the\r\n * document key is not present in the set;\r\n */\n DocumentSet.prototype.indexOf = function (key) {\n var doc = this.keyedMap.get(key);\n return doc ? this.sortedSet.indexOf(doc) : -1;\n };\n Object.defineProperty(DocumentSet.prototype, \"size\", {\n get: function get() {\n return this.sortedSet.size;\n },\n enumerable: true,\n configurable: true\n });\n /** Iterates documents in order defined by \"comparator\" */\n DocumentSet.prototype.forEach = function (cb) {\n this.sortedSet.inorderTraversal(function (k, v) {\n cb(k);\n return false;\n });\n };\n /** Inserts or updates a document with the same key */\n DocumentSet.prototype.add = function (doc) {\n // First remove the element if we have it.\n var set = this.delete(doc.key);\n return set.copy(set.keyedMap.insert(doc.key, doc), set.sortedSet.insert(doc, null));\n };\n /** Deletes a document with a given key */\n DocumentSet.prototype.delete = function (key) {\n var doc = this.get(key);\n if (!doc) {\n return this;\n }\n return this.copy(this.keyedMap.remove(key), this.sortedSet.remove(doc));\n };\n DocumentSet.prototype.equals = function (other) {\n if (!(other instanceof DocumentSet)) return false;\n if (this.size !== other.size) return false;\n var thisIt = this.sortedSet.getIterator();\n var otherIt = other.sortedSet.getIterator();\n while (thisIt.hasNext()) {\n var thisDoc = thisIt.getNext().key;\n var otherDoc = otherIt.getNext().key;\n if (!thisDoc.equals(otherDoc)) return false;\n }\n return true;\n };\n DocumentSet.prototype.toString = function () {\n var docStrings = [];\n this.forEach(function (doc) {\n docStrings.push(doc.toString());\n });\n if (docStrings.length === 0) {\n return 'DocumentSet ()';\n } else {\n return 'DocumentSet (\\n ' + docStrings.join(' \\n') + '\\n)';\n }\n };\n DocumentSet.prototype.copy = function (keyedMap, sortedSet) {\n var newSet = new DocumentSet();\n newSet.comparator = this.comparator;\n newSet.keyedMap = keyedMap;\n newSet.sortedSet = sortedSet;\n return newSet;\n };\n return DocumentSet;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/util/obj_map.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n/**\r\n * A map implementation that uses objects as keys. Objects must implement the\r\n * Equatable interface and must be immutable. Entries in the map are stored\r\n * together with the key being produced from the mapKeyFn. This map\r\n * automatically handles collisions of keys.\r\n */\nvar obj_map_ObjectMap = /** @class */function () {\n function ObjectMap(mapKeyFn) {\n this.mapKeyFn = mapKeyFn;\n /**\r\n * The inner map for a key -> value pair. Due to the possibility of\r\n * collisions we keep a list of entries that we do a linear search through\r\n * to find an actual match. Note that collisions should be rare, so we still\r\n * expect near constant time lookups in practice.\r\n */\n this.inner = {};\n }\n /** Get a value for this key, or undefined if it does not exist. */\n ObjectMap.prototype.get = function (key) {\n var id = this.mapKeyFn(key);\n var matches = this.inner[id];\n if (matches === undefined) {\n return undefined;\n }\n for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) {\n var _a = matches_1[_i],\n otherKey = _a[0],\n value = _a[1];\n if (otherKey.equals(key)) {\n return value;\n }\n }\n return undefined;\n };\n ObjectMap.prototype.has = function (key) {\n return this.get(key) !== undefined;\n };\n /** Put this key and value in the map. */\n ObjectMap.prototype.set = function (key, value) {\n var id = this.mapKeyFn(key);\n var matches = this.inner[id];\n if (matches === undefined) {\n this.inner[id] = [[key, value]];\n return;\n }\n for (var i = 0; i < matches.length; i++) {\n if (matches[i][0].equals(key)) {\n matches[i] = [key, value];\n return;\n }\n }\n matches.push([key, value]);\n };\n /**\r\n * Remove this key from the map. Returns a boolean if anything was deleted.\r\n */\n ObjectMap.prototype.delete = function (key) {\n var id = this.mapKeyFn(key);\n var matches = this.inner[id];\n if (matches === undefined) {\n return false;\n }\n for (var i = 0; i < matches.length; i++) {\n if (matches[i][0].equals(key)) {\n if (matches.length === 1) {\n delete this.inner[id];\n } else {\n matches.splice(i, 1);\n }\n return true;\n }\n }\n return false;\n };\n ObjectMap.prototype.forEach = function (fn) {\n forEach(this.inner, function (_, entries) {\n for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {\n var _a = entries_1[_i],\n k = _a[0],\n v = _a[1];\n fn(k, v);\n }\n });\n };\n ObjectMap.prototype.isEmpty = function () {\n return isEmpty(this.inner);\n };\n return ObjectMap;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/event_manager.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n/**\r\n * Holds the listeners and the last received ViewSnapshot for a query being\r\n * tracked by EventManager.\r\n */\nvar QueryListenersInfo = /** @class */function () {\n function QueryListenersInfo() {\n this.listeners = [];\n }\n return QueryListenersInfo;\n}();\n/**\r\n * EventManager is responsible for mapping queries to query event emitters.\r\n * It handles \"fan-out\". -- Identical queries will re-use the same watch on the\r\n * backend.\r\n */\nvar event_manager_EventManager = /** @class */function () {\n function EventManager(syncEngine) {\n this.syncEngine = syncEngine;\n this.queries = new obj_map_ObjectMap(function (q) {\n return q.canonicalId();\n });\n this.onlineState = OnlineState.Unknown;\n this.syncEngine.subscribe(this.onChange.bind(this), this.onError.bind(this));\n }\n EventManager.prototype.listen = function (listener) {\n var query = listener.query;\n var firstListen = false;\n var queryInfo = this.queries.get(query);\n if (!queryInfo) {\n firstListen = true;\n queryInfo = new QueryListenersInfo();\n this.queries.set(query, queryInfo);\n }\n queryInfo.listeners.push(listener);\n listener.onOnlineStateChanged(this.onlineState);\n if (queryInfo.viewSnap) listener.onViewSnapshot(queryInfo.viewSnap);\n if (firstListen) {\n return this.syncEngine.listen(query).then(function (targetId) {\n queryInfo.targetId = targetId;\n return targetId;\n });\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve(queryInfo.targetId);\n }\n };\n EventManager.prototype.unlisten = function (listener) {\n var query = listener.query;\n var lastListen = false;\n var queryInfo = this.queries.get(query);\n if (queryInfo) {\n var i = queryInfo.listeners.indexOf(listener);\n if (i >= 0) {\n queryInfo.listeners.splice(i, 1);\n lastListen = queryInfo.listeners.length === 0;\n }\n }\n if (lastListen) {\n this.queries.delete(query);\n return this.syncEngine.unlisten(query);\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n };\n EventManager.prototype.onChange = function (viewSnaps) {\n for (var _i = 0, viewSnaps_1 = viewSnaps; _i < viewSnaps_1.length; _i++) {\n var viewSnap = viewSnaps_1[_i];\n var query = viewSnap.query;\n var queryInfo = this.queries.get(query);\n if (queryInfo) {\n for (var _a = 0, _b = queryInfo.listeners; _a < _b.length; _a++) {\n var listener = _b[_a];\n listener.onViewSnapshot(viewSnap);\n }\n queryInfo.viewSnap = viewSnap;\n }\n }\n };\n EventManager.prototype.onError = function (query, error) {\n var queryInfo = this.queries.get(query);\n if (queryInfo) {\n for (var _i = 0, _a = queryInfo.listeners; _i < _a.length; _i++) {\n var listener = _a[_i];\n listener.onError(error);\n }\n }\n // Remove all listeners. NOTE: We don't need to call syncEngine.unlisten()\n // after an error.\n this.queries.delete(query);\n };\n EventManager.prototype.onOnlineStateChanged = function (onlineState) {\n this.onlineState = onlineState;\n this.queries.forEach(function (_, queryInfo) {\n for (var _i = 0, _a = queryInfo.listeners; _i < _a.length; _i++) {\n var listener = _a[_i];\n listener.onOnlineStateChanged(onlineState);\n }\n });\n };\n return EventManager;\n}();\n\n/**\r\n * QueryListener takes a series of internal view snapshots and determines\r\n * when to raise the event.\r\n *\r\n * It uses an Observer to dispatch events.\r\n */\nvar event_manager_QueryListener = /** @class */function () {\n function QueryListener(query, queryObserver, options) {\n this.query = query;\n this.queryObserver = queryObserver;\n /**\r\n * Initial snapshots (e.g. from cache) may not be propagated to the wrapped\r\n * observer. This flag is set to true once we've actually raised an event.\r\n */\n this.raisedInitialEvent = false;\n this.onlineState = OnlineState.Unknown;\n this.options = options || {};\n }\n QueryListener.prototype.onViewSnapshot = function (snap) {\n assert(snap.docChanges.length > 0 || snap.syncStateChanged, 'We got a new snapshot with no changes?');\n if (!this.options.includeDocumentMetadataChanges) {\n // Remove the metadata only changes.\n var docChanges = [];\n for (var _i = 0, _a = snap.docChanges; _i < _a.length; _i++) {\n var docChange = _a[_i];\n if (docChange.type !== ChangeType.Metadata) {\n docChanges.push(docChange);\n }\n }\n snap = {\n query: snap.query,\n docs: snap.docs,\n oldDocs: snap.oldDocs,\n docChanges: docChanges,\n fromCache: snap.fromCache,\n hasPendingWrites: snap.hasPendingWrites,\n syncStateChanged: snap.syncStateChanged\n };\n }\n if (!this.raisedInitialEvent) {\n if (this.shouldRaiseInitialEvent(snap, this.onlineState)) {\n this.raiseInitialEvent(snap);\n }\n } else if (this.shouldRaiseEvent(snap)) {\n this.queryObserver.next(snap);\n }\n this.snap = snap;\n };\n QueryListener.prototype.onError = function (error) {\n this.queryObserver.error(error);\n };\n QueryListener.prototype.onOnlineStateChanged = function (onlineState) {\n this.onlineState = onlineState;\n if (this.snap && !this.raisedInitialEvent && this.shouldRaiseInitialEvent(this.snap, onlineState)) {\n this.raiseInitialEvent(this.snap);\n }\n };\n QueryListener.prototype.shouldRaiseInitialEvent = function (snap, onlineState) {\n assert(!this.raisedInitialEvent, 'Determining whether to raise first event but already had first event');\n // Always raise the first event when we're synced\n if (!snap.fromCache) {\n return true;\n }\n // NOTE: We consider OnlineState.Unknown as online (it should become Failed\n // or Online if we wait long enough).\n var maybeOnline = onlineState !== OnlineState.Failed;\n // Don't raise the event if we're online, aren't synced yet (checked\n // above) and are waiting for a sync.\n if (this.options.waitForSyncWhenOnline && maybeOnline) {\n assert(snap.fromCache, 'Waiting for sync, but snapshot is not from cache');\n return false;\n }\n // Raise data from cache if we have any documents or we are offline\n return !snap.docs.isEmpty() || onlineState === OnlineState.Failed;\n };\n QueryListener.prototype.shouldRaiseEvent = function (snap) {\n // We don't need to handle includeDocumentMetadataChanges here because\n // the Metadata only changes have already been stripped out if needed.\n // At this point the only changes we will see are the ones we should\n // propagate.\n if (snap.docChanges.length > 0) {\n return true;\n }\n var hasPendingWritesChanged = this.snap && this.snap.hasPendingWrites !== snap.hasPendingWrites;\n if (snap.syncStateChanged || hasPendingWritesChanged) {\n return this.options.includeQueryMetadataChanges === true;\n }\n // Generally we should have hit one of the cases above, but it's possible\n // to get here if there were only metadata docChanges and they got\n // stripped out.\n return false;\n };\n QueryListener.prototype.raiseInitialEvent = function (snap) {\n assert(!this.raisedInitialEvent, 'Trying to raise initial events for second time');\n snap = {\n query: snap.query,\n docs: snap.docs,\n oldDocs: document_set_DocumentSet.emptySet(snap.docs),\n docChanges: QueryListener.getInitialViewChanges(snap),\n fromCache: snap.fromCache,\n hasPendingWrites: snap.hasPendingWrites,\n syncStateChanged: true\n };\n this.raisedInitialEvent = true;\n this.queryObserver.next(snap);\n };\n /** Returns changes as if all documents in the snap were added. */\n QueryListener.getInitialViewChanges = function (snap) {\n var result = [];\n snap.docs.forEach(function (doc) {\n result.push({ type: ChangeType.Added, doc: doc });\n });\n return result;\n };\n return QueryListener;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/persistence_promise.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * PersistencePromise<> is essentially a re-implementation of Promise<> except\r\n * it has a .next() method instead of .then() and .next() and .catch() callbacks\r\n * are executed synchronously when a PersistencePromise resolves rather than\r\n * asynchronously (Promise<> implementations use setImmediate() or similar).\r\n *\r\n * This is necessary to interoperate with IndexedDB which will automatically\r\n * commit transactions if control is returned to the event loop without\r\n * synchronously initiating another operation on the transaction.\r\n *\r\n * NOTE: .then() and .catch() only allow a single consumer, unlike normal\r\n * Promises.\r\n */\nvar persistence_promise_PersistencePromise = /** @class */function () {\n function PersistencePromise(callback) {\n var _this = this;\n // NOTE: next/catchCallback will always point to our own wrapper functions,\n // not the user's raw next() or catch() callbacks.\n this.nextCallback = null;\n this.catchCallback = null;\n // When the operation resolves, we'll set result or error and mark isDone.\n this.result = undefined;\n this.error = null;\n this.isDone = false;\n // Set to true when .then() or .catch() are called and prevents additional\n // chaining.\n this.callbackAttached = false;\n callback(function (value) {\n _this.isDone = true;\n _this.result = value;\n if (_this.nextCallback) {\n // value should be defined unless T is Void, but we can't express\n // that in the type system.\n _this.nextCallback(value);\n }\n }, function (error) {\n _this.isDone = true;\n _this.error = error;\n if (_this.catchCallback) {\n _this.catchCallback(error);\n }\n });\n }\n PersistencePromise.prototype.catch = function (fn) {\n return this.next(undefined, fn);\n };\n PersistencePromise.prototype.next = function (nextFn, catchFn) {\n var _this = this;\n if (this.callbackAttached) {\n fail('Called next() or catch() twice for PersistencePromise');\n }\n this.callbackAttached = true;\n if (this.isDone) {\n if (!this.error) {\n return this.wrapSuccess(nextFn, this.result);\n } else {\n return this.wrapFailure(catchFn, this.error);\n }\n } else {\n return new PersistencePromise(function (resolve, reject) {\n _this.nextCallback = function (value) {\n _this.wrapSuccess(nextFn, value).next(resolve, reject);\n };\n _this.catchCallback = function (error) {\n _this.wrapFailure(catchFn, error).next(resolve, reject);\n };\n });\n }\n };\n PersistencePromise.prototype.toPromise = function () {\n var _this = this;\n return new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n _this.next(resolve, reject);\n });\n };\n PersistencePromise.prototype.wrapUserFunction = function (fn) {\n try {\n var result = fn();\n if (result instanceof PersistencePromise) {\n return result;\n } else {\n return PersistencePromise.resolve(result);\n }\n } catch (e) {\n return PersistencePromise.reject(e);\n }\n };\n PersistencePromise.prototype.wrapSuccess = function (nextFn, value) {\n if (nextFn) {\n return this.wrapUserFunction(function () {\n return nextFn(value);\n });\n } else {\n // If there's no nextFn, then R must be the same as T but we\n // can't express that in the type system.\n return PersistencePromise.resolve(value);\n }\n };\n PersistencePromise.prototype.wrapFailure = function (catchFn, error) {\n if (catchFn) {\n return this.wrapUserFunction(function () {\n return catchFn(error);\n });\n } else {\n return PersistencePromise.reject(error);\n }\n };\n PersistencePromise.resolve = function (result) {\n return new PersistencePromise(function (resolve, reject) {\n resolve(result);\n });\n };\n PersistencePromise.reject = function (error) {\n return new PersistencePromise(function (resolve, reject) {\n reject(error);\n });\n };\n PersistencePromise.waitFor = function (all) {\n return all.reduce(function (promise, nextPromise, idx) {\n return promise.next(function () {\n return nextPromise;\n });\n }, PersistencePromise.resolve());\n };\n PersistencePromise.map = function (all) {\n var results = [];\n var first = true;\n // initial is ignored, so we can cheat on the type.\n var initial = PersistencePromise.resolve(null);\n return all.reduce(function (promise, nextPromise) {\n return promise.next(function (result) {\n if (!first) {\n results.push(result);\n }\n first = false;\n return nextPromise;\n });\n }, initial).next(function (result) {\n results.push(result);\n return results;\n });\n };\n return PersistencePromise;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/eager_garbage_collector.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * A garbage collector implementation that eagerly collects documents as soon as\r\n * they're no longer referenced in any of its registered GarbageSources.\r\n *\r\n * This implementation keeps track of a set of keys that are potentially garbage\r\n * without keeping an exact reference count. During collectGarbage, the\r\n * collector verifies that all potential garbage keys actually have no\r\n * references by consulting its list of garbage sources.\r\n */\nvar eager_garbage_collector_EagerGarbageCollector = /** @class */function () {\n function EagerGarbageCollector() {\n this.isEager = true;\n /**\r\n * The garbage collectible sources to double-check during garbage collection.\r\n */\n this.sources = [];\n /**\r\n * A set of potentially garbage keys.\r\n * PORTING NOTE: This would be a mutable set if Javascript had one.\r\n */\n this.potentialGarbage = documentKeySet();\n }\n EagerGarbageCollector.prototype.addGarbageSource = function (garbageSource) {\n this.sources.push(garbageSource);\n garbageSource.setGarbageCollector(this);\n };\n EagerGarbageCollector.prototype.removeGarbageSource = function (garbageSource) {\n this.sources.splice(this.sources.indexOf(garbageSource), 1);\n garbageSource.setGarbageCollector(null);\n };\n EagerGarbageCollector.prototype.addPotentialGarbageKey = function (key) {\n this.potentialGarbage = this.potentialGarbage.add(key);\n };\n EagerGarbageCollector.prototype.collectGarbage = function (txn) {\n var _this = this;\n var promises = [];\n var garbageKeys = documentKeySet();\n this.potentialGarbage.forEach(function (key) {\n var hasRefsPromise = _this.documentHasAnyReferences(txn, key);\n promises.push(hasRefsPromise.next(function (hasRefs) {\n // If there are no references, get the key.\n if (!hasRefs) {\n garbageKeys = garbageKeys.add(key);\n }\n return persistence_promise_PersistencePromise.resolve();\n }));\n });\n // Clear locally retained potential keys and returned confirmed garbage.\n this.potentialGarbage = documentKeySet();\n return persistence_promise_PersistencePromise.waitFor(promises).next(function () {\n return garbageKeys;\n });\n };\n EagerGarbageCollector.prototype.documentHasAnyReferences = function (txn, key) {\n var initial = persistence_promise_PersistencePromise.resolve(false);\n return this.sources.map(function (source) {\n return function () {\n return source.containsKey(txn, key);\n };\n }).reduce(function (promise, nextPromise) {\n return promise.next(function (result) {\n if (result) {\n return persistence_promise_PersistencePromise.resolve(true);\n } else {\n return nextPromise();\n }\n });\n }, initial);\n };\n return EagerGarbageCollector;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/local_view_changes.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * A set of changes to what documents are currently in view and out of view for\r\n * a given query. These changes are sent to the LocalStore by the View (via\r\n * the SyncEngine) and are used to pin / unpin documents as appropriate.\r\n */\nvar local_view_changes_LocalViewChanges = /** @class */function () {\n function LocalViewChanges(query, addedKeys, removedKeys) {\n this.query = query;\n this.addedKeys = addedKeys;\n this.removedKeys = removedKeys;\n }\n LocalViewChanges.fromSnapshot = function (viewSnapshot) {\n var addedKeys = documentKeySet();\n var removedKeys = documentKeySet();\n for (var _i = 0, _a = viewSnapshot.docChanges; _i < _a.length; _i++) {\n var docChange = _a[_i];\n switch (docChange.type) {\n case ChangeType.Added:\n addedKeys = addedKeys.add(docChange.doc.key);\n break;\n case ChangeType.Removed:\n removedKeys = removedKeys.add(docChange.doc.key);\n break;\n default:\n }\n }\n return new LocalViewChanges(viewSnapshot.query, addedKeys, removedKeys);\n };\n return LocalViewChanges;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/reference_set.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n/**\r\n * A collection of references to a document from some kind of numbered entity\r\n * (either a target ID or batch ID). As references are added to or removed from\r\n * the set corresponding events are emitted to a registered garbage collector.\r\n *\r\n * Each reference is represented by a DocumentReference object. Each of them\r\n * contains enough information to uniquely identify the reference. They are all\r\n * stored primarily in a set sorted by key. A document is considered garbage if\r\n * there's no references in that set (this can be efficiently checked thanks to\r\n * sorting by key).\r\n *\r\n * ReferenceSet also keeps a secondary set that contains references sorted by\r\n * IDs. This one is used to efficiently implement removal of all references by\r\n * some target ID.\r\n */\nvar reference_set_ReferenceSet = /** @class */function () {\n function ReferenceSet() {\n // A set of outstanding references to a document sorted by key.\n this.refsByKey = new sorted_set_SortedSet(reference_set_DocReference.compareByKey);\n // A set of outstanding references to a document sorted by target id.\n this.refsByTarget = new sorted_set_SortedSet(reference_set_DocReference.compareByTargetId);\n /** Keeps track of keys that have references */\n this.garbageCollector = null;\n }\n /** Returns true if the reference set contains no references. */\n ReferenceSet.prototype.isEmpty = function () {\n return this.refsByKey.isEmpty();\n };\n /** Adds a reference to the given document key for the given ID. */\n ReferenceSet.prototype.addReference = function (key, id) {\n var ref = new reference_set_DocReference(key, id);\n this.refsByKey = this.refsByKey.add(ref);\n this.refsByTarget = this.refsByTarget.add(ref);\n };\n /** Add references to the given document keys for the given ID. */\n ReferenceSet.prototype.addReferences = function (keys, id) {\n var _this = this;\n keys.forEach(function (key) {\n return _this.addReference(key, id);\n });\n };\n /**\r\n * Removes a reference to the given document key for the given\r\n * ID.\r\n */\n ReferenceSet.prototype.removeReference = function (key, id) {\n this.removeRef(new reference_set_DocReference(key, id));\n };\n ReferenceSet.prototype.removeReferences = function (keys, id) {\n var _this = this;\n keys.forEach(function (key) {\n return _this.removeReference(key, id);\n });\n };\n /**\r\n * Clears all references with a given ID. Calls removeRef() for each key\r\n * removed.\r\n */\n ReferenceSet.prototype.removeReferencesForId = function (id) {\n var _this = this;\n var emptyKey = document_key_DocumentKey.EMPTY;\n var startRef = new reference_set_DocReference(emptyKey, id);\n var endRef = new reference_set_DocReference(emptyKey, id + 1);\n this.refsByTarget.forEachInRange([startRef, endRef], function (ref) {\n _this.removeRef(ref);\n });\n };\n ReferenceSet.prototype.removeAllReferences = function () {\n var _this = this;\n this.refsByKey.forEach(function (ref) {\n return _this.removeRef(ref);\n });\n };\n ReferenceSet.prototype.removeRef = function (ref) {\n this.refsByKey = this.refsByKey.delete(ref);\n this.refsByTarget = this.refsByTarget.delete(ref);\n if (this.garbageCollector !== null) {\n this.garbageCollector.addPotentialGarbageKey(ref.key);\n }\n };\n ReferenceSet.prototype.referencesForId = function (id) {\n var emptyKey = document_key_DocumentKey.EMPTY;\n var startRef = new reference_set_DocReference(emptyKey, id);\n var endRef = new reference_set_DocReference(emptyKey, id + 1);\n var keys = documentKeySet();\n this.refsByTarget.forEachInRange([startRef, endRef], function (ref) {\n keys = keys.add(ref.key);\n });\n return keys;\n };\n ReferenceSet.prototype.setGarbageCollector = function (garbageCollector) {\n this.garbageCollector = garbageCollector;\n };\n ReferenceSet.prototype.containsKey = function (txn, key) {\n var ref = new reference_set_DocReference(key, 0);\n var firstRef = this.refsByKey.firstAfterOrEqual(ref);\n return persistence_promise_PersistencePromise.resolve(firstRef !== null && key.equals(firstRef.key));\n };\n return ReferenceSet;\n}();\n\nvar reference_set_DocReference = /** @class */function () {\n function DocReference(key, targetOrBatchId) {\n this.key = key;\n this.targetOrBatchId = targetOrBatchId;\n }\n /** Compare by key then by ID */\n DocReference.compareByKey = function (left, right) {\n return document_key_DocumentKey.comparator(left.key, right.key) || primitiveComparator(left.targetOrBatchId, right.targetOrBatchId);\n };\n /** Compare by ID then by key */\n DocReference.compareByTargetId = function (left, right) {\n return primitiveComparator(left.targetOrBatchId, right.targetOrBatchId) || document_key_DocumentKey.comparator(left.key, right.key);\n };\n return DocReference;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/target_id_generator.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar RESERVED_BITS = 1;\nvar GeneratorIds;\n(function (GeneratorIds) {\n GeneratorIds[GeneratorIds[\"LocalStore\"] = 0] = \"LocalStore\";\n GeneratorIds[GeneratorIds[\"SyncEngine\"] = 1] = \"SyncEngine\";\n})(GeneratorIds || (GeneratorIds = {}));\n/**\r\n * TargetIdGenerator generates monotonically increasing integer IDs. There are\r\n * separate generators for different scopes. While these generators will operate\r\n * independently of each other, they are scoped, such that no two generators\r\n * will ever produce the same ID. This is useful, because sometimes the backend\r\n * may group IDs from separate parts of the client into the same ID space.\r\n */\nvar TargetIdGenerator = /** @class */function () {\n function TargetIdGenerator(generatorId, initAfter) {\n if (initAfter === void 0) {\n initAfter = 0;\n }\n this.generatorId = generatorId;\n // Replace the generator part of initAfter with this generator's ID.\n var afterWithoutGenerator = initAfter >> RESERVED_BITS << RESERVED_BITS;\n var afterGenerator = initAfter - afterWithoutGenerator;\n if (afterGenerator >= generatorId) {\n // For example, if:\n // this.generatorId = 0b0000\n // after = 0b1011\n // afterGenerator = 0b0001\n // Then:\n // previous = 0b1010\n // next = 0b1100\n this.previousId = afterWithoutGenerator | this.generatorId;\n } else {\n // For example, if:\n // this.generatorId = 0b0001\n // after = 0b1010\n // afterGenerator = 0b0000\n // Then:\n // previous = 0b1001\n // next = 0b1011\n this.previousId = (afterWithoutGenerator | this.generatorId) - (1 << RESERVED_BITS);\n }\n }\n TargetIdGenerator.prototype.next = function () {\n this.previousId += 1 << RESERVED_BITS;\n return this.previousId;\n };\n TargetIdGenerator.forLocalStore = function (initAfter) {\n if (initAfter === void 0) {\n initAfter = 0;\n }\n return new TargetIdGenerator(GeneratorIds.LocalStore, initAfter);\n };\n TargetIdGenerator.forSyncEngine = function () {\n return new TargetIdGenerator(GeneratorIds.SyncEngine);\n };\n return TargetIdGenerator;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/view.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\nvar AddedLimboDocument = /** @class */function () {\n function AddedLimboDocument(key) {\n this.key = key;\n }\n return AddedLimboDocument;\n}();\n\nvar RemovedLimboDocument = /** @class */function () {\n function RemovedLimboDocument(key) {\n this.key = key;\n }\n return RemovedLimboDocument;\n}();\n\n/**\r\n * View is responsible for computing the final merged truth of what docs are in\r\n * a query. It gets notified of local and remote changes to docs, and applies\r\n * the query filters and limits to determine the most correct possible results.\r\n */\nvar view_View = /** @class */function () {\n function View(query,\n /** Documents included in the remote target */\n syncedDocuments) {\n this.query = query;\n this.syncedDocuments = syncedDocuments;\n this.syncState = null;\n /**\r\n * A flag whether the view is current with the backend. A view is considered\r\n * current after it has seen the current flag from the backend and did not\r\n * lose consistency within the watch stream (e.g. because of an existence\r\n * filter mismatch).\r\n */\n this.current = false;\n /** Documents in the view but not in the remote target */\n this.limboDocuments = documentKeySet();\n /** Document Keys that have local changes */\n this.mutatedKeys = documentKeySet();\n this.documentSet = new document_set_DocumentSet(query.docComparator.bind(query));\n }\n /**\r\n * Iterates over a set of doc changes, applies the query limit, and computes\r\n * what the new results should be, what the changes were, and whether we may\r\n * need to go back to the local cache for more results. Does not make any\r\n * changes to the view.\r\n * @param docChanges The doc changes to apply to this view.\r\n * @param previousChanges If this is being called with a refill, then start\r\n * with this set of docs and changes instead of the current view.\r\n * @return a new set of docs, changes, and refill flag.\r\n */\n View.prototype.computeDocChanges = function (docChanges, previousChanges) {\n var _this = this;\n var changeSet = previousChanges ? previousChanges.changeSet : new view_snapshot_DocumentChangeSet();\n var oldDocumentSet = previousChanges ? previousChanges.documentSet : this.documentSet;\n var newMutatedKeys = previousChanges ? previousChanges.mutatedKeys : this.mutatedKeys;\n var newDocumentSet = oldDocumentSet;\n var needsRefill = false;\n // Track the last doc in a (full) limit. This is necessary, because some\n // update (a delete, or an update moving a doc past the old limit) might\n // mean there is some other document in the local cache that either should\n // come (1) between the old last limit doc and the new last document, in the\n // case of updates, or (2) after the new last document, in the case of\n // deletes. So we keep this doc at the old limit to compare the updates to.\n //\n // Note that this should never get used in a refill (when previousChanges is\n // set), because there will only be adds -- no deletes or updates.\n var lastDocInLimit = this.query.hasLimit() && oldDocumentSet.size === this.query.limit ? oldDocumentSet.last() : null;\n docChanges.inorderTraversal(function (key, newMaybeDoc) {\n var oldDoc = oldDocumentSet.get(key);\n var newDoc = newMaybeDoc instanceof document_Document ? newMaybeDoc : null;\n if (newDoc) {\n assert(key.equals(newDoc.key), 'Mismatching keys found in document changes: ' + key + ' != ' + newDoc.key);\n newDoc = _this.query.matches(newDoc) ? newDoc : null;\n }\n if (newDoc) {\n newDocumentSet = newDocumentSet.add(newDoc);\n if (newDoc.hasLocalMutations) {\n newMutatedKeys = newMutatedKeys.add(key);\n } else {\n newMutatedKeys = newMutatedKeys.delete(key);\n }\n } else {\n newDocumentSet = newDocumentSet.delete(key);\n newMutatedKeys = newMutatedKeys.delete(key);\n }\n // Calculate change\n if (oldDoc && newDoc) {\n var docsEqual = oldDoc.data.equals(newDoc.data);\n if (!docsEqual || oldDoc.hasLocalMutations !== newDoc.hasLocalMutations) {\n // only report a change if document actually changed\n if (docsEqual) {\n changeSet.track({ type: ChangeType.Metadata, doc: newDoc });\n } else {\n changeSet.track({ type: ChangeType.Modified, doc: newDoc });\n }\n if (lastDocInLimit && _this.query.docComparator(newDoc, lastDocInLimit) > 0) {\n // This doc moved from inside the limit to after the limit.\n // That means there may be some doc in the local cache that's\n // actually less than this one.\n needsRefill = true;\n }\n }\n } else if (!oldDoc && newDoc) {\n changeSet.track({ type: ChangeType.Added, doc: newDoc });\n } else if (oldDoc && !newDoc) {\n changeSet.track({ type: ChangeType.Removed, doc: oldDoc });\n if (lastDocInLimit) {\n // A doc was removed from a full limit query. We'll need to\n // requery from the local cache to see if we know about some other\n // doc that should be in the results.\n needsRefill = true;\n }\n }\n });\n if (this.query.hasLimit()) {\n // TODO(klimt): Make DocumentSet size be constant time.\n while (newDocumentSet.size > this.query.limit) {\n var oldDoc = newDocumentSet.last();\n newDocumentSet = newDocumentSet.delete(oldDoc.key);\n changeSet.track({ type: ChangeType.Removed, doc: oldDoc });\n }\n }\n assert(!needsRefill || !previousChanges, 'View was refilled using docs that themselves needed refilling.');\n return {\n documentSet: newDocumentSet,\n changeSet: changeSet,\n needsRefill: needsRefill,\n mutatedKeys: newMutatedKeys\n };\n };\n /**\r\n * Updates the view with the given ViewDocumentChanges and updates limbo docs\r\n * and sync state from the given (optional) target change.\r\n * @param docChanges The set of changes to make to the view's docs.\r\n * @param targetChange A target change to apply for computing limbo docs and\r\n * sync state.\r\n * @return A new ViewChange with the given docs, changes, and sync state.\r\n */\n View.prototype.applyChanges = function (docChanges, targetChange) {\n var _this = this;\n assert(!docChanges.needsRefill, 'Cannot apply changes that need a refill');\n var oldDocs = this.documentSet;\n this.documentSet = docChanges.documentSet;\n this.mutatedKeys = docChanges.mutatedKeys;\n // Sort changes based on type and query comparator\n var changes = docChanges.changeSet.getChanges();\n changes.sort(function (c1, c2) {\n return compareChangeType(c1.type, c2.type) || _this.query.docComparator(c1.doc, c2.doc);\n });\n var limboChanges = this.applyTargetChange(targetChange);\n var synced = this.limboDocuments.size === 0 && this.current;\n var newSyncState = synced ? SyncState.Synced : SyncState.Local;\n var syncStateChanged = newSyncState !== this.syncState;\n this.syncState = newSyncState;\n if (changes.length === 0 && !syncStateChanged) {\n // no changes\n return { limboChanges: limboChanges };\n } else {\n return {\n snapshot: {\n query: this.query,\n docs: docChanges.documentSet,\n oldDocs: oldDocs,\n docChanges: changes,\n fromCache: newSyncState === SyncState.Local,\n syncStateChanged: syncStateChanged,\n hasPendingWrites: !docChanges.mutatedKeys.isEmpty()\n },\n limboChanges: limboChanges\n };\n }\n };\n /**\r\n * Returns whether the doc for the given key should be in limbo.\r\n */\n View.prototype.shouldBeInLimbo = function (key) {\n // If the remote end says it's part of this query, it's not in limbo.\n if (this.syncedDocuments.has(key)) {\n return false;\n }\n // The local store doesn't think it's a result, so it shouldn't be in limbo.\n if (!this.documentSet.has(key)) {\n return false;\n }\n // If there are local changes to the doc, they might explain why the server\n // doesn't know that it's part of the query. So don't put it in limbo.\n // TODO(klimt): Ideally, we would only consider changes that might actually\n // affect this specific query.\n if (this.documentSet.get(key).hasLocalMutations) {\n return false;\n }\n // Everything else is in limbo.\n return true;\n };\n /**\r\n * Updates syncedDocuments, current, and limbo docs based on the given change.\r\n * Returns the list of changes to which docs are in limbo.\r\n */\n View.prototype.applyTargetChange = function (targetChange) {\n var _this = this;\n if (targetChange) {\n var targetMapping = targetChange.mapping;\n if (targetMapping instanceof ResetMapping) {\n this.syncedDocuments = targetMapping.documents;\n } else if (targetMapping instanceof UpdateMapping) {\n this.syncedDocuments = targetMapping.applyToKeySet(this.syncedDocuments);\n }\n switch (targetChange.currentStatusUpdate) {\n case CurrentStatusUpdate.MarkCurrent:\n this.current = true;\n break;\n case CurrentStatusUpdate.MarkNotCurrent:\n this.current = false;\n break;\n case CurrentStatusUpdate.None:\n break;\n default:\n fail('Unknown current status update: ' + targetChange.currentStatusUpdate);\n }\n }\n // Recompute the set of limbo docs.\n // TODO(klimt): Do this incrementally so that it's not quadratic when\n // updating many documents.\n var oldLimboDocuments = this.limboDocuments;\n this.limboDocuments = documentKeySet();\n if (this.current) {\n this.documentSet.forEach(function (doc) {\n if (_this.shouldBeInLimbo(doc.key)) {\n _this.limboDocuments = _this.limboDocuments.add(doc.key);\n }\n });\n }\n // Diff the new limbo docs with the old limbo docs.\n var changes = [];\n oldLimboDocuments.forEach(function (key) {\n if (!_this.limboDocuments.has(key)) {\n changes.push(new RemovedLimboDocument(key));\n }\n });\n this.limboDocuments.forEach(function (key) {\n if (!oldLimboDocuments.has(key)) {\n changes.push(new AddedLimboDocument(key));\n }\n });\n return changes;\n };\n return View;\n}();\n\nfunction compareChangeType(c1, c2) {\n var order = function order(change) {\n switch (change) {\n case ChangeType.Added:\n return 1;\n case ChangeType.Modified:\n return 2;\n case ChangeType.Metadata:\n // A metadata change is converted to a modified change at the public\n // api layer. Since we sort by document key and then change type,\n // metadata and modified changes must be sorted equivalently.\n return 2;\n case ChangeType.Removed:\n return 0;\n default:\n return fail('Unknown ChangeType: ' + change);\n }\n };\n return order(c1) - order(c2);\n}\n// CONCATENATED MODULE: ./src/firestore/core/sync_engine.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar sync_engine_LOG_TAG = 'SyncEngine';\n/**\r\n * QueryView contains all of the data that SyncEngine needs to keep track of for\r\n * a particular query.\r\n */\nvar QueryView = /** @class */function () {\n function QueryView(\n /**\r\n * The query itself.\r\n */\n query,\n /**\r\n * The target number created by the client that is used in the watch\r\n * stream to identify this query.\r\n */\n targetId,\n /**\r\n * An identifier from the datastore backend that indicates the last state\r\n * of the results that was received. This can be used to indicate where\r\n * to continue receiving new doc changes for the query.\r\n */\n resumeToken,\n /**\r\n * The view is responsible for computing the final merged truth of what\r\n * docs are in the query. It gets notified of local and remote changes,\r\n * and applies the query filters and limits to determine the most correct\r\n * possible results.\r\n */\n view) {\n this.query = query;\n this.targetId = targetId;\n this.resumeToken = resumeToken;\n this.view = view;\n }\n return QueryView;\n}();\n/**\r\n * SyncEngine is the central controller in the client SDK architecture. It is\r\n * the glue code between the EventManager, LocalStore, and RemoteStore. Some of\r\n * SyncEngine's responsibilities include:\r\n * 1. Coordinating client requests and remote events between the EventManager\r\n * and the local and remote data stores.\r\n * 2. Managing a View object for each query, providing the unified view between\r\n * the local and remote data stores.\r\n * 3. Notifying the RemoteStore when the LocalStore has new mutations in its\r\n * queue that need sending to the backend.\r\n *\r\n * The SyncEngine’s methods should only ever be called by methods running in the\r\n * global async queue.\r\n */\nvar sync_engine_SyncEngine = /** @class */function () {\n function SyncEngine(localStore, remoteStore, currentUser) {\n this.localStore = localStore;\n this.remoteStore = remoteStore;\n this.currentUser = currentUser;\n this.viewHandler = null;\n this.errorHandler = null;\n this.queryViewsByQuery = new obj_map_ObjectMap(function (q) {\n return q.canonicalId();\n });\n this.queryViewsByTarget = {};\n this.limboTargetsByKey = new sorted_map_SortedMap(document_key_DocumentKey.comparator);\n this.limboKeysByTarget = {};\n this.limboDocumentRefs = new reference_set_ReferenceSet();\n this.limboCollector = new eager_garbage_collector_EagerGarbageCollector();\n /** Stores user completion handlers, indexed by User and BatchId. */\n this.mutationUserCallbacks = {};\n this.targetIdGenerator = TargetIdGenerator.forSyncEngine();\n }\n /** Subscribes view and error handler. Can be called only once. */\n SyncEngine.prototype.subscribe = function (viewHandler, errorHandler) {\n assert(viewHandler !== null && errorHandler !== null, 'View and error handlers cannot be null');\n assert(this.viewHandler === null && this.errorHandler === null, 'SyncEngine already has a subscriber.');\n this.viewHandler = viewHandler;\n this.errorHandler = errorHandler;\n this.limboCollector.addGarbageSource(this.limboDocumentRefs);\n };\n /**\r\n * Initiates the new listen, resolves promise when listen enqueued to the\r\n * server. All the subsequent view snapshots or errors are sent to the\r\n * subscribed handlers. Returns the targetId of the query.\r\n */\n SyncEngine.prototype.listen = function (query) {\n var _this = this;\n this.assertSubscribed('listen()');\n assert(!this.queryViewsByQuery.has(query), 'We already listen to the query: ' + query);\n return this.localStore.allocateQuery(query).then(function (queryData) {\n return _this.localStore.executeQuery(query).then(function (docs) {\n return _this.localStore.remoteDocumentKeys(queryData.targetId).then(function (remoteKeys) {\n var view = new view_View(query, remoteKeys);\n var viewDocChanges = view.computeDocChanges(docs);\n var viewChange = view.applyChanges(viewDocChanges);\n assert(viewChange.limboChanges.length === 0, 'View returned limbo docs before target ack from the server.');\n assert(!!viewChange.snapshot, 'applyChanges for new view should always return a snapshot');\n var data = new QueryView(query, queryData.targetId, queryData.resumeToken, view);\n _this.queryViewsByQuery.set(query, data);\n _this.queryViewsByTarget[queryData.targetId] = data;\n _this.viewHandler([viewChange.snapshot]);\n _this.remoteStore.listen(queryData);\n });\n }).then(function () {\n return queryData.targetId;\n });\n });\n };\n /** Stops listening to the query. */\n SyncEngine.prototype.unlisten = function (query) {\n var _this = this;\n this.assertSubscribed('unlisten()');\n var queryView = this.queryViewsByQuery.get(query);\n assert(!!queryView, 'Trying to unlisten on query not found:' + query);\n return this.localStore.releaseQuery(query).then(function () {\n _this.remoteStore.unlisten(queryView.targetId);\n return _this.removeAndCleanupQuery(queryView).then(function () {\n return _this.localStore.collectGarbage();\n });\n });\n };\n /**\r\n * Initiates the write of local mutation batch which involves adding the\r\n * writes to the mutation queue, notifying the remote store about new\r\n * mutations and raising events for any changes this write caused.\r\n *\r\n * The promise returned by this call is resolved when the above steps\r\n * have completed, *not* when the write was acked by the backend. The\r\n * userCallback is resolved once the write was acked/rejected by the\r\n * backend (or failed locally for any other reason).\r\n */\n SyncEngine.prototype.write = function (batch, userCallback) {\n var _this = this;\n this.assertSubscribed('write()');\n return this.localStore.localWrite(batch).then(function (result) {\n _this.addMutationCallback(result.batchId, userCallback);\n return _this.emitNewSnapsAndNotifyLocalStore(result.changes);\n }).then(function () {\n return _this.remoteStore.fillWritePipeline();\n });\n };\n // TODO(klimt): Wrap the given error in a standard Firestore error object.\n SyncEngine.prototype.wrapUpdateFunctionError = function (error) {\n return error;\n };\n /**\r\n * Takes an updateFunction in which a set of reads and writes can be performed\r\n * atomically. In the updateFunction, the client can read and write values\r\n * using the supplied transaction object. After the updateFunction, all\r\n * changes will be committed. If some other client has changed any of the data\r\n * referenced, then the updateFunction will be called again. If the\r\n * updateFunction still fails after the given number of retries, then the\r\n * transaction will be rejection.\r\n *\r\n * The transaction object passed to the updateFunction contains methods for\r\n * accessing documents and collections. Unlike other datastore access, data\r\n * accessed with the transaction will not reflect local changes that have not\r\n * been committed. For this reason, it is required that all reads are\r\n * performed before any writes. Transactions must be performed while online.\r\n *\r\n * The promise returned is resolved when the transaction is fully committed.\r\n */\n SyncEngine.prototype.runTransaction = function (updateFunction, retries) {\n var _this = this;\n if (retries === void 0) {\n retries = 5;\n }\n assert(retries >= 0, 'Got negative number of retries for transaction.');\n var transaction = this.remoteStore.createTransaction();\n var wrappedUpdateFunction = function wrappedUpdateFunction() {\n try {\n var userPromise = updateFunction(transaction);\n if (isNullOrUndefined(userPromise) || !userPromise.catch || !userPromise.then) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(Error('Transaction callback must return a Promise'));\n }\n return userPromise.catch(function (e) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(_this.wrapUpdateFunctionError(e));\n });\n } catch (e) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(_this.wrapUpdateFunctionError(e));\n }\n };\n return wrappedUpdateFunction().then(function (result) {\n return transaction.commit().then(function () {\n return result;\n }).catch(function (error) {\n if (retries === 0) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(error);\n }\n // TODO(klimt): Put in a retry delay?\n return _this.runTransaction(updateFunction, retries - 1);\n });\n });\n };\n SyncEngine.prototype.applyRemoteEvent = function (remoteEvent) {\n var _this = this;\n this.assertSubscribed('applyRemoteEvent()');\n // Make sure limbo documents are deleted if there were no results\n forEachNumber(remoteEvent.targetChanges, function (targetId, targetChange) {\n var limboKey = _this.limboKeysByTarget[targetId];\n if (limboKey && targetChange.currentStatusUpdate === CurrentStatusUpdate.MarkCurrent && !remoteEvent.documentUpdates.get(limboKey)) {\n // When listening to a query the server responds with a snapshot\n // containing documents matching the query and a current marker\n // telling us we're now in sync. It's possible for these to arrive\n // as separate remote events or as a single remote event.\n // For a document query, there will be no documents sent in the\n // response if the document doesn't exist.\n //\n // If the snapshot arrives separately from the current marker,\n // we handle it normally and updateTrackedLimbos will resolve the\n // limbo status of the document, removing it from limboDocumentRefs.\n // This works because clients only initiate limbo resolution when\n // a target is current and because all current targets are\n // always at a consistent snapshot.\n //\n // However, if the document doesn't exist and the current marker\n // arrives, the document is not present in the snapshot and our\n // normal view handling would consider the document to remain in\n // limbo indefinitely because there are no updates to the document.\n // To avoid this, we specially handle this just this case here:\n // synthesizing a delete.\n //\n // TODO(dimond): Ideally we would have an explicit lookup query\n // instead resulting in an explicit delete message and we could\n // remove this special logic.\n remoteEvent.addDocumentUpdate(new document_NoDocument(limboKey, remoteEvent.snapshotVersion));\n }\n });\n return this.localStore.applyRemoteEvent(remoteEvent).then(function (changes) {\n return _this.emitNewSnapsAndNotifyLocalStore(changes, remoteEvent);\n });\n };\n SyncEngine.prototype.rejectListen = function (targetId, err) {\n var _this = this;\n this.assertSubscribed('rejectListens()');\n var limboKey = this.limboKeysByTarget[targetId];\n if (limboKey) {\n // Since this query failed, we won't want to manually unlisten to it.\n // So go ahead and remove it from bookkeeping.\n this.limboTargetsByKey = this.limboTargetsByKey.remove(limboKey);\n delete this.limboKeysByTarget[targetId];\n // TODO(klimt): We really only should do the following on permission\n // denied errors, but we don't have the cause code here.\n // It's a limbo doc. Create a synthetic event saying it was deleted.\n // This is kind of a hack. Ideally, we would have a method in the local\n // store to purge a document. However, it would be tricky to keep all of\n // the local store's invariants with another method.\n var docMap = new sorted_map_SortedMap(document_key_DocumentKey.comparator);\n docMap = docMap.insert(limboKey, new document_NoDocument(limboKey, snapshot_version_SnapshotVersion.forDeletedDoc()));\n var event_1 = new remote_event_RemoteEvent(snapshot_version_SnapshotVersion.MIN, {}, docMap);\n return this.applyRemoteEvent(event_1);\n } else {\n var queryView_1 = this.queryViewsByTarget[targetId];\n assert(!!queryView_1, 'Unknown targetId: ' + targetId);\n return this.localStore.releaseQuery(queryView_1.query).then(function () {\n return _this.removeAndCleanupQuery(queryView_1).then(function () {\n _this.errorHandler(queryView_1.query, err);\n });\n });\n }\n };\n SyncEngine.prototype.applySuccessfulWrite = function (mutationBatchResult) {\n var _this = this;\n this.assertSubscribed('applySuccessfulWrite()');\n // The local store may or may not be able to apply the write result and\n // raise events immediately (depending on whether the watcher is caught\n // up), so we raise user callbacks first so that they consistently happen\n // before listen events.\n this.processUserCallback(mutationBatchResult.batch.batchId,\n /*error=*/null);\n return this.localStore.acknowledgeBatch(mutationBatchResult).then(function (changes) {\n return _this.emitNewSnapsAndNotifyLocalStore(changes);\n });\n };\n SyncEngine.prototype.rejectFailedWrite = function (batchId, error) {\n var _this = this;\n this.assertSubscribed('rejectFailedWrite()');\n // The local store may or may not be able to apply the write result and\n // raise events immediately (depending on whether the watcher is caught up),\n // so we raise user callbacks first so that they consistently happen before\n // listen events.\n this.processUserCallback(batchId, error);\n return this.localStore.rejectBatch(batchId).then(function (changes) {\n return _this.emitNewSnapsAndNotifyLocalStore(changes);\n });\n };\n SyncEngine.prototype.addMutationCallback = function (batchId, callback) {\n var newCallbacks = this.mutationUserCallbacks[this.currentUser.toKey()];\n if (!newCallbacks) {\n newCallbacks = new sorted_map_SortedMap(primitiveComparator);\n }\n newCallbacks = newCallbacks.insert(batchId, callback);\n this.mutationUserCallbacks[this.currentUser.toKey()] = newCallbacks;\n };\n /**\r\n * Resolves or rejects the user callback for the given batch and then discards\r\n * it.\r\n */\n SyncEngine.prototype.processUserCallback = function (batchId, error) {\n var newCallbacks = this.mutationUserCallbacks[this.currentUser.toKey()];\n // NOTE: Mutations restored from persistence won't have callbacks, so it's\n // okay for there to be no callback for this ID.\n if (newCallbacks) {\n var callback = newCallbacks.get(batchId);\n if (callback) {\n assert(batchId === newCallbacks.minKey(), 'Mutation callbacks processed out-of-order?');\n if (error) {\n callback.reject(error);\n } else {\n callback.resolve();\n }\n newCallbacks = newCallbacks.remove(batchId);\n }\n this.mutationUserCallbacks[this.currentUser.toKey()] = newCallbacks;\n }\n };\n SyncEngine.prototype.removeAndCleanupQuery = function (queryView) {\n this.queryViewsByQuery.delete(queryView.query);\n delete this.queryViewsByTarget[queryView.targetId];\n this.limboDocumentRefs.removeReferencesForId(queryView.targetId);\n return this.gcLimboDocuments();\n };\n SyncEngine.prototype.updateTrackedLimbos = function (targetId, limboChanges) {\n for (var _i = 0, limboChanges_1 = limboChanges; _i < limboChanges_1.length; _i++) {\n var limboChange = limboChanges_1[_i];\n if (limboChange instanceof AddedLimboDocument) {\n this.limboDocumentRefs.addReference(limboChange.key, targetId);\n this.trackLimboChange(limboChange);\n } else if (limboChange instanceof RemovedLimboDocument) {\n debug(sync_engine_LOG_TAG, 'Document no longer in limbo: ' + limboChange.key);\n this.limboDocumentRefs.removeReference(limboChange.key, targetId);\n } else {\n fail('Unknown limbo change: ' + JSON.stringify(limboChange));\n }\n }\n return this.gcLimboDocuments();\n };\n SyncEngine.prototype.trackLimboChange = function (limboChange) {\n var key = limboChange.key;\n if (!this.limboTargetsByKey.get(key)) {\n debug(sync_engine_LOG_TAG, 'New document in limbo: ' + key);\n var limboTargetId = this.targetIdGenerator.next();\n var query = query_Query.atPath(key.path);\n this.limboKeysByTarget[limboTargetId] = key;\n this.remoteStore.listen(new query_data_QueryData(query, limboTargetId, QueryPurpose.Listen));\n this.limboTargetsByKey = this.limboTargetsByKey.insert(key, limboTargetId);\n }\n };\n SyncEngine.prototype.gcLimboDocuments = function () {\n var _this = this;\n // HACK: We can use a null transaction here, because we know that the\n // reference set is entirely within memory and doesn't need a store engine.\n return this.limboCollector.collectGarbage(null).next(function (keys) {\n keys.forEach(function (key) {\n var limboTargetId = _this.limboTargetsByKey.get(key);\n if (limboTargetId === null) {\n // This target already got removed, because the query failed.\n return;\n }\n _this.remoteStore.unlisten(limboTargetId);\n _this.limboTargetsByKey = _this.limboTargetsByKey.remove(key);\n delete _this.limboKeysByTarget[limboTargetId];\n });\n }).toPromise();\n };\n // Visible for testing\n SyncEngine.prototype.currentLimboDocs = function () {\n return this.limboTargetsByKey;\n };\n SyncEngine.prototype.emitNewSnapsAndNotifyLocalStore = function (changes, remoteEvent) {\n var _this = this;\n var newSnaps = [];\n var docChangesInAllViews = [];\n var queriesProcessed = [];\n this.queryViewsByQuery.forEach(function (_, queryView) {\n queriesProcessed.push(utils_promise[\"b\" /* PromiseImpl */].resolve().then(function () {\n var viewDocChanges = queryView.view.computeDocChanges(changes);\n if (!viewDocChanges.needsRefill) {\n return viewDocChanges;\n }\n // The query has a limit and some docs were removed, so we need\n // to re-run the query against the local store to make sure we\n // didn't lose any good docs that had been past the limit.\n return _this.localStore.executeQuery(queryView.query).then(function (docs) {\n return queryView.view.computeDocChanges(docs, viewDocChanges);\n });\n }).then(function (viewDocChanges) {\n var targetChange = remoteEvent && remoteEvent.targetChanges[queryView.targetId];\n var viewChange = queryView.view.applyChanges(viewDocChanges, targetChange);\n return _this.updateTrackedLimbos(queryView.targetId, viewChange.limboChanges).then(function () {\n if (viewChange.snapshot) {\n newSnaps.push(viewChange.snapshot);\n var docChanges = local_view_changes_LocalViewChanges.fromSnapshot(viewChange.snapshot);\n docChangesInAllViews.push(docChanges);\n }\n });\n }));\n });\n return utils_promise[\"b\" /* PromiseImpl */].all(queriesProcessed).then(function () {\n _this.viewHandler(newSnaps);\n return _this.localStore.notifyLocalViewChanges(docChangesInAllViews);\n }).then(function () {\n return _this.localStore.collectGarbage();\n });\n };\n SyncEngine.prototype.assertSubscribed = function (fnName) {\n assert(this.viewHandler !== null && this.errorHandler !== null, 'Trying to call ' + fnName + ' before calling subscribe().');\n };\n SyncEngine.prototype.handleUserChange = function (user) {\n var _this = this;\n this.currentUser = user;\n return this.localStore.handleUserChange(user).then(function (changes) {\n return _this.emitNewSnapsAndNotifyLocalStore(changes);\n }).then(function () {\n return _this.remoteStore.handleUserChange(user);\n });\n };\n return SyncEngine;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/model/mutation_batch.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\nvar BATCHID_UNKNOWN = -1;\n/**\r\n * A batch of mutations that will be sent as one unit to the backend.\r\n */\nvar mutation_batch_MutationBatch = /** @class */function () {\n function MutationBatch(batchId, localWriteTime, mutations) {\n this.batchId = batchId;\n this.localWriteTime = localWriteTime;\n this.mutations = mutations;\n }\n /**\r\n * Applies all the mutations in this MutationBatch to the specified document\r\n * to create a new remote document\r\n *\r\n * @param docKey The key of the document to apply mutations to.\r\n * @param maybeDoc The document to apply mutations to.\r\n * @param batchResult The result of applying the MutationBatch to the\r\n * backend.\r\n */\n MutationBatch.prototype.applyToRemoteDocument = function (docKey, maybeDoc, batchResult) {\n if (maybeDoc) {\n assert(maybeDoc.key.equals(docKey), \"applyToRemoteDocument: key \" + docKey + \" should match maybeDoc key\\n \" + maybeDoc.key);\n }\n var mutationResults = batchResult.mutationResults;\n assert(mutationResults.length === this.mutations.length, \"Mismatch between mutations length\\n (\" + this.mutations.length + \") and mutation results length\\n (\" + mutationResults.length + \").\");\n for (var i = 0; i < this.mutations.length; i++) {\n var mutation = this.mutations[i];\n if (mutation.key.equals(docKey)) {\n var mutationResult = mutationResults[i];\n maybeDoc = mutation.applyToRemoteDocument(maybeDoc, mutationResult);\n }\n }\n return maybeDoc;\n };\n /**\r\n * Computes the local view of a document given all the mutations in this\r\n * batch.\r\n *\r\n * @param docKey The key of the document to apply mutations to.\r\n * @param maybeDoc The document to apply mutations to.\r\n */\n MutationBatch.prototype.applyToLocalView = function (docKey, maybeDoc) {\n if (maybeDoc) {\n assert(maybeDoc.key.equals(docKey), \"applyToLocalDocument: key \" + docKey + \" should match maybeDoc key\\n \" + maybeDoc.key);\n }\n for (var i = 0; i < this.mutations.length; i++) {\n var mutation = this.mutations[i];\n if (mutation.key.equals(docKey)) {\n maybeDoc = mutation.applyToLocalView(maybeDoc, this.localWriteTime);\n }\n }\n return maybeDoc;\n };\n MutationBatch.prototype.keys = function () {\n var keySet = documentKeySet();\n for (var _i = 0, _a = this.mutations; _i < _a.length; _i++) {\n var mutation = _a[_i];\n keySet = keySet.add(mutation.key);\n }\n return keySet;\n };\n MutationBatch.prototype.equals = function (other) {\n return this.batchId === other.batchId && arrayEquals(this.mutations, other.mutations);\n };\n /**\r\n * Returns true if this mutation batch has already been removed from the\r\n * mutation queue.\r\n *\r\n * Note that not all implementations of the MutationQueue necessarily use\r\n * tombstones as part of their implementation and generally speaking no code\r\n * outside the mutation queues should really care about this.\r\n */\n MutationBatch.prototype.isTombstone = function () {\n return this.mutations.length === 0;\n };\n /** Converts this batch into a tombstone */\n MutationBatch.prototype.toTombstone = function () {\n return new MutationBatch(this.batchId, this.localWriteTime, []);\n };\n return MutationBatch;\n}();\n\n/** The result of applying a mutation batch to the backend. */\nvar mutation_batch_MutationBatchResult = /** @class */function () {\n function MutationBatchResult(batch, commitVersion, mutationResults, streamToken,\n /**\r\n * A pre-computed mapping from each mutated document to the resulting\r\n * version.\r\n */\n docVersions) {\n this.batch = batch;\n this.commitVersion = commitVersion;\n this.mutationResults = mutationResults;\n this.streamToken = streamToken;\n this.docVersions = docVersions;\n }\n /**\r\n * Creates a new MutationBatchResult for the given batch and results. There\r\n * must be one result for each mutation in the batch. This static factory\r\n * caches a document=>version mapping (docVersions).\r\n */\n MutationBatchResult.from = function (batch, commitVersion, results, streamToken) {\n assert(batch.mutations.length === results.length, 'Mutations sent ' + batch.mutations.length + ' must equal results received ' + results.length);\n var versionMap = documentVersionMap();\n var mutations = batch.mutations;\n for (var i = 0; i < mutations.length; i++) {\n var version = results[i].version;\n if (version === null) {\n // deletes don't have a version, so we substitute the commitVersion\n // of the entire batch.\n version = commitVersion;\n }\n versionMap = versionMap.insert(mutations[i].key, version);\n }\n return new MutationBatchResult(batch, commitVersion, results, streamToken, versionMap);\n };\n return MutationBatchResult;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/encoded_resource_path.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\nvar escapeChar = '\\x01';\nvar encodedSeparatorChar = '\\x01';\nvar encodedNul = '\\x10';\nvar encodedEscape = '\\x11';\n/**\r\n * Encodes a resource path into a IndexedDb-compatible string form.\r\n */\nfunction encode(path) {\n var result = '';\n for (var i = 0; i < path.length; i++) {\n if (result.length > 0) {\n result = encodeSeparator(result);\n }\n result = encodeSegment(path.get(i), result);\n }\n return encodeSeparator(result);\n}\n/** Encodes a single segment of a resource path into the given result */\nfunction encodeSegment(segment, resultBuf) {\n var result = resultBuf;\n var length = segment.length;\n for (var i = 0; i < length; i++) {\n var c = segment.charAt(i);\n switch (c) {\n case '\\0':\n result += escapeChar + encodedNul;\n break;\n case escapeChar:\n result += escapeChar + encodedEscape;\n break;\n default:\n result += c;\n }\n }\n return result;\n}\n/** Encodes a path separator into the given result */\nfunction encodeSeparator(result) {\n return result + escapeChar + encodedSeparatorChar;\n}\n/**\r\n * Decodes the given IndexedDb-compatible string form of a resource path into\r\n * a ResourcePath instance. Note that this method is not suitable for use with\r\n * decoding resource names from the server; those are One Platform format\r\n * strings.\r\n */\nfunction decode(path) {\n // Event the empty path must encode as a path of at least length 2. A path\n // with exactly 2 must be the empty path.\n var length = path.length;\n assert(length >= 2, 'Invalid path ' + path);\n if (length === 2) {\n assert(path.charAt(0) === escapeChar && path.charAt(1) === encodedSeparatorChar, 'Non-empty path ' + path + ' had length 2');\n return path_ResourcePath.EMPTY_PATH;\n }\n // Escape characters cannot exist past the second-to-last position in the\n // source value.\n var lastReasonableEscapeIndex = length - 2;\n var segments = [];\n var segmentBuilder = '';\n for (var start = 0; start < length;) {\n // The last two characters of a valid encoded path must be a separator, so\n // there must be an end to this segment.\n var end = path.indexOf(escapeChar, start);\n if (end < 0 || end > lastReasonableEscapeIndex) {\n fail('Invalid encoded resource path: \"' + path + '\"');\n }\n var next = path.charAt(end + 1);\n switch (next) {\n case encodedSeparatorChar:\n var currentPiece = path.substring(start, end);\n var segment = void 0;\n if (segmentBuilder.length === 0) {\n // Avoid copying for the common case of a segment that excludes \\0\n // and \\001\n segment = currentPiece;\n } else {\n segmentBuilder += currentPiece;\n segment = segmentBuilder;\n segmentBuilder = '';\n }\n segments.push(segment);\n break;\n case encodedNul:\n segmentBuilder += path.substring(start, end);\n segmentBuilder += '\\0';\n break;\n case encodedEscape:\n // The escape character can be used in the output to encode itself.\n segmentBuilder += path.substring(start, end + 1);\n break;\n default:\n fail('Invalid encoded resource path: \"' + path + '\"');\n }\n start = end + 2;\n }\n return new path_ResourcePath(segments);\n}\n/**\r\n * Computes the prefix successor of the given path, computed by encode above.\r\n * A prefix successor is the first key that cannot be prefixed by the given\r\n * path. It's useful for defining the end of a prefix scan such that all keys\r\n * in the scan have the same prefix.\r\n *\r\n * Note that this is not a general prefix successor implementation, which is\r\n * tricky to get right with Strings, given that they encode down to UTF-8.\r\n * Instead this relies on the fact that all paths encoded by this class are\r\n * always terminated with a separator, and so a successor can always be\r\n * cheaply computed by incrementing the last character of the path.\r\n */\nfunction prefixSuccessor(path) {\n var c = path.charCodeAt(path.length - 1);\n // TODO(mcg): this really should be a general thing, but not worth it right\n // now\n assert(c === 1, 'successor may only operate on paths generated by encode');\n return path.substring(0, path.length - 1) + String.fromCharCode(c + 1);\n}\n// CONCATENATED MODULE: ./src/firestore/local/indexeddb_schema.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\nvar SCHEMA_VERSION = 1;\n/** Performs database creation and (in the future) upgrades between versions. */\nfunction createOrUpgradeDb(db, oldVersion) {\n assert(oldVersion === 0, 'Unexpected upgrade from version ' + oldVersion);\n db.createObjectStore(DbMutationQueue.store, {\n keyPath: DbMutationQueue.keyPath\n });\n // TODO(mikelehen): Get rid of \"as any\" if/when TypeScript fixes their\n // types. https://github.com/Microsoft/TypeScript/issues/14322\n db.createObjectStore(\n // tslint:disable-next-line:no-any\n DbMutationBatch.store, { keyPath: DbMutationBatch.keyPath });\n var targetDocumentsStore = db.createObjectStore(\n // tslint:disable-next-line:no-any\n DbTargetDocument.store, { keyPath: DbTargetDocument.keyPath });\n targetDocumentsStore.createIndex(DbTargetDocument.documentTargetsIndex, DbTargetDocument.documentTargetsKeyPath, { unique: true });\n var targetStore = db.createObjectStore(DbTarget.store, {\n keyPath: DbTarget.keyPath\n });\n // NOTE: This is unique only because the TargetId is the suffix.\n targetStore.createIndex(DbTarget.queryTargetsIndexName, DbTarget.queryTargetsKeyPath, { unique: true });\n // NOTE: keys for these stores are specified explicitly rather than using a\n // keyPath.\n db.createObjectStore(indexeddb_schema_DbDocumentMutation.store);\n db.createObjectStore(DbRemoteDocument.store);\n db.createObjectStore(DbOwner.store);\n db.createObjectStore(DbTargetGlobal.store);\n}\n/**\r\n * Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.\r\n */\nvar DbTimestamp = /** @class */function () {\n function DbTimestamp(seconds, nanos) {\n this.seconds = seconds;\n this.nanos = nanos;\n }\n return DbTimestamp;\n}();\n\n/**\r\n * A singleton object to be stored in the 'owner' store in IndexedDb.\r\n *\r\n * A given database can be owned by a single tab at a given time. That tab\r\n * must validate that it is still the owner before every write operation and\r\n * should regularly write an updated timestamp to prevent other tabs from\r\n * \"stealing\" ownership of the db.\r\n */\nvar DbOwner = /** @class */function () {\n function DbOwner(ownerId, leaseTimestampMs) {\n this.ownerId = ownerId;\n this.leaseTimestampMs = leaseTimestampMs;\n }\n /** Name of the IndexedDb object store. */\n DbOwner.store = 'owner';\n return DbOwner;\n}();\n\n/**\r\n * An object to be stored in the 'mutationQueues' store in IndexedDb.\r\n *\r\n * Each user gets a single queue of MutationBatches to apply to the server.\r\n * DbMutationQueue tracks the metadata about the queue.\r\n */\nvar DbMutationQueue = /** @class */function () {\n function DbMutationQueue(\n /**\r\n * The normalized user ID to which this queue belongs.\r\n */\n userId,\n /**\r\n * An identifier for the highest numbered batch that has been acknowledged\r\n * by the server. All MutationBatches in this queue with batchIds less\r\n * than or equal to this value are considered to have been acknowledged by\r\n * the server.\r\n */\n lastAcknowledgedBatchId,\n /**\r\n * A stream token that was previously sent by the server.\r\n *\r\n * See StreamingWriteRequest in datastore.proto for more details about\r\n * usage.\r\n *\r\n * After sending this token, earlier tokens may not be used anymore so\r\n * only a single stream token is retained.\r\n */\n lastStreamToken) {\n this.userId = userId;\n this.lastAcknowledgedBatchId = lastAcknowledgedBatchId;\n this.lastStreamToken = lastStreamToken;\n }\n /** Name of the IndexedDb object store. */\n DbMutationQueue.store = 'mutationQueues';\n /** Keys are automatically assigned via the userId property. */\n DbMutationQueue.keyPath = 'userId';\n return DbMutationQueue;\n}();\n\n/**\r\n * An object to be stored in the 'mutations' store in IndexedDb.\r\n *\r\n * Represents a batch of user-level mutations intended to be sent to the server\r\n * in a single write. Each user-level batch gets a separate DbMutationBatch\r\n * with a new batchId.\r\n */\nvar DbMutationBatch = /** @class */function () {\n function DbMutationBatch(\n /**\r\n * The normalized user ID to which this batch belongs.\r\n */\n userId,\n /**\r\n * An identifier for this batch, allocated by the mutation queue in a\r\n * monotonically increasing manner.\r\n */\n batchId,\n /**\r\n * The local write time of the batch, stored as milliseconds since the\r\n * epoch.\r\n */\n localWriteTimeMs,\n /**\r\n * A list of mutations to apply. All mutations will be applied atomically.\r\n *\r\n * Mutations are serialized via JsonProtoSerializer.toMutation().\r\n */\n mutations) {\n this.userId = userId;\n this.batchId = batchId;\n this.localWriteTimeMs = localWriteTimeMs;\n this.mutations = mutations;\n }\n /** Name of the IndexedDb object store. */\n DbMutationBatch.store = 'mutations';\n /** Keys are automatically assigned via the userId, batchId properties. */\n DbMutationBatch.keyPath = ['userId', 'batchId'];\n return DbMutationBatch;\n}();\n\n/**\r\n * An object to be stored in the 'documentMutations' store in IndexedDb.\r\n *\r\n * A manually maintained index of all the mutation batches that affect a given\r\n * document key. The rows in this table are references based on the contents of\r\n * DbMutationBatch.mutations.\r\n */\nvar indexeddb_schema_DbDocumentMutation = /** @class */function () {\n function DbDocumentMutation() {}\n /**\r\n * Creates a [userId] key for use in the DbDocumentMutations index to iterate\r\n * over all of a user's document mutations.\r\n */\n DbDocumentMutation.prefixForUser = function (userId) {\n return [userId];\n };\n /**\r\n * Creates a [userId, encodedPath] key for use in the DbDocumentMutations\r\n * index to iterate over all at document mutations for a given path or lower.\r\n */\n DbDocumentMutation.prefixForPath = function (userId, path) {\n return [userId, encode(path)];\n };\n /**\r\n * Creates a full index key of [userId, encodedPath, batchId] for inserting\r\n * and deleting into the DbDocumentMutations index.\r\n */\n DbDocumentMutation.key = function (userId, path, batchId) {\n return [userId, encode(path), batchId];\n };\n DbDocumentMutation.store = 'documentMutations';\n /**\r\n * Because we store all the useful information for this store in the key,\r\n * there is no useful information to store as the value. The raw (unencoded)\r\n * path cannot be stored because IndexedDb doesn't store prototype\r\n * information.\r\n */\n DbDocumentMutation.PLACEHOLDER = new DbDocumentMutation();\n return DbDocumentMutation;\n}();\n\n/**\r\n * Represents the known absence of a document at a particular version.\r\n * Stored in IndexedDb as part of a DbRemoteDocument object.\r\n */\nvar DbNoDocument = /** @class */function () {\n function DbNoDocument(path, readTime) {\n this.path = path;\n this.readTime = readTime;\n }\n return DbNoDocument;\n}();\n\n/**\r\n * An object to be stored in the 'remoteDocuments' store in IndexedDb. It\r\n * represents either a cached document (if it exists) or a cached \"no-document\"\r\n * (if it is known to not exist).\r\n *\r\n * Note: This is the persisted equivalent of a MaybeDocument and could perhaps\r\n * be made more general if necessary.\r\n */\nvar DbRemoteDocument = /** @class */function () {\n function DbRemoteDocument(\n /**\r\n * Set to an instance of a DbNoDocument if it is known that no document\r\n * exists.\r\n */\n noDocument,\n /**\r\n * Set to an instance of a Document if there's a cached version of the\r\n * document.\r\n */\n document) {\n this.noDocument = noDocument;\n this.document = document;\n }\n DbRemoteDocument.store = 'remoteDocuments';\n return DbRemoteDocument;\n}();\n\n/**\r\n * An object to be stored in the 'targets' store in IndexedDb.\r\n *\r\n * This is based on and should be kept in sync with the proto used in the iOS\r\n * client.\r\n *\r\n * Each query the client listens to against the server is tracked on disk so\r\n * that the query can be efficiently resumed on restart.\r\n */\nvar DbTarget = /** @class */function () {\n function DbTarget(\n /**\r\n * An auto-generated sequential numeric identifier for the query.\r\n *\r\n * Queries are stored using their canonicalId as the key, but these\r\n * canonicalIds can be quite long so we additionally assign a unique\r\n * queryId which can be used by referenced data structures (e.g.\r\n * indexes) to minimize the on-disk cost.\r\n */\n targetId,\n /**\r\n * The canonical string representing this query. This is not unique.\r\n */\n canonicalId,\n /**\r\n * The last readTime received from the Watch Service for this query.\r\n *\r\n * This is the same value as TargetChange.read_time in the protos.\r\n */\n readTime,\n /**\r\n * An opaque, server-assigned token that allows watching a query to be\r\n * resumed after disconnecting without retransmitting all the data\r\n * that matches the query. The resume token essentially identifies a\r\n * point in time from which the server should resume sending results.\r\n *\r\n * This is related to the snapshotVersion in that the resumeToken\r\n * effectively also encodes that value, but the resumeToken is opaque\r\n * and sometimes encodes additional information.\r\n *\r\n * A consequence of this is that the resumeToken should be used when\r\n * asking the server to reason about where this client is in the watch\r\n * stream, but the client should use the snapshotVersion for its own\r\n * purposes.\r\n *\r\n * This is the same value as TargetChange.resume_token in the protos.\r\n */\n resumeToken,\n /**\r\n * A sequence number representing the last time this query was\r\n * listened to, used for garbage collection purposes.\r\n *\r\n * Conventionally this would be a timestamp value, but device-local\r\n * clocks are unreliable and they must be able to create new listens\r\n * even while disconnected. Instead this should be a monotonically\r\n * increasing number that's incremented on each listen call.\r\n *\r\n * This is different from the queryId since the queryId is an\r\n * immutable identifier assigned to the Query on first use while\r\n * lastListenSequenceNumber is updated every time the query is\r\n * listened to.\r\n */\n lastListenSequenceNumber,\n /**\r\n * The query for this target.\r\n *\r\n * Because canonical ids are not unique we must store the actual query. We\r\n * use the proto to have an object we can persist without having to\r\n * duplicate translation logic to and from a `Query` object.\r\n */\n query) {\n this.targetId = targetId;\n this.canonicalId = canonicalId;\n this.readTime = readTime;\n this.resumeToken = resumeToken;\n this.lastListenSequenceNumber = lastListenSequenceNumber;\n this.query = query;\n }\n DbTarget.store = 'targets';\n /** Keys are automatically assigned via the targetId property. */\n DbTarget.keyPath = 'targetId';\n /** The name of the queryTargets index. */\n DbTarget.queryTargetsIndexName = 'queryTargetsIndex';\n /**\r\n * The index of all canonicalIds to the targets that they match. This is not\r\n * a unique mapping because canonicalId does not promise a unique name for all\r\n * possible queries, so we append the targetId to make the mapping unique.\r\n */\n DbTarget.queryTargetsKeyPath = ['canonicalId', 'targetId'];\n return DbTarget;\n}();\n\n/**\r\n * An object representing an association between a target and a document.\r\n * Stored in the targetDocument object store to store the documents tracked by a\r\n * particular target.\r\n */\nvar DbTargetDocument = /** @class */function () {\n function DbTargetDocument(\n /**\r\n * The targetId identifying a target.\r\n */\n targetId,\n /**\r\n * The path to the document, as encoded in the key.\r\n */\n path) {\n this.targetId = targetId;\n this.path = path;\n }\n /** Name of the IndexedDb object store. */\n DbTargetDocument.store = 'targetDocuments';\n /** Keys are automatically assigned via the targetId, path properties. */\n DbTargetDocument.keyPath = ['targetId', 'path'];\n /** The index name for the reverse index. */\n DbTargetDocument.documentTargetsIndex = 'documentTargetsIndex';\n /** We also need to create the reverse index for these properties. */\n DbTargetDocument.documentTargetsKeyPath = ['path', 'targetId'];\n return DbTargetDocument;\n}();\n\n/**\r\n * A record of global state tracked across all Targets, tracked separately\r\n * to avoid the need for extra indexes.\r\n *\r\n * This should be kept in-sync with the proto used in the iOS client.\r\n */\nvar DbTargetGlobal = /** @class */function () {\n function DbTargetGlobal(\n /**\r\n * The highest numbered target id across all targets.\r\n *\r\n * See DbTarget.targetId.\r\n */\n highestTargetId,\n /**\r\n * The highest numbered lastListenSequenceNumber across all targets.\r\n *\r\n * See DbTarget.lastListenSequenceNumber.\r\n */\n highestListenSequenceNumber,\n /**\r\n * A global snapshot version representing the last consistent snapshot we\r\n * received from the backend. This is monotonically increasing and any\r\n * snapshots received from the backend prior to this version (e.g. for\r\n * targets resumed with a resumeToken) should be suppressed (buffered)\r\n * until the backend has caught up to this snapshot version again. This\r\n * prevents our cache from ever going backwards in time.\r\n */\n lastRemoteSnapshotVersion) {\n this.highestTargetId = highestTargetId;\n this.highestListenSequenceNumber = highestListenSequenceNumber;\n this.lastRemoteSnapshotVersion = lastRemoteSnapshotVersion;\n }\n /**\r\n * The key string used for the single object that exists in the\r\n * DbTargetGlobal store.\r\n */\n DbTargetGlobal.key = 'targetGlobalKey';\n DbTargetGlobal.store = 'targetGlobal';\n return DbTargetGlobal;\n}();\n\n/**\r\n * The list of all IndexedDB stored used by the SDK. This is used when creating\r\n * transactions so that access across all stores is done atomically.\r\n */\nvar ALL_STORES = [DbMutationQueue.store, DbMutationBatch.store, indexeddb_schema_DbDocumentMutation.store, DbRemoteDocument.store, DbTarget.store, DbOwner.store, DbTargetGlobal.store, DbTargetDocument.store];\n// CONCATENATED MODULE: ./src/firestore/local/simple_db.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\nvar simple_db_LOG_TAG = 'SimpleDb';\n/**\r\n * Provides a wrapper around IndexedDb with a simplified interface that uses\r\n * Promise-like return values to chain operations. Real promises cannot be used\r\n * since .then() continuations are executed asynchronously (e.g. via\r\n * .setImmediate), which would cause IndexedDB to end the transaction.\r\n * See PersistencePromise for more details.\r\n */\nvar simple_db_SimpleDb = /** @class */function () {\n function SimpleDb(db) {\n this.db = db;\n }\n /** Opens the specified database, creating or upgrading it if necessary. */\n SimpleDb.openOrCreate = function (name, version, runUpgrade) {\n assert(SimpleDb.isAvailable(), 'IndexedDB not supported in current environment.');\n debug(simple_db_LOG_TAG, 'Opening database:', name);\n return new persistence_promise_PersistencePromise(function (resolve, reject) {\n // TODO(mikelehen): Investigate browser compatibility.\n // https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB\n // suggests IE9 and older WebKit browsers handle upgrade\n // differently.\n var request = window.indexedDB.open(name, version);\n request.onsuccess = function (event) {\n var db = event.target.result;\n resolve(new SimpleDb(db));\n };\n request.onerror = function (event) {\n reject(event.target.error);\n };\n request.onupgradeneeded = function (event) {\n debug(simple_db_LOG_TAG, 'Database \"' + name + '\" requires upgrade from version:', event.oldVersion);\n // TODO(mikelehen): If/when we need to do an actual data\n // migration, we'll want to wrap db in a SimpleDb and have the\n // runUpgrade function return a PersistencePromise, since we'll\n // likely need to do async reads and writes. For now we're\n // cheating and just passing the raw IndexedDB in, since\n // createObjectStore(), etc. are synchronous.\n var db = event.target.result;\n runUpgrade(db, event.oldVersion);\n };\n }).toPromise();\n };\n /** Deletes the specified database. */\n SimpleDb.delete = function (name) {\n debug(simple_db_LOG_TAG, 'Removing database:', name);\n return wrapRequest(window.indexedDB.deleteDatabase(name)).toPromise();\n };\n /** Returns true if IndexedDB is available in the current environment. */\n SimpleDb.isAvailable = function () {\n if (typeof window === 'undefined' || window.indexedDB == null) {\n return false;\n }\n // We extensively use indexed array values and compound keys,\n // which IE and Edge do not support. However, they still have indexedDB\n // defined on the window, so we need to check for them here and make sure\n // to return that persistence is not enabled for those browsers.\n // For tracking support of this feature, see here:\n // https://developer.microsoft.com/en-us/microsoft-edge/platform/status/indexeddbarraysandmultientrysupport/\n // Check the UA string to find out the browser.\n var ua = window.navigator.userAgent;\n // IE 10\n // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';\n // IE 11\n // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';\n // Edge\n // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,\n // like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';\n if (ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0) {\n return false;\n } else {\n return true;\n }\n };\n SimpleDb.prototype.runTransaction = function (mode, objectStores, transactionFn) {\n var transaction = new simple_db_SimpleDbTransaction(this.db, mode, objectStores);\n var transactionFnResult = transactionFn(transaction).catch(function (error) {\n // Abort the transaction if there was an\n // error.\n transaction.abort();\n return persistence_promise_PersistencePromise.reject(error);\n }).toPromise();\n // Wait for the transaction to complete (i.e. IndexedDb's onsuccess event to\n // fire), but still return the original transactionFnResult back to the\n // caller.\n return transaction.completionPromise.then(function () {\n return transactionFnResult;\n });\n };\n SimpleDb.prototype.close = function () {\n this.db.close();\n };\n return SimpleDb;\n}();\n\n/**\r\n * A controller for iterating over a key range or index. It allows an iterate\r\n * callback to delete the currently-referenced object, or jump to a new key\r\n * within the key range or index.\r\n */\nvar IterationController = /** @class */function () {\n function IterationController(dbCursor) {\n this.dbCursor = dbCursor;\n this.shouldStop = false;\n this.nextKey = null;\n }\n Object.defineProperty(IterationController.prototype, \"isDone\", {\n get: function get() {\n return this.shouldStop;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(IterationController.prototype, \"skipToKey\", {\n get: function get() {\n return this.nextKey;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(IterationController.prototype, \"cursor\", {\n set: function set(value) {\n this.dbCursor = value;\n },\n enumerable: true,\n configurable: true\n });\n /**\r\n * This function can be called to stop iteration at any point.\r\n */\n IterationController.prototype.done = function () {\n this.shouldStop = true;\n };\n /**\r\n * This function can be called to skip to that next key, which could be\r\n * an index or a primary key.\r\n */\n IterationController.prototype.skip = function (key) {\n this.nextKey = key;\n };\n /**\r\n * Delete the current cursor value from the object store.\r\n *\r\n * NOTE: You CANNOT do this with a keysOnly query.\r\n */\n IterationController.prototype.delete = function () {\n return wrapRequest(this.dbCursor.delete());\n };\n return IterationController;\n}();\n\n/**\r\n * Wraps an IDBTransaction and exposes a store() method to get a handle to a\r\n * specific object store.\r\n */\nvar simple_db_SimpleDbTransaction = /** @class */function () {\n function SimpleDbTransaction(db, mode, objectStoresNames) {\n var _this = this;\n this.aborted = false;\n this.transaction = db.transaction(objectStoresNames, mode);\n this.completionPromise = new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n // We consider aborting to be \"normal\" and just resolve the promise.\n // May need to revisit if/when we actually need to abort transactions.\n _this.transaction.onabort = _this.transaction.oncomplete = function (event) {\n resolve();\n };\n _this.transaction.onerror = function (event) {\n reject(event.target.error);\n };\n });\n }\n SimpleDbTransaction.prototype.abort = function () {\n if (!this.aborted) {\n debug(simple_db_LOG_TAG, 'Aborting transaction.');\n this.aborted = true;\n this.transaction.abort();\n }\n };\n /**\r\n * Returns a SimpleDbStore for the specified store. All\r\n * operations performed on the SimpleDbStore happen within the context of this\r\n * transaction and it cannot be used anymore once the transaction is\r\n * completed.\r\n *\r\n * Note that we can't actually enforce that the KeyType and ValueType are\r\n * correct, but they allow type safety through the rest of the consuming code.\r\n */\n SimpleDbTransaction.prototype.store = function (storeName) {\n var store = this.transaction.objectStore(storeName);\n assert(!!store, 'Object store not part of transaction: ' + storeName);\n return new simple_db_SimpleDbStore(store);\n };\n return SimpleDbTransaction;\n}();\n\n/**\r\n * A wrapper around an IDBObjectStore providing an API that:\r\n *\r\n * 1) Has generic KeyType / ValueType parameters to provide strongly-typed\r\n * methods for acting against the object store.\r\n * 2) Deals with IndexedDB's onsuccess / onerror event callbacks, making every\r\n * method return a PersistencePromise instead.\r\n * 3) Provides a higher-level API to avoid needing to do excessive wrapping of\r\n * intermediate IndexedDB types (IDBCursorWithValue, etc.)\r\n */\nvar simple_db_SimpleDbStore = /** @class */function () {\n function SimpleDbStore(store) {\n this.store = store;\n }\n SimpleDbStore.prototype.put = function (keyOrValue, value) {\n var request;\n if (value !== undefined) {\n debug(simple_db_LOG_TAG, 'PUT', this.store.name, keyOrValue, value);\n request = this.store.put(value, keyOrValue);\n } else {\n debug(simple_db_LOG_TAG, 'PUT', this.store.name, '', keyOrValue);\n request = this.store.put(keyOrValue);\n }\n return wrapRequest(request);\n };\n /**\r\n * Gets the object with the specified key from the specified store, or null\r\n * if no object exists with the specified key.\r\n *\r\n * @key The key of the object to get.\r\n * @return The object with the specified key or null if no object exists.\r\n */\n SimpleDbStore.prototype.get = function (key) {\n var _this = this;\n var request = this.store.get(key);\n // tslint:disable-next-line:no-any We're doing an unsafe cast to ValueType.\n return wrapRequest(request).next(function (result) {\n // Normalize nonexistence to null.\n if (result === undefined) {\n result = null;\n }\n debug(simple_db_LOG_TAG, 'GET', _this.store.name, key, result);\n return result;\n });\n };\n SimpleDbStore.prototype.delete = function (key) {\n debug(simple_db_LOG_TAG, 'DELETE', this.store.name, key);\n var request = this.store.delete(key);\n return wrapRequest(request);\n };\n SimpleDbStore.prototype.loadAll = function (indexOrRange, range) {\n var cursor = this.cursor(this.options(indexOrRange, range));\n var results = [];\n return this.iterateCursor(cursor, function (key, value) {\n results.push(value);\n }).next(function () {\n return results;\n });\n };\n SimpleDbStore.prototype.deleteAll = function (indexOrRange, range) {\n debug(simple_db_LOG_TAG, 'DELETE ALL', this.store.name);\n var options = this.options(indexOrRange, range);\n options.keysOnly = false;\n var cursor = this.cursor(options);\n return this.iterateCursor(cursor, function (key, value, control) {\n // NOTE: Calling delete() on a cursor is documented as more efficient than\n // calling delete() on an object store with a single key\n // (https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/delete),\n // however, this requires us *not* to use a keysOnly cursor\n // (https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor/delete). We\n // may want to compare the performance of each method.\n return control.delete();\n });\n };\n SimpleDbStore.prototype.iterate = function (optionsOrCallback, callback) {\n var options;\n if (!callback) {\n options = {};\n callback = optionsOrCallback;\n } else {\n options = optionsOrCallback;\n }\n var cursor = this.cursor(options);\n return this.iterateCursor(cursor, callback);\n };\n SimpleDbStore.prototype.iterateCursor = function (cursorRequest, fn) {\n var results = [];\n return new persistence_promise_PersistencePromise(function (resolve, reject) {\n cursorRequest.onerror = function (event) {\n reject(event.target.error);\n };\n cursorRequest.onsuccess = function (event) {\n var cursor = event.target.result;\n if (!cursor) {\n resolve();\n return;\n }\n var controller = new IterationController(cursor);\n var userResult = fn(cursor.primaryKey, cursor.value, controller);\n if (userResult instanceof persistence_promise_PersistencePromise) {\n results.push(userResult);\n }\n if (controller.isDone) {\n resolve();\n } else if (controller.skipToKey === null) {\n cursor.continue();\n } else {\n cursor.continue(controller.skipToKey);\n }\n };\n }).next(function () {\n return persistence_promise_PersistencePromise.waitFor(results);\n });\n };\n SimpleDbStore.prototype.options = function (indexOrRange, range) {\n var indexName = undefined;\n if (indexOrRange !== undefined) {\n if (typeof indexOrRange === 'string') {\n indexName = indexOrRange;\n } else {\n assert(range === undefined, '3rd argument must not be defined if 2nd is a range.');\n range = indexOrRange;\n }\n }\n return { index: indexName, range: range };\n };\n SimpleDbStore.prototype.cursor = function (options) {\n var direction = 'next';\n if (options.reverse) {\n direction = 'prev';\n }\n if (options.index) {\n var index = this.store.index(options.index);\n if (options.keysOnly) {\n return index.openKeyCursor(options.range, direction);\n } else {\n return index.openCursor(options.range, direction);\n }\n } else {\n return this.store.openCursor(options.range, direction);\n }\n };\n return SimpleDbStore;\n}();\n\n/**\r\n * Wraps an IDBRequest in a PersistencePromise, using the onsuccess / onerror\r\n * handlers to resolve / reject the PersistencePromise as appropriate.\r\n */\nfunction wrapRequest(request) {\n return new persistence_promise_PersistencePromise(function (resolve, reject) {\n request.onsuccess = function (event) {\n var result = event.target.result;\n resolve(result);\n };\n request.onerror = function (event) {\n reject(event.target.error);\n };\n });\n}\n// CONCATENATED MODULE: ./src/firestore/local/indexeddb_mutation_queue.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n/** A mutation queue for a specific user, backed by IndexedDB. */\nvar indexeddb_mutation_queue_IndexedDbMutationQueue = /** @class */function () {\n function IndexedDbMutationQueue(\n /**\r\n * The normalized userId (e.g. null UID => \"\" userId) used to store /\r\n * retrieve mutations.\r\n */\n userId, serializer) {\n this.userId = userId;\n this.serializer = serializer;\n this.garbageCollector = null;\n }\n /**\r\n * Creates a new mutation queue for the given user.\r\n * @param user The user for which to create a mutation queue.\r\n * @param serializer The serializer to use when persisting to IndexedDb.\r\n */\n IndexedDbMutationQueue.forUser = function (user, serializer) {\n // TODO(mcg): Figure out what constraints there are on userIDs\n // In particular, are there any reserved characters? are empty ids allowed?\n // For the moment store these together in the same mutations table assuming\n // that empty userIDs aren't allowed.\n assert(user.uid !== '', 'UserID must not be an empty string.');\n var userId = user.isUnauthenticated() ? '' : user.uid;\n return new IndexedDbMutationQueue(userId, serializer);\n };\n IndexedDbMutationQueue.prototype.start = function (transaction) {\n var _this = this;\n return IndexedDbMutationQueue.loadNextBatchIdFromDb(transaction).next(function (nextBatchId) {\n _this.nextBatchId = nextBatchId;\n return mutationQueuesStore(transaction).get(_this.userId);\n }).next(function (metadata) {\n if (!metadata) {\n metadata = new DbMutationQueue(_this.userId, BATCHID_UNKNOWN,\n /*lastStreamToken=*/'');\n }\n _this.metadata = metadata;\n // On restart, nextBatchId may end up lower than\n // lastAcknowledgedBatchId since it's computed from the queue\n // contents, and there may be no mutations in the queue. In this\n // case, we need to reset lastAcknowledgedBatchId (which is safe\n // since the queue must be empty).\n if (_this.metadata.lastAcknowledgedBatchId >= _this.nextBatchId) {\n return _this.checkEmpty(transaction).next(function (empty) {\n assert(empty, 'Reset nextBatchID is only possible when the queue is empty');\n _this.metadata.lastAcknowledgedBatchId = BATCHID_UNKNOWN;\n return mutationQueuesStore(transaction).put(_this.metadata);\n });\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n });\n };\n /**\r\n * Returns one larger than the largest batch ID that has been stored. If there\r\n * are no mutations returns 0. Note that batch IDs are global.\r\n */\n IndexedDbMutationQueue.loadNextBatchIdFromDb = function (txn) {\n var maxBatchId = BATCHID_UNKNOWN;\n return mutationsStore(txn).iterate({ reverse: true }, function (key, batch, control) {\n var userId = key[0],\n batchId = key[1];\n if (batchId > maxBatchId) {\n maxBatchId = batch.batchId;\n }\n if (userId === '') {\n // We can't compute a predecessor for the empty string, since it\n // is lexographically first. That also means that no other\n // userIds can come before this one, so we can just exit early.\n control.done();\n } else {\n var nextUser = immediatePredecessor(userId);\n control.skip([nextUser]);\n }\n }).next(function () {\n return maxBatchId + 1;\n });\n };\n IndexedDbMutationQueue.prototype.checkEmpty = function (transaction) {\n var empty = true;\n var range = IDBKeyRange.bound(this.keyForBatchId(Number.NEGATIVE_INFINITY), this.keyForBatchId(Number.POSITIVE_INFINITY));\n return mutationsStore(transaction).iterate({ range: range }, function (key, value, control) {\n empty = false;\n control.done();\n }).next(function () {\n return empty;\n });\n };\n IndexedDbMutationQueue.prototype.getNextBatchId = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.nextBatchId);\n };\n IndexedDbMutationQueue.prototype.getHighestAcknowledgedBatchId = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.metadata.lastAcknowledgedBatchId);\n };\n IndexedDbMutationQueue.prototype.acknowledgeBatch = function (transaction, batch, streamToken) {\n var batchId = batch.batchId;\n assert(batchId > this.metadata.lastAcknowledgedBatchId, 'Mutation batchIDs must be acknowledged in order');\n this.metadata.lastAcknowledgedBatchId = batchId;\n this.metadata.lastStreamToken = validateStreamToken(streamToken);\n return mutationQueuesStore(transaction).put(this.metadata);\n };\n IndexedDbMutationQueue.prototype.getLastStreamToken = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.metadata.lastStreamToken);\n };\n IndexedDbMutationQueue.prototype.setLastStreamToken = function (transaction, streamToken) {\n this.metadata.lastStreamToken = validateStreamToken(streamToken);\n return mutationQueuesStore(transaction).put(this.metadata);\n };\n IndexedDbMutationQueue.prototype.addMutationBatch = function (transaction, localWriteTime, mutations) {\n var _this = this;\n var batchId = this.nextBatchId;\n this.nextBatchId++;\n var batch = new mutation_batch_MutationBatch(batchId, localWriteTime, mutations);\n var dbBatch = this.serializer.toDbMutationBatch(this.userId, batch);\n return mutationsStore(transaction).put(dbBatch).next(function () {\n var promises = [];\n for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) {\n var mutation = mutations_1[_i];\n var encodedPath = encode(mutation.key.path);\n var indexKey = indexeddb_schema_DbDocumentMutation.key(_this.userId, mutation.key.path, batchId);\n documentMutationsStore(transaction).put(indexKey, indexeddb_schema_DbDocumentMutation.PLACEHOLDER);\n }\n return persistence_promise_PersistencePromise.waitFor(promises);\n }).next(function () {\n return batch;\n });\n };\n IndexedDbMutationQueue.prototype.lookupMutationBatch = function (transaction, batchId) {\n var _this = this;\n return mutationsStore(transaction).get(this.keyForBatchId(batchId)).next(function (dbBatch) {\n return dbBatch ? _this.serializer.fromDbMutationBatch(dbBatch) : null;\n });\n };\n IndexedDbMutationQueue.prototype.getNextMutationBatchAfterBatchId = function (transaction, batchId) {\n var _this = this;\n var range = IDBKeyRange.lowerBound(this.keyForBatchId(batchId + 1));\n var foundBatch = null;\n return mutationsStore(transaction).iterate({ range: range }, function (key, dbBatch, control) {\n if (dbBatch.userId === _this.userId) {\n assert(dbBatch.batchId > batchId, 'Should have found mutation after ' + batchId);\n foundBatch = _this.serializer.fromDbMutationBatch(dbBatch);\n }\n control.done();\n }).next(function () {\n return foundBatch;\n });\n };\n IndexedDbMutationQueue.prototype.getAllMutationBatches = function (transaction) {\n var _this = this;\n var range = IDBKeyRange.bound(this.keyForBatchId(BATCHID_UNKNOWN), this.keyForBatchId(Number.POSITIVE_INFINITY));\n return mutationsStore(transaction).loadAll(range).next(function (dbBatches) {\n return dbBatches.map(function (dbBatch) {\n return _this.serializer.fromDbMutationBatch(dbBatch);\n });\n });\n };\n IndexedDbMutationQueue.prototype.getAllMutationBatchesThroughBatchId = function (transaction, batchId) {\n var _this = this;\n var range = IDBKeyRange.bound(this.keyForBatchId(BATCHID_UNKNOWN), this.keyForBatchId(batchId));\n return mutationsStore(transaction).loadAll(range).next(function (dbBatches) {\n return dbBatches.map(function (dbBatch) {\n return _this.serializer.fromDbMutationBatch(dbBatch);\n });\n });\n };\n IndexedDbMutationQueue.prototype.getAllMutationBatchesAffectingDocumentKey = function (transaction, documentKey) {\n var _this = this;\n // Scan the document-mutation index starting with a prefix starting with\n // the given documentKey.\n var indexPrefix = indexeddb_schema_DbDocumentMutation.prefixForPath(this.userId, documentKey.path);\n var indexStart = IDBKeyRange.lowerBound(indexPrefix);\n var results = [];\n return documentMutationsStore(transaction).iterate({ range: indexStart }, function (indexKey, _, control) {\n var userID = indexKey[0],\n encodedPath = indexKey[1],\n batchID = indexKey[2];\n // Only consider rows matching exactly the specific key of\n // interest. Note that because we order by path first, and we\n // order terminators before path separators, we'll encounter all\n // the index rows for documentKey contiguously. In particular, all\n // the rows for documentKey will occur before any rows for\n // documents nested in a subcollection beneath documentKey so we\n // can stop as soon as we hit any such row.\n var path = decode(encodedPath);\n if (userID !== _this.userId || !documentKey.path.equals(path)) {\n control.done();\n return;\n }\n var mutationKey = _this.keyForBatchId(batchID);\n // Look up the mutation batch in the store.\n // PORTING NOTE: because iteration is callback driven in the web,\n // we just look up the key instead of keeping an open iterator\n // like iOS.\n return mutationsStore(transaction).get(mutationKey).next(function (dbBatch) {\n if (dbBatch === null) {\n fail('Dangling document-mutation reference found: ' + indexKey + ' which points to ' + mutationKey);\n }\n results.push(_this.serializer.fromDbMutationBatch(dbBatch));\n });\n }).next(function () {\n return results;\n });\n };\n IndexedDbMutationQueue.prototype.getAllMutationBatchesAffectingQuery = function (transaction, query) {\n var _this = this;\n assert(!query.isDocumentQuery(), \"Document queries shouldn't go down this path\");\n var queryPath = query.path;\n var immediateChildrenLength = queryPath.length + 1;\n // TODO(mcg): Actually implement a single-collection query\n //\n // This is actually executing an ancestor query, traversing the whole\n // subtree below the collection which can be horrifically inefficient for\n // some structures. The right way to solve this is to implement the full\n // value index, but that's not in the cards in the near future so this is\n // the best we can do for the moment.\n //\n // Since we don't yet index the actual properties in the mutations, our\n // current approach is to just return all mutation batches that affect\n // documents in the collection being queried.\n var indexPrefix = indexeddb_schema_DbDocumentMutation.prefixForPath(this.userId, queryPath);\n var encodedQueryPath = indexPrefix[1];\n var indexStart = IDBKeyRange.lowerBound(indexPrefix);\n // Collect up unique batchIDs encountered during a scan of the index. Use a\n // SortedSet to accumulate batch IDs so they can be traversed in order in a\n // scan of the main table.\n var uniqueBatchIDs = new sorted_set_SortedSet(primitiveComparator);\n return documentMutationsStore(transaction).iterate({ range: indexStart }, function (indexKey, _, control) {\n var userID = indexKey[0],\n encodedPath = indexKey[1],\n batchID = indexKey[2];\n var path = decode(encodedPath);\n if (userID !== _this.userId || !queryPath.isPrefixOf(path)) {\n control.done();\n return;\n }\n // Rows with document keys more than one segment longer than the\n // query path can't be matches. For example, a query on 'rooms'\n // can't match the document /rooms/abc/messages/xyx.\n // TODO(mcg): we'll need a different scanner when we implement\n // ancestor queries.\n if (path.length !== immediateChildrenLength) {\n return;\n }\n uniqueBatchIDs = uniqueBatchIDs.add(batchID);\n }).next(function () {\n var results = [];\n var promises = [];\n // TODO(rockwood): Implement this using iterate.\n uniqueBatchIDs.forEach(function (batchID) {\n var mutationKey = _this.keyForBatchId(batchID);\n promises.push(mutationsStore(transaction).get(mutationKey).next(function (mutation) {\n if (mutation === null) {\n fail('Dangling document-mutation reference found, ' + 'which points to ' + mutationKey);\n }\n results.push(_this.serializer.fromDbMutationBatch(mutation));\n }));\n });\n return persistence_promise_PersistencePromise.waitFor(promises).next(function () {\n return results;\n });\n });\n };\n IndexedDbMutationQueue.prototype.removeMutationBatches = function (transaction, batches) {\n var txn = mutationsStore(transaction);\n var indexTxn = documentMutationsStore(transaction);\n var promises = [];\n var _loop_1 = function _loop_1(batch) {\n var range = IDBKeyRange.only(this_1.keyForBatchId(batch.batchId));\n var numDeleted = 0;\n var removePromise = txn.iterate({ range: range }, function (key, value, control) {\n numDeleted++;\n return control.delete();\n });\n promises.push(removePromise.next(function () {\n assert(numDeleted === 1, 'Dangling document-mutation reference found: Missing batch ' + batch.batchId);\n }));\n for (var _i = 0, _a = batch.mutations; _i < _a.length; _i++) {\n var mutation = _a[_i];\n var indexKey = indexeddb_schema_DbDocumentMutation.key(this_1.userId, mutation.key.path, batch.batchId);\n promises.push(indexTxn.delete(indexKey));\n if (this_1.garbageCollector !== null) {\n this_1.garbageCollector.addPotentialGarbageKey(mutation.key);\n }\n }\n };\n var this_1 = this;\n for (var _i = 0, batches_1 = batches; _i < batches_1.length; _i++) {\n var batch = batches_1[_i];\n _loop_1(batch);\n }\n return persistence_promise_PersistencePromise.waitFor(promises);\n };\n IndexedDbMutationQueue.prototype.performConsistencyCheck = function (txn) {\n var _this = this;\n return this.checkEmpty(txn).next(function (empty) {\n if (!empty) {\n return persistence_promise_PersistencePromise.resolve();\n }\n // Verify that there are no entries in the documentMutations index if\n // the queue is empty.\n var startRange = IDBKeyRange.lowerBound(indexeddb_schema_DbDocumentMutation.prefixForUser(_this.userId));\n var danglingMutationReferences = [];\n return documentMutationsStore(txn).iterate({ range: startRange }, function (key, _, control) {\n var userID = key[0];\n if (userID !== _this.userId) {\n control.done();\n return;\n } else {\n var path = decode(key[1]);\n danglingMutationReferences.push(path);\n }\n }).next(function () {\n assert(danglingMutationReferences.length === 0, 'Document leak -- detected dangling mutation references when queue is empty. Dangling keys: ' + danglingMutationReferences.map(function (p) {\n return p.canonicalString();\n }));\n });\n });\n };\n IndexedDbMutationQueue.prototype.setGarbageCollector = function (gc) {\n this.garbageCollector = gc;\n };\n IndexedDbMutationQueue.prototype.containsKey = function (txn, key) {\n var _this = this;\n var indexKey = indexeddb_schema_DbDocumentMutation.prefixForPath(this.userId, key.path);\n var encodedPath = indexKey[1];\n var startRange = IDBKeyRange.lowerBound(indexKey);\n var containsKey = false;\n return documentMutationsStore(txn).iterate({ range: startRange, keysOnly: true }, function (key, _, control) {\n var userID = key[0],\n keyPath = key[1],\n batchID = key[2];\n if (userID === _this.userId && keyPath === encodedPath) {\n containsKey = true;\n }\n control.done();\n }).next(function () {\n return containsKey;\n });\n };\n /**\r\n * Creates a [userId, batchId] key for use with the DbMutationQueue object\r\n * store.\r\n */\n IndexedDbMutationQueue.prototype.keyForBatchId = function (batchId) {\n return [this.userId, batchId];\n };\n return IndexedDbMutationQueue;\n}();\n\nfunction validateStreamToken(token) {\n assert(typeof token === 'string', 'Persisting non-string stream token not supported.');\n return token;\n}\n/**\r\n * Helper to get a typed SimpleDbStore for the mutations object store.\r\n */\nfunction mutationsStore(txn) {\n return getStore(txn, DbMutationBatch.store);\n}\n/**\r\n * Helper to get a typed SimpleDbStore for the mutationQueues object store.\r\n */\nfunction documentMutationsStore(txn) {\n return getStore(txn, indexeddb_schema_DbDocumentMutation.store);\n}\n/**\r\n * Helper to get a typed SimpleDbStore for the mutationQueues object store.\r\n */\nfunction mutationQueuesStore(txn) {\n return getStore(txn, DbMutationQueue.store);\n}\n/**\r\n * Helper to get a typed SimpleDbStore from a transaction.\r\n */\nfunction getStore(txn, store) {\n if (txn instanceof simple_db_SimpleDbTransaction) {\n return txn.store(store);\n } else {\n return fail('Invalid transaction object provided!');\n }\n}\n// CONCATENATED MODULE: ./src/firestore/local/indexeddb_query_cache.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\nvar indexeddb_query_cache_IndexedDbQueryCache = /** @class */function () {\n function IndexedDbQueryCache(serializer) {\n this.serializer = serializer;\n /**\r\n * The last received snapshot version. We store this seperately from the\r\n * metadata to avoid the extra conversion to/from DbTimestamp.\r\n */\n this.lastRemoteSnapshotVersion = snapshot_version_SnapshotVersion.MIN;\n /**\r\n * A cached copy of the metadata for the query cache.\r\n */\n this.metadata = new DbTargetGlobal(\n /*highestTargetId=*/0,\n /*lastListenSequenceNumber=*/0, snapshot_version_SnapshotVersion.MIN.toTimestamp());\n /** The garbage collector to notify about potential garbage keys. */\n this.garbageCollector = null;\n }\n IndexedDbQueryCache.prototype.start = function (transaction) {\n var _this = this;\n return globalTargetStore(transaction).get(DbTargetGlobal.key).next(function (metadata) {\n if (metadata !== null) {\n _this.metadata = metadata;\n var lastSavedVersion = metadata.lastRemoteSnapshotVersion;\n _this.lastRemoteSnapshotVersion = snapshot_version_SnapshotVersion.fromTimestamp(new timestamp_Timestamp(lastSavedVersion.seconds, lastSavedVersion.nanos));\n }\n return persistence_promise_PersistencePromise.resolve();\n });\n };\n IndexedDbQueryCache.prototype.getHighestTargetId = function () {\n return this.metadata.highestTargetId;\n };\n IndexedDbQueryCache.prototype.getLastRemoteSnapshotVersion = function () {\n return this.lastRemoteSnapshotVersion;\n };\n IndexedDbQueryCache.prototype.setLastRemoteSnapshotVersion = function (transaction, snapshotVersion) {\n this.lastRemoteSnapshotVersion = snapshotVersion;\n this.metadata.lastRemoteSnapshotVersion = snapshotVersion.toTimestamp();\n return globalTargetStore(transaction).put(DbTargetGlobal.key, this.metadata);\n };\n IndexedDbQueryCache.prototype.addQueryData = function (transaction, queryData) {\n var _this = this;\n var targetId = queryData.targetId;\n var addedQueryPromise = targetsStore(transaction).put(this.serializer.toDbTarget(queryData));\n if (targetId > this.metadata.highestTargetId) {\n this.metadata.highestTargetId = targetId;\n return addedQueryPromise.next(function () {\n return globalTargetStore(transaction).put(DbTargetGlobal.key, _this.metadata);\n });\n } else {\n return addedQueryPromise;\n }\n };\n IndexedDbQueryCache.prototype.removeQueryData = function (transaction, queryData) {\n return this.removeMatchingKeysForTargetId(transaction, queryData.targetId).next(function () {\n targetsStore(transaction).delete(queryData.targetId);\n });\n };\n IndexedDbQueryCache.prototype.getQueryData = function (transaction, query) {\n var _this = this;\n // Iterating by the canonicalId may yield more than one result because\n // canonicalId values are not required to be unique per target. This query\n // depends on the queryTargets index to be efficent.\n var canonicalId = query.canonicalId();\n var range = IDBKeyRange.bound([canonicalId, Number.NEGATIVE_INFINITY], [canonicalId, Number.POSITIVE_INFINITY]);\n var result = null;\n return targetsStore(transaction).iterate({ range: range, index: DbTarget.queryTargetsIndexName }, function (key, value, control) {\n var found = _this.serializer.fromDbTarget(value);\n // After finding a potential match, check that the query is\n // actually equal to the requested query.\n if (query.equals(found.query)) {\n result = found;\n control.done();\n }\n }).next(function () {\n return result;\n });\n };\n IndexedDbQueryCache.prototype.addMatchingKeys = function (txn, keys, targetId) {\n // PORTING NOTE: The reverse index (documentsTargets) is maintained by\n // Indexeddb.\n var promises = [];\n var store = documentTargetStore(txn);\n keys.forEach(function (key) {\n var path = encode(key.path);\n promises.push(store.put(new DbTargetDocument(targetId, path)));\n });\n return persistence_promise_PersistencePromise.waitFor(promises);\n };\n IndexedDbQueryCache.prototype.removeMatchingKeys = function (txn, keys, targetId) {\n var _this = this;\n // PORTING NOTE: The reverse index (documentsTargets) is maintained by\n // IndexedDb.\n var promises = [];\n var store = documentTargetStore(txn);\n keys.forEach(function (key) {\n var path = encode(key.path);\n promises.push(store.delete([targetId, path]));\n if (_this.garbageCollector !== null) {\n _this.garbageCollector.addPotentialGarbageKey(key);\n }\n });\n return persistence_promise_PersistencePromise.waitFor(promises);\n };\n IndexedDbQueryCache.prototype.removeMatchingKeysForTargetId = function (txn, targetId) {\n var store = documentTargetStore(txn);\n var range = IDBKeyRange.bound([targetId], [targetId + 1],\n /*lowerOpen=*/false,\n /*upperOpen=*/true);\n return this.notifyGCForRemovedKeys(txn, range).next(function () {\n return store.delete(range);\n });\n };\n IndexedDbQueryCache.prototype.notifyGCForRemovedKeys = function (txn, range) {\n var _this = this;\n var store = documentTargetStore(txn);\n if (this.garbageCollector !== null && this.garbageCollector.isEager) {\n // In order to generate garbage events properly, we need to read these\n // keys before deleting.\n return store.iterate({ range: range, keysOnly: true }, function (key, _, control) {\n var path = decode(key[1]);\n var docKey = new document_key_DocumentKey(path);\n // Paranoid assertion in case the the collector is set to null\n // during the iteration.\n assert(_this.garbageCollector !== null, 'GarbageCollector for query cache set to null during key removal.');\n _this.garbageCollector.addPotentialGarbageKey(docKey);\n });\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n };\n IndexedDbQueryCache.prototype.getMatchingKeysForTargetId = function (txn, targetId) {\n var promises = [];\n var range = IDBKeyRange.bound([targetId], [targetId + 1],\n /*lowerOpen=*/false,\n /*upperOpen=*/true);\n var store = documentTargetStore(txn);\n var result = documentKeySet();\n return store.iterate({ range: range, keysOnly: true }, function (key, _, control) {\n var path = decode(key[1]);\n var docKey = new document_key_DocumentKey(path);\n result = result.add(docKey);\n }).next(function () {\n return result;\n });\n };\n IndexedDbQueryCache.prototype.setGarbageCollector = function (gc) {\n this.garbageCollector = gc;\n };\n IndexedDbQueryCache.prototype.containsKey = function (txn, key) {\n assert(txn !== null, 'Persistence Transaction cannot be null for query cache containsKey');\n var path = encode(key.path);\n var range = IDBKeyRange.bound([path], [immediateSuccessor(path)],\n /*lowerOpen=*/false,\n /*upperOpen=*/true);\n var count = 0;\n return documentTargetStore(txn).iterate({\n index: DbTargetDocument.documentTargetsIndex,\n keysOnly: true,\n range: range\n }, function (key, _, control) {\n count++;\n control.done();\n }).next(function () {\n return count > 0;\n });\n };\n return IndexedDbQueryCache;\n}();\n\n/**\r\n * Helper to get a typed SimpleDbStore for the queries object store.\r\n */\nfunction targetsStore(txn) {\n return indexeddb_query_cache_getStore(txn, DbTarget.store);\n}\n/**\r\n * Helper to get a typed SimpleDbStore for the target globals object store.\r\n */\nfunction globalTargetStore(txn) {\n return indexeddb_query_cache_getStore(txn, DbTargetGlobal.store);\n}\n/**\r\n * Helper to get a typed SimpleDbStore for the document target object store.\r\n */\nfunction documentTargetStore(txn) {\n return indexeddb_query_cache_getStore(txn, DbTargetDocument.store);\n}\n/**\r\n * Helper to get a typed SimpleDbStore from a transaction.\r\n */\nfunction indexeddb_query_cache_getStore(txn, store) {\n if (txn instanceof simple_db_SimpleDbTransaction) {\n return txn.store(store);\n } else {\n return fail('Invalid transaction object provided!');\n }\n}\n// CONCATENATED MODULE: ./src/firestore/local/indexeddb_remote_document_cache.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\nvar indexeddb_remote_document_cache_IndexedDbRemoteDocumentCache = /** @class */function () {\n function IndexedDbRemoteDocumentCache(serializer) {\n this.serializer = serializer;\n }\n IndexedDbRemoteDocumentCache.prototype.addEntry = function (transaction, maybeDocument) {\n return remoteDocumentsStore(transaction).put(dbKey(maybeDocument.key), this.serializer.toDbRemoteDocument(maybeDocument));\n };\n IndexedDbRemoteDocumentCache.prototype.removeEntry = function (transaction, documentKey) {\n return remoteDocumentsStore(transaction).delete(dbKey(documentKey));\n };\n IndexedDbRemoteDocumentCache.prototype.getEntry = function (transaction, documentKey) {\n var _this = this;\n return remoteDocumentsStore(transaction).get(dbKey(documentKey)).next(function (dbRemoteDoc) {\n return dbRemoteDoc ? _this.serializer.fromDbRemoteDocument(dbRemoteDoc) : null;\n });\n };\n IndexedDbRemoteDocumentCache.prototype.getDocumentsMatchingQuery = function (transaction, query) {\n var _this = this;\n var results = documentMap();\n // Documents are ordered by key, so we can use a prefix scan to narrow down\n // the documents we need to match the query against.\n var startKey = query.path.toArray();\n var range = IDBKeyRange.lowerBound(startKey);\n return remoteDocumentsStore(transaction).iterate({ range: range }, function (key, dbRemoteDoc, control) {\n var maybeDoc = _this.serializer.fromDbRemoteDocument(dbRemoteDoc);\n if (!query.path.isPrefixOf(maybeDoc.key.path)) {\n control.done();\n } else if (maybeDoc instanceof document_Document && query.matches(maybeDoc)) {\n results = results.insert(maybeDoc.key, maybeDoc);\n }\n }).next(function () {\n return results;\n });\n };\n return IndexedDbRemoteDocumentCache;\n}();\n\n/**\r\n * Helper to get a typed SimpleDbStore for the remoteDocuments object store.\r\n */\nfunction remoteDocumentsStore(txn) {\n if (txn instanceof simple_db_SimpleDbTransaction) {\n return txn.store(DbRemoteDocument.store);\n } else {\n return fail('Invalid transaction object provided!');\n }\n}\nfunction dbKey(docKey) {\n return docKey.path.toArray();\n}\n// CONCATENATED MODULE: ./src/firestore/local/local_serializer.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n/** Serializer for values stored in the LocalStore. */\nvar local_serializer_LocalSerializer = /** @class */function () {\n function LocalSerializer(remoteSerializer) {\n this.remoteSerializer = remoteSerializer;\n }\n /** Decodes a remote document from storage locally to a Document. */\n LocalSerializer.prototype.fromDbRemoteDocument = function (remoteDoc) {\n if (remoteDoc.document) {\n return this.remoteSerializer.fromDocument(remoteDoc.document);\n } else if (remoteDoc.noDocument) {\n var key = document_key_DocumentKey.fromSegments(remoteDoc.noDocument.path);\n var readTime = remoteDoc.noDocument.readTime;\n var timestamp = new timestamp_Timestamp(readTime.seconds, readTime.nanos);\n return new document_NoDocument(key, snapshot_version_SnapshotVersion.fromTimestamp(timestamp));\n } else {\n return fail('Unexpected DbRemoteDocument');\n }\n };\n /** Encodes a document for storage locally. */\n LocalSerializer.prototype.toDbRemoteDocument = function (maybeDoc) {\n if (maybeDoc instanceof document_Document) {\n var doc = this.remoteSerializer.toDocument(maybeDoc);\n return new DbRemoteDocument(null, doc);\n } else {\n var path = maybeDoc.key.path.toArray();\n var timestamp = maybeDoc.version.toTimestamp();\n var readTime = new DbTimestamp(timestamp.seconds, timestamp.nanos);\n return new DbRemoteDocument(new DbNoDocument(path, readTime), null);\n }\n };\n /** Encodes a batch of mutations into a DbMutationBatch for local storage. */\n LocalSerializer.prototype.toDbMutationBatch = function (userId, batch) {\n var _this = this;\n var serializedMutations = batch.mutations.map(function (m) {\n return _this.remoteSerializer.toMutation(m);\n });\n return new DbMutationBatch(userId, batch.batchId, batch.localWriteTime.toEpochMilliseconds(), serializedMutations);\n };\n /** Decodes a DbMutationBatch into a MutationBatch */\n LocalSerializer.prototype.fromDbMutationBatch = function (dbBatch) {\n var _this = this;\n var mutations = dbBatch.mutations.map(function (m) {\n return _this.remoteSerializer.fromMutation(m);\n });\n var timestamp = timestamp_Timestamp.fromEpochMilliseconds(dbBatch.localWriteTimeMs);\n return new mutation_batch_MutationBatch(dbBatch.batchId, timestamp, mutations);\n };\n /** Decodes a DbTarget into QueryData */\n LocalSerializer.prototype.fromDbTarget = function (dbTarget) {\n var readTime = new timestamp_Timestamp(dbTarget.readTime.seconds, dbTarget.readTime.nanos);\n var version = snapshot_version_SnapshotVersion.fromTimestamp(readTime);\n var query;\n if (isDocumentQuery(dbTarget.query)) {\n query = this.remoteSerializer.fromDocumentsTarget(dbTarget.query);\n } else {\n query = this.remoteSerializer.fromQueryTarget(dbTarget.query);\n }\n return new query_data_QueryData(query, dbTarget.targetId, QueryPurpose.Listen, version, dbTarget.resumeToken);\n };\n /** Encodes QueryData into a DbTarget for storage locally. */\n LocalSerializer.prototype.toDbTarget = function (queryData) {\n assert(QueryPurpose.Listen === queryData.purpose, 'Only queries with purpose ' + QueryPurpose.Listen + ' may be stored, got ' + queryData.purpose);\n var timestamp = queryData.snapshotVersion.toTimestamp();\n var dbTimestamp = new DbTimestamp(timestamp.seconds, timestamp.nanos);\n var queryProto;\n if (queryData.query.isDocumentQuery()) {\n queryProto = this.remoteSerializer.toDocumentsTarget(queryData.query);\n } else {\n queryProto = this.remoteSerializer.toQueryTarget(queryData.query);\n }\n assert(typeof queryData.resumeToken === 'string', 'Persisting non-string resume token not supported.');\n var resumeToken = queryData.resumeToken;\n // lastListenSequenceNumber is always 0 until we do real GC.\n return new DbTarget(queryData.targetId, queryData.query.canonicalId(), dbTimestamp, resumeToken, 0, queryProto);\n };\n return LocalSerializer;\n}();\n\n/**\r\n * A helper function for figuring out what kind of query has been stored.\r\n */\nfunction isDocumentQuery(dbQuery) {\n return dbQuery.documents !== undefined;\n}\n// CONCATENATED MODULE: ./src/firestore/local/indexeddb_persistence.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar indexeddb_persistence_LOG_TAG = 'IndexedDbPersistence';\n/** If the owner lease is older than 5 seconds, try to take ownership. */\nvar OWNER_LEASE_MAX_AGE_MS = 5000;\n/** Refresh the owner lease every 4 seconds while owner. */\nvar OWNER_LEASE_REFRESH_INTERVAL_MS = 4000;\n/** LocalStorage location to indicate a zombied ownerId (see class comment). */\nvar ZOMBIE_OWNER_LOCALSTORAGE_SUFFIX = 'zombiedOwnerId';\n/** Error when the owner lease cannot be acquired or is lost. */\nvar EXISTING_OWNER_ERROR_MSG = 'There is another tab open with offline' + ' persistence enabled. Only one such tab is allowed at a time. The' + ' other tab must be closed or persistence must be disabled.';\nvar UNSUPPORTED_PLATFORM_ERROR_MSG = 'This platform is either missing' + ' IndexedDB or is known to have an incomplete implementation. Offline' + ' persistence has been disabled.';\n/**\r\n * An IndexedDB-backed instance of Persistence. Data is stored persistently\r\n * across sessions.\r\n *\r\n * Currently the Firestore SDK only supports a single consumer of the database,\r\n * but browsers obviously support multiple tabs. IndexedDbPersistence ensures a\r\n * single consumer of the database via an \"owner lease\" stored in the database.\r\n *\r\n * On startup, IndexedDbPersistence assigns itself a random \"ownerId\" and writes\r\n * it to a special \"owner\" object in the database (if no entry exists already or\r\n * the current entry is expired). This owner lease is then verified inside every\r\n * transaction to ensure the lease has not been lost.\r\n *\r\n * If a tab opts not to acquire the owner lease (because there's an existing\r\n * non-expired owner) or loses the owner lease, IndexedDbPersistence enters a\r\n * failed state and all subsequent operations will automatically fail.\r\n *\r\n * The current owner regularly refreshes the owner lease with new timestamps to\r\n * prevent newly-opened tabs from taking over ownership.\r\n *\r\n * Additionally there is an optimization so that when a tab is closed, the owner\r\n * lease is released immediately (this is especially important to make sure that\r\n * a refreshed tab is able to immediately re-acquire the owner lease).\r\n * Unfortunately, IndexedDB cannot be reliably used in window.unload since it is\r\n * an asynchronous API. So in addition to attempting to give up the lease,\r\n * the owner writes its ownerId to a \"zombiedOwnerId\" entry in LocalStorage\r\n * which acts as an indicator that another tab should go ahead and take the\r\n * owner lease immediately regardless of the current lease timestamp.\r\n */\nvar indexeddb_persistence_IndexedDbPersistence = /** @class */function () {\n function IndexedDbPersistence(prefix, serializer) {\n this.ownerId = this.generateOwnerId();\n this.dbName = prefix + IndexedDbPersistence.MAIN_DATABASE;\n this.serializer = new local_serializer_LocalSerializer(serializer);\n this.localStoragePrefix = prefix;\n }\n IndexedDbPersistence.prototype.start = function () {\n var _this = this;\n if (!IndexedDbPersistence.isAvailable()) {\n this.persistenceError = new FirestoreError(Code.UNIMPLEMENTED, UNSUPPORTED_PLATFORM_ERROR_MSG);\n return utils_promise[\"b\" /* PromiseImpl */].reject(this.persistenceError);\n }\n assert(!this.started, 'IndexedDbPersistence double-started!');\n this.started = true;\n return simple_db_SimpleDb.openOrCreate(this.dbName, SCHEMA_VERSION, createOrUpgradeDb).then(function (db) {\n _this.simpleDb = db;\n }).then(function () {\n return _this.tryAcquireOwnerLease();\n }).then(function () {\n _this.scheduleOwnerLeaseRefreshes();\n _this.attachWindowUnloadHook();\n });\n };\n IndexedDbPersistence.prototype.shutdown = function () {\n var _this = this;\n assert(this.started, 'IndexedDbPersistence shutdown without start!');\n this.started = false;\n this.detachWindowUnloadHook();\n this.stopOwnerLeaseRefreshes();\n return this.releaseOwnerLease().then(function () {\n _this.simpleDb.close();\n });\n };\n IndexedDbPersistence.prototype.getMutationQueue = function (user) {\n return indexeddb_mutation_queue_IndexedDbMutationQueue.forUser(user, this.serializer);\n };\n IndexedDbPersistence.prototype.getQueryCache = function () {\n return new indexeddb_query_cache_IndexedDbQueryCache(this.serializer);\n };\n IndexedDbPersistence.prototype.getRemoteDocumentCache = function () {\n return new indexeddb_remote_document_cache_IndexedDbRemoteDocumentCache(this.serializer);\n };\n IndexedDbPersistence.prototype.runTransaction = function (action, operation) {\n var _this = this;\n if (this.persistenceError) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(this.persistenceError);\n }\n debug(indexeddb_persistence_LOG_TAG, 'Starting transaction:', action);\n // Do all transactions as readwrite against all object stores, since we\n // are the only reader/writer.\n return this.simpleDb.runTransaction('readwrite', ALL_STORES, function (txn) {\n // Verify that we still have the owner lease as part of every transaction.\n return _this.ensureOwnerLease(txn).next(function () {\n return operation(txn);\n });\n });\n };\n IndexedDbPersistence.isAvailable = function () {\n return simple_db_SimpleDb.isAvailable();\n };\n /**\r\n * Generates a string used as a prefix when storing data in IndexedDB and\r\n * LocalStorage.\r\n */\n IndexedDbPersistence.buildStoragePrefix = function (databaseInfo) {\n // Use two different prefix formats:\n //\n // * firestore / persistenceKey / projectID . databaseID / ...\n // * firestore / persistenceKey / projectID / ...\n //\n // projectIDs are DNS-compatible names and cannot contain dots\n // so there's no danger of collisions.\n var database = databaseInfo.databaseId.projectId;\n if (!databaseInfo.databaseId.isDefaultDatabase) {\n database += '.' + databaseInfo.databaseId.database;\n }\n return 'firestore/' + databaseInfo.persistenceKey + '/' + database + '/';\n };\n /**\r\n * Acquires the owner lease if there's no valid owner. Else returns a rejected\r\n * promise.\r\n */\n IndexedDbPersistence.prototype.tryAcquireOwnerLease = function () {\n var _this = this;\n // NOTE: Don't use this.runTransaction, since it requires us to already\n // have the lease.\n return this.simpleDb.runTransaction('readwrite', [DbOwner.store], function (txn) {\n var store = txn.store(DbOwner.store);\n return store.get('owner').next(function (dbOwner) {\n if (!_this.validOwner(dbOwner)) {\n var newDbOwner = new DbOwner(_this.ownerId, Date.now());\n debug(indexeddb_persistence_LOG_TAG, 'No valid owner. Acquiring owner lease. Current owner:', dbOwner, 'New owner:', newDbOwner);\n return store.put('owner', newDbOwner);\n } else {\n debug(indexeddb_persistence_LOG_TAG, 'Valid owner already. Failing. Current owner:', dbOwner);\n _this.persistenceError = new FirestoreError(Code.FAILED_PRECONDITION, EXISTING_OWNER_ERROR_MSG);\n return persistence_promise_PersistencePromise.reject(_this.persistenceError);\n }\n });\n });\n };\n /** Checks the owner lease and deletes it if we are the current owner. */\n IndexedDbPersistence.prototype.releaseOwnerLease = function () {\n var _this = this;\n // NOTE: Don't use this.runTransaction, since it requires us to already\n // have the lease.\n return this.simpleDb.runTransaction('readwrite', [DbOwner.store], function (txn) {\n var store = txn.store(DbOwner.store);\n return store.get('owner').next(function (dbOwner) {\n if (dbOwner !== null && dbOwner.ownerId === _this.ownerId) {\n debug(indexeddb_persistence_LOG_TAG, 'Releasing owner lease.');\n return store.delete('owner');\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n });\n });\n };\n /**\r\n * Checks the owner lease and returns a rejected promise if we are not the\r\n * current owner. This should be included in every transaction to guard\r\n * against losing the owner lease.\r\n */\n IndexedDbPersistence.prototype.ensureOwnerLease = function (txn) {\n var _this = this;\n var store = txn.store(DbOwner.store);\n return store.get('owner').next(function (dbOwner) {\n if (dbOwner === null || dbOwner.ownerId !== _this.ownerId) {\n _this.persistenceError = new FirestoreError(Code.FAILED_PRECONDITION, EXISTING_OWNER_ERROR_MSG);\n return persistence_promise_PersistencePromise.reject(_this.persistenceError);\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n });\n };\n /**\r\n * Returns true if the provided owner exists, has a recent timestamp, and\r\n * isn't zombied.\r\n *\r\n * NOTE: To determine if the owner is zombied, this method reads from\r\n * LocalStorage which could be mildly expensive.\r\n */\n IndexedDbPersistence.prototype.validOwner = function (dbOwner) {\n var now = Date.now();\n var minAcceptable = now - OWNER_LEASE_MAX_AGE_MS;\n var maxAcceptable = now;\n if (dbOwner === null) {\n return false; // no owner.\n } else if (dbOwner.leaseTimestampMs < minAcceptable) {\n return false; // owner lease has expired.\n } else if (dbOwner.leaseTimestampMs > maxAcceptable) {\n log_error('Persistence owner-lease is in the future. Discarding.', dbOwner);\n return false;\n } else if (dbOwner.ownerId === this.getZombiedOwnerId()) {\n return false; // owner's tab closed.\n } else {\n return true;\n }\n };\n /**\r\n * Schedules a recurring timer to update the owner lease timestamp to prevent\r\n * other tabs from taking the lease.\r\n */\n IndexedDbPersistence.prototype.scheduleOwnerLeaseRefreshes = function () {\n var _this = this;\n // NOTE: This doesn't need to be scheduled on the async queue and doing so\n // would increase the chances of us not refreshing on time if the queue is\n // backed up for some reason.\n this.ownerLeaseRefreshHandle = setInterval(function () {\n var txResult = _this.runTransaction('Refresh owner timestamp', function (txn) {\n // NOTE: We don't need to validate the current owner contents, since\n // runTransaction does that automatically.\n var store = txn.store(DbOwner.store);\n return store.put('owner', new DbOwner(_this.ownerId, Date.now()));\n });\n txResult.catch(function (reason) {\n // Probably means we lost the lease. Report the error and stop trying to\n // refresh the lease.\n log_error(reason);\n _this.stopOwnerLeaseRefreshes();\n });\n }, OWNER_LEASE_REFRESH_INTERVAL_MS);\n };\n IndexedDbPersistence.prototype.stopOwnerLeaseRefreshes = function () {\n if (this.ownerLeaseRefreshHandle) {\n clearInterval(this.ownerLeaseRefreshHandle);\n this.ownerLeaseRefreshHandle = null;\n }\n };\n /**\r\n * Attaches a window.unload handler that will synchronously write our\r\n * ownerId to a \"zombie owner id\" location in localstorage. This can be used\r\n * by tabs trying to acquire the lease to determine that the lease should be\r\n * acquired immediately even if the timestamp is recent. This is particularly\r\n * important for the refresh case (so the tab correctly re-acquires the owner\r\n * lease). LocalStorage is used for this rather than IndexedDb because it is\r\n * a synchronous API and so can be used reliably from an unload handler.\r\n */\n IndexedDbPersistence.prototype.attachWindowUnloadHook = function () {\n var _this = this;\n this.windowUnloadHandler = function () {\n // Record that we're zombied.\n _this.setZombiedOwnerId(_this.ownerId);\n // Attempt graceful shutdown (including releasing our owner lease), but\n // there's no guarantee it will complete.\n _this.shutdown();\n };\n window.addEventListener('unload', this.windowUnloadHandler);\n };\n IndexedDbPersistence.prototype.detachWindowUnloadHook = function () {\n if (this.windowUnloadHandler) {\n window.removeEventListener('unload', this.windowUnloadHandler);\n this.windowUnloadHandler = null;\n }\n };\n /**\r\n * Returns any recorded \"zombied owner\" (i.e. a previous owner that became\r\n * zombied due to their tab closing) from LocalStorage, or null if no such\r\n * record exists.\r\n */\n IndexedDbPersistence.prototype.getZombiedOwnerId = function () {\n try {\n var zombiedOwnerId = window.localStorage.getItem(this.zombiedOwnerLocalStorageKey());\n debug(indexeddb_persistence_LOG_TAG, 'Zombied ownerID from LocalStorage:', zombiedOwnerId);\n return zombiedOwnerId;\n } catch (e) {\n // Gracefully handle if LocalStorage isn't available / working.\n log_error(indexeddb_persistence_LOG_TAG, 'Failed to get zombie owner id.', e);\n return null;\n }\n };\n /**\r\n * Records a zombied owner (an owner that had its tab closed) in LocalStorage\r\n * or, if passed null, deletes any recorded zombied owner.\r\n */\n IndexedDbPersistence.prototype.setZombiedOwnerId = function (zombieOwnerId) {\n try {\n if (zombieOwnerId === null) {\n window.localStorage.removeItem(this.zombiedOwnerLocalStorageKey());\n } else {\n window.localStorage.setItem(this.zombiedOwnerLocalStorageKey(), zombieOwnerId);\n }\n } catch (e) {\n // Gracefully handle if LocalStorage isn't available / working.\n log_error(indexeddb_persistence_LOG_TAG, 'Failed to set zombie owner id.', e);\n }\n };\n IndexedDbPersistence.prototype.zombiedOwnerLocalStorageKey = function () {\n return this.localStoragePrefix + ZOMBIE_OWNER_LOCALSTORAGE_SUFFIX;\n };\n IndexedDbPersistence.prototype.generateOwnerId = function () {\n // For convenience, just use an AutoId.\n return misc_AutoId.newId();\n };\n /**\r\n * The name of the main (and currently only) IndexedDB database. this name is\r\n * appended to the prefix provided to the IndexedDbPersistence constructor.\r\n */\n IndexedDbPersistence.MAIN_DATABASE = 'main';\n return IndexedDbPersistence;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/local_documents_view.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n/**\r\n * A readonly view of the local state of all documents we're tracking (i.e. we\r\n * have a cached version in remoteDocumentCache or local mutations for the\r\n * document). The view is computed by applying the mutations in the\r\n * MutationQueue to the RemoteDocumentCache.\r\n */\nvar local_documents_view_LocalDocumentsView = /** @class */function () {\n function LocalDocumentsView(remoteDocumentCache, mutationQueue) {\n this.remoteDocumentCache = remoteDocumentCache;\n this.mutationQueue = mutationQueue;\n }\n /**\r\n * Get the local view of the document identified by `key`.\r\n *\r\n * @return Local view of the document or null if we don't have any cached\r\n * state for it.\r\n */\n LocalDocumentsView.prototype.getDocument = function (transaction, key) {\n var _this = this;\n return this.remoteDocumentCache.getEntry(transaction, key).next(function (remoteDoc) {\n return _this.computeLocalDocument(transaction, key, remoteDoc);\n });\n };\n /**\r\n * Gets the local view of the documents identified by `keys`.\r\n *\r\n * If we don't have cached state for a document in `keys`, a NoDocument will\r\n * be stored for that key in the resulting set.\r\n */\n LocalDocumentsView.prototype.getDocuments = function (transaction, keys) {\n var _this = this;\n var promises = [];\n var results = maybeDocumentMap();\n keys.forEach(function (key) {\n promises.push(_this.getDocument(transaction, key).next(function (maybeDoc) {\n // TODO(http://b/32275378): Don't conflate missing / deleted.\n if (!maybeDoc) {\n maybeDoc = new document_NoDocument(key, snapshot_version_SnapshotVersion.forDeletedDoc());\n }\n results = results.insert(key, maybeDoc);\n }));\n });\n return persistence_promise_PersistencePromise.waitFor(promises).next(function () {\n return results;\n });\n };\n /** Performs a query against the local view of all documents. */\n LocalDocumentsView.prototype.getDocumentsMatchingQuery = function (transaction, query) {\n if (document_key_DocumentKey.isDocumentKey(query.path)) {\n return this.getDocumentsMatchingDocumentQuery(transaction, query.path);\n } else {\n return this.getDocumentsMatchingCollectionQuery(transaction, query);\n }\n };\n LocalDocumentsView.prototype.getDocumentsMatchingDocumentQuery = function (transaction, docPath) {\n // Just do a simple document lookup.\n return this.getDocument(transaction, new document_key_DocumentKey(docPath)).next(function (maybeDoc) {\n var result = documentMap();\n if (maybeDoc instanceof document_Document) {\n result = result.insert(maybeDoc.key, maybeDoc);\n }\n return result;\n });\n };\n LocalDocumentsView.prototype.getDocumentsMatchingCollectionQuery = function (transaction, query) {\n var _this = this;\n // Query the remote documents and overlay mutations.\n // TODO(mikelehen): There may be significant overlap between the mutations\n // affecting these remote documents and the\n // getAllMutationBatchesAffectingQuery() mutations. Consider optimizing.\n var results;\n return this.remoteDocumentCache.getDocumentsMatchingQuery(transaction, query).next(function (queryResults) {\n return _this.computeLocalDocuments(transaction, queryResults);\n }).next(function (promisedResults) {\n results = promisedResults;\n // Now use the mutation queue to discover any other documents that may\n // match the query after applying mutations.\n return _this.mutationQueue.getAllMutationBatchesAffectingQuery(transaction, query);\n }).next(function (matchingMutationBatches) {\n var matchingKeys = documentKeySet();\n for (var _i = 0, matchingMutationBatches_1 = matchingMutationBatches; _i < matchingMutationBatches_1.length; _i++) {\n var batch = matchingMutationBatches_1[_i];\n for (var _a = 0, _b = batch.mutations; _a < _b.length; _a++) {\n var mutation = _b[_a];\n // TODO(mikelehen): PERF: Check if this mutation actually\n // affects the query to reduce work.\n if (!results.get(mutation.key)) {\n matchingKeys = matchingKeys.add(mutation.key);\n }\n }\n }\n // Now add in the results for the matchingKeys.\n var promises = [];\n matchingKeys.forEach(function (key) {\n promises.push(_this.getDocument(transaction, key).next(function (doc) {\n if (doc instanceof document_Document) {\n results = results.insert(doc.key, doc);\n }\n }));\n });\n return persistence_promise_PersistencePromise.waitFor(promises);\n }).next(function () {\n // Finally, filter out any documents that don't actually match\n // the query.\n results.forEach(function (key, doc) {\n if (!query.matches(doc)) {\n results = results.remove(key);\n }\n });\n return results;\n });\n };\n /**\r\n * Takes a remote document and applies local mutations to generate the local\r\n * view of the document.\r\n * @param transaction The transaction in which to perform any persistence\r\n * operations.\r\n * @param documentKey The key of the document (necessary when remoteDocument\r\n * is null).\r\n * @param document The base remote document to apply mutations to or null.\r\n */\n LocalDocumentsView.prototype.computeLocalDocument = function (transaction, documentKey, document) {\n return this.mutationQueue.getAllMutationBatchesAffectingDocumentKey(transaction, documentKey).next(function (batches) {\n for (var _i = 0, batches_1 = batches; _i < batches_1.length; _i++) {\n var batch = batches_1[_i];\n document = batch.applyToLocalView(documentKey, document);\n }\n return document;\n });\n };\n /**\r\n * Takes a set of remote documents and applies local mutations to generate the\r\n * local view of the documents.\r\n * @param transaction The transaction in which to perform any persistence\r\n * operations.\r\n * @param documents The base remote documents to apply mutations to.\r\n * @return The local view of the documents.\r\n */\n LocalDocumentsView.prototype.computeLocalDocuments = function (transaction, documents) {\n var _this = this;\n var promises = [];\n documents.forEach(function (key, doc) {\n promises.push(_this.computeLocalDocument(transaction, key, doc).next(function (mutatedDoc) {\n if (mutatedDoc instanceof document_Document) {\n documents = documents.insert(mutatedDoc.key, mutatedDoc);\n } else if (mutatedDoc instanceof document_NoDocument) {\n documents = documents.remove(mutatedDoc.key);\n } else {\n fail('Unknown MaybeDocument: ' + mutatedDoc);\n }\n }));\n });\n return persistence_promise_PersistencePromise.waitFor(promises).next(function () {\n return documents;\n });\n };\n return LocalDocumentsView;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/remote_document_change_buffer.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n/**\r\n * An in-memory buffer of entries to be written to a RemoteDocumentCache.\r\n * It can be used to batch up a set of changes to be written to the cache, but\r\n * additionally supports reading entries back with the `getEntry()` method,\r\n * falling back to the underlying RemoteDocumentCache if no entry is\r\n * buffered.\r\n *\r\n * NOTE: This class was introduced in iOS to work around a limitation in\r\n * LevelDB. Given IndexedDb has full transaction support with\r\n * read-your-own-writes capability, this class is not technically needed, but\r\n * has been preserved as a convenience and to aid portability.\r\n */\nvar remote_document_change_buffer_RemoteDocumentChangeBuffer = /** @class */function () {\n function RemoteDocumentChangeBuffer(remoteDocumentCache) {\n this.remoteDocumentCache = remoteDocumentCache;\n this.changes = maybeDocumentMap();\n }\n /** Buffers a `RemoteDocumentCache.addEntry()` call. */\n RemoteDocumentChangeBuffer.prototype.addEntry = function (maybeDocument) {\n var changes = this.assertChanges();\n this.changes = changes.insert(maybeDocument.key, maybeDocument);\n };\n // NOTE: removeEntry() is not presently necessary and so is omitted.\n /**\r\n * Looks up an entry in the cache. The buffered changes will first be checked,\r\n * and if no buffered change applies, this will forward to\r\n * `RemoteDocumentCache.getEntry()`.\r\n *\r\n * @param transaction The transaction in which to perform any persistence\r\n * operations.\r\n * @param documentKey The key of the entry to look up.\r\n * @return The cached Document or NoDocument entry, or null if we have nothing\r\n * cached.\r\n */\n RemoteDocumentChangeBuffer.prototype.getEntry = function (transaction, documentKey) {\n var changes = this.assertChanges();\n var bufferedEntry = changes.get(documentKey);\n if (bufferedEntry) {\n return persistence_promise_PersistencePromise.resolve(bufferedEntry);\n } else {\n return this.remoteDocumentCache.getEntry(transaction, documentKey);\n }\n };\n /**\r\n * Applies buffered changes to the underlying RemoteDocumentCache, using\r\n * the provided transaction.\r\n */\n RemoteDocumentChangeBuffer.prototype.apply = function (transaction) {\n var _this = this;\n var changes = this.assertChanges();\n var promises = [];\n changes.forEach(function (key, maybeDoc) {\n promises.push(_this.remoteDocumentCache.addEntry(transaction, maybeDoc));\n });\n // We should not be used to buffer any more changes.\n this.changes = null;\n return persistence_promise_PersistencePromise.waitFor(promises);\n };\n /** Helper to assert this.changes is not null and return it. */\n RemoteDocumentChangeBuffer.prototype.assertChanges = function () {\n assert(this.changes !== null, 'Changes have already been applied.');\n return this.changes;\n };\n return RemoteDocumentChangeBuffer;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/local_store.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar local_store_LOG_TAG = 'LocalStore';\n/**\r\n * Local storage in the Firestore client. Coordinates persistence components\r\n * like the mutation queue and remote document cache to present a\r\n * latency-compensated view of stored data.\r\n *\r\n * The LocalStore is responsible for accepting mutations from the Sync Engine.\r\n * Writes from the client are put into a queue as provisional Mutations until\r\n * they are processed by the RemoteStore and confirmed as having been written\r\n * to the server.\r\n *\r\n * The local store provides the local version of documents that have been\r\n * modified locally. It maintains the constraint:\r\n *\r\n * LocalDocument = RemoteDocument + Active(LocalMutations)\r\n *\r\n * (Active mutations are those that are enqueued and have not been previously\r\n * acknowledged or rejected).\r\n *\r\n * The RemoteDocument (\"ground truth\") state is provided via the\r\n * applyChangeBatch method. It will be some version of a server-provided\r\n * document OR will be a server-provided document PLUS acknowledged mutations:\r\n *\r\n * RemoteDocument' = RemoteDocument + Acknowledged(LocalMutations)\r\n *\r\n * Note that this \"dirty\" version of a RemoteDocument will not be identical to a\r\n * server base version, since it has LocalMutations added to it pending getting\r\n * an authoritative copy from the server.\r\n *\r\n * Since LocalMutations can be rejected by the server, we have to be able to\r\n * revert a LocalMutation that has already been applied to the LocalDocument\r\n * (typically done by replaying all remaining LocalMutations to the\r\n * RemoteDocument to re-apply).\r\n *\r\n * The LocalStore is responsible for the garbage collection of the documents it\r\n * contains. For now, it every doc referenced by a view, the mutation queue, or\r\n * the RemoteStore.\r\n *\r\n * It also maintains the persistence of mapping queries to resume tokens and\r\n * target ids. It needs to know this data about queries to properly know what\r\n * docs it would be allowed to garbage collect.\r\n *\r\n * The LocalStore must be able to efficiently execute queries against its local\r\n * cache of the documents, to provide the initial set of results before any\r\n * remote changes have been received.\r\n *\r\n * Note: In TypeScript, most methods return Promises since the implementation\r\n * may rely on fetching data from IndexedDB which is async.\r\n * These Promises will only be rejected on an I/O error or other internal\r\n * (unexpected) failure (e.g. failed assert) and always represent an\r\n * unrecoverable error (should be caught / reported by the async_queue).\r\n */\nvar local_store_LocalStore = /** @class */function () {\n function LocalStore(\n /** Manages our in-memory or durable persistence. */\n persistence, initialUser,\n /**\r\n * The garbage collector collects documents that should no longer be\r\n * cached (e.g. if they are no longer retained by the above reference sets\r\n * and the garbage collector is performing eager collection).\r\n */\n garbageCollector) {\n this.persistence = persistence;\n this.garbageCollector = garbageCollector;\n /**\r\n * The set of document references maintained by any local views.\r\n */\n this.localViewReferences = new reference_set_ReferenceSet();\n /** Maps a targetID to data about its query. */\n this.targetIds = {};\n /** Used to generate targetIDs for queries tracked locally. */\n this.targetIdGenerator = TargetIdGenerator.forLocalStore();\n /**\r\n * A heldBatchResult is a mutation batch result (from a write acknowledgement)\r\n * that arrived before the watch stream got notified of a snapshot that\r\n * includes the write. So we \"hold\" it until the watch stream catches up. It\r\n * ensures that the local write remains visible (latency compensation) and\r\n * doesn't temporarily appear reverted because the watch stream is slower than\r\n * the write stream and so wasn't reflecting it.\r\n *\r\n * NOTE: Eventually we want to move this functionality into the remote store.\r\n */\n this.heldBatchResults = [];\n this.mutationQueue = persistence.getMutationQueue(initialUser);\n this.remoteDocuments = persistence.getRemoteDocumentCache();\n this.queryCache = persistence.getQueryCache();\n this.localDocuments = new local_documents_view_LocalDocumentsView(this.remoteDocuments, this.mutationQueue);\n this.garbageCollector.addGarbageSource(this.localViewReferences);\n this.garbageCollector.addGarbageSource(this.queryCache);\n this.garbageCollector.addGarbageSource(this.mutationQueue);\n }\n /** Performs any initial startup actions required by the local store. */\n LocalStore.prototype.start = function () {\n var _this = this;\n return this.persistence.runTransaction('Start LocalStore', function (txn) {\n return _this.startMutationQueue(txn).next(function () {\n return _this.startQueryCache(txn);\n });\n });\n };\n /**\r\n * Tells the LocalStore that the currently authenticated user has changed.\r\n *\r\n * In response the local store switches the mutation queue to the new user and\r\n * returns any resulting document changes.\r\n */\n LocalStore.prototype.handleUserChange = function (user) {\n var _this = this;\n return this.persistence.runTransaction('Handle user change', function (txn) {\n // Swap out the mutation queue, grabbing the pending mutation batches\n // before and after.\n var oldBatches;\n return _this.mutationQueue.getAllMutationBatches(txn).next(function (promisedOldBatches) {\n oldBatches = promisedOldBatches;\n _this.garbageCollector.removeGarbageSource(_this.mutationQueue);\n _this.mutationQueue = _this.persistence.getMutationQueue(user);\n _this.garbageCollector.addGarbageSource(_this.mutationQueue);\n return _this.startMutationQueue(txn);\n }).next(function () {\n // Recreate our LocalDocumentsView using the new\n // MutationQueue.\n _this.localDocuments = new local_documents_view_LocalDocumentsView(_this.remoteDocuments, _this.mutationQueue);\n return _this.mutationQueue.getAllMutationBatches(txn);\n }).next(function (newBatches) {\n // Union the old/new changed keys.\n var changedKeys = documentKeySet();\n for (var _i = 0, _a = [oldBatches, newBatches]; _i < _a.length; _i++) {\n var batches = _a[_i];\n for (var _b = 0, batches_1 = batches; _b < batches_1.length; _b++) {\n var batch = batches_1[_b];\n for (var _c = 0, _d = batch.mutations; _c < _d.length; _c++) {\n var mutation = _d[_c];\n changedKeys = changedKeys.add(mutation.key);\n }\n }\n }\n // Return the set of all (potentially) changed documents as the\n // result of the user change.\n return _this.localDocuments.getDocuments(txn, changedKeys);\n });\n });\n };\n LocalStore.prototype.startQueryCache = function (txn) {\n var _this = this;\n return this.queryCache.start(txn).next(function () {\n var targetId = _this.queryCache.getHighestTargetId();\n _this.targetIdGenerator = TargetIdGenerator.forLocalStore(targetId);\n });\n };\n LocalStore.prototype.startMutationQueue = function (txn) {\n var _this = this;\n return this.mutationQueue.start(txn).next(function () {\n // If we have any leftover mutation batch results from a prior run,\n // just drop them.\n // TODO(http://b/33446471): We probably need to repopulate\n // heldBatchResults or similar instead, but that is not\n // straightforward since we're not persisting the write ack versions.\n _this.heldBatchResults = [];\n return _this.mutationQueue.getHighestAcknowledgedBatchId(txn);\n }).next(function (highestAck) {\n // TODO(mikelehen): This is the only usage of\n // getAllMutationBatchesThroughBatchId(). Consider removing it in\n // favor of a getAcknowledgedBatches() method.\n if (highestAck !== BATCHID_UNKNOWN) {\n return _this.mutationQueue.getAllMutationBatchesThroughBatchId(txn, highestAck);\n } else {\n return persistence_promise_PersistencePromise.resolve([]);\n }\n }).next(function (ackedBatches) {\n if (ackedBatches.length > 0) {\n return _this.mutationQueue.removeMutationBatches(txn, ackedBatches);\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n });\n };\n /* Accept locally generated Mutations and commit them to storage. */\n LocalStore.prototype.localWrite = function (mutations) {\n var _this = this;\n return this.persistence.runTransaction('Locally write mutations', function (txn) {\n var batch;\n var localWriteTime = timestamp_Timestamp.now();\n return _this.mutationQueue.addMutationBatch(txn, localWriteTime, mutations).next(function (promisedBatch) {\n batch = promisedBatch;\n // TODO(koss): This is doing an N^2 update by replaying ALL the\n // mutations on each document (instead of just the ones added) in\n // this batch.\n var keys = batch.keys();\n return _this.localDocuments.getDocuments(txn, keys);\n }).next(function (changedDocuments) {\n return { batchId: batch.batchId, changes: changedDocuments };\n });\n });\n };\n /**\r\n * Acknowledge the given batch.\r\n *\r\n * On the happy path when a batch is acknowledged, the local store will\r\n *\r\n * + remove the batch from the mutation queue;\r\n * + apply the changes to the remote document cache;\r\n * + recalculate the latency compensated view implied by those changes (there\r\n * may be mutations in the queue that affect the documents but haven't been\r\n * acknowledged yet); and\r\n * + give the changed documents back the sync engine\r\n *\r\n * @returns The resulting (modified) documents.\r\n */\n LocalStore.prototype.acknowledgeBatch = function (batchResult) {\n var _this = this;\n return this.persistence.runTransaction('Acknowledge batch', function (txn) {\n var affected;\n return _this.mutationQueue.acknowledgeBatch(txn, batchResult.batch, batchResult.streamToken).next(function () {\n if (_this.shouldHoldBatchResult(batchResult.commitVersion)) {\n _this.heldBatchResults.push(batchResult);\n affected = documentKeySet();\n return persistence_promise_PersistencePromise.resolve();\n } else {\n var documentBuffer_1 = new remote_document_change_buffer_RemoteDocumentChangeBuffer(_this.remoteDocuments);\n return _this.releaseBatchResults(txn, [batchResult], documentBuffer_1).next(function (promisedAffectedKeys) {\n affected = promisedAffectedKeys;\n return documentBuffer_1.apply(txn);\n });\n }\n }).next(function () {\n return _this.mutationQueue.performConsistencyCheck(txn);\n }).next(function () {\n return _this.localDocuments.getDocuments(txn, affected);\n });\n });\n };\n /**\r\n * Remove mutations from the MutationQueue for the specified batch;\r\n * LocalDocuments will be recalculated.\r\n *\r\n * @returns The resulting modified documents.\r\n */\n LocalStore.prototype.rejectBatch = function (batchId) {\n var _this = this;\n return this.persistence.runTransaction('Reject batch', function (txn) {\n var toReject;\n var affectedKeys;\n return _this.mutationQueue.lookupMutationBatch(txn, batchId).next(function (promisedToReject) {\n assert(promisedToReject != null, 'Attempt to reject nonexistent batch!');\n toReject = promisedToReject;\n return _this.mutationQueue.getHighestAcknowledgedBatchId(txn).next(function (lastAcked) {\n assert(batchId > lastAcked, \"Acknowledged batches can't be rejected.\");\n return toReject;\n });\n }).next(function () {\n return _this.removeMutationBatch(txn, toReject);\n }).next(function (promisedAffectedKeys) {\n affectedKeys = promisedAffectedKeys;\n return _this.mutationQueue.performConsistencyCheck(txn);\n }).next(function () {\n return _this.localDocuments.getDocuments(txn, affectedKeys);\n });\n });\n };\n /** Returns the last recorded stream token for the current user. */\n LocalStore.prototype.getLastStreamToken = function () {\n var _this = this;\n return this.persistence.runTransaction('Get last stream token', function (txn) {\n return _this.mutationQueue.getLastStreamToken(txn);\n });\n };\n /**\r\n * Sets the stream token for the current user without acknowledging any\r\n * mutation batch. This is usually only useful after a stream handshake or in\r\n * response to an error that requires clearing the stream token.\r\n */\n LocalStore.prototype.setLastStreamToken = function (streamToken) {\n var _this = this;\n return this.persistence.runTransaction('Set last stream token', function (txn) {\n return _this.mutationQueue.setLastStreamToken(txn, streamToken);\n });\n };\n /**\r\n * Returns the last consistent snapshot processed (used by the RemoteStore to\r\n * determine whether to buffer incoming snapshots from the backend).\r\n */\n LocalStore.prototype.getLastRemoteSnapshotVersion = function () {\n return this.queryCache.getLastRemoteSnapshotVersion();\n };\n /**\r\n * Update the \"ground-state\" (remote) documents. We assume that the remote\r\n * event reflects any write batches that have been acknowledged or rejected\r\n * (i.e. we do not re-apply local mutations to updates from this event).\r\n *\r\n * LocalDocuments are re-calculated if there are remaining mutations in the\r\n * queue.\r\n */\n LocalStore.prototype.applyRemoteEvent = function (remoteEvent) {\n var _this = this;\n var documentBuffer = new remote_document_change_buffer_RemoteDocumentChangeBuffer(this.remoteDocuments);\n return this.persistence.runTransaction('Apply remote event', function (txn) {\n var promises = [];\n forEachNumber(remoteEvent.targetChanges, function (targetId, change) {\n // Do not ref/unref unassigned targetIds - it may lead to leaks.\n var queryData = _this.targetIds[targetId];\n if (!queryData) return;\n var mapping = change.mapping;\n if (mapping) {\n // First make sure that all references are deleted\n if (mapping instanceof ResetMapping) {\n promises.push(_this.queryCache.removeMatchingKeysForTargetId(txn, targetId).next(function () {\n return _this.queryCache.addMatchingKeys(txn, mapping.documents, targetId);\n }));\n } else if (mapping instanceof UpdateMapping) {\n promises.push(_this.queryCache.removeMatchingKeys(txn, mapping.removedDocuments, targetId).next(function () {\n return _this.queryCache.addMatchingKeys(txn, mapping.addedDocuments, targetId);\n }));\n } else {\n return fail('Unknown mapping type: ' + JSON.stringify(mapping));\n }\n }\n // Update the resume token if the change includes one. Don't clear\n // any preexisting value.\n var resumeToken = change.resumeToken;\n if (resumeToken.length > 0) {\n queryData = queryData.update({\n resumeToken: resumeToken,\n snapshotVersion: change.snapshotVersion\n });\n _this.targetIds[targetId] = queryData;\n promises.push(_this.queryCache.addQueryData(txn, queryData));\n }\n });\n var changedDocKeys = documentKeySet();\n remoteEvent.documentUpdates.forEach(function (key, doc) {\n changedDocKeys = changedDocKeys.add(key);\n promises.push(documentBuffer.getEntry(txn, key).next(function (existingDoc) {\n // Make sure we don't apply an old document version to the remote\n // cache, though we make an exception for SnapshotVersion.MIN which\n // can happen for manufactured events (e.g. in the case of a limbo\n // document resolution failing).\n if (existingDoc == null || doc.version.equals(snapshot_version_SnapshotVersion.MIN) || doc.version.compareTo(existingDoc.version) >= 0) {\n documentBuffer.addEntry(doc);\n } else {\n debug(local_store_LOG_TAG, 'Ignoring outdated watch update for ', key, '. Current version:', existingDoc.version, ' Watch version:', doc.version);\n }\n // The document might be garbage because it was unreferenced by\n // everything. Make sure to mark it as garbage if it is...\n _this.garbageCollector.addPotentialGarbageKey(key);\n }));\n });\n // HACK: The only reason we allow a null snapshot version is so that we\n // can synthesize remote events when we get permission denied errors while\n // trying to resolve the state of a locally cached document that is in\n // limbo.\n var lastRemoteVersion = _this.queryCache.getLastRemoteSnapshotVersion();\n var remoteVersion = remoteEvent.snapshotVersion;\n if (!remoteVersion.equals(snapshot_version_SnapshotVersion.MIN)) {\n assert(remoteVersion.compareTo(lastRemoteVersion) >= 0, 'Watch stream reverted to previous snapshot?? ' + remoteVersion + ' < ' + lastRemoteVersion);\n promises.push(_this.queryCache.setLastRemoteSnapshotVersion(txn, remoteVersion));\n }\n var releasedWriteKeys;\n return persistence_promise_PersistencePromise.waitFor(promises).next(function () {\n return _this.releaseHeldBatchResults(txn, documentBuffer);\n }).next(function (promisedReleasedWriteKeys) {\n releasedWriteKeys = promisedReleasedWriteKeys;\n return documentBuffer.apply(txn);\n }).next(function () {\n return _this.localDocuments.getDocuments(txn, changedDocKeys.unionWith(releasedWriteKeys));\n });\n });\n };\n /**\r\n * Notify local store of the changed views to locally pin documents.\r\n */\n LocalStore.prototype.notifyLocalViewChanges = function (viewChanges) {\n var _this = this;\n return this.persistence.runTransaction('Notify local view changes', function (txn) {\n var promises = [];\n var _loop_1 = function _loop_1(view) {\n promises.push(_this.queryCache.getQueryData(txn, view.query).next(function (queryData) {\n assert(queryData !== null, 'Local view changes contain unallocated query.');\n var targetId = queryData.targetId;\n _this.localViewReferences.addReferences(view.addedKeys, targetId);\n _this.localViewReferences.removeReferences(view.removedKeys, targetId);\n }));\n };\n for (var _i = 0, viewChanges_1 = viewChanges; _i < viewChanges_1.length; _i++) {\n var view = viewChanges_1[_i];\n _loop_1(view);\n }\n return persistence_promise_PersistencePromise.waitFor(promises);\n });\n };\n /**\r\n * Gets the mutation batch after the passed in batchId in the mutation queue\r\n * or null if empty.\r\n * @param afterBatchId If provided, the batch to search after.\r\n * @returns The next mutation or null if there wasn't one.\r\n */\n LocalStore.prototype.nextMutationBatch = function (afterBatchId) {\n var _this = this;\n return this.persistence.runTransaction('Get next mutation batch', function (txn) {\n if (afterBatchId === undefined) {\n afterBatchId = BATCHID_UNKNOWN;\n }\n return _this.mutationQueue.getNextMutationBatchAfterBatchId(txn, afterBatchId);\n });\n };\n /**\r\n * Read the current value of a Document with a given key or null if not\r\n * found - used for testing.\r\n */\n LocalStore.prototype.readDocument = function (key) {\n var _this = this;\n return this.persistence.runTransaction('read document', function (txn) {\n return _this.localDocuments.getDocument(txn, key);\n });\n };\n /**\r\n * Assigns the given query an internal ID so that its results can be pinned so\r\n * they don't get GC'd. A query must be allocated in the local store before\r\n * the store can be used to manage its view.\r\n */\n LocalStore.prototype.allocateQuery = function (query) {\n var _this = this;\n return this.persistence.runTransaction('Allocate query', function (txn) {\n var queryData;\n return _this.queryCache.getQueryData(txn, query).next(function (cached) {\n if (cached) {\n // This query has been listened to previously, so reuse the\n // previous targetID.\n // TODO(mcg): freshen last accessed date?\n queryData = cached;\n return persistence_promise_PersistencePromise.resolve();\n } else {\n var targetId = _this.targetIdGenerator.next();\n queryData = new query_data_QueryData(query, targetId, QueryPurpose.Listen);\n return _this.queryCache.addQueryData(txn, queryData);\n }\n }).next(function () {\n assert(!_this.targetIds[queryData.targetId], 'Tried to allocate an already allocated query: ' + query);\n _this.targetIds[queryData.targetId] = queryData;\n return queryData;\n });\n });\n };\n /** Unpin all the documents associated with the given query. */\n LocalStore.prototype.releaseQuery = function (query) {\n var _this = this;\n return this.persistence.runTransaction('Release query', function (txn) {\n return _this.queryCache.getQueryData(txn, query).next(function (queryData) {\n assert(queryData != null, 'Tried to release nonexistent query: ' + query);\n _this.localViewReferences.removeReferencesForId(queryData.targetId);\n delete _this.targetIds[queryData.targetId];\n if (_this.garbageCollector.isEager) {\n return _this.queryCache.removeQueryData(txn, queryData);\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n }).next(function () {\n // If this was the last watch target, then we won't get any more\n // watch snapshots, so we should release any held batch results.\n if (isEmpty(_this.targetIds)) {\n var documentBuffer_2 = new remote_document_change_buffer_RemoteDocumentChangeBuffer(_this.remoteDocuments);\n return _this.releaseHeldBatchResults(txn, documentBuffer_2).next(function () {\n documentBuffer_2.apply(txn);\n });\n } else {\n return persistence_promise_PersistencePromise.resolve();\n }\n });\n });\n };\n /**\r\n * Runs the specified query against all the documents in the local store and\r\n * returns the results.\r\n */\n LocalStore.prototype.executeQuery = function (query) {\n var _this = this;\n return this.persistence.runTransaction('Execute query', function (txn) {\n return _this.localDocuments.getDocumentsMatchingQuery(txn, query);\n });\n };\n /**\r\n * Returns the keys of the documents that are associated with the given\r\n * target id in the remote table.\r\n */\n LocalStore.prototype.remoteDocumentKeys = function (targetId) {\n var _this = this;\n return this.persistence.runTransaction('Remote document keys', function (txn) {\n return _this.queryCache.getMatchingKeysForTargetId(txn, targetId);\n });\n };\n /**\r\n * Collect garbage if necessary.\r\n * Should be called periodically by Sync Engine to recover resources. The\r\n * implementation must guarantee that GC won't happen in other places than\r\n * this method call.\r\n */\n LocalStore.prototype.collectGarbage = function () {\n var _this = this;\n // Call collectGarbage regardless of whether isGCEnabled so the referenceSet\n // doesn't continue to accumulate the garbage keys.\n return this.persistence.runTransaction('Garbage collection', function (txn) {\n return _this.garbageCollector.collectGarbage(txn).next(function (garbage) {\n var promises = [];\n garbage.forEach(function (key) {\n promises.push(_this.remoteDocuments.removeEntry(txn, key));\n });\n return persistence_promise_PersistencePromise.waitFor(promises);\n });\n });\n };\n LocalStore.prototype.releaseHeldBatchResults = function (txn, documentBuffer) {\n var toRelease = [];\n for (var _i = 0, _a = this.heldBatchResults; _i < _a.length; _i++) {\n var batchResult = _a[_i];\n if (!this.isRemoteUpToVersion(batchResult.commitVersion)) {\n break;\n }\n toRelease.push(batchResult);\n }\n if (toRelease.length === 0) {\n return persistence_promise_PersistencePromise.resolve(documentKeySet());\n } else {\n this.heldBatchResults.splice(0, toRelease.length);\n return this.releaseBatchResults(txn, toRelease, documentBuffer);\n }\n };\n LocalStore.prototype.isRemoteUpToVersion = function (version) {\n // If there are no watch targets, then we won't get remote snapshots, and\n // we are always \"up-to-date.\"\n var lastRemoteVersion = this.queryCache.getLastRemoteSnapshotVersion();\n return version.compareTo(lastRemoteVersion) <= 0 || isEmpty(this.targetIds);\n };\n LocalStore.prototype.shouldHoldBatchResult = function (version) {\n // Check if watcher isn't up to date or prior results are already held.\n return !this.isRemoteUpToVersion(version) || this.heldBatchResults.length > 0;\n };\n LocalStore.prototype.releaseBatchResults = function (txn, batchResults, documentBuffer) {\n var _this = this;\n var promiseChain = persistence_promise_PersistencePromise.resolve();\n var _loop_2 = function _loop_2(batchResult) {\n promiseChain = promiseChain.next(function () {\n return _this.applyWriteToRemoteDocuments(txn, batchResult, documentBuffer);\n });\n };\n for (var _i = 0, batchResults_1 = batchResults; _i < batchResults_1.length; _i++) {\n var batchResult = batchResults_1[_i];\n _loop_2(batchResult);\n }\n return promiseChain.next(function () {\n return _this.removeMutationBatches(txn, batchResults.map(function (result) {\n return result.batch;\n }));\n });\n };\n LocalStore.prototype.removeMutationBatch = function (txn, batch) {\n return this.removeMutationBatches(txn, [batch]);\n };\n /** Removes all the mutation batches named in the given array. */\n LocalStore.prototype.removeMutationBatches = function (txn, batches) {\n var affectedDocs = documentKeySet();\n for (var _i = 0, batches_2 = batches; _i < batches_2.length; _i++) {\n var batch = batches_2[_i];\n for (var _a = 0, _b = batch.mutations; _a < _b.length; _a++) {\n var mutation = _b[_a];\n var key = mutation.key;\n affectedDocs = affectedDocs.add(key);\n }\n }\n return this.mutationQueue.removeMutationBatches(txn, batches).next(function () {\n return affectedDocs;\n });\n };\n LocalStore.prototype.applyWriteToRemoteDocuments = function (txn, batchResult, documentBuffer) {\n var batch = batchResult.batch;\n var docKeys = batch.keys();\n var promiseChain = persistence_promise_PersistencePromise.resolve();\n docKeys.forEach(function (docKey) {\n promiseChain = promiseChain.next(function () {\n return documentBuffer.getEntry(txn, docKey);\n }).next(function (remoteDoc) {\n var doc = remoteDoc;\n var ackVersion = batchResult.docVersions.get(docKey);\n assert(ackVersion !== null, 'ackVersions should contain every doc in the write.');\n if (!doc || doc.version.compareTo(ackVersion) < 0) {\n doc = batch.applyToRemoteDocument(docKey, doc, batchResult);\n if (!doc) {\n assert(!remoteDoc, 'Mutation batch ' + batch + ' applied to document ' + remoteDoc + ' resulted in null');\n } else {\n documentBuffer.addEntry(doc);\n }\n }\n });\n });\n return promiseChain;\n };\n return LocalStore;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/memory_mutation_queue.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\nvar memory_mutation_queue_MemoryMutationQueue = /** @class */function () {\n function MemoryMutationQueue() {\n /**\r\n * The set of all mutations that have been sent but not yet been applied to\r\n * the backend.\r\n */\n this.mutationQueue = [];\n /** Next value to use when assigning sequential IDs to each mutation batch. */\n this.nextBatchId = 1;\n /** The highest acknowledged mutation in the queue. */\n this.highestAcknowledgedBatchId = BATCHID_UNKNOWN;\n /** The last received stream token from the server, used to acknowledge which\r\n * responses the client has processed. Stream tokens are opaque checkpoint\r\n * markers whose only real value is their inclusion in the next request.\r\n */\n this.lastStreamToken = emptyByteString();\n /** The garbage collector to notify about potential garbage keys. */\n this.garbageCollector = null;\n /** An ordered mapping between documents and the mutations batch IDs. */\n this.batchesByDocumentKey = new sorted_set_SortedSet(reference_set_DocReference.compareByKey);\n }\n MemoryMutationQueue.prototype.start = function (transaction) {\n // NOTE: The queue may be shutdown / started multiple times, since we\n // maintain the queue for the duration of the app session in case a user\n // logs out / back in. To behave like the LevelDB-backed MutationQueue (and\n // accommodate tests that expect as much), we reset nextBatchId and\n // highestAcknowledgedBatchId if the queue is empty.\n if (this.mutationQueue.length === 0) {\n this.nextBatchId = 1;\n this.highestAcknowledgedBatchId = BATCHID_UNKNOWN;\n }\n assert(this.highestAcknowledgedBatchId < this.nextBatchId, 'highestAcknowledgedBatchId must be less than the nextBatchId');\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryMutationQueue.prototype.checkEmpty = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.mutationQueue.length === 0);\n };\n MemoryMutationQueue.prototype.getNextBatchId = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.nextBatchId);\n };\n MemoryMutationQueue.prototype.getHighestAcknowledgedBatchId = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.highestAcknowledgedBatchId);\n };\n MemoryMutationQueue.prototype.acknowledgeBatch = function (transaction, batch, streamToken) {\n var batchId = batch.batchId;\n assert(batchId > this.highestAcknowledgedBatchId, 'Mutation batchIDs must be acknowledged in order');\n var batchIndex = this.indexOfExistingBatchId(batchId, 'acknowledged');\n // Verify that the batch in the queue is the one to be acknowledged.\n var check = this.mutationQueue[batchIndex];\n assert(batchId === check.batchId, 'Queue ordering failure: expected batch ' + batchId + ', got batch ' + check.batchId);\n assert(!check.isTombstone(), \"Can't acknowledge a previously removed batch\");\n this.highestAcknowledgedBatchId = batchId;\n this.lastStreamToken = streamToken;\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryMutationQueue.prototype.getLastStreamToken = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.lastStreamToken);\n };\n MemoryMutationQueue.prototype.setLastStreamToken = function (transaction, streamToken) {\n this.lastStreamToken = streamToken;\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryMutationQueue.prototype.addMutationBatch = function (transaction, localWriteTime, mutations) {\n assert(mutations.length !== 0, 'Mutation batches should not be empty');\n var batchId = this.nextBatchId;\n this.nextBatchId++;\n if (this.mutationQueue.length > 0) {\n var prior = this.mutationQueue[this.mutationQueue.length - 1];\n assert(prior.batchId < batchId, 'Mutation batchIDs must be monotonically increasing order');\n }\n var batch = new mutation_batch_MutationBatch(batchId, localWriteTime, mutations);\n this.mutationQueue.push(batch);\n // Track references by document key.\n for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) {\n var mutation = mutations_1[_i];\n this.batchesByDocumentKey = this.batchesByDocumentKey.add(new reference_set_DocReference(mutation.key, batchId));\n }\n return persistence_promise_PersistencePromise.resolve(batch);\n };\n MemoryMutationQueue.prototype.lookupMutationBatch = function (transaction, batchId) {\n return persistence_promise_PersistencePromise.resolve(this.findMutationBatch(batchId));\n };\n MemoryMutationQueue.prototype.getNextMutationBatchAfterBatchId = function (transaction, batchId) {\n var size = this.mutationQueue.length;\n // All batches with batchId <= this.highestAcknowledgedBatchId have been\n // acknowledged so the first unacknowledged batch after batchID will have a\n // batchID larger than both of these values.\n batchId = Math.max(batchId + 1, this.highestAcknowledgedBatchId);\n // The requested batchId may still be out of range so normalize it to the\n // start of the queue.\n var rawIndex = this.indexOfBatchId(batchId);\n var index = rawIndex < 0 ? 0 : rawIndex;\n // Finally return the first non-tombstone batch.\n for (; index < size; index++) {\n var batch = this.mutationQueue[index];\n if (!batch.isTombstone()) {\n return persistence_promise_PersistencePromise.resolve(batch);\n }\n }\n return persistence_promise_PersistencePromise.resolve(null);\n };\n MemoryMutationQueue.prototype.getAllMutationBatches = function (transaction) {\n return persistence_promise_PersistencePromise.resolve(this.getAllLiveMutationBatchesBeforeIndex(this.mutationQueue.length));\n };\n MemoryMutationQueue.prototype.getAllMutationBatchesThroughBatchId = function (transaction, batchId) {\n var count = this.mutationQueue.length;\n var endIndex = this.indexOfBatchId(batchId);\n if (endIndex < 0) {\n endIndex = 0;\n } else if (endIndex >= count) {\n endIndex = count;\n } else {\n // The endIndex is in the queue so increment to pull everything in the\n // queue including it.\n endIndex++;\n }\n return persistence_promise_PersistencePromise.resolve(this.getAllLiveMutationBatchesBeforeIndex(endIndex));\n };\n MemoryMutationQueue.prototype.getAllMutationBatchesAffectingDocumentKey = function (transaction, documentKey) {\n var _this = this;\n var start = new reference_set_DocReference(documentKey, 0);\n var end = new reference_set_DocReference(documentKey, Number.POSITIVE_INFINITY);\n var result = [];\n this.batchesByDocumentKey.forEachInRange([start, end], function (ref) {\n assert(documentKey.equals(ref.key), \"Should only iterate over a single key's batches\");\n var batch = _this.findMutationBatch(ref.targetOrBatchId);\n assert(batch !== null, 'Batches in the index must exist in the main table');\n result.push(batch);\n });\n return persistence_promise_PersistencePromise.resolve(result);\n };\n MemoryMutationQueue.prototype.getAllMutationBatchesAffectingQuery = function (transaction, query) {\n var _this = this;\n // Use the query path as a prefix for testing if a document matches the\n // query.\n var prefix = query.path;\n var immediateChildrenPathLength = prefix.length + 1;\n // Construct a document reference for actually scanning the index. Unlike\n // the prefix the document key in this reference must have an even number of\n // segments. The empty segment can be used a suffix of the query path\n // because it precedes all other segments in an ordered traversal.\n var startPath = prefix;\n if (!document_key_DocumentKey.isDocumentKey(startPath)) {\n startPath = startPath.child('');\n }\n var start = new reference_set_DocReference(new document_key_DocumentKey(startPath), 0);\n // Find unique batchIDs referenced by all documents potentially matching the\n // query.\n var uniqueBatchIDs = new sorted_set_SortedSet(primitiveComparator);\n this.batchesByDocumentKey.forEachWhile(function (ref) {\n var rowKeyPath = ref.key.path;\n if (!prefix.isPrefixOf(rowKeyPath)) {\n return false;\n } else {\n // Rows with document keys more than one segment longer than the query\n // path can't be matches. For example, a query on 'rooms' can't match\n // the document /rooms/abc/messages/xyx.\n // TODO(mcg): we'll need a different scanner when we implement\n // ancestor queries.\n if (rowKeyPath.length === immediateChildrenPathLength) {\n uniqueBatchIDs = uniqueBatchIDs.add(ref.targetOrBatchId);\n }\n return true;\n }\n }, start);\n // Construct an array of matching batches, sorted by batchID to ensure that\n // multiple mutations affecting the same document key are applied in order.\n var result = [];\n uniqueBatchIDs.forEach(function (batchId) {\n var batch = _this.findMutationBatch(batchId);\n if (batch !== null) {\n result.push(batch);\n }\n });\n return persistence_promise_PersistencePromise.resolve(result);\n };\n MemoryMutationQueue.prototype.removeMutationBatches = function (transaction, batches) {\n var batchCount = batches.length;\n assert(batchCount > 0, 'Should not remove mutations when none exist.');\n var firstBatchId = batches[0].batchId;\n var queueCount = this.mutationQueue.length;\n // Find the position of the first batch for removal. This need not be the\n // first entry in the queue.\n var startIndex = this.indexOfExistingBatchId(firstBatchId, 'removed');\n assert(this.mutationQueue[startIndex].batchId === firstBatchId, 'Removed batches must exist in the queue');\n // Check that removed batches are contiguous (while excluding tombstones).\n var batchIndex = 1;\n var queueIndex = startIndex + 1;\n while (batchIndex < batchCount && queueIndex < queueCount) {\n var batch = this.mutationQueue[queueIndex];\n if (batch.isTombstone()) {\n queueIndex++;\n continue;\n }\n assert(batch.batchId === batches[batchIndex].batchId, 'Removed batches must be contiguous in the queue');\n batchIndex++;\n queueIndex++;\n }\n // Only actually remove batches if removing at the front of the queue.\n // Previously rejected batches may have left tombstones in the queue, so\n // expand the removal range to include any tombstones.\n if (startIndex === 0) {\n for (; queueIndex < queueCount; queueIndex++) {\n var batch = this.mutationQueue[queueIndex];\n if (!batch.isTombstone()) {\n break;\n }\n }\n var length_1 = queueIndex - startIndex;\n this.mutationQueue.splice(startIndex, length_1);\n } else {\n // Mark the tombstones\n for (var i = startIndex; i < queueIndex; i++) {\n this.mutationQueue[i] = this.mutationQueue[i].toTombstone();\n }\n }\n var references = this.batchesByDocumentKey;\n for (var _i = 0, batches_1 = batches; _i < batches_1.length; _i++) {\n var batch = batches_1[_i];\n var batchId = batch.batchId;\n for (var _a = 0, _b = batch.mutations; _a < _b.length; _a++) {\n var mutation = _b[_a];\n var key = mutation.key;\n if (this.garbageCollector !== null) {\n this.garbageCollector.addPotentialGarbageKey(key);\n }\n var ref = new reference_set_DocReference(key, batchId);\n references = references.delete(ref);\n }\n }\n this.batchesByDocumentKey = references;\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryMutationQueue.prototype.setGarbageCollector = function (garbageCollector) {\n this.garbageCollector = garbageCollector;\n };\n MemoryMutationQueue.prototype.containsKey = function (txn, key) {\n var ref = new reference_set_DocReference(key, 0);\n var firstRef = this.batchesByDocumentKey.firstAfterOrEqual(ref);\n return persistence_promise_PersistencePromise.resolve(key.equals(firstRef && firstRef.key));\n };\n MemoryMutationQueue.prototype.performConsistencyCheck = function (txn) {\n if (this.mutationQueue.length === 0) {\n assert(this.batchesByDocumentKey.isEmpty(), 'Document leak -- detected dangling mutation references when queue is empty.');\n }\n return persistence_promise_PersistencePromise.resolve();\n };\n /**\r\n * A private helper that collects all the mutations batches in the queue up to\r\n * but not including the given endIndex. All tombstones in the queue are\r\n * excluded.\r\n */\n MemoryMutationQueue.prototype.getAllLiveMutationBatchesBeforeIndex = function (endIndex) {\n var result = [];\n for (var i = 0; i < endIndex; i++) {\n var batch = this.mutationQueue[i];\n if (!batch.isTombstone()) {\n result.push(batch);\n }\n }\n return result;\n };\n /**\r\n * Finds the index of the given batchId in the mutation queue and asserts that\r\n * the resulting index is within the bounds of the queue.\r\n *\r\n * @param batchId The batchId to search for\r\n * @param action A description of what the caller is doing, phrased in passive\r\n * form (e.g. \"acknowledged\" in a routine that acknowledges batches).\r\n */\n MemoryMutationQueue.prototype.indexOfExistingBatchId = function (batchId, action) {\n var index = this.indexOfBatchId(batchId);\n assert(index >= 0 && index < this.mutationQueue.length, 'Batches must exist to be ' + action);\n return index;\n };\n /**\r\n * Finds the index of the given batchId in the mutation queue. This operation\r\n * is O(1).\r\n *\r\n * @return The computed index of the batch with the given batchId, based on\r\n * the state of the queue. Note this index can be negative if the requested\r\n * batchId has already been remvoed from the queue or past the end of the\r\n * queue if the batchId is larger than the last added batch.\r\n */\n MemoryMutationQueue.prototype.indexOfBatchId = function (batchId) {\n if (this.mutationQueue.length === 0) {\n // As an index this is past the end of the queue\n return 0;\n }\n // Examine the front of the queue to figure out the difference between the\n // batchId and indexes in the array. Note that since the queue is ordered\n // by batchId, if the first batch has a larger batchId then the requested\n // batchId doesn't exist in the queue.\n var firstBatchId = this.mutationQueue[0].batchId;\n return batchId - firstBatchId;\n };\n /**\r\n * A version of lookupMutationBatch that doesn't return a promise, this makes\r\n * other functions that uses this code easier to read and more efficent.\r\n */\n MemoryMutationQueue.prototype.findMutationBatch = function (batchId) {\n var index = this.indexOfBatchId(batchId);\n if (index < 0 || index >= this.mutationQueue.length) {\n return null;\n }\n var batch = this.mutationQueue[index];\n assert(batch.batchId === batchId, 'If found batch must match');\n return batch.isTombstone() ? null : batch;\n };\n return MemoryMutationQueue;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/memory_query_cache.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\nvar memory_query_cache_MemoryQueryCache = /** @class */function () {\n function MemoryQueryCache() {\n /**\r\n * Maps a query to the data about that query\r\n */\n this.queries = new obj_map_ObjectMap(function (q) {\n return q.canonicalId();\n });\n /** The last received snapshot version. */\n this.lastRemoteSnapshotVersion = snapshot_version_SnapshotVersion.MIN;\n /** The highest numbered target ID encountered. */\n this.highestTargetId = 0;\n /**\r\n * A ordered bidirectional mapping between documents and the remote target\r\n * IDs.\r\n */\n this.references = new reference_set_ReferenceSet();\n }\n MemoryQueryCache.prototype.start = function (transaction) {\n // Nothing to do.\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.getLastRemoteSnapshotVersion = function () {\n return this.lastRemoteSnapshotVersion;\n };\n MemoryQueryCache.prototype.getHighestTargetId = function () {\n return this.highestTargetId;\n };\n MemoryQueryCache.prototype.setLastRemoteSnapshotVersion = function (transaction, snapshotVersion) {\n this.lastRemoteSnapshotVersion = snapshotVersion;\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.addQueryData = function (transaction, queryData) {\n this.queries.set(queryData.query, queryData);\n var targetId = queryData.targetId;\n if (targetId > this.highestTargetId) {\n this.highestTargetId = targetId;\n }\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.removeQueryData = function (transaction, queryData) {\n this.queries.delete(queryData.query);\n this.references.removeReferencesForId(queryData.targetId);\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.getQueryData = function (transaction, query) {\n var queryData = this.queries.get(query) || null;\n return persistence_promise_PersistencePromise.resolve(queryData);\n };\n MemoryQueryCache.prototype.addMatchingKeys = function (txn, keys, targetId) {\n this.references.addReferences(keys, targetId);\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.removeMatchingKeys = function (txn, keys, targetId) {\n this.references.removeReferences(keys, targetId);\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.removeMatchingKeysForTargetId = function (txn, targetId) {\n this.references.removeReferencesForId(targetId);\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryQueryCache.prototype.getMatchingKeysForTargetId = function (txn, targetId) {\n var matchingKeys = this.references.referencesForId(targetId);\n return persistence_promise_PersistencePromise.resolve(matchingKeys);\n };\n MemoryQueryCache.prototype.setGarbageCollector = function (gc) {\n this.references.setGarbageCollector(gc);\n };\n MemoryQueryCache.prototype.containsKey = function (txn, key) {\n return this.references.containsKey(txn, key);\n };\n return MemoryQueryCache;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/memory_remote_document_cache.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\nvar memory_remote_document_cache_MemoryRemoteDocumentCache = /** @class */function () {\n function MemoryRemoteDocumentCache() {\n this.docs = maybeDocumentMap();\n }\n MemoryRemoteDocumentCache.prototype.addEntry = function (transaction, maybeDocument) {\n this.docs = this.docs.insert(maybeDocument.key, maybeDocument);\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryRemoteDocumentCache.prototype.removeEntry = function (transaction, documentKey) {\n this.docs = this.docs.remove(documentKey);\n return persistence_promise_PersistencePromise.resolve();\n };\n MemoryRemoteDocumentCache.prototype.getEntry = function (transaction, documentKey) {\n return persistence_promise_PersistencePromise.resolve(this.docs.get(documentKey));\n };\n MemoryRemoteDocumentCache.prototype.getDocumentsMatchingQuery = function (transaction, query) {\n var results = documentMap();\n // Documents are ordered by key, so we can use a prefix scan to narrow down\n // the documents we need to match the query against.\n var prefix = new document_key_DocumentKey(query.path.child(''));\n var iterator = this.docs.getIteratorFrom(prefix);\n while (iterator.hasNext()) {\n var _a = iterator.getNext(),\n key = _a.key,\n maybeDoc = _a.value;\n if (!query.path.isPrefixOf(key.path)) {\n break;\n }\n if (maybeDoc instanceof document_Document && query.matches(maybeDoc)) {\n results = results.insert(maybeDoc.key, maybeDoc);\n }\n }\n return persistence_promise_PersistencePromise.resolve(results);\n };\n return MemoryRemoteDocumentCache;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/local/memory_persistence.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\nvar memory_persistence_LOG_TAG = 'MemoryPersistence';\n/**\r\n * A memory-backed instance of Persistence. Data is stored only in RAM and\r\n * not persisted across sessions.\r\n */\nvar memory_persistence_MemoryPersistence = /** @class */function () {\n function MemoryPersistence() {\n /**\r\n * Note that these are retained here to make it easier to write tests\r\n * affecting both the in-memory and IndexedDB-backed persistence layers. Tests\r\n * can create a new LocalStore wrapping this Persistence instance and this\r\n * will make the in-memory persistence layer behave as if it were actually\r\n * persisting values.\r\n */\n this.mutationQueues = {};\n this.remoteDocumentCache = new memory_remote_document_cache_MemoryRemoteDocumentCache();\n this.queryCache = new memory_query_cache_MemoryQueryCache();\n this.started = false;\n }\n MemoryPersistence.prototype.start = function () {\n assert(!this.started, 'MemoryPersistence double-started!');\n this.started = true;\n // No durable state to read on startup.\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n };\n MemoryPersistence.prototype.shutdown = function () {\n // No durable state to ensure is closed on shutdown.\n assert(this.started, 'MemoryPersistence shutdown without start!');\n this.started = false;\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n };\n MemoryPersistence.prototype.getMutationQueue = function (user) {\n var queue = this.mutationQueues[user.toKey()];\n if (!queue) {\n queue = new memory_mutation_queue_MemoryMutationQueue();\n this.mutationQueues[user.toKey()] = queue;\n }\n return queue;\n };\n MemoryPersistence.prototype.getQueryCache = function () {\n return this.queryCache;\n };\n MemoryPersistence.prototype.getRemoteDocumentCache = function () {\n return this.remoteDocumentCache;\n };\n MemoryPersistence.prototype.runTransaction = function (action, operation) {\n debug(memory_persistence_LOG_TAG, 'Starting transaction:', action);\n return operation(new MemoryPersistenceTransaction()).toPromise();\n };\n return MemoryPersistence;\n}();\n\n/** Dummy class since memory persistence doesn't actually use transactions. */\nvar MemoryPersistenceTransaction = /** @class */function () {\n function MemoryPersistenceTransaction() {}\n return MemoryPersistenceTransaction;\n}();\n// CONCATENATED MODULE: ./src/firestore/local/no_op_garbage_collector.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n/**\r\n * A garbage collector implementation that does absolutely nothing. It ignores\r\n * all addGarbageSource and addPotentialGarbageKey messages and and never\r\n * produces any garbage.\r\n */\nvar no_op_garbage_collector_NoOpGarbageCollector = /** @class */function () {\n function NoOpGarbageCollector() {\n this.isEager = false;\n }\n NoOpGarbageCollector.prototype.addGarbageSource = function (garbageSource) {\n // Not tracking garbage so don't track sources.\n };\n NoOpGarbageCollector.prototype.removeGarbageSource = function (garbageSource) {\n // Not tracking garbage so don't track sources.\n };\n NoOpGarbageCollector.prototype.addPotentialGarbageKey = function (key) {\n // Not tracking garbage so ignore.\n };\n NoOpGarbageCollector.prototype.collectGarbage = function (txn) {\n return persistence_promise_PersistencePromise.resolve(documentKeySet());\n };\n return NoOpGarbageCollector;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/util/promise.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\nvar promise_Deferred = /** @class */function () {\n function Deferred() {\n var _this = this;\n this.promise = new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n _this.resolve = resolve;\n _this.reject = reject;\n });\n }\n return Deferred;\n}();\n\n/**\r\n * Takes an array of values and sequences them using the promise (or value)\r\n * returned by the supplied callback. The callback for each item is called\r\n * after the promise is resolved for the previous item.\r\n * The function returns a promise which is resolved after the promise for\r\n * the last item is resolved.\r\n */\nfunction sequence(values, fn, initialValue) {\n var result = utils_promise[\"b\" /* PromiseImpl */].resolve(initialValue);\n values.forEach(function (value) {\n result = result.then(function (lastResult) {\n return fn(value, lastResult);\n });\n });\n return result;\n}\n// CONCATENATED MODULE: ./src/firestore/remote/backoff.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\nvar backoff_LOG_TAG = 'ExponentialBackoff';\n/**\r\n * A helper for running delayed tasks following an exponential backoff curve\r\n * between attempts.\r\n *\r\n * Each delay is made up of a \"base\" delay which follows the exponential\r\n * backoff curve, and a +/- 50% \"jitter\" that is calculated and added to the\r\n * base delay. This prevents clients from accidentally synchronizing their\r\n * delays causing spikes of load to the backend.\r\n */\nvar backoff_ExponentialBackoff = /** @class */function () {\n function ExponentialBackoff(\n /**\r\n * The initial delay (used as the base delay on the first retry attempt).\r\n * Note that jitter will still be applied, so the actual delay could be as\r\n * little as 0.5*initialDelayMs.\r\n */\n initialDelayMs,\n /**\r\n * The multiplier to use to determine the extended base delay after each\r\n * attempt.\r\n */\n backoffFactor,\n /**\r\n * The maximum base delay after which no further backoff is performed.\r\n * Note that jitter will still be applied, so the actual delay could be as\r\n * much as 1.5*maxDelayMs.\r\n */\n maxDelayMs) {\n this.initialDelayMs = initialDelayMs;\n this.backoffFactor = backoffFactor;\n this.maxDelayMs = maxDelayMs;\n this.reset();\n }\n /**\r\n * Resets the backoff delay.\r\n *\r\n * The very next backoffAndWait() will have no delay. If it is called again\r\n * (i.e. due to an error), initialDelayMs (plus jitter) will be used, and\r\n * subsequent ones will increase according to the backoffFactor.\r\n */\n ExponentialBackoff.prototype.reset = function () {\n this.currentBaseMs = 0;\n };\n /**\r\n * Resets the backoff delay to the maximum delay (e.g. for use after a\r\n * RESOURCE_EXHAUSTED error).\r\n */\n ExponentialBackoff.prototype.resetToMax = function () {\n this.currentBaseMs = this.maxDelayMs;\n };\n /**\r\n * Returns a promise that resolves after currentDelayMs, and increases the\r\n * delay for any subsequent attempts.\r\n */\n ExponentialBackoff.prototype.backoffAndWait = function () {\n var def = new promise_Deferred();\n // First schedule using the current base (which may be 0 and should be\n // honored as such).\n var delayWithJitterMs = this.currentBaseMs + this.jitterDelayMs();\n if (this.currentBaseMs > 0) {\n debug(backoff_LOG_TAG, \"Backing off for \" + delayWithJitterMs + \" ms \" + (\"(base delay: \" + this.currentBaseMs + \" ms)\"));\n }\n setTimeout(function () {\n def.resolve();\n }, delayWithJitterMs);\n // Apply backoff factor to determine next delay and ensure it is within\n // bounds.\n this.currentBaseMs *= this.backoffFactor;\n if (this.currentBaseMs < this.initialDelayMs) {\n this.currentBaseMs = this.initialDelayMs;\n }\n if (this.currentBaseMs > this.maxDelayMs) {\n this.currentBaseMs = this.maxDelayMs;\n }\n return def.promise;\n };\n /** Returns a random value in the range [-currentBaseMs/2, currentBaseMs/2] */\n ExponentialBackoff.prototype.jitterDelayMs = function () {\n return (Math.random() - 0.5) * this.currentBaseMs;\n };\n return ExponentialBackoff;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/remote/persistent_stream.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar persistent_stream___extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\nvar persistent_stream_LOG_TAG = 'PersistentStream';\nvar PersistentStreamState;\n(function (PersistentStreamState) {\n /**\r\n * The streaming RPC is not running and there's no error condition.\r\n * Calling `start` will start the stream immediately without backoff.\r\n * While in this state isStarted will return false.\r\n */\n PersistentStreamState[PersistentStreamState[\"Initial\"] = 0] = \"Initial\";\n /**\r\n * The stream is starting, and is waiting for an auth token to attach to\r\n * the initial request. While in this state, isStarted will return\r\n * true but isOpen will return false.\r\n */\n PersistentStreamState[PersistentStreamState[\"Auth\"] = 1] = \"Auth\";\n /**\r\n * The streaming RPC is up and running. Requests and responses can flow\r\n * freely. Both isStarted and isOpen will return true.\r\n */\n PersistentStreamState[PersistentStreamState[\"Open\"] = 2] = \"Open\";\n /**\r\n * The stream encountered an error. The next start attempt will back off.\r\n * While in this state isStarted() will return false.\r\n *\r\n */\n PersistentStreamState[PersistentStreamState[\"Error\"] = 3] = \"Error\";\n /**\r\n * An in-between state after an error where the stream is waiting before\r\n * re-starting. After\r\n * waiting is complete, the stream will try to open. While in this\r\n * state isStarted() will return YES but isOpen will return false.\r\n */\n PersistentStreamState[PersistentStreamState[\"Backoff\"] = 4] = \"Backoff\";\n /**\r\n * The stream has been explicitly stopped; no further events will be emitted.\r\n */\n PersistentStreamState[PersistentStreamState[\"Stopped\"] = 5] = \"Stopped\";\n})(PersistentStreamState || (PersistentStreamState = {}));\n/**\r\n * Initial backoff time in milliseconds after an error.\r\n * Set to 1s according to https://cloud.google.com/apis/design/errors.\r\n */\nvar BACKOFF_INITIAL_DELAY_MS = 1000;\n/** Maximum backoff time in milliseconds */\nvar BACKOFF_MAX_DELAY_MS = 60 * 1000;\nvar BACKOFF_FACTOR = 1.5;\n/**\r\n * A PersistentStream is an abstract base class that represents a streaming RPC\r\n * to the Firestore backend. It's built on top of the connections own support\r\n * for streaming RPCs, and adds several critical features for our clients:\r\n *\r\n * - Exponential backoff on failure\r\n * - Authentication via CredentialsProvider\r\n * - Dispatching all callbacks into the shared worker queue\r\n *\r\n * Subclasses of PersistentStream implement serialization of models to and\r\n * from the JSON representation of the protocol buffers for a specific\r\n * streaming RPC.\r\n *\r\n * ## Starting and Stopping\r\n *\r\n * Streaming RPCs are stateful and need to be `start`ed before messages can\r\n * be sent and received. The PersistentStream will call the onOpen function\r\n * of the listener once the stream is ready to accept requests.\r\n *\r\n * Should a `start` fail, PersistentStream will call the registered\r\n * onClose with a FirestoreError indicating what went wrong.\r\n *\r\n * A PersistentStream can be started and stopped repeatedly.\r\n *\r\n * Generic types:\r\n * SendType: The type of the outgoing message of the underlying\r\n * connection stream\r\n * ReceiveType: The type of the incoming message of the underlying\r\n * connection stream\r\n * ListenerType: The type of the listener that will be used for callbacks\r\n */\nvar persistent_stream_PersistentStream = /** @class */function () {\n function PersistentStream(queue, connection, credentialsProvider, listener,\n // Used for faster retries in testing\n initialBackoffDelay) {\n this.queue = queue;\n this.connection = connection;\n this.credentialsProvider = credentialsProvider;\n this.stream = null;\n this.listener = null;\n this.backoff = new backoff_ExponentialBackoff(initialBackoffDelay ? initialBackoffDelay : BACKOFF_INITIAL_DELAY_MS, BACKOFF_FACTOR, BACKOFF_MAX_DELAY_MS);\n this.state = PersistentStreamState.Initial;\n this.listener = listener;\n }\n /**\r\n * Returns true if `start` has been called and no error has occurred. True\r\n * indicates the stream is open or in the process of opening (which\r\n * encompasses respecting backoff, getting auth tokens, and starting the\r\n * actual RPC). Use `isOpen` to determine if the stream is open and ready for\r\n * outbound requests.\r\n */\n PersistentStream.prototype.isStarted = function () {\n return this.state === PersistentStreamState.Backoff || this.state === PersistentStreamState.Auth || this.state === PersistentStreamState.Open;\n };\n /**\r\n * Returns true if the underlying RPC is open (the openHandler has been\r\n * called) and the stream is ready for outbound requests.\r\n */\n PersistentStream.prototype.isOpen = function () {\n return this.state === PersistentStreamState.Open;\n };\n /**\r\n * Starts the RPC. Only allowed if isStarted returns false. The stream is\r\n * not immediately ready for use: onOpen will be invoked when the RPC is ready\r\n * for outbound requests, at which point isOpen will return true.\r\n *\r\n * When start returns, isStarted will return true.\r\n */\n PersistentStream.prototype.start = function () {\n if (this.state === PersistentStreamState.Error) {\n this.performBackoff();\n return;\n }\n assert(this.state === PersistentStreamState.Initial, 'Already started');\n this.auth();\n };\n /**\r\n * Stops the RPC. This call is idempotent and allowed regardless of the\r\n * current isStarted state.\r\n *\r\n * When stop returns, isStarted and isOpen will both return false.\r\n */\n PersistentStream.prototype.stop = function () {\n // Prevent any possible future restart of this stream\n this.state = PersistentStreamState.Stopped;\n // Clear the listener to avoid bleeding of events from the underlying\n // streams\n this.listener = null;\n // Clean up the underlying stream because we are no longer interested in\n // events\n if (this.stream !== null) {\n this.stream.close();\n this.stream = null;\n }\n };\n /**\r\n * After an error the stream will usually back off on the next attempt to\r\n * start it. If the error warrants an immediate restart of the stream, the\r\n * sender can use this to indicate that the receiver should not back off.\r\n *\r\n * Each error will call the onClose function. That function can decide to\r\n * inhibit backoff if required.\r\n */\n PersistentStream.prototype.inhibitBackoff = function () {\n assert(!this.isStarted(), 'Can only inhibit backoff in a stopped state');\n this.state = PersistentStreamState.Initial;\n this.backoff.reset();\n };\n PersistentStream.prototype.auth = function () {\n var _this = this;\n assert(this.state === PersistentStreamState.Initial, 'Must be in initial state to auth');\n this.state = PersistentStreamState.Auth;\n this.credentialsProvider.getToken( /*forceRefresh=*/false).then(function (token) {\n // Normally we'd have to schedule the callback on the AsyncQueue.\n // However, the following calls are safe to be called outside the\n // AsyncQueue since they don't chain asynchronous calls\n _this.startStream(token);\n }, function (error) {\n _this.queue.schedule(function () {\n if (_this.state !== PersistentStreamState.Stopped) {\n // Stream can be stopped while waiting for authorization.\n var rpcError = new FirestoreError(Code.UNKNOWN, 'Fetching auth token failed: ' + error.message);\n return _this.handleStreamClose(rpcError);\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n });\n });\n };\n PersistentStream.prototype.startStream = function (token) {\n var _this = this;\n if (this.state === PersistentStreamState.Stopped) {\n // Stream can be stopped while waiting for authorization.\n return;\n }\n assert(this.state === PersistentStreamState.Auth, 'Trying to start stream in a non-auth state');\n // Helper function to dispatch to AsyncQueue and make sure that any\n // close will seem instantaneous and events are prevented from being\n // raised after the close call\n var dispatchIfNotStopped = function dispatchIfNotStopped(fn) {\n _this.queue.schedule(function () {\n // Only raise events if the listener has not changed\n if (_this.state !== PersistentStreamState.Stopped) {\n return fn();\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n });\n };\n // Only start stream if listener has not changed\n if (this.listener !== null) {\n this.stream = this.startRpc(token);\n this.stream.onOpen(function () {\n dispatchIfNotStopped(function () {\n assert(_this.state === PersistentStreamState.Auth, 'Expected stream to be in state auth, but was ' + _this.state);\n _this.state = PersistentStreamState.Open;\n return _this.listener.onOpen();\n });\n });\n this.stream.onClose(function (error) {\n dispatchIfNotStopped(function () {\n return _this.handleStreamClose(error);\n });\n });\n this.stream.onMessage(function (msg) {\n dispatchIfNotStopped(function () {\n return _this.onMessage(msg);\n });\n });\n }\n };\n PersistentStream.prototype.performBackoff = function () {\n var _this = this;\n assert(this.state === PersistentStreamState.Error, 'Should only perform backoff in an error case');\n this.state = PersistentStreamState.Backoff;\n this.backoff.backoffAndWait().then(function () {\n // Backoff does not run on the AsyncQueue, so we need to reschedule to\n // make sure the queue blocks\n _this.queue.schedule(function () {\n if (_this.state === PersistentStreamState.Stopped) {\n // Stream can be stopped while waiting for backoff to complete.\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n _this.state = PersistentStreamState.Initial;\n _this.start();\n assert(_this.isStarted(), 'PersistentStream should have started');\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n });\n });\n };\n PersistentStream.prototype.handleStreamClose = function (error) {\n assert(this.isStarted(), \"Can't handle server close on non-started stream\");\n debug(persistent_stream_LOG_TAG, \"close with error: \" + error);\n this.stream = null;\n // In theory the stream could close cleanly, however, in our current model\n // we never expect this to happen because if we stop a stream ourselves,\n // this callback will never be called. To prevent cases where we retry\n // without a backoff accidentally, we set the stream to error in all cases.\n this.state = PersistentStreamState.Error;\n if (error && error.code === Code.RESOURCE_EXHAUSTED) {\n debug(persistent_stream_LOG_TAG, 'Using maximum backoff delay to prevent overloading the backend.');\n this.backoff.resetToMax();\n }\n return this.listener.onClose(error);\n };\n return PersistentStream;\n}();\n\n/**\r\n * A PersistentStream that implements the Listen RPC.\r\n *\r\n * Once the Listen stream has called the openHandler, any number of listen and\r\n * unlisten calls calls can be sent to control what changes will be sent from\r\n * the server for ListenResponses.\r\n */\nvar PersistentListenStream = /** @class */function (_super) {\n persistent_stream___extends(PersistentListenStream, _super);\n function PersistentListenStream(databaseInfo, queue, connection, credentials, serializer, listener, initialBackoffDelay) {\n var _this = _super.call(this, queue, connection, credentials, listener, initialBackoffDelay) || this;\n _this.databaseInfo = databaseInfo;\n _this.serializer = serializer;\n return _this;\n }\n PersistentListenStream.prototype.startRpc = function (token) {\n return this.connection.openStream('Listen', token);\n };\n PersistentListenStream.prototype.onMessage = function (watchChangeProto) {\n // A successful response means the stream is healthy\n this.backoff.reset();\n var watchChange = this.serializer.fromWatchChange(watchChangeProto);\n var snapshot = this.serializer.versionFromListenResponse(watchChangeProto);\n return this.listener.onWatchChange(watchChange, snapshot);\n };\n /**\r\n * Registers interest in the results of the given query. If the query\r\n * includes a resumeToken it will be included in the request. Results that\r\n * affect the query will be streamed back as WatchChange messages that\r\n * reference the targetId.\r\n */\n PersistentListenStream.prototype.watch = function (queryData) {\n var request = {};\n request.database = this.serializer.encodedDatabaseId;\n request.addTarget = this.serializer.toTarget(queryData);\n var labels = this.serializer.toListenRequestLabels(queryData);\n if (labels) {\n request.labels = labels;\n }\n this.stream.send(request);\n };\n /**\r\n * Unregisters interest in the results of the query associated with the\r\n * given targetId.\r\n */\n PersistentListenStream.prototype.unwatch = function (targetId) {\n var request = {};\n request.database = this.serializer.encodedDatabaseId;\n request.removeTarget = targetId;\n this.stream.send(request);\n };\n return PersistentListenStream;\n}(persistent_stream_PersistentStream);\n\n/**\r\n * A Stream that implements the Write RPC.\r\n *\r\n * The Write RPC requires the caller to maintain special streamToken\r\n * state in between calls, to help the server understand which responses the\r\n * client has processed by the time the next request is made. Every response\r\n * will contain a streamToken; this value must be passed to the next\r\n * request.\r\n *\r\n * After calling start() on this stream, the next request must be a handshake,\r\n * containing whatever streamToken is on hand. Once a response to this\r\n * request is received, all pending mutations may be submitted. When\r\n * submitting multiple batches of mutations at the same time, it's\r\n * okay to use the same streamToken for the calls to writeMutations.\r\n *\r\n * TODO(b/33271235): Use proto types\r\n */\nvar persistent_stream_PersistentWriteStream = /** @class */function (_super) {\n persistent_stream___extends(PersistentWriteStream, _super);\n function PersistentWriteStream(databaseInfo, queue, connection, credentials, serializer, listener, initialBackoffDelay) {\n var _this = _super.call(this, queue, connection, credentials, listener, initialBackoffDelay) || this;\n _this.databaseInfo = databaseInfo;\n _this.serializer = serializer;\n _this.handshakeComplete_ = false;\n return _this;\n }\n Object.defineProperty(PersistentWriteStream.prototype, \"handshakeComplete\", {\n /**\r\n * Tracks whether or not a handshake has been successfully exchanged and\r\n * the stream is ready to accept mutations.\r\n */\n get: function get() {\n return this.handshakeComplete_;\n },\n enumerable: true,\n configurable: true\n });\n // Override of PersistentStream.start\n PersistentWriteStream.prototype.start = function () {\n this.handshakeComplete_ = false;\n _super.prototype.start.call(this);\n };\n PersistentWriteStream.prototype.startRpc = function (token) {\n return this.connection.openStream('Write', token);\n };\n PersistentWriteStream.prototype.onMessage = function (responseProto) {\n // Always capture the last stream token.\n assert(!!responseProto.streamToken, 'Got a write response without a stream token');\n this.lastStreamToken = responseProto.streamToken;\n if (!this.handshakeComplete_) {\n // The first response is always the handshake response\n assert(!responseProto.writeResults || responseProto.writeResults.length === 0, 'Got mutation results for handshake');\n this.handshakeComplete_ = true;\n return this.listener.onHandshakeComplete();\n } else {\n // A successful first write response means the stream is healthy,\n // Note, that we could consider a successful handshake healthy, however,\n // the write itself might be causing an error we want to back off from.\n this.backoff.reset();\n var results = this.serializer.fromWriteResults(responseProto.writeResults);\n var commitVersion = this.serializer.fromVersion(responseProto.commitTime);\n return this.listener.onMutationResult(commitVersion, results);\n }\n };\n /**\r\n * Sends an initial streamToken to the server, performing the handshake\r\n * required to make the StreamingWrite RPC work. Subsequent\r\n * calls should wait until onHandshakeComplete was called.\r\n */\n PersistentWriteStream.prototype.writeHandshake = function () {\n assert(this.isOpen(), 'Writing handshake requires an opened stream');\n assert(!this.handshakeComplete_, 'Handshake already completed');\n // TODO(dimond): Support stream resumption. We intentionally do not set the\n // stream token on the handshake, ignoring any stream token we might have.\n var request = {};\n request.database = this.serializer.encodedDatabaseId;\n this.stream.send(request);\n };\n /** Sends a group of mutations to the Firestore backend to apply. */\n PersistentWriteStream.prototype.writeMutations = function (mutations) {\n var _this = this;\n assert(this.isOpen(), 'Writing mutations requires an opened stream');\n assert(this.handshakeComplete_, 'Handshake must be complete before writing mutations');\n assert(this.lastStreamToken.length > 0, 'Trying to write mutation without a token');\n var request = {\n // Protos are typed with string, but we support UInt8Array on Node\n // tslint:disable-next-line:no-any\n streamToken: this.lastStreamToken,\n writes: mutations.map(function (mutation) {\n return _this.serializer.toMutation(mutation);\n })\n };\n this.stream.send(request);\n };\n return PersistentWriteStream;\n}(persistent_stream_PersistentStream);\n\n// CONCATENATED MODULE: ./src/firestore/remote/datastore.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n/**\r\n * Datastore is a wrapper around the external Google Cloud Datastore grpc API,\r\n * which provides an interface that is more convenient for the rest of the\r\n * client SDK architecture to consume.\r\n */\nvar datastore_Datastore = /** @class */function () {\n function Datastore(databaseInfo, queue, connection, credentials, serializer, initialBackoffDelay) {\n this.databaseInfo = databaseInfo;\n this.queue = queue;\n this.connection = connection;\n this.credentials = credentials;\n this.serializer = serializer;\n this.initialBackoffDelay = initialBackoffDelay;\n }\n Datastore.prototype.newPersistentWriteStream = function (listener) {\n return new persistent_stream_PersistentWriteStream(this.databaseInfo, this.queue, this.connection, this.credentials, this.serializer, listener, this.initialBackoffDelay);\n };\n Datastore.prototype.newPersistentWatchStream = function (listener) {\n return new PersistentListenStream(this.databaseInfo, this.queue, this.connection, this.credentials, this.serializer, listener, this.initialBackoffDelay);\n };\n Datastore.prototype.commit = function (mutations) {\n var _this = this;\n var params = {\n writes: mutations.map(function (m) {\n return _this.serializer.toMutation(m);\n })\n };\n return this.invokeRPC('commit', params).then(function (response) {\n return _this.serializer.fromWriteResults(response.writeResults);\n });\n };\n Datastore.prototype.lookup = function (keys) {\n var _this = this;\n var params = {\n documents: keys.map(function (k) {\n return _this.serializer.toName(k);\n })\n };\n return this.invokeRPC('batchGet', params).then(function (response) {\n var docs = maybeDocumentMap();\n response.forEach(function (proto) {\n var doc = _this.serializer.fromMaybeDocument(proto);\n docs = docs.insert(doc.key, doc);\n });\n var result = [];\n keys.forEach(function (key) {\n var doc = docs.get(key);\n assert(!!doc, 'Missing entity in write response for ' + key);\n result.push(doc);\n });\n return result;\n });\n };\n /** Gets an auth token and invokes the provided RPC. */\n Datastore.prototype.invokeRPC = function (rpcName, request) {\n var _this = this;\n // TODO(mikelehen): Retry (with backoff) on token failures?\n return this.credentials.getToken( /*forceRefresh=*/false).then(function (token) {\n return _this.connection.invoke(rpcName, request, token);\n });\n };\n return Datastore;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/transaction.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n/**\r\n * Internal transaction object responsible for accumulating the mutations to\r\n * perform and the base versions for any documents read.\r\n */\nvar transaction_Transaction = /** @class */function () {\n function Transaction(datastore) {\n this.datastore = datastore;\n // The version of each document that was read during this transaction.\n this.readVersions = documentVersionMap();\n this.mutations = [];\n this.committed = false;\n }\n Transaction.prototype.recordVersion = function (doc) {\n var docVersion = doc.version;\n if (doc instanceof document_NoDocument) {\n // For deleted docs, we must use baseVersion 0 when we overwrite them.\n docVersion = snapshot_version_SnapshotVersion.forDeletedDoc();\n }\n var existingVersion = this.readVersions.get(doc.key);\n if (existingVersion !== null) {\n if (!docVersion.equals(existingVersion)) {\n // This transaction will fail no matter what.\n throw new FirestoreError(Code.ABORTED, 'Document version changed between two reads.');\n }\n } else {\n this.readVersions = this.readVersions.insert(doc.key, docVersion);\n }\n };\n Transaction.prototype.lookup = function (keys) {\n var _this = this;\n if (this.committed) {\n return utils_promise[\"b\" /* PromiseImpl */].reject('Transaction has already completed.');\n }\n if (this.mutations.length > 0) {\n return utils_promise[\"b\" /* PromiseImpl */].reject('Transactions lookups are invalid after writes.');\n }\n return this.datastore.lookup(keys).then(function (docs) {\n docs.forEach(function (doc) {\n return _this.recordVersion(doc);\n });\n return docs;\n });\n };\n Transaction.prototype.write = function (mutations) {\n if (this.committed) {\n throw new FirestoreError(Code.FAILED_PRECONDITION, 'Transaction has already completed.');\n }\n this.mutations = this.mutations.concat(mutations);\n };\n /**\r\n * Returns the version of this document when it was read in this transaction,\r\n * as a precondition, or no precondition if it was not read.\r\n */\n Transaction.prototype.precondition = function (key) {\n var version = this.readVersions.get(key);\n if (version) {\n return mutation_Precondition.updateTime(version);\n } else {\n return mutation_Precondition.NONE;\n }\n };\n /**\r\n * Returns the precondition for a document if the operation is an update.\r\n */\n Transaction.prototype.preconditionForUpdate = function (key) {\n var version = this.readVersions.get(key);\n if (version && version.equals(snapshot_version_SnapshotVersion.forDeletedDoc())) {\n // The document doesn't exist, so fail the transaction.\n throw new FirestoreError(Code.FAILED_PRECONDITION, \"Can't update a document that doesn't exist.\");\n } else if (version) {\n // Document exists, base precondition on document update time.\n return mutation_Precondition.updateTime(version);\n } else {\n // Document was not read, so we just use the preconditions for a blind\n // update.\n return mutation_Precondition.exists(true);\n }\n };\n Transaction.prototype.set = function (key, data) {\n this.write(data.toMutations(key, this.precondition(key)));\n };\n Transaction.prototype.update = function (key, data) {\n this.write(data.toMutations(key, this.preconditionForUpdate(key)));\n };\n Transaction.prototype.delete = function (key) {\n this.write([new mutation_DeleteMutation(key, this.precondition(key))]);\n // Since the delete will be applied before all following writes, we need to\n // ensure that the precondition for the next write will be exists: false.\n this.readVersions = this.readVersions.insert(key, snapshot_version_SnapshotVersion.forDeletedDoc());\n };\n Transaction.prototype.commit = function () {\n var _this = this;\n var unwritten = this.readVersions;\n // For each mutation, note that the doc was written.\n this.mutations.forEach(function (mutation) {\n unwritten = unwritten.remove(mutation.key);\n });\n if (!unwritten.isEmpty()) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(Error('Every document read in a transaction must also be written.'));\n }\n return this.datastore.commit(this.mutations).then(function () {\n _this.committed = true;\n });\n };\n return Transaction;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/remote/remote_store.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar remote_store_LOG_TAG = 'RemoteStore';\n// TODO(b/35853402): Negotiate this with the stream.\nvar MAX_PENDING_WRITES = 10;\n// The RemoteStore notifies an onlineStateHandler with OnlineState.Failed if we\n// fail to connect to the backend. This subsequently triggers get() requests to\n// fail or use cached data, etc. Unfortunately, our connections have\n// historically been subject to various transient failures. So we wait for\n// multiple failures before notifying the onlineStateHandler.\nvar ONLINE_ATTEMPTS_BEFORE_FAILURE = 2;\n/**\r\n * RemoteStore - An interface to remotely stored data, basically providing a\r\n * wrapper around the Datastore that is more reliable for the rest of the\r\n * system.\r\n *\r\n * RemoteStore is responsible for maintaining the connection to the server.\r\n * - maintaining a list of active listens.\r\n * - reconnecting when the connection is dropped.\r\n * - resuming all the active listens on reconnect.\r\n *\r\n * RemoteStore handles all incoming events from the Datastore.\r\n * - listening to the watch stream and repackaging the events as RemoteEvents\r\n * - notifying SyncEngine of any changes to the active listens.\r\n *\r\n * RemoteStore takes writes from other components and handles them reliably.\r\n * - pulling pending mutations from LocalStore and sending them to Datastore.\r\n * - retrying mutations that failed because of network problems.\r\n * - acking mutations to the SyncEngine once they are accepted or rejected.\r\n */\nvar remote_store_RemoteStore = /** @class */function () {\n function RemoteStore(databaseInfo, asyncQueue,\n /**\r\n * The local store, used to fill the write pipeline with outbound\r\n * mutations and resolve existence filter mismatches.\r\n */\n localStore,\n /** The client-side proxy for interacting with the backend. */\n datastore, onlineStateHandler) {\n this.databaseInfo = databaseInfo;\n this.asyncQueue = asyncQueue;\n this.localStore = localStore;\n this.datastore = datastore;\n this.onlineStateHandler = onlineStateHandler;\n this.pendingWrites = [];\n this.lastBatchSeen = BATCHID_UNKNOWN;\n /**\r\n * A mapping of watched targets that the client cares about tracking and the\r\n * user has explicitly called a 'listen' for this target.\r\n *\r\n * These targets may or may not have been sent to or acknowledged by the\r\n * server. On re-establishing the listen stream, these targets should be sent\r\n * to the server. The targets removed with unlistens are removed eagerly\r\n * without waiting for confirmation from the listen stream.\r\n */\n this.listenTargets = {};\n /**\r\n * A mapping of targetId to pending acks needed.\r\n *\r\n * If a targetId is present in this map, then we're waiting for watch to\r\n * acknowledge a removal or addition of the target. If a target is not in this\r\n * mapping, and it's in the listenTargets map, then we consider the target to\r\n * be active.\r\n *\r\n * We increment the count here every time we issue a request over the stream\r\n * to watch or unwatch. We then decrement the count every time we get a target\r\n * added or target removed message from the server. Once the count is equal to\r\n * 0 we know that the client and server are in the same state (once this state\r\n * is reached the targetId is removed from the map to free the memory).\r\n */\n this.pendingTargetResponses = {};\n this.accumulatedWatchChanges = [];\n /**\r\n * The online state of the watch stream. The state is set to healthy if and\r\n * only if there are messages received by the backend.\r\n */\n this.watchStreamOnlineState = OnlineState.Unknown;\n /** A count of consecutive failures to open the stream. */\n this.watchStreamFailures = 0;\n }\n /**\r\n * Starts up the remote store, creating streams, restoring state from\r\n * LocalStore, etc.\r\n */\n RemoteStore.prototype.start = function () {\n var _this = this;\n return this.setupStreams().then(function () {\n // Resume any writes\n return _this.fillWritePipeline();\n });\n };\n RemoteStore.prototype.setOnlineStateToHealthy = function () {\n this.updateAndBroadcastOnlineState(OnlineState.Healthy);\n };\n RemoteStore.prototype.setOnlineStateToUnknown = function () {\n // The state is set to unknown when a healthy stream is closed (e.g. due to\n // a token timeout) or when we have no active listens and therefore there's\n // no need to start the stream. Assuming there is (possibly in the future)\n // an active listen, then we will eventually move to state Online or Failed,\n // but we always want to make at least ONLINE_ATTEMPTS_BEFORE_FAILURE\n // attempts before failing, so we reset the count here.\n this.watchStreamFailures = 0;\n this.updateAndBroadcastOnlineState(OnlineState.Unknown);\n };\n RemoteStore.prototype.updateOnlineStateAfterFailure = function () {\n // The first failure after we are successfully connected moves us to the\n // 'Unknown' state. We then may make multiple attempts (based on\n // ONLINE_ATTEMPTS_BEFORE_FAILURE) before we actually report failure.\n if (this.watchStreamOnlineState === OnlineState.Healthy) {\n this.setOnlineStateToUnknown();\n } else {\n this.watchStreamFailures++;\n if (this.watchStreamFailures >= ONLINE_ATTEMPTS_BEFORE_FAILURE) {\n this.updateAndBroadcastOnlineState(OnlineState.Failed);\n }\n }\n };\n RemoteStore.prototype.updateAndBroadcastOnlineState = function (onlineState) {\n var didChange = this.watchStreamOnlineState !== onlineState;\n this.watchStreamOnlineState = onlineState;\n if (didChange) {\n this.onlineStateHandler(onlineState);\n }\n };\n RemoteStore.prototype.setupStreams = function () {\n var _this = this;\n this.watchStream = this.datastore.newPersistentWatchStream({\n onOpen: this.onWatchStreamOpen.bind(this),\n onClose: this.onWatchStreamClose.bind(this),\n onWatchChange: this.onWatchStreamChange.bind(this)\n });\n this.writeStream = this.datastore.newPersistentWriteStream({\n onOpen: this.onWriteStreamOpen.bind(this),\n onClose: this.onWriteStreamClose.bind(this),\n onHandshakeComplete: this.onWriteHandshakeComplete.bind(this),\n onMutationResult: this.onMutationResult.bind(this)\n });\n // Load any saved stream token from persistent storage\n return this.localStore.getLastStreamToken().then(function (token) {\n _this.writeStream.lastStreamToken = token;\n });\n };\n RemoteStore.prototype.shutdown = function () {\n debug(remote_store_LOG_TAG, 'RemoteStore shutting down.');\n this.cleanupWatchStreamState();\n this.writeStream.stop();\n this.watchStream.stop();\n return utils_promise[\"b\" /* PromiseImpl */].resolve(undefined);\n };\n /** Starts new listen for the given query. Uses resume token if provided */\n RemoteStore.prototype.listen = function (queryData) {\n assert(!contains(this.listenTargets, queryData.targetId), 'listen called with duplicate targetId!');\n // Mark this as something the client is currently listening for.\n this.listenTargets[queryData.targetId] = queryData;\n if (this.watchStream.isOpen()) {\n this.sendWatchRequest(queryData);\n } else if (!this.watchStream.isStarted()) {\n // The listen will be sent in onWatchStreamOpen\n this.startWatchStream();\n }\n };\n /** Removes the listen from server */\n RemoteStore.prototype.unlisten = function (targetId) {\n assert(contains(this.listenTargets, targetId), 'unlisten called without assigned target ID!');\n var queryData = this.listenTargets[targetId];\n delete this.listenTargets[targetId];\n if (this.watchStream.isOpen()) {\n this.sendUnwatchRequest(targetId);\n }\n };\n /**\r\n * We need to increment the the expected number of pending responses we're due\r\n * from watch so we wait for the ack to process any messages from this target.\r\n */\n RemoteStore.prototype.sendWatchRequest = function (queryData) {\n this.recordPendingTargetRequest(queryData.targetId);\n this.watchStream.watch(queryData);\n };\n /**\r\n * We need to increment the expected number of pending responses we're due\r\n * from watch so we wait for the removal on the server before we process any\r\n * messages from this target.\r\n */\n RemoteStore.prototype.sendUnwatchRequest = function (targetId) {\n this.recordPendingTargetRequest(targetId);\n this.watchStream.unwatch(targetId);\n };\n /**\r\n * Increment the mapping of how many acks are needed from watch before we can\r\n * consider the server to be 'in-sync' with the client's active targets.\r\n */\n RemoteStore.prototype.recordPendingTargetRequest = function (targetId) {\n // For each request we get we need to record we need a response for it.\n this.pendingTargetResponses[targetId] = (this.pendingTargetResponses[targetId] || 0) + 1;\n };\n RemoteStore.prototype.startWatchStream = function () {\n assert(!this.watchStream.isStarted(), \"Can't restart started watch stream\");\n assert(this.shouldStartWatchStream(), 'Tried to start watch stream even though it should not be started');\n this.watchStream.start();\n };\n /**\r\n * Returns whether the watch stream should be started because there are\r\n * active targets trying to be listened too\r\n */\n RemoteStore.prototype.shouldStartWatchStream = function () {\n return !isEmpty(this.listenTargets);\n };\n RemoteStore.prototype.cleanupWatchStreamState = function () {\n // If the connection is closed then we'll never get a snapshot version for\n // the accumulated changes and so we'll never be able to complete the batch.\n // When we start up again the server is going to resend these changes\n // anyway, so just toss the accumulated state.\n this.accumulatedWatchChanges = [];\n this.pendingTargetResponses = {};\n };\n RemoteStore.prototype.onWatchStreamOpen = function () {\n var _this = this;\n // TODO(b/35852690): close the stream again (with some timeout?) if no watch\n // targets are active\n forEachNumber(this.listenTargets, function (targetId, queryData) {\n _this.sendWatchRequest(queryData);\n });\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n };\n RemoteStore.prototype.onWatchStreamClose = function (error) {\n this.cleanupWatchStreamState();\n // If there was an error, retry the connection.\n if (this.shouldStartWatchStream()) {\n this.updateOnlineStateAfterFailure();\n this.startWatchStream();\n } else {\n // No need to restart watch stream because there are no active targets.\n // The online state is set to unknown because there is no active attempt\n // at establishing a connection\n this.setOnlineStateToUnknown();\n }\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n };\n RemoteStore.prototype.onWatchStreamChange = function (watchChange, snapshotVersion) {\n // Mark the connection as healthy because we got a message from the server\n this.setOnlineStateToHealthy();\n if (watchChange instanceof watch_change_WatchTargetChange && watchChange.state === WatchTargetChangeState.Removed && watchChange.cause) {\n // There was an error on a target, don't wait for a consistent snapshot\n // to raise events\n return this.handleTargetError(watchChange);\n }\n // Accumulate watch changes but don't process them if there's no\n // snapshotVersion or it's older than a previous snapshot we've processed\n // (can happen after we resume a target using a resume token).\n this.accumulatedWatchChanges.push(watchChange);\n if (!snapshotVersion.equals(snapshot_version_SnapshotVersion.MIN) && snapshotVersion.compareTo(this.localStore.getLastRemoteSnapshotVersion()) >= 0) {\n var changes = this.accumulatedWatchChanges;\n this.accumulatedWatchChanges = [];\n return this.handleWatchChangeBatch(snapshotVersion, changes);\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n };\n /**\r\n * Takes a batch of changes from the Datastore, repackages them as a\r\n * RemoteEvent, and passes that on to the listener, which is typically the\r\n * SyncEngine.\r\n */\n RemoteStore.prototype.handleWatchChangeBatch = function (snapshotVersion, changes) {\n var _this = this;\n var aggregator = new watch_change_WatchChangeAggregator(snapshotVersion, this.listenTargets, this.pendingTargetResponses);\n aggregator.addChanges(changes);\n var remoteEvent = aggregator.createRemoteEvent();\n // Get the new response counts from the aggregator\n this.pendingTargetResponses = aggregator.pendingTargetResponses;\n var promises = [];\n // Handle existence filters and existence filter mismatches.\n forEachNumber(aggregator.existenceFilters, function (targetId, filter) {\n var queryData = _this.listenTargets[targetId];\n if (!queryData) {\n // A watched target might have been removed already.\n return;\n }\n var query = queryData.query;\n if (query.isDocumentQuery()) {\n if (filter.count === 0) {\n // The existence filter told us the document does not exist.\n // We need to deduce that this document does not exist and apply\n // a deleted document to our updates. Without applying a deleted\n // document there might be another query that will raise this\n // document as part of a snapshot until it is resolved,\n // essentially exposing inconsistency between queries.\n var key = new document_key_DocumentKey(query.path);\n var deletedDoc = new document_NoDocument(key, snapshotVersion);\n remoteEvent.addDocumentUpdate(deletedDoc);\n } else {\n assert(filter.count === 1, 'Single document existence filter with count: ' + filter.count);\n }\n } else {\n // Not a document query.\n var promise = _this.localStore.remoteDocumentKeys(targetId).then(function (trackedRemote) {\n if (remoteEvent.targetChanges[targetId]) {\n var mapping = remoteEvent.targetChanges[targetId].mapping;\n if (mapping !== null) {\n if (mapping instanceof UpdateMapping) {\n trackedRemote = mapping.applyToKeySet(trackedRemote);\n } else {\n assert(mapping instanceof ResetMapping, 'Expected either reset or update mapping but got something else: ' + mapping);\n trackedRemote = mapping.documents;\n }\n }\n }\n if (trackedRemote.size !== filter.count) {\n // Existence filter mismatch, resetting mapping.\n // Make sure the mismatch is exposed in the remote event.\n remoteEvent.handleExistenceFilterMismatch(targetId);\n // Clear the resume token for the query, since we're in a\n // known mismatch state.\n var newQueryData = new query_data_QueryData(query, targetId, queryData.purpose);\n _this.listenTargets[targetId] = newQueryData;\n // Cause a hard reset by unwatching and rewatching\n // immediately, but deliberately don't send a resume token\n // so that we get a full update.\n // Make sure we expect that this acks are going to happen.\n _this.sendUnwatchRequest(targetId);\n // Mark the query we send as being on behalf of an existence\n // filter mismatch, but don't actually retain that in\n // listenTargets. This ensures that we flag the first\n // re-listen this way without impacting future listens of\n // this target (that might happen e.g. on reconnect).\n var requestQueryData = new query_data_QueryData(query, targetId, QueryPurpose.ExistenceFilterMismatch);\n _this.sendWatchRequest(requestQueryData);\n }\n });\n promises.push(promise);\n }\n });\n return utils_promise[\"b\" /* PromiseImpl */].all(promises).then(function () {\n // Update in-memory resume tokens. LocalStore will update the\n // persistent view of these when applying the completed RemoteEvent.\n forEachNumber(remoteEvent.targetChanges, function (targetId, change) {\n if (change.resumeToken.length > 0) {\n var queryData = _this.listenTargets[targetId];\n // A watched target might have been removed already.\n if (queryData) {\n _this.listenTargets[targetId] = queryData.update({\n resumeToken: change.resumeToken,\n snapshotVersion: change.snapshotVersion\n });\n }\n }\n });\n // Finally handle remote event\n return _this.syncEngine.applyRemoteEvent(remoteEvent);\n });\n };\n /** Handles an error on a target */\n RemoteStore.prototype.handleTargetError = function (watchChange) {\n var _this = this;\n assert(!!watchChange.cause, 'Handling target error without a cause');\n var error = watchChange.cause;\n var promiseChain = utils_promise[\"b\" /* PromiseImpl */].resolve();\n watchChange.targetIds.forEach(function (targetId) {\n promiseChain = promiseChain.then(function () {\n if (contains(_this.listenTargets, targetId)) {\n delete _this.listenTargets[targetId];\n return _this.syncEngine.rejectListen(targetId, error);\n } else {\n // A watched target might have been removed already.\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n });\n });\n return promiseChain;\n };\n /**\r\n * Notifies that there are new mutations to process in the queue. This is\r\n * typically called by SyncEngine after it has sent mutations to LocalStore.\r\n *\r\n */\n RemoteStore.prototype.fillWritePipeline = function () {\n var _this = this;\n if (!this.canWriteMutations()) {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n } else {\n return this.localStore.nextMutationBatch(this.lastBatchSeen).then(function (batch) {\n if (batch === null) {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n } else {\n _this.commit(batch);\n return _this.fillWritePipeline();\n }\n });\n }\n };\n /**\r\n * Returns true if the backend can accept additional write requests.\r\n *\r\n * When sending mutations to the write stream (e.g. in fillWritePipeline),\r\n * call this method first to check if more mutations can be sent.\r\n *\r\n * Currently the only thing that can prevent the backend from accepting\r\n * write requests is if there are too many requests already outstanding. As\r\n * writes complete the backend will be able to accept more.\r\n */\n RemoteStore.prototype.canWriteMutations = function () {\n return this.pendingWrites.length < MAX_PENDING_WRITES;\n };\n // For testing\n RemoteStore.prototype.outstandingWrites = function () {\n return this.pendingWrites.length;\n };\n /**\r\n * Given mutations to commit, actually commits them to the Datastore. Note\r\n * that this does *not* return a Promise specifically because the AsyncQueue\r\n * should not block operations for this.\r\n */\n RemoteStore.prototype.commit = function (batch) {\n assert(this.canWriteMutations(), \"commit called when batches can't be written\");\n this.lastBatchSeen = batch.batchId;\n this.pendingWrites.push(batch);\n if (!this.writeStream.isStarted()) {\n this.startWriteStream();\n } else if (this.writeStream.handshakeComplete) {\n this.writeStream.writeMutations(batch.mutations);\n }\n };\n RemoteStore.prototype.startWriteStream = function () {\n assert(!this.writeStream.isStarted(), \"Can't restart started write stream\");\n this.writeStream.start();\n };\n RemoteStore.prototype.onWriteStreamOpen = function () {\n this.writeStream.writeHandshake();\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n };\n RemoteStore.prototype.onWriteHandshakeComplete = function () {\n var _this = this;\n // Record the stream token.\n return this.localStore.setLastStreamToken(this.writeStream.lastStreamToken).then(function () {\n // Drain any pending writes.\n //\n // Note that at this point pendingWrites contains mutations that\n // have already been accepted by fillWritePipeline/commitBatch. If\n // the pipeline is full, canWriteMutations will be false, despite\n // the fact that we actually need to send mutations over.\n //\n // This also means that this method indirectly respects the limits\n // imposed by canWriteMutations since writes can't be added to the\n // pendingWrites array when canWriteMutations is false. If the\n // limits imposed by canWriteMutations actually protect us from\n // DOSing ourselves then those limits won't be exceeded here and\n // we'll continue to make progress.\n for (var _i = 0, _a = _this.pendingWrites; _i < _a.length; _i++) {\n var batch = _a[_i];\n _this.writeStream.writeMutations(batch.mutations);\n }\n });\n };\n RemoteStore.prototype.onMutationResult = function (commitVersion, results) {\n var _this = this;\n // This is a response to a write containing mutations and should be\n // correlated to the first pending write.\n assert(this.pendingWrites.length > 0, 'Got result for empty pending writes');\n var batch = this.pendingWrites.shift();\n var success = mutation_batch_MutationBatchResult.from(batch, commitVersion, results, this.writeStream.lastStreamToken);\n return this.syncEngine.applySuccessfulWrite(success).then(function () {\n // It's possible that with the completion of this mutation another\n // slot has freed up.\n return _this.fillWritePipeline();\n });\n };\n RemoteStore.prototype.onWriteStreamClose = function (error) {\n var _this = this;\n // Ignore close if there are no pending writes.\n if (this.pendingWrites.length > 0) {\n assert(!!error, 'We have pending writes, but the write stream closed without an error');\n // A promise that is resolved after we processed the error\n var errorHandling = void 0;\n if (this.writeStream.handshakeComplete) {\n // This error affects the actual write.\n errorHandling = this.handleWriteError(error);\n } else {\n // If there was an error before the handshake has finished, it's\n // possible that the server is unable to process the stream token\n // we're sending. (Perhaps it's too old?)\n errorHandling = this.handleHandshakeError(error);\n }\n return errorHandling.then(function () {\n // The write stream might have been started by refilling the write\n // pipeline for failed writes\n if (_this.pendingWrites.length > 0 && !_this.writeStream.isStarted()) {\n _this.startWriteStream();\n }\n });\n } else {\n // No pending writes, nothing to do\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n };\n RemoteStore.prototype.handleHandshakeError = function (error) {\n // Reset the token if it's a permanent error or the error code is\n // ABORTED, signaling the write stream is no longer valid.\n if (isPermanentError(error.code) || error.code === Code.ABORTED) {\n debug(remote_store_LOG_TAG, 'RemoteStore error before completed handshake; resetting stream token: ', this.writeStream.lastStreamToken);\n this.writeStream.lastStreamToken = emptyByteString();\n return this.localStore.setLastStreamToken(emptyByteString());\n } else {\n // Some other error, don't reset stream token. Our stream logic will\n // just retry with exponential backoff.\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n };\n RemoteStore.prototype.handleWriteError = function (error) {\n var _this = this;\n if (isPermanentError(error.code)) {\n // This was a permanent error, the request itself was the problem\n // so it's not going to succeed if we resend it.\n var batch = this.pendingWrites.shift();\n // In this case it's also unlikely that the server itself is melting\n // down -- this was just a bad request so inhibit backoff on the next\n // restart.\n this.writeStream.inhibitBackoff();\n return this.syncEngine.rejectFailedWrite(batch.batchId, error).then(function () {\n // It's possible that with the completion of this mutation\n // another slot has freed up.\n return _this.fillWritePipeline();\n });\n } else {\n // Transient error, just let the retry logic kick in.\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n };\n RemoteStore.prototype.createTransaction = function () {\n return new transaction_Transaction(this.datastore);\n };\n RemoteStore.prototype.handleUserChange = function (user) {\n var _this = this;\n debug(remote_store_LOG_TAG, 'RemoteStore changing users: uid=', user.uid);\n // Clear pending writes because those are per-user. Watched targets\n // persist across users so don't clear those.\n this.lastBatchSeen = BATCHID_UNKNOWN;\n this.pendingWrites = [];\n // Stop the streams. They promise not to call us back.\n this.watchStream.stop();\n this.writeStream.stop();\n this.cleanupWatchStreamState();\n // Create new streams (but note they're not started yet).\n return this.setupStreams().then(function () {\n // If there are any watchedTargets, properly handle the stream\n // restart now that RemoteStore is ready to handle them.\n if (_this.shouldStartWatchStream()) {\n _this.startWatchStream();\n }\n // Resume any writes\n return _this.fillWritePipeline();\n }).then(function () {\n // User change moves us back to the unknown state because we might\n // not want to re-open the stream\n _this.setOnlineStateToUnknown();\n });\n };\n return RemoteStore;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/core/firestore_client.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar firestore_client_LOG_TAG = 'FirestoreClient';\n/**\r\n * FirestoreClient is a top-level class that constructs and owns all of the\r\n * pieces of the client SDK architecture. It is responsible for creating the\r\n * async queue that is shared by all of the other components in the system.\r\n */\nvar firestore_client_FirestoreClient = /** @class */function () {\n function FirestoreClient(platform, databaseInfo, credentials,\n /**\r\n * Asynchronous queue responsible for all of our internal processing. When\r\n * we get incoming work from the user (via public API) or the network\r\n * (incoming GRPC messages), we should always schedule onto this queue.\r\n * This ensures all of our work is properly serialized (e.g. we don't\r\n * start processing a new operation while the previous one is waiting for\r\n * an async I/O to complete).\r\n */\n asyncQueue) {\n this.platform = platform;\n this.databaseInfo = databaseInfo;\n this.credentials = credentials;\n this.asyncQueue = asyncQueue;\n }\n /**\r\n * Starts up the FirestoreClient, returning only whether or not enabling\r\n * persistence succeeded.\r\n *\r\n * The intent here is to \"do the right thing\" as far as users are concerned.\r\n * Namely, in cases where offline persistence is requested and possible,\r\n * enable it, but otherwise fall back to persistence disabled. For the most\r\n * part we expect this to succeed one way or the other so we don't expect our\r\n * users to actually wait on the firestore.enablePersistence Promise since\r\n * they generally won't care.\r\n *\r\n * Of course some users actually do care about whether or not persistence\r\n * was successfully enabled, so the Promise returned from this method\r\n * indicates this outcome.\r\n *\r\n * This presents a problem though: even before enablePersistence resolves or\r\n * rejects, users may have made calls to e.g. firestore.collection() which\r\n * means that the FirestoreClient in there will be available and will be\r\n * enqueuing actions on the async queue.\r\n *\r\n * Meanwhile any failure of an operation on the async queue causes it to\r\n * panic and reject any further work, on the premise that unhandled errors\r\n * are fatal.\r\n *\r\n * Consequently the fallback is handled internally here in start, and if the\r\n * fallback succeeds we signal success to the async queue even though the\r\n * start() itself signals failure.\r\n *\r\n * @param usePersistence Whether or not to attempt to enable persistence.\r\n * @returns A deferred result indicating the user-visible result of enabling\r\n * offline persistence. This method will reject this if IndexedDB fails to\r\n * start for any reason. If usePersistence is false this is\r\n * unconditionally resolved.\r\n */\n FirestoreClient.prototype.start = function (usePersistence) {\n var _this = this;\n // We defer our initialization until we get the current user from\n // setUserChangeListener(). We block the async queue until we got the\n // initial user and the initialization is completed. This will prevent\n // any scheduled work from happening before initialization is completed.\n //\n // If initializationDone resolved then the FirestoreClient is in a usable\n // state.\n var initializationDone = new promise_Deferred();\n // If usePersistence is true, certain classes of errors while starting are\n // recoverable but only by falling back to persistence disabled.\n //\n // If there's an error in the first case but not in recovery we cannot\n // reject the promise blocking the async queue because this will cause the\n // async queue to panic.\n var persistenceResult = new promise_Deferred();\n var initialized = false;\n this.credentials.setUserChangeListener(function (user) {\n if (!initialized) {\n initialized = true;\n _this.initializePersistence(usePersistence, persistenceResult).then(function () {\n return _this.initializeRest(user);\n }).then(initializationDone.resolve, initializationDone.reject);\n } else {\n _this.asyncQueue.schedule(function () {\n return _this.handleUserChange(user);\n });\n }\n });\n // Block the async queue until initialization is done\n this.asyncQueue.schedule(function () {\n return initializationDone.promise;\n });\n // Return only the result of enabling persistence. Note that this does not\n // need to await the completion of initializationDone because the result of\n // this method should not reflect any other kind of failure to start.\n return persistenceResult.promise;\n };\n /**\r\n * Initializes persistent storage, attempting to use IndexedDB if\r\n * usePersistence is true or memory-only if false.\r\n *\r\n * If IndexedDB fails because it's already open in another tab or because the\r\n * platform can't possibly support our implementation then this method rejects\r\n * the persistenceResult and falls back on memory-only persistence.\r\n *\r\n * @param usePersistence indicates whether or not to use offline persistence\r\n * @param persistenceResult A deferred result indicating the user-visible\r\n * result of enabling offline persistence. This method will reject this if\r\n * IndexedDB fails to start for any reason. If usePersistence is false\r\n * this is unconditionally resolved.\r\n * @returns a Promise indicating whether or not initialization should\r\n * continue, i.e. that one of the persistence implementations actually\r\n * succeeded.\r\n */\n FirestoreClient.prototype.initializePersistence = function (usePersistence, persistenceResult) {\n var _this = this;\n if (usePersistence) {\n return this.startIndexedDbPersistence().then(persistenceResult.resolve).catch(function (error) {\n // Regardless of whether or not the retry succeeds, from an user\n // perspective, offline persistence has failed.\n persistenceResult.reject(error);\n // An unknown failure on the first stage shuts everything down.\n if (!_this.canFallback(error)) {\n return utils_promise[\"b\" /* PromiseImpl */].reject(error);\n }\n console.warn('Error enabling offline storage. Falling back to' + ' storage disabled: ' + error);\n return _this.startMemoryPersistence();\n });\n } else {\n // When usePersistence == false, enabling offline persistence is defined\n // to unconditionally succeed. This allows start() to have the same\n // signature for both cases, despite the fact that the returned promise\n // is only used in the enablePersistence call.\n persistenceResult.resolve();\n return this.startMemoryPersistence();\n }\n };\n FirestoreClient.prototype.canFallback = function (error) {\n return error.code === Code.FAILED_PRECONDITION || error.code === Code.UNIMPLEMENTED;\n };\n /**\r\n * Starts IndexedDB-based persistence.\r\n *\r\n * @returns A promise indicating success or failure.\r\n */\n FirestoreClient.prototype.startIndexedDbPersistence = function () {\n // TODO(http://b/33384523): For now we just disable garbage collection\n // when persistence is enabled.\n this.garbageCollector = new no_op_garbage_collector_NoOpGarbageCollector();\n var storagePrefix = indexeddb_persistence_IndexedDbPersistence.buildStoragePrefix(this.databaseInfo);\n // Opt to use proto3 JSON in case the platform doesn't support Uint8Array.\n var serializer = new serializer_JsonProtoSerializer(this.databaseInfo.databaseId, {\n useProto3Json: true\n });\n this.persistence = new indexeddb_persistence_IndexedDbPersistence(storagePrefix, serializer);\n return this.persistence.start();\n };\n /**\r\n * Starts Memory-backed persistence. In practice this cannot fail.\r\n *\r\n * @returns A promise that will successfully resolve.\r\n */\n FirestoreClient.prototype.startMemoryPersistence = function () {\n this.garbageCollector = new eager_garbage_collector_EagerGarbageCollector();\n this.persistence = new memory_persistence_MemoryPersistence();\n return this.persistence.start();\n };\n /**\r\n * Initializes the rest of the FirestoreClient, assuming the initial user\r\n * has been obtained from the credential provider and some persistence\r\n * implementation is available in this.persistence.\r\n */\n FirestoreClient.prototype.initializeRest = function (user) {\n var _this = this;\n return this.platform.loadConnection(this.databaseInfo).then(function (connection) {\n _this.localStore = new local_store_LocalStore(_this.persistence, user, _this.garbageCollector);\n var serializer = _this.platform.newSerializer(_this.databaseInfo.databaseId);\n var datastore = new datastore_Datastore(_this.databaseInfo, _this.asyncQueue, connection, _this.credentials, serializer);\n var onlineStateChangedHandler = function onlineStateChangedHandler(onlineState) {\n _this.eventMgr.onOnlineStateChanged(onlineState);\n };\n _this.remoteStore = new remote_store_RemoteStore(_this.databaseInfo, _this.asyncQueue, _this.localStore, datastore, onlineStateChangedHandler);\n _this.syncEngine = new sync_engine_SyncEngine(_this.localStore, _this.remoteStore, user);\n // Setup wiring between sync engine and remote store\n _this.remoteStore.syncEngine = _this.syncEngine;\n _this.eventMgr = new event_manager_EventManager(_this.syncEngine);\n // NOTE: RemoteStore depends on LocalStore (for persisting stream\n // tokens, refilling mutation queue, etc.) so must be started after\n // LocalStore.\n return _this.localStore.start();\n }).then(function () {\n return _this.remoteStore.start();\n });\n };\n FirestoreClient.prototype.handleUserChange = function (user) {\n this.asyncQueue.verifyOperationInProgress();\n debug(firestore_client_LOG_TAG, 'User Changed: ' + user.uid);\n return this.syncEngine.handleUserChange(user);\n };\n FirestoreClient.prototype.shutdown = function () {\n var _this = this;\n return this.asyncQueue.schedule(function () {\n _this.credentials.removeUserChangeListener();\n return _this.remoteStore.shutdown();\n }).then(function () {\n // PORTING NOTE: LocalStore does not need an explicit shutdown on web.\n return _this.persistence.shutdown();\n });\n };\n FirestoreClient.prototype.listen = function (query, observer, options) {\n var _this = this;\n var listener = new event_manager_QueryListener(query, observer, options);\n this.asyncQueue.schedule(function () {\n return _this.eventMgr.listen(listener);\n });\n return listener;\n };\n FirestoreClient.prototype.unlisten = function (listener) {\n var _this = this;\n this.asyncQueue.schedule(function () {\n return _this.eventMgr.unlisten(listener);\n });\n };\n FirestoreClient.prototype.write = function (mutations) {\n var _this = this;\n var deferred = new promise_Deferred();\n this.asyncQueue.schedule(function () {\n return _this.syncEngine.write(mutations, deferred);\n });\n return deferred.promise;\n };\n FirestoreClient.prototype.databaseId = function () {\n return this.databaseInfo.databaseId;\n };\n FirestoreClient.prototype.transaction = function (updateFunction) {\n var _this = this;\n // We have to wait for the async queue to be sure syncEngine is initialized.\n return this.asyncQueue.schedule(function () {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }).then(function () {\n return _this.syncEngine.runTransaction(updateFunction);\n });\n };\n return FirestoreClient;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/util/async_observer.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n/*\r\n * A wrapper implementation of Observer that will dispatch events\r\n * asynchronously. To allow immediate silencing, a mute call is added which\r\n * causes events scheduled to no longer be raised.\r\n */\nvar AsyncObserver = /** @class */function () {\n function AsyncObserver(observer) {\n this.observer = observer;\n /**\r\n * When set to true, will not raise future events. Necessary to deal with\r\n * async detachment of listener.\r\n */\n this.muted = false;\n }\n AsyncObserver.prototype.next = function (value) {\n this.scheduleEvent(this.observer.next, value);\n };\n AsyncObserver.prototype.error = function (error) {\n this.scheduleEvent(this.observer.error, error);\n };\n AsyncObserver.prototype.mute = function () {\n this.muted = true;\n };\n AsyncObserver.prototype.scheduleEvent = function (eventHandler, event) {\n var _this = this;\n if (!this.muted) {\n setTimeout(function () {\n if (!_this.muted) {\n eventHandler(event);\n }\n }, 0);\n }\n };\n return AsyncObserver;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/util/async_queue.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\nvar async_queue_AsyncQueue = /** @class */function () {\n function AsyncQueue() {\n // The last promise in the queue.\n this.tail = utils_promise[\"b\" /* PromiseImpl */].resolve();\n // The number of ops that are queued to be run in the future (i.e. they had a\n // delay that has not yet elapsed).\n this.delayedOpCount = 0;\n // Flag set while there's an outstanding AsyncQueue operation, used for\n // assertion sanity-checks.\n this.operationInProgress = false;\n }\n /**\r\n * Adds a new operation to the queue. Returns a promise that will be resolved\r\n * when the promise returned by the new operation is (with its value).\r\n *\r\n * Can optionally specify a delay to wait before queuing the operation.\r\n */\n AsyncQueue.prototype.schedule = function (op, delay) {\n var _this = this;\n if (this.failure) {\n fail('AsyncQueue is already failed: ' + this.failure.message);\n }\n if ((delay || 0) > 0) {\n this.delayedOpCount++;\n var deferred_1 = new promise_Deferred();\n setTimeout(function () {\n _this.scheduleInternal(function () {\n return op().then(function (result) {\n deferred_1.resolve(result);\n });\n });\n _this.delayedOpCount--; // decrement once it's actually queued.\n }, delay);\n return deferred_1.promise;\n } else {\n return this.scheduleInternal(op);\n }\n };\n AsyncQueue.prototype.scheduleInternal = function (op) {\n var _this = this;\n this.tail = this.tail.then(function () {\n _this.operationInProgress = true;\n return op().catch(function (error) {\n _this.failure = error;\n _this.operationInProgress = false;\n log_error('INTERNAL UNHANDLED ERROR: ', error.stack || error.message);\n throw error;\n }).then(function () {\n _this.operationInProgress = false;\n });\n });\n return this.tail;\n };\n /**\r\n * Verifies there's an operation currently in-progress on the AsyncQueue.\r\n * Unfortunately we can't verify that the running code is in the promise chain\r\n * of that operation, so this isn't a foolproof check, but it should be enough\r\n * to catch some bugs.\r\n */\n AsyncQueue.prototype.verifyOperationInProgress = function () {\n assert(this.operationInProgress, 'verifyOpInProgress() called when no op in progress on this queue.');\n };\n AsyncQueue.prototype.drain = function () {\n // TODO(mikelehen): This should perhaps also drain items that are queued to\n // run in the future (perhaps by artificially running them early), but since\n // no tests need that yet, I didn't bother for now.\n assert(this.delayedOpCount === 0, \"draining doesn't handle delayed ops.\");\n return this.schedule(function () {\n return utils_promise[\"b\" /* PromiseImpl */].resolve(undefined);\n });\n };\n return AsyncQueue;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/auth/user.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n/**\r\n * Simple wrapper around a nullable UID. Mostly exists to make code more\r\n * readable.\r\n */\nvar User = /** @class */function () {\n function User(uid) {\n this.uid = uid;\n }\n User.prototype.isUnauthenticated = function () {\n return this.uid == null;\n };\n /**\r\n * Returns a key representing this user, suitable for inclusion in a\r\n * dictionary.\r\n */\n User.prototype.toKey = function () {\n if (this.isUnauthenticated()) {\n return 'anonymous-user';\n } else {\n return 'uid:' + this.uid;\n }\n };\n User.prototype.equals = function (otherUser) {\n return otherUser.uid === this.uid;\n };\n /** A user with a null UID. */\n User.UNAUTHENTICATED = new User(null);\n // TODO(mikelehen): Look into getting a proper uid-equivalent for\n // non-FirebaseAuth providers.\n User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');\n User.FIRST_PARTY = new User('first-party-uid');\n return User;\n}();\n\n// CONCATENATED MODULE: ./src/firestore/api/credentials.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\nvar OAuthToken = /** @class */function () {\n function OAuthToken(value, user) {\n this.user = user;\n this.type = 'OAuth';\n this.authHeaders = { Authorization: \"Bearer \" + value };\n }\n return OAuthToken;\n}();\n\n/** A CredentialsProvider that always yields an empty token. */\nvar credentials_EmptyCredentialsProvider = /** @class */function () {\n function EmptyCredentialsProvider() {\n /**\r\n * Stores the User listener registered with setUserChangeListener()\r\n * This isn't actually necessary since the UID never changes, but we use this\r\n * to verify the listen contract is adhered to in tests.\r\n */\n this.userListener = null;\n }\n EmptyCredentialsProvider.prototype.getToken = function (forceRefresh) {\n return utils_promise[\"b\" /* PromiseImpl */].resolve(null);\n };\n EmptyCredentialsProvider.prototype.setUserChangeListener = function (listener) {\n assert(!this.userListener, 'Can only call setUserChangeListener() once.');\n this.userListener = listener;\n // Fire with initial user.\n listener(User.UNAUTHENTICATED);\n };\n EmptyCredentialsProvider.prototype.removeUserChangeListener = function () {\n assert(this.userListener !== null, 'removeUserChangeListener() when no listener registered');\n this.userListener = null;\n };\n return EmptyCredentialsProvider;\n}();\n\nvar credentials_FirebaseCredentialsProvider = /** @class */function () {\n function FirebaseCredentialsProvider(app) {\n var _this = this;\n this.app = app;\n /**\r\n * The auth token listener registered with FirebaseApp, retained here so we\r\n * can unregister it.\r\n */\n this.tokenListener = null;\n /**\r\n * Counter used to detect if the user changed while a getToken request was\r\n * outstanding.\r\n */\n this.userCounter = 0;\n /** The User listener registered with setUserChangeListener(). */\n this.userListener = null;\n // We listen for token changes but all we really care about is knowing when\n // the uid may have changed.\n this.tokenListener = function () {\n var newUser = _this.getUser();\n if (!_this.currentUser || !newUser.equals(_this.currentUser)) {\n _this.currentUser = newUser;\n _this.userCounter++;\n if (_this.userListener) {\n _this.userListener(_this.currentUser);\n }\n }\n };\n this.userCounter = 0;\n // Will fire at least once where we set this.currentUser\n this.app.INTERNAL.addAuthTokenListener(this.tokenListener);\n }\n FirebaseCredentialsProvider.prototype.getToken = function (forceRefresh) {\n var _this = this;\n assert(this.tokenListener != null, 'getToken cannot be called after listener removed.');\n // Take note of the current value of the userCounter so that this method can\n // fail (with an ABORTED error) if there is a user change while the request\n // is outstanding.\n var initialUserCounter = this.userCounter;\n return this.app.INTERNAL.getToken(forceRefresh).then(function (tokenData) {\n // Cancel the request since the user changed while the request was\n // outstanding so the response is likely for a previous user (which\n // user, we can't be sure).\n if (_this.userCounter !== initialUserCounter) {\n throw new FirestoreError(Code.ABORTED, 'getToken aborted due to uid change.');\n } else {\n if (tokenData) {\n assert(typeof tokenData.accessToken === 'string', 'Invalid tokenData returned from getToken():' + tokenData);\n return new OAuthToken(tokenData.accessToken, _this.currentUser);\n } else {\n return null;\n }\n }\n });\n };\n FirebaseCredentialsProvider.prototype.setUserChangeListener = function (listener) {\n assert(!this.userListener, 'Can only call setUserChangeListener() once.');\n this.userListener = listener;\n // Fire the initial event, but only if we received the initial user\n if (this.currentUser) {\n listener(this.currentUser);\n }\n };\n FirebaseCredentialsProvider.prototype.removeUserChangeListener = function () {\n assert(this.tokenListener != null, 'removeUserChangeListener() called twice');\n assert(this.userListener !== null, 'removeUserChangeListener() called when no listener registered');\n this.app.INTERNAL.removeAuthTokenListener(this.tokenListener);\n this.tokenListener = null;\n this.userListener = null;\n };\n FirebaseCredentialsProvider.prototype.getUser = function () {\n // TODO(mikelehen): Remove this check once we're shipping with firebase.js.\n if (typeof this.app.INTERNAL.getUid !== 'function') {\n fail('This version of the Firestore SDK requires at least version' + ' 3.7.0 of firebase.js.');\n }\n var currentUid = this.app.INTERNAL.getUid();\n assert(currentUid === null || typeof currentUid === 'string', 'Received invalid UID: ' + currentUid);\n return new User(currentUid);\n };\n return FirebaseCredentialsProvider;\n}();\n\n// Wrap a google-auth-library client as a CredentialsProvider.\n// NOTE: grpc-connection can natively accept a google-auth-library\n// client via createFromGoogleCredential(), but we opt to plumb the tokens\n// through our CredentialsProvider interface, at least for now.\nvar credentials_GoogleCredentialsProvider = /** @class */function () {\n function GoogleCredentialsProvider(authClient) {\n this.authClient = authClient;\n }\n GoogleCredentialsProvider.prototype.getToken = function (forceRefresh) {\n var _this = this;\n return new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n // TODO(b/32935141): ideally this would be declared as an extern\n _this.authClient['getAccessToken'](function (error, tokenLiteral) {\n if (error) {\n reject(error);\n } else {\n resolve(new OAuthToken(tokenLiteral, User.GOOGLE_CREDENTIALS));\n }\n });\n });\n };\n // NOTE: A google-auth-library client represents an immutable \"user\", so\n // once we fire the initial event, it'll never change.\n GoogleCredentialsProvider.prototype.setUserChangeListener = function (listener) {\n // Fire with initial uid.\n listener(User.GOOGLE_CREDENTIALS);\n };\n GoogleCredentialsProvider.prototype.removeUserChangeListener = function () {};\n return GoogleCredentialsProvider;\n}();\n\n/*\r\n * FirstPartyToken provides a fresh token each time its value\r\n * is requested, because if the token is too old, requests will be rejected.\r\n * TODO(b/33147818) this implementation violates the current assumption that\r\n * tokens are immutable. We need to either revisit this assumption or come\r\n * up with some way for FPA to use the listen/unlisten interface.\r\n */\nvar credentials_FirstPartyToken = /** @class */function () {\n function FirstPartyToken(gapi, sessionIndex) {\n this.gapi = gapi;\n this.sessionIndex = sessionIndex;\n this.type = 'FirstParty';\n this.user = User.FIRST_PARTY;\n assert(this.gapi && this.gapi['auth'] && this.gapi['auth']['getAuthHeaderValueForFirstParty'], 'unexpected gapi interface');\n }\n Object.defineProperty(FirstPartyToken.prototype, \"authHeaders\", {\n get: function get() {\n return {\n Authorization: this.gapi['auth']['getAuthHeaderValueForFirstParty']([]),\n 'X-Goog-AuthUser': this.sessionIndex\n };\n },\n enumerable: true,\n configurable: true\n });\n return FirstPartyToken;\n}();\n\n/*\r\n * Provides user credentials required for the Firestore JavaScript SDK\r\n * to authenticate the user, using technique that is only available\r\n * to applications hosted by Google.\r\n */\nvar credentials_FirstPartyCredentialsProvider = /** @class */function () {\n function FirstPartyCredentialsProvider(gapi, sessionIndex) {\n this.gapi = gapi;\n this.sessionIndex = sessionIndex;\n assert(this.gapi && this.gapi['auth'] && this.gapi['auth']['getAuthHeaderValueForFirstParty'], 'unexpected gapi interface');\n }\n FirstPartyCredentialsProvider.prototype.getToken = function (forceRefresh) {\n return utils_promise[\"b\" /* PromiseImpl */].resolve(new credentials_FirstPartyToken(this.gapi, this.sessionIndex));\n };\n // TODO(33108925): can someone switch users w/o a page refresh?\n // TODO(33110621): need to understand token/session lifecycle\n FirstPartyCredentialsProvider.prototype.setUserChangeListener = function (listener) {\n // Fire with initial uid.\n listener(User.FIRST_PARTY);\n };\n FirstPartyCredentialsProvider.prototype.removeUserChangeListener = function () {};\n return FirstPartyCredentialsProvider;\n}();\n\n/**\r\n * Builds a CredentialsProvider depending on the type of\r\n * the credentials passed in.\r\n */\nfunction makeCredentialsProvider(credentials) {\n if (!credentials) {\n return new credentials_EmptyCredentialsProvider();\n }\n switch (credentials.type) {\n case 'google-auth':\n return new credentials_GoogleCredentialsProvider(credentials.client);\n case 'gapi':\n return new credentials_FirstPartyCredentialsProvider(credentials.client, credentials.sessionIndex || '0');\n case 'provider':\n return credentials.client;\n default:\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'makeCredentialsProvider failed due to invalid credential type');\n }\n}\n// CONCATENATED MODULE: ./src/firestore/api/observer.ts\nvar observer__typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nfunction isPartialObserver(obj) {\n return implementsAnyMethods(obj, ['next', 'error', 'complete']);\n}\n/**\r\n * Returns true if obj is an object and contains at least one of the specified\r\n * methods.\r\n */\nfunction implementsAnyMethods(obj, methods) {\n if ((typeof obj === 'undefined' ? 'undefined' : observer__typeof(obj)) !== 'object' || obj === null) {\n return false;\n }\n var object = obj;\n for (var _i = 0, methods_1 = methods; _i < methods_1.length; _i++) {\n var method = methods_1[_i];\n if (method in object && typeof object[method] === 'function') {\n return true;\n }\n }\n return false;\n}\n// CONCATENATED MODULE: ./src/firestore/api/field_value.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar api_field_value___extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n/**\r\n * An opaque base class for FieldValue sentinel objects in our public API,\r\n * with public static methods for creating said sentinel objects.\r\n */\n// tslint:disable-next-line:class-as-namespace We use this as a base class.\nvar FieldValueImpl = /** @class */function () {\n function FieldValueImpl() {}\n FieldValueImpl.delete = function () {\n return DeleteFieldValueImpl.instance;\n };\n FieldValueImpl.serverTimestamp = function () {\n return ServerTimestampFieldValueImpl.instance;\n };\n return FieldValueImpl;\n}();\n\nvar DeleteFieldValueImpl = /** @class */function (_super) {\n api_field_value___extends(DeleteFieldValueImpl, _super);\n function DeleteFieldValueImpl() {\n return _super.call(this) || this;\n }\n /** Singleton instance. */\n DeleteFieldValueImpl.instance = new DeleteFieldValueImpl();\n return DeleteFieldValueImpl;\n}(FieldValueImpl);\n\nvar ServerTimestampFieldValueImpl = /** @class */function (_super) {\n api_field_value___extends(ServerTimestampFieldValueImpl, _super);\n function ServerTimestampFieldValueImpl() {\n return _super.call(this) || this;\n }\n /** Singleton instance. */\n ServerTimestampFieldValueImpl.instance = new ServerTimestampFieldValueImpl();\n return ServerTimestampFieldValueImpl;\n}(FieldValueImpl);\n\n// Public instance that disallows construction at runtime. This constructor is\n// used when exporting FieldValueImpl on firebase.firestore.FieldValue and will\n// be called FieldValue publicly. Internally we still use FieldValueImpl which\n// has a type-checked private constructor. Note that FieldValueImpl and\n// PublicFieldValue can be used interchangeably in instanceof checks.\n// For our internal TypeScript code PublicFieldValue doesn't exist as a type,\n// and so we need to use FieldValueImpl as type and export it too.\n// tslint:disable-next-line:variable-name We treat this as a class name.\nvar PublicFieldValue = makeConstructorPrivate(FieldValueImpl, 'Use FieldValue.() instead.');\n// CONCATENATED MODULE: ./src/firestore/api/user_data_converter.ts\nvar user_data_converter__typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar RESERVED_FIELD_REGEX = /^__.*__$/;\n/** The result of parsing document data (e.g. for a setData call). */\nvar user_data_converter_ParsedSetData = /** @class */function () {\n function ParsedSetData(data, fieldMask, fieldTransforms) {\n this.data = data;\n this.fieldMask = fieldMask;\n this.fieldTransforms = fieldTransforms;\n }\n ParsedSetData.prototype.toMutations = function (key, precondition) {\n var mutations = [];\n if (this.fieldMask !== null) {\n mutations.push(new mutation_PatchMutation(key, this.data, this.fieldMask, precondition));\n } else {\n mutations.push(new mutation_SetMutation(key, this.data, precondition));\n }\n if (this.fieldTransforms.length > 0) {\n mutations.push(new mutation_TransformMutation(key, this.fieldTransforms));\n }\n return mutations;\n };\n return ParsedSetData;\n}();\n\n/** The result of parsing \"update\" data (i.e. for an updateData call). */\nvar user_data_converter_ParsedUpdateData = /** @class */function () {\n function ParsedUpdateData(data, fieldMask, fieldTransforms) {\n this.data = data;\n this.fieldMask = fieldMask;\n this.fieldTransforms = fieldTransforms;\n }\n ParsedUpdateData.prototype.toMutations = function (key, precondition) {\n var mutations = [new mutation_PatchMutation(key, this.data, this.fieldMask, precondition)];\n if (this.fieldTransforms.length > 0) {\n mutations.push(new mutation_TransformMutation(key, this.fieldTransforms));\n }\n return mutations;\n };\n return ParsedUpdateData;\n}();\n\n/*\r\n * Represents what type of API method provided the data being parsed; useful\r\n * for determining which error conditions apply during parsing and providing\r\n * better error messages.\r\n */\nvar UserDataSource;\n(function (UserDataSource) {\n UserDataSource[UserDataSource[\"Set\"] = 0] = \"Set\";\n UserDataSource[UserDataSource[\"Update\"] = 1] = \"Update\";\n UserDataSource[UserDataSource[\"QueryValue\"] = 2] = \"QueryValue\"; // from a where clause or cursor bound\n})(UserDataSource || (UserDataSource = {}));\n/** A \"context\" object passed around while parsing user data. */\nvar user_data_converter_ParseContext = /** @class */function () {\n /**\r\n * Initializes a ParseContext with the given source and path.\r\n *\r\n * @param dataSource Indicates what kind of API method this data came from.\r\n * @param path A path within the object being parsed. This could be an empty\r\n * path (in which case the context represents the root of the data being\r\n * parsed), or a nonempty path (indicating the context represents a nested\r\n * location within the data).\r\n *\r\n * TODO(b/34871131): We don't support array paths right now, so path can be\r\n * null to indicate the context represents any location within an array (in\r\n * which case certain features will not work and errors will be somewhat\r\n * compromised).\r\n * @param fieldTransforms A mutable list of field transforms encountered while\r\n * parsing the data.\r\n * @param fieldMask A mutable list of field paths encountered while parsing\r\n * the data.\r\n */\n function ParseContext(dataSource, methodName, path, fieldTransforms, fieldMask) {\n this.dataSource = dataSource;\n this.methodName = methodName;\n this.path = path;\n // Minor hack: If fieldTransforms is undefined, we assume this is an\n // external call and we need to validate the entire path.\n if (fieldTransforms === undefined) {\n this.validatePath();\n }\n this.fieldTransforms = fieldTransforms || [];\n this.fieldMask = fieldMask || [];\n }\n ParseContext.prototype.childContext = function (field) {\n var childPath;\n if (typeof field === 'number') {\n // TODO(b/34871131): We don't support array paths right now; so make path\n // null.\n childPath = null;\n } else {\n childPath = this.path == null ? null : this.path.child(field);\n }\n var context = new ParseContext(this.dataSource, this.methodName, childPath, this.fieldTransforms, this.fieldMask);\n if (typeof field === 'string') {\n // We only need to validate the new segment.\n context.validatePathSegment(field);\n } else if ((typeof field === 'undefined' ? 'undefined' : user_data_converter__typeof(field)) === 'object' && field instanceof path_FieldPath) {\n // Validate the whole path.\n context.validatePath();\n }\n return context;\n };\n ParseContext.prototype.createError = function (reason) {\n var fieldDescription = this.path === null || this.path.isEmpty() ? '' : \" (found in field \" + this.path.toString() + \")\";\n return new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + this.methodName + \"() called with invalid data. \" + reason + fieldDescription);\n };\n ParseContext.prototype.validatePath = function () {\n // TODO(b/34871131): Remove null check once we have proper paths for fields\n // within arrays.\n if (this.path === null) {\n return;\n }\n for (var i = 0; i < this.path.length; i++) {\n this.validatePathSegment(this.path.get(i));\n }\n };\n ParseContext.prototype.validatePathSegment = function (segment) {\n if (this.isWrite() && RESERVED_FIELD_REGEX.test(segment)) {\n throw this.createError('Document fields cannot begin and end with __');\n }\n };\n ParseContext.prototype.isWrite = function () {\n return this.dataSource === UserDataSource.Set || this.dataSource === UserDataSource.Update;\n };\n return ParseContext;\n}();\n/**\r\n * A placeholder object for DocumentReferences in this file, in order to\r\n * avoid a circular dependency. See the comments for `DataPreConverter` for\r\n * the full context.\r\n */\nvar DocumentKeyReference = /** @class */function () {\n function DocumentKeyReference(databaseId, key) {\n this.databaseId = databaseId;\n this.key = key;\n }\n return DocumentKeyReference;\n}();\n\n/**\r\n * Helper for parsing raw user input (provided via the API) into internal model\r\n * classes.\r\n */\nvar user_data_converter_UserDataConverter = /** @class */function () {\n function UserDataConverter(preConverter) {\n this.preConverter = preConverter;\n }\n /** Parse document data (e.g. from a set() call). */\n UserDataConverter.prototype.parseSetData = function (methodName, input, options) {\n var _this = this;\n var context = new user_data_converter_ParseContext(UserDataSource.Set, methodName, path_FieldPath.EMPTY_PATH);\n validatePlainObject('Data must be an object, but it was:', context, input);\n var merge = options.merge !== undefined ? options.merge : false;\n var updateData = field_value_ObjectValue.EMPTY;\n forEach(input, function (key, value) {\n var path = new field_path_FieldPath(key)._internalPath;\n var childContext = context.childContext(path);\n value = _this.runPreConverter(value, childContext);\n var parsedValue = _this.parseData(value, childContext);\n if (parsedValue) {\n updateData = updateData.set(path, parsedValue);\n }\n });\n var fieldMask = merge ? new mutation_FieldMask(context.fieldMask) : null;\n return new user_data_converter_ParsedSetData(updateData, fieldMask, context.fieldTransforms);\n };\n /** Parse update data (e.g. from an update() call). */\n UserDataConverter.prototype.parseUpdateData = function (methodName, input) {\n var _this = this;\n var context = new user_data_converter_ParseContext(UserDataSource.Update, methodName, path_FieldPath.EMPTY_PATH);\n validatePlainObject('Data must be an object, but it was:', context, input);\n var fieldMaskPaths = [];\n var updateData = field_value_ObjectValue.EMPTY;\n forEach(input, function (key, value) {\n var path = fieldPathFromDotSeparatedString(methodName, key);\n var childContext = context.childContext(path);\n value = _this.runPreConverter(value, childContext);\n if (value instanceof DeleteFieldValueImpl) {\n // Add it to the field mask, but don't add anything to updateData.\n fieldMaskPaths.push(path);\n } else {\n var parsedValue = _this.parseData(value, childContext);\n if (parsedValue != null) {\n fieldMaskPaths.push(path);\n updateData = updateData.set(path, parsedValue);\n }\n }\n });\n var mask = new mutation_FieldMask(fieldMaskPaths);\n return new user_data_converter_ParsedUpdateData(updateData, mask, context.fieldTransforms);\n };\n /** Parse update data from a list of field/value arguments. */\n UserDataConverter.prototype.parseUpdateVarargs = function (methodName, field, value, moreFieldsAndValues) {\n var context = new user_data_converter_ParseContext(UserDataSource.Update, methodName, path_FieldPath.EMPTY_PATH);\n var keys = [fieldPathFromArgument(methodName, field)];\n var values = [value];\n if (moreFieldsAndValues.length % 2 !== 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + methodName + \"() needs to be called with an even number \" + 'of arguments that alternate between field names and values.');\n }\n for (var i = 0; i < moreFieldsAndValues.length; i += 2) {\n keys.push(fieldPathFromArgument(methodName, moreFieldsAndValues[i]));\n values.push(moreFieldsAndValues[i + 1]);\n }\n var fieldMaskPaths = [];\n var updateData = field_value_ObjectValue.EMPTY;\n for (var i = 0; i < keys.length; ++i) {\n var path = keys[i];\n var childContext = context.childContext(path);\n var value_1 = this.runPreConverter(values[i], childContext);\n if (value_1 instanceof DeleteFieldValueImpl) {\n // Add it to the field mask, but don't add anything to updateData.\n fieldMaskPaths.push(path);\n } else {\n var parsedValue = this.parseData(value_1, childContext);\n if (parsedValue != null) {\n fieldMaskPaths.push(path);\n updateData = updateData.set(path, parsedValue);\n }\n }\n }\n var mask = new mutation_FieldMask(fieldMaskPaths);\n return new user_data_converter_ParsedUpdateData(updateData, mask, context.fieldTransforms);\n };\n /**\r\n * Parse a \"query value\" (e.g. value in a where filter or a value in a cursor\r\n * bound).\r\n */\n UserDataConverter.prototype.parseQueryValue = function (methodName, input) {\n var context = new user_data_converter_ParseContext(UserDataSource.QueryValue, methodName, path_FieldPath.EMPTY_PATH);\n var parsed = this.parseData(input, context);\n assert(parsed != null, 'Parsed data should not be null.');\n assert(context.fieldTransforms.length === 0, 'Field transforms should have been disallowed.');\n return parsed;\n };\n /** Sends data through this.preConverter, handling any thrown errors. */\n UserDataConverter.prototype.runPreConverter = function (input, context) {\n try {\n return this.preConverter(input);\n } catch (e) {\n var message = errorMessage(e);\n throw context.createError(message);\n }\n };\n /**\r\n * Internal helper for parsing user data.\r\n *\r\n * @param input Data to be parsed.\r\n * @param context A context object representing the current path being parsed,\r\n * the source of the data being parsed, etc.\r\n * @return The parsed value, or null if the value was a FieldValue sentinel\r\n * that should not be included in the resulting parsed data.\r\n */\n UserDataConverter.prototype.parseData = function (input, context) {\n input = this.runPreConverter(input, context);\n if (input instanceof Array) {\n // TODO(b/34871131): We may need a different way to detect nested arrays\n // once we support array paths (at which point we should include the path\n // containing the array in the error message).\n if (!context.path) {\n throw context.createError('Nested arrays are not supported');\n }\n // We don't support field mask paths more granular than the top-level\n // array.\n context.fieldMask.push(context.path);\n return this.parseArray(input, context);\n } else if (looksLikeJsonObject(input)) {\n validatePlainObject('Unsupported field value:', context, input);\n return this.parseObject(input, context);\n } else {\n // If context.path is null, we are inside an array and we should have\n // already added the root of the array to the field mask.\n if (context.path) {\n context.fieldMask.push(context.path);\n }\n return this.parseScalarValue(input, context);\n }\n };\n UserDataConverter.prototype.parseArray = function (array, context) {\n var result = [];\n var entryIndex = 0;\n for (var _i = 0, array_1 = array; _i < array_1.length; _i++) {\n var entry = array_1[_i];\n var parsedEntry = this.parseData(entry, context.childContext(entryIndex));\n if (parsedEntry == null) {\n // Just include nulls in the array for fields being replaced with a\n // sentinel.\n parsedEntry = NullValue.INSTANCE;\n }\n result.push(parsedEntry);\n entryIndex++;\n }\n return new field_value_ArrayValue(result);\n };\n UserDataConverter.prototype.parseObject = function (obj, context) {\n var _this = this;\n var result = new sorted_map_SortedMap(primitiveComparator);\n forEach(obj, function (key, val) {\n var parsedValue = _this.parseData(val, context.childContext(key));\n if (parsedValue != null) {\n result = result.insert(key, parsedValue);\n }\n });\n return new field_value_ObjectValue(result);\n };\n /**\r\n * Helper to parse a scalar value (i.e. not an Object or Array)\r\n *\r\n * @return The parsed value, or null if the value was a FieldValue sentinel\r\n * that should not be included in the resulting parsed data.\r\n */\n UserDataConverter.prototype.parseScalarValue = function (value, context) {\n if (value === null) {\n return NullValue.INSTANCE;\n } else if (typeof value === 'number') {\n if (isSafeInteger(value)) {\n return new IntegerValue(value);\n } else {\n return new DoubleValue(value);\n }\n } else if (typeof value === 'boolean') {\n return field_value_BooleanValue.of(value);\n } else if (typeof value === 'string') {\n return new field_value_StringValue(value);\n } else if (value instanceof Date) {\n return new TimestampValue(timestamp_Timestamp.fromDate(value));\n } else if (value instanceof geo_point_GeoPoint) {\n return new GeoPointValue(value);\n } else if (value instanceof blob_Blob) {\n return new BlobValue(value);\n } else if (value instanceof DocumentKeyReference) {\n return new field_value_RefValue(value.databaseId, value.key);\n } else if (value instanceof FieldValueImpl) {\n if (value instanceof DeleteFieldValueImpl) {\n // We shouldn't encounter delete sentinels here. Provide a good error.\n if (context.dataSource !== UserDataSource.Update) {\n throw context.createError('FieldValue.delete() can only be used with update()');\n } else {\n assert(context.path == null || context.path.length > 0, 'FieldValue.delete() at the top level should have already' + ' been handled.');\n throw context.createError('FieldValue.delete() can only appear at the top level ' + 'of your update data');\n }\n } else if (value instanceof ServerTimestampFieldValueImpl) {\n if (context.dataSource !== UserDataSource.Set && context.dataSource !== UserDataSource.Update) {\n throw context.createError('FieldValue.serverTimestamp() can only be used with set()' + ' and update()');\n }\n if (context.path === null) {\n throw context.createError('FieldValue.serverTimestamp() is not currently' + ' supported inside arrays');\n }\n context.fieldTransforms.push(new FieldTransform(context.path, ServerTimestampTransform.instance));\n // Return null so this value is omitted from the parsed result.\n return null;\n } else {\n return fail('Unknown FieldValue type: ' + value);\n }\n } else {\n throw context.createError(\"Unsupported field value: \" + valueDescription(value));\n }\n };\n return UserDataConverter;\n}();\n\n/**\r\n * Checks whether an object looks like a JSON object that should be converted\r\n * into a struct. Normal class/prototype instances are considered to look like\r\n * JSON objects since they should be converted to a struct value. Arrays, Dates,\r\n * GeoPoints, etc. are not considered to look like JSON objects since they map\r\n * to specific FieldValue types other than ObjectValue.\r\n */\nfunction looksLikeJsonObject(input) {\n return (typeof input === 'undefined' ? 'undefined' : user_data_converter__typeof(input)) === 'object' && input !== null && !(input instanceof Array) && !(input instanceof Date) && !(input instanceof geo_point_GeoPoint) && !(input instanceof blob_Blob) && !(input instanceof DocumentKeyReference) && !(input instanceof FieldValueImpl);\n}\nfunction validatePlainObject(message, context, input) {\n if (!looksLikeJsonObject(input) || !isPlainObject(input)) {\n var description = valueDescription(input);\n if (description === 'an object') {\n // Massage the error if it was an object.\n throw context.createError(message + ' a custom object');\n } else {\n throw context.createError(message + ' ' + description);\n }\n }\n}\n/**\r\n * Helper that calls fromDotSeparatedString() but wraps any error thrown.\r\n */\nfunction fieldPathFromArgument(methodName, path) {\n if (path instanceof field_path_FieldPath) {\n return path._internalPath;\n } else if (typeof path === 'string') {\n return fieldPathFromDotSeparatedString(methodName, path);\n } else {\n var message = 'Field path arguments must be of type string or FieldPath.';\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + methodName + \"() called with invalid data. \" + message);\n }\n}\n/**\r\n * Wraps fromDotSeparatedString with an error message about the method that\r\n * was thrown.\r\n * @param methodName The publicly visible method name\r\n * @param path The dot-separated string form of a field path which will be split\r\n * on dots.\r\n */\nfunction fieldPathFromDotSeparatedString(methodName, path) {\n try {\n return fromDotSeparatedString(path)._internalPath;\n } catch (e) {\n var message = errorMessage(e);\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function \" + methodName + \"() called with invalid data. \" + message);\n }\n}\n/**\r\n * Extracts the message from a caught exception, which should be an Error object\r\n * though JS doesn't guarantee that.\r\n */\nfunction errorMessage(error) {\n return error instanceof Error ? error.message : error.toString();\n}\n// CONCATENATED MODULE: ./src/firestore/api/database.ts\nvar database__typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\nvar database___extends = this && this.__extends || function () {\n var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (b.hasOwnProperty(p)) d[p] = b[p];\n }\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() {\n this.constructor = d;\n }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// The objects that are a part of this API are exposed to third-parties as\n// compiled javascript so we want to flag our private members with a leading\n// underscore to discourage their use.\n// tslint:disable:strip-private-property-underscore\nvar DEFAULT_HOST = 'firestore.googleapis.com';\nvar DEFAULT_SSL = true;\n/**\r\n * A concrete type describing all the values that can be applied via a\r\n * user-supplied firestore.Settings object. This is a separate type so that\r\n * defaults can be supplied and the value can be checked for equality.\r\n */\nvar database_FirestoreSettings = /** @class */function () {\n function FirestoreSettings(settings) {\n if (settings.host === undefined) {\n if (settings.ssl !== undefined) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Can't provide ssl option if host option is not set\");\n }\n this.host = DEFAULT_HOST;\n this.ssl = DEFAULT_SSL;\n } else {\n validateNamedType('settings', 'string', 'host', settings.host);\n this.host = settings.host;\n validateNamedOptionalType('settings', 'boolean', 'ssl', settings.ssl);\n this.ssl = defaulted(settings.ssl, DEFAULT_SSL);\n }\n validateOptionNames('settings', settings, ['host', 'ssl', 'credentials']);\n validateNamedOptionalType('settings', 'object', 'credentials', settings.credentials);\n this.credentials = settings.credentials;\n }\n FirestoreSettings.prototype.equals = function (other) {\n return this.host === other.host && this.ssl === other.ssl && this.credentials === other.credentials;\n };\n return FirestoreSettings;\n}();\nvar FirestoreConfig = /** @class */function () {\n function FirestoreConfig() {}\n return FirestoreConfig;\n}();\n/**\r\n * The root reference to the database.\r\n */\nvar database_Firestore = /** @class */function () {\n function Firestore(databaseIdOrApp) {\n var _this = this;\n this.INTERNAL = {\n delete: function _delete() {\n if (_this._firestoreClient) {\n return _this._firestoreClient.shutdown();\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n }\n };\n var config = new FirestoreConfig();\n if (database__typeof(databaseIdOrApp.options) === 'object') {\n // This is very likely a Firebase app object\n // TODO(b/34177605): Can we somehow use instanceof?\n var app = databaseIdOrApp;\n config.firebaseApp = app;\n config.databaseId = Firestore.databaseIdFromApp(app);\n config.persistenceKey = config.firebaseApp.name;\n config.credentials = new credentials_FirebaseCredentialsProvider(app);\n } else {\n var external_1 = databaseIdOrApp;\n if (!external_1.projectId) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Must provide projectId');\n }\n config.databaseId = new database_info_DatabaseId(external_1.projectId, external_1.database);\n // Use a default persistenceKey that lines up with firebase.app.App.\n config.persistenceKey = '[DEFAULT]';\n config.credentials = new credentials_EmptyCredentialsProvider();\n }\n config.settings = new database_FirestoreSettings({});\n this._config = config;\n }\n Object.defineProperty(Firestore.prototype, \"_databaseId\", {\n get: function get() {\n return this._config.databaseId;\n },\n enumerable: true,\n configurable: true\n });\n Firestore.prototype.settings = function (settingsLiteral) {\n validateExactNumberOfArgs('Firestore.settings', arguments, 1);\n validateArgType('Firestore.settings', 'object', 1, settingsLiteral);\n if (contains(settingsLiteral, 'persistence')) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, '\"persistence\" is now specified with a separate call to ' + 'firestore.enablePersistence().');\n }\n var newSettings = new database_FirestoreSettings(settingsLiteral);\n if (this._firestoreClient && !this._config.settings.equals(newSettings)) {\n throw new FirestoreError(Code.FAILED_PRECONDITION, 'Firestore has already been started and its settings can no longer ' + 'be changed. You can only call settings() before calling any other ' + 'methods on a Firestore object.');\n }\n this._config.settings = newSettings;\n if (newSettings.credentials !== undefined) {\n this._config.credentials = makeCredentialsProvider(newSettings.credentials);\n }\n };\n Firestore.prototype.enablePersistence = function () {\n if (this._firestoreClient) {\n throw new FirestoreError(Code.FAILED_PRECONDITION, 'Firestore has already been started and persistence can no longer ' + 'be enabled. You can only call enablePersistence() before calling ' + 'any other methods on a Firestore object.');\n }\n return this.configureClient( /* persistence= */true);\n };\n Firestore.prototype.ensureClientConfigured = function () {\n if (!this._firestoreClient) {\n this.configureClient( /* persistence= */false);\n }\n return this._firestoreClient;\n };\n Firestore.prototype.configureClient = function (persistence) {\n var _this = this;\n assert(!!this._config.settings.host, 'FirestoreSettings.host cannot be falsey');\n assert(!this._firestoreClient, 'configureClient() called multiple times');\n var databaseInfo = new DatabaseInfo(this._config.databaseId, this._config.persistenceKey, this._config.settings.host, this._config.settings.ssl);\n var preConverter = function preConverter(value) {\n if (value instanceof database_DocumentReference) {\n var thisDb = _this._config.databaseId;\n var otherDb = value.firestore._config.databaseId;\n if (!otherDb.equals(thisDb)) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Document reference is for database ' + (otherDb.projectId + \"/\" + otherDb.database + \" but should be \") + (\"for database \" + thisDb.projectId + \"/\" + thisDb.database));\n }\n return new DocumentKeyReference(_this._config.databaseId, value._key);\n } else {\n return value;\n }\n };\n this._dataConverter = new user_data_converter_UserDataConverter(preConverter);\n this._firestoreClient = new firestore_client_FirestoreClient(platform_PlatformSupport.getPlatform(), databaseInfo, this._config.credentials, new async_queue_AsyncQueue());\n return this._firestoreClient.start(persistence);\n };\n Firestore.databaseIdFromApp = function (app) {\n var options = app.options;\n if (!contains(options, 'projectId')) {\n // TODO(b/62673263): We can safely remove the special handling of\n // 'firestoreId' once alpha testers have upgraded.\n if (contains(options, 'firestoreId')) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, '\"firestoreId\" is now specified as \"projectId\" in ' + 'firebase.initializeApp.');\n }\n throw new FirestoreError(Code.INVALID_ARGUMENT, '\"projectId\" not provided in firebase.initializeApp.');\n }\n if (contains(options, 'firestoreOptions')) {\n // TODO(b/62673263): We can safely remove the special handling of\n // 'firestoreOptions' once alpha testers have upgraded.\n throw new FirestoreError(Code.INVALID_ARGUMENT, '\"firestoreOptions\" values are now specified with ' + 'Firestore.settings()');\n }\n var projectId = options['projectId'];\n if (!projectId || typeof projectId !== 'string') {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'projectId must be a string in firebase.app.App.options');\n }\n return new database_info_DatabaseId(projectId);\n };\n Object.defineProperty(Firestore.prototype, \"app\", {\n get: function get() {\n if (!this._config.firebaseApp) {\n throw new FirestoreError(Code.FAILED_PRECONDITION, \"Firestore was not initialized using the Firebase SDK. 'app' is \" + 'not available');\n }\n return this._config.firebaseApp;\n },\n enumerable: true,\n configurable: true\n });\n Firestore.prototype.collection = function (pathString) {\n validateExactNumberOfArgs('Firestore.collection', arguments, 1);\n validateArgType('Firestore.collection', 'string', 1, pathString);\n if (!pathString) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Must provide a non-empty collection path to collection()');\n }\n this.ensureClientConfigured();\n return new database_CollectionReference(path_ResourcePath.fromString(pathString), this);\n };\n Firestore.prototype.doc = function (pathString) {\n validateExactNumberOfArgs('Firestore.doc', arguments, 1);\n validateArgType('Firestore.doc', 'string', 1, pathString);\n if (!pathString) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Must provide a non-empty document path to doc()');\n }\n this.ensureClientConfigured();\n return database_DocumentReference.forPath(path_ResourcePath.fromString(pathString), this);\n };\n Firestore.prototype.runTransaction = function (updateFunction) {\n var _this = this;\n validateExactNumberOfArgs('Firestore.runTransaction', arguments, 1);\n validateArgType('Firestore.runTransaction', 'function', 1, updateFunction);\n return this.ensureClientConfigured().transaction(function (transaction) {\n return updateFunction(new database_Transaction(_this, transaction));\n });\n };\n Firestore.prototype.batch = function () {\n this.ensureClientConfigured();\n return new database_WriteBatch(this);\n };\n Object.defineProperty(Firestore, \"logLevel\", {\n get: function get() {\n switch (getLogLevel()) {\n case LogLevel.DEBUG:\n return 'debug';\n case LogLevel.ERROR:\n return 'error';\n case LogLevel.SILENT:\n return 'silent';\n default:\n return fail('Unknown log level: ' + getLogLevel());\n }\n },\n enumerable: true,\n configurable: true\n });\n Firestore.setLogLevel = function (level) {\n validateExactNumberOfArgs('Firestore.setLogLevel', arguments, 1);\n validateArgType('Firestore.setLogLevel', 'string', 1, level);\n switch (level) {\n case 'debug':\n setLogLevel(LogLevel.DEBUG);\n break;\n case 'error':\n setLogLevel(LogLevel.ERROR);\n break;\n case 'silent':\n setLogLevel(LogLevel.SILENT);\n break;\n default:\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid log level: ' + level);\n }\n };\n return Firestore;\n}();\n\n/**\r\n * A reference to a transaction.\r\n */\nvar database_Transaction = /** @class */function () {\n function Transaction(_firestore, _transaction) {\n this._firestore = _firestore;\n this._transaction = _transaction;\n }\n Transaction.prototype.get = function (documentRef) {\n var _this = this;\n validateExactNumberOfArgs('Transaction.get', arguments, 1);\n var ref = validateReference('Transaction.get', documentRef, this._firestore);\n return this._transaction.lookup([ref._key]).then(function (docs) {\n if (!docs || docs.length !== 1) {\n return fail('Mismatch in docs returned from document lookup.');\n }\n var doc = docs[0];\n if (doc instanceof document_NoDocument) {\n return new database_DocumentSnapshot(_this._firestore, ref._key, null, false);\n }\n return new database_DocumentSnapshot(_this._firestore, ref._key, doc, false);\n });\n };\n Transaction.prototype.set = function (documentRef, value, options) {\n validateBetweenNumberOfArgs('Transaction.set', arguments, 2, 3);\n var ref = validateReference('Transaction.set', documentRef, this._firestore);\n options = validateSetOptions('Transaction.set', options);\n var parsed = this._firestore._dataConverter.parseSetData('Transaction.set', value, options);\n this._transaction.set(ref._key, parsed);\n return this;\n };\n Transaction.prototype.update = function (documentRef, fieldOrUpdateData, value) {\n var moreFieldsAndValues = [];\n for (var _i = 3; _i < arguments.length; _i++) {\n moreFieldsAndValues[_i - 3] = arguments[_i];\n }\n var ref;\n var parsed;\n if (typeof fieldOrUpdateData === 'string' || fieldOrUpdateData instanceof field_path_FieldPath) {\n validateAtLeastNumberOfArgs('Transaction.update', arguments, 3);\n ref = validateReference('Transaction.update', documentRef, this._firestore);\n parsed = this._firestore._dataConverter.parseUpdateVarargs('Transaction.update', fieldOrUpdateData, value, moreFieldsAndValues);\n } else {\n validateExactNumberOfArgs('Transaction.update', arguments, 2);\n ref = validateReference('Transaction.update', documentRef, this._firestore);\n parsed = this._firestore._dataConverter.parseUpdateData('Transaction.update', fieldOrUpdateData);\n }\n this._transaction.update(ref._key, parsed);\n return this;\n };\n Transaction.prototype.delete = function (documentRef) {\n validateExactNumberOfArgs('Transaction.delete', arguments, 1);\n var ref = validateReference('Transaction.delete', documentRef, this._firestore);\n this._transaction.delete(ref._key);\n return this;\n };\n return Transaction;\n}();\n\nvar database_WriteBatch = /** @class */function () {\n function WriteBatch(_firestore) {\n this._firestore = _firestore;\n this._mutations = [];\n this._committed = false;\n }\n WriteBatch.prototype.set = function (documentRef, value, options) {\n validateBetweenNumberOfArgs('WriteBatch.set', arguments, 2, 3);\n this.verifyNotCommitted();\n var ref = validateReference('WriteBatch.set', documentRef, this._firestore);\n options = validateSetOptions('WriteBatch.set', options);\n var parsed = this._firestore._dataConverter.parseSetData('WriteBatch.set', value, options);\n this._mutations = this._mutations.concat(parsed.toMutations(ref._key, mutation_Precondition.NONE));\n return this;\n };\n WriteBatch.prototype.update = function (documentRef, fieldOrUpdateData, value) {\n var moreFieldsAndValues = [];\n for (var _i = 3; _i < arguments.length; _i++) {\n moreFieldsAndValues[_i - 3] = arguments[_i];\n }\n this.verifyNotCommitted();\n var ref;\n var parsed;\n if (typeof fieldOrUpdateData === 'string' || fieldOrUpdateData instanceof field_path_FieldPath) {\n validateAtLeastNumberOfArgs('WriteBatch.update', arguments, 3);\n ref = validateReference('WriteBatch.update', documentRef, this._firestore);\n parsed = this._firestore._dataConverter.parseUpdateVarargs('WriteBatch.update', fieldOrUpdateData, value, moreFieldsAndValues);\n } else {\n validateExactNumberOfArgs('WriteBatch.update', arguments, 2);\n ref = validateReference('WriteBatch.update', documentRef, this._firestore);\n parsed = this._firestore._dataConverter.parseUpdateData('WriteBatch.update', fieldOrUpdateData);\n }\n this._mutations = this._mutations.concat(parsed.toMutations(ref._key, mutation_Precondition.exists(true)));\n return this;\n };\n WriteBatch.prototype.delete = function (documentRef) {\n validateExactNumberOfArgs('WriteBatch.delete', arguments, 1);\n this.verifyNotCommitted();\n var ref = validateReference('WriteBatch.delete', documentRef, this._firestore);\n this._mutations = this._mutations.concat(new mutation_DeleteMutation(ref._key, mutation_Precondition.NONE));\n return this;\n };\n WriteBatch.prototype.commit = function () {\n this.verifyNotCommitted();\n this._committed = true;\n if (this._mutations.length > 0) {\n return this._firestore.ensureClientConfigured().write(this._mutations);\n } else {\n return utils_promise[\"b\" /* PromiseImpl */].resolve();\n }\n };\n WriteBatch.prototype.verifyNotCommitted = function () {\n if (this._committed) {\n throw new FirestoreError(Code.FAILED_PRECONDITION, 'A write batch can no longer be used after commit() ' + 'has been called.');\n }\n };\n return WriteBatch;\n}();\n\n/**\r\n * A reference to a particular document in a collection in the database.\r\n */\nvar database_DocumentReference = /** @class */function () {\n function DocumentReference(_key, firestore) {\n this._key = _key;\n this.firestore = firestore;\n this._firestoreClient = this.firestore.ensureClientConfigured();\n }\n DocumentReference.forPath = function (path, firestore) {\n if (path.length % 2 !== 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid document reference. Document ' + 'references must have an even number of segments, but ' + (path.canonicalString() + \" has \" + path.length));\n }\n return new DocumentReference(new document_key_DocumentKey(path), firestore);\n };\n Object.defineProperty(DocumentReference.prototype, \"id\", {\n get: function get() {\n return this._key.path.lastSegment();\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DocumentReference.prototype, \"parent\", {\n get: function get() {\n return new database_CollectionReference(this._key.path.popLast(), this.firestore);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DocumentReference.prototype, \"path\", {\n get: function get() {\n return this._key.path.canonicalString();\n },\n enumerable: true,\n configurable: true\n });\n DocumentReference.prototype.collection = function (pathString) {\n validateExactNumberOfArgs('DocumentReference.collection', arguments, 1);\n validateArgType('DocumentReference.collection', 'string', 1, pathString);\n if (!pathString) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Must provide a non-empty collection name to collection()');\n }\n var path = path_ResourcePath.fromString(pathString);\n return new database_CollectionReference(this._key.path.child(path), this.firestore);\n };\n DocumentReference.prototype.set = function (value, options) {\n validateBetweenNumberOfArgs('DocumentReference.set', arguments, 1, 2);\n options = validateSetOptions('DocumentReference.set', options);\n var parsed = this.firestore._dataConverter.parseSetData('DocumentReference.set', value, options);\n return this._firestoreClient.write(parsed.toMutations(this._key, mutation_Precondition.NONE));\n };\n DocumentReference.prototype.update = function (fieldOrUpdateData, value) {\n var moreFieldsAndValues = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n moreFieldsAndValues[_i - 2] = arguments[_i];\n }\n var parsed;\n if (typeof fieldOrUpdateData === 'string' || fieldOrUpdateData instanceof field_path_FieldPath) {\n validateAtLeastNumberOfArgs('DocumentReference.update', arguments, 2);\n parsed = this.firestore._dataConverter.parseUpdateVarargs('DocumentReference.update', fieldOrUpdateData, value, moreFieldsAndValues);\n } else {\n validateExactNumberOfArgs('DocumentReference.update', arguments, 1);\n parsed = this.firestore._dataConverter.parseUpdateData('DocumentReference.update', fieldOrUpdateData);\n }\n return this._firestoreClient.write(parsed.toMutations(this._key, mutation_Precondition.exists(true)));\n };\n DocumentReference.prototype.delete = function () {\n validateExactNumberOfArgs('DocumentReference.delete', arguments, 0);\n return this._firestoreClient.write([new mutation_DeleteMutation(this._key, mutation_Precondition.NONE)]);\n };\n DocumentReference.prototype.onSnapshot = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n validateBetweenNumberOfArgs('DocumentReference.onSnapshot', arguments, 1, 4);\n var options = {\n includeMetadataChanges: false\n };\n var observer;\n var currArg = 0;\n if (database__typeof(args[currArg]) === 'object' && !isPartialObserver(args[currArg])) {\n options = args[currArg];\n validateOptionNames('DocumentReference.onSnapshot', options, ['includeMetadataChanges']);\n validateNamedOptionalType('DocumentReference.onSnapshot', 'boolean', 'includeMetadataChanges', options.includeMetadataChanges);\n currArg++;\n }\n var internalOptions = {\n includeDocumentMetadataChanges: options.includeMetadataChanges,\n includeQueryMetadataChanges: options.includeMetadataChanges\n };\n if (isPartialObserver(args[currArg])) {\n observer = args[currArg];\n } else {\n validateArgType('DocumentReference.onSnapshot', 'function', currArg, args[currArg]);\n validateOptionalArgType('DocumentReference.onSnapshot', 'function', currArg + 1, args[currArg + 1]);\n validateOptionalArgType('DocumentReference.onSnapshot', 'function', currArg + 2, args[currArg + 2]);\n observer = {\n next: args[currArg],\n error: args[currArg + 1],\n complete: args[currArg + 2]\n };\n }\n return this.onSnapshotInternal(internalOptions, observer);\n };\n DocumentReference.prototype.onSnapshotInternal = function (options, observer) {\n var _this = this;\n var errHandler = function errHandler(err) {\n console.error('Uncaught Error in onSnapshot:', err);\n };\n if (observer.error) {\n errHandler = observer.error.bind(observer);\n }\n var asyncObserver = new AsyncObserver({\n next: function next(snapshot) {\n if (observer.next) {\n assert(snapshot.docs.size <= 1, 'Too many documents returned on a document query');\n var doc = snapshot.docs.get(_this._key);\n observer.next(new database_DocumentSnapshot(_this.firestore, _this._key, doc, snapshot.fromCache));\n }\n },\n error: errHandler\n });\n var internalListener = this._firestoreClient.listen(query_Query.atPath(this._key.path), asyncObserver, options);\n return function () {\n asyncObserver.mute();\n _this._firestoreClient.unlisten(internalListener);\n };\n };\n DocumentReference.prototype.get = function () {\n var _this = this;\n validateExactNumberOfArgs('DocumentReference.get', arguments, 0);\n return new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n var unlisten = _this.onSnapshotInternal({\n includeQueryMetadataChanges: true,\n includeDocumentMetadataChanges: true,\n waitForSyncWhenOnline: true\n }, {\n next: function next(snap) {\n // Remove query first before passing event to user to avoid\n // user actions affecting the now stale query.\n unlisten();\n if (!snap.exists && snap.metadata.fromCache) {\n // TODO(dimond): If we're online and the document doesn't\n // exist then we resolve with a doc.exists set to false. If\n // we're offline however, we reject the Promise in this\n // case. Two options: 1) Cache the negative response from\n // the server so we can deliver that even when you're\n // offline 2) Actually reject the Promise in the online case\n // if the document doesn't exist.\n reject(new FirestoreError(Code.ABORTED, 'Failed to get document because the client is ' + 'offline.'));\n } else {\n resolve(snap);\n }\n },\n error: reject\n });\n });\n };\n return DocumentReference;\n}();\n\nvar database_DocumentSnapshot = /** @class */function () {\n function DocumentSnapshot(_firestore, _key, _document, _fromCache) {\n this._firestore = _firestore;\n this._key = _key;\n this._document = _document;\n this._fromCache = _fromCache;\n }\n DocumentSnapshot.prototype.data = function () {\n validateExactNumberOfArgs('DocumentSnapshot.data', arguments, 0);\n if (!this._document) {\n throw new FirestoreError(Code.NOT_FOUND, \"This document doesn't exist. Check doc.exists to make sure \" + 'the document exists before calling doc.data().');\n }\n return this.convertObject(this._document.data);\n };\n DocumentSnapshot.prototype.get = function (fieldPath) {\n validateExactNumberOfArgs('DocumentSnapshot.get', arguments, 1);\n if (!this._document) {\n throw new FirestoreError(Code.NOT_FOUND, \"This document doesn't exist. Check doc.exists to make sure \" + 'the document exists before calling doc.get().');\n }\n var value = this._document.data.field(fieldPathFromArgument('DocumentSnapshot.get', fieldPath));\n return value === undefined ? undefined : this.convertValue(value);\n };\n Object.defineProperty(DocumentSnapshot.prototype, \"id\", {\n get: function get() {\n return this._key.path.lastSegment();\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DocumentSnapshot.prototype, \"ref\", {\n get: function get() {\n return new database_DocumentReference(this._key, this._firestore);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DocumentSnapshot.prototype, \"exists\", {\n get: function get() {\n return this._document !== null;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(DocumentSnapshot.prototype, \"metadata\", {\n get: function get() {\n return {\n hasPendingWrites: this._document !== null && this._document.hasLocalMutations,\n fromCache: this._fromCache\n };\n },\n enumerable: true,\n configurable: true\n });\n DocumentSnapshot.prototype.convertObject = function (data) {\n var _this = this;\n var result = {};\n data.forEach(function (key, value) {\n result[key] = _this.convertValue(value);\n });\n return result;\n };\n DocumentSnapshot.prototype.convertValue = function (value) {\n if (value instanceof field_value_ObjectValue) {\n return this.convertObject(value);\n } else if (value instanceof field_value_ArrayValue) {\n return this.convertArray(value);\n } else if (value instanceof field_value_RefValue) {\n var key = value.value();\n var database = this._firestore.ensureClientConfigured().databaseId();\n if (!value.databaseId.equals(database)) {\n // TODO(b/64130202): Somehow support foreign references.\n log_error(\"Document \" + this._key.path + \" contains a document \" + \"reference within a different database (\" + (value.databaseId.projectId + \"/\" + value.databaseId.database + \") which is not \") + \"supported. It will be treated as a reference in the current \" + (\"database (\" + database.projectId + \"/\" + database.database + \") \") + \"instead.\");\n }\n return new database_DocumentReference(key, this._firestore);\n } else {\n return value.value();\n }\n };\n DocumentSnapshot.prototype.convertArray = function (data) {\n var _this = this;\n return data.internalValue.map(function (value) {\n return _this.convertValue(value);\n });\n };\n return DocumentSnapshot;\n}();\n\nvar database_Query = /** @class */function () {\n function Query(_query, firestore) {\n this._query = _query;\n this.firestore = firestore;\n }\n Query.prototype.where = function (field, opStr, value) {\n validateExactNumberOfArgs('Query.where', arguments, 3);\n validateArgType('Query.where', 'string', 2, opStr);\n validateDefined('Query.where', 3, value);\n var fieldValue;\n var fieldPath = fieldPathFromArgument('Query.where', field);\n if (fieldPath.isKeyField()) {\n if (typeof value === 'string') {\n if (value.indexOf('/') !== -1) {\n // TODO(dimond): Allow slashes once ancestor queries are supported\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Function Query.where() requires its third parameter to be a ' + 'valid document ID if the first parameter is ' + 'FieldPath.documentId(), but it contains a slash.');\n }\n if (value === '') {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Function Query.where() requires its third parameter to be a ' + 'valid document ID if the first parameter is ' + 'FieldPath.documentId(), but it was an empty string.');\n }\n var path = this._query.path.child(new path_ResourcePath([value]));\n assert(path.length % 2 === 0, 'Path should be a document key');\n fieldValue = new field_value_RefValue(this.firestore._databaseId, new document_key_DocumentKey(path));\n } else if (value instanceof database_DocumentReference) {\n var ref = value;\n fieldValue = new field_value_RefValue(this.firestore._databaseId, ref._key);\n } else {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function Query.where() requires its third parameter to be a \" + \"string or a DocumentReference if the first parameter is \" + \"FieldPath.documentId(), but it was: \" + (valueDescription(value) + \".\"));\n }\n } else {\n fieldValue = this.firestore._dataConverter.parseQueryValue('Query.where', value);\n }\n var filter = fieldFilter(fieldPath, query_RelationOp.fromString(opStr), fieldValue);\n this.validateNewFilter(filter);\n return new Query(this._query.addFilter(filter), this.firestore);\n };\n Query.prototype.orderBy = function (field, directionStr) {\n validateBetweenNumberOfArgs('Query.orderBy', arguments, 1, 2);\n validateOptionalArgType('Query.orderBy', 'string', 2, directionStr);\n var direction;\n if (directionStr === undefined || directionStr === 'asc') {\n direction = Direction.ASCENDING;\n } else if (directionStr === 'desc') {\n direction = Direction.DESCENDING;\n } else {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Function Query.orderBy() has unknown direction '\" + directionStr + \"', \" + \"expected 'asc' or 'desc'.\");\n }\n if (this._query.startAt !== null) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid query. You must not call Query.startAt() or ' + 'Query.startAfter() before calling Query.orderBy().');\n }\n if (this._query.endAt !== null) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid query. You must not call Query.endAt() or ' + 'Query.endBefore() before calling Query.orderBy().');\n }\n var fieldPath = fieldPathFromArgument('Query.orderBy', field);\n var orderBy = new query_OrderBy(fieldPath, direction);\n this.validateNewOrderBy(orderBy);\n return new Query(this._query.addOrderBy(orderBy), this.firestore);\n };\n Query.prototype.limit = function (n) {\n validateExactNumberOfArgs('Query.limit', arguments, 1);\n validateArgType('Query.limit', 'number', 1, n);\n if (n <= 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid Query. Query limit (\" + n + \") is invalid. Limit must be \" + 'positive.');\n }\n return new Query(this._query.withLimit(n), this.firestore);\n };\n Query.prototype.startAt = function (docOrField) {\n var fields = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n fields[_i - 1] = arguments[_i];\n }\n validateAtLeastNumberOfArgs('Query.startAt', arguments, 1);\n var bound = this.boundFromDocOrFields('Query.startAt', docOrField, fields,\n /*before=*/true);\n return new Query(this._query.withStartAt(bound), this.firestore);\n };\n Query.prototype.startAfter = function (docOrField) {\n var fields = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n fields[_i - 1] = arguments[_i];\n }\n validateAtLeastNumberOfArgs('Query.startAfter', arguments, 1);\n var bound = this.boundFromDocOrFields('Query.startAfter', docOrField, fields,\n /*before=*/false);\n return new Query(this._query.withStartAt(bound), this.firestore);\n };\n Query.prototype.endBefore = function (docOrField) {\n var fields = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n fields[_i - 1] = arguments[_i];\n }\n validateAtLeastNumberOfArgs('Query.endBefore', arguments, 1);\n var bound = this.boundFromDocOrFields('Query.endBefore', docOrField, fields,\n /*before=*/true);\n return new Query(this._query.withEndAt(bound), this.firestore);\n };\n Query.prototype.endAt = function (docOrField) {\n var fields = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n fields[_i - 1] = arguments[_i];\n }\n validateAtLeastNumberOfArgs('Query.endAt', arguments, 1);\n var bound = this.boundFromDocOrFields('Query.endAt', docOrField, fields,\n /*before=*/false);\n return new Query(this._query.withEndAt(bound), this.firestore);\n };\n /** Helper function to create a bound from a document or fields */\n Query.prototype.boundFromDocOrFields = function (methodName, docOrField, fields, before) {\n validateDefined(methodName, 1, docOrField);\n if (docOrField instanceof database_DocumentSnapshot) {\n if (fields.length > 0) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Too many arguments provided to \" + methodName + \"().\");\n }\n var snap = docOrField;\n if (!snap.exists) {\n throw new FirestoreError(Code.NOT_FOUND, \"Can't use a DocumentSnapshot that doesn't exist for \" + (methodName + \"().\"));\n }\n return this.boundFromDocument(methodName, snap._document, before);\n } else {\n var allFields = [docOrField].concat(fields);\n return this.boundFromFields(methodName, allFields, before);\n }\n };\n /**\r\n * Create a Bound from a query and a document.\r\n *\r\n * Note that the Bound will always include the key of the document\r\n * and so only the provided document will compare equal to the returned\r\n * position.\r\n *\r\n * Will throw if the document does not contain all fields of the order by\r\n * of the query.\r\n */\n Query.prototype.boundFromDocument = function (methodName, doc, before) {\n var components = [];\n // Because people expect to continue/end a query at the exact document\n // provided, we need to use the implicit sort order rather than the explicit\n // sort order, because it's guaranteed to contain the document key. That way\n // the position becomes unambiguous and the query continues/ends exactly at\n // the provided document. Without the key (by using the explicit sort\n // orders), multiple documents could match the position, yielding duplicate\n // results.\n for (var _i = 0, _a = this._query.orderBy; _i < _a.length; _i++) {\n var orderBy = _a[_i];\n if (orderBy.field.isKeyField()) {\n components.push(new field_value_RefValue(this.firestore._databaseId, doc.key));\n } else {\n var value = doc.field(orderBy.field);\n if (value !== undefined) {\n components.push(value);\n } else {\n var field = orderBy.field.canonicalString();\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid query. You are trying to start or end a query using a \" + (\"document for which the field '\" + field + \"' (used as the \") + \"orderBy) does not exist.\");\n }\n }\n }\n return new query_Bound(components, before);\n };\n /**\r\n * Converts a list of field values to a Bound for the given query.\r\n */\n Query.prototype.boundFromFields = function (methodName, values, before) {\n // Use explicit order by's because it has to match the query the user made\n var orderBy = this._query.explicitOrderBy;\n if (values.length > orderBy.length) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Too many arguments provided to \" + methodName + \"(). \" + \"The number of arguments must be less than or equal to the \" + \"number of Query.orderBy() clauses\");\n }\n var components = [];\n for (var i = 0; i < values.length; i++) {\n var rawValue = values[i];\n var orderByComponent = orderBy[i];\n if (orderByComponent.field.isKeyField()) {\n if (typeof rawValue !== 'string') {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid query. Expected a string for document ID in \" + (methodName + \"(), but got a \" + (typeof rawValue === 'undefined' ? 'undefined' : database__typeof(rawValue))));\n }\n if (rawValue.indexOf('/') !== -1) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid query. Document ID '\" + rawValue + \"' contains a slash in \" + (methodName + \"()\"));\n }\n var key = new document_key_DocumentKey(this._query.path.child(rawValue));\n components.push(new field_value_RefValue(this.firestore._databaseId, key));\n } else {\n var wrapped = this.firestore._dataConverter.parseQueryValue(methodName, rawValue);\n components.push(wrapped);\n }\n }\n return new query_Bound(components, before);\n };\n Query.prototype.onSnapshot = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n validateBetweenNumberOfArgs('Query.onSnapshot', arguments, 1, 4);\n var options = {};\n var observer;\n var currArg = 0;\n if (database__typeof(args[currArg]) === 'object' && !isPartialObserver(args[currArg])) {\n options = args[currArg];\n validateOptionNames('Query.onSnapshot', options, ['includeQueryMetadataChanges', 'includeDocumentMetadataChanges']);\n validateNamedOptionalType('Query.onSnapshot', 'boolean', 'includeDocumentMetadataChanges', options.includeDocumentMetadataChanges);\n validateNamedOptionalType('Query.onSnapshot', 'boolean', 'includeQueryMetadataChanges', options.includeQueryMetadataChanges);\n currArg++;\n }\n if (isPartialObserver(args[currArg])) {\n observer = args[currArg];\n } else {\n validateArgType('Query.onSnapshot', 'function', currArg, args[currArg]);\n validateOptionalArgType('Query.onSnapshot', 'function', currArg + 1, args[currArg + 1]);\n validateOptionalArgType('Query.onSnapshot', 'function', currArg + 2, args[currArg + 2]);\n observer = {\n next: args[currArg],\n error: args[currArg + 1],\n complete: args[currArg + 2]\n };\n }\n return this.onSnapshotInternal(options, observer);\n };\n Query.prototype.onSnapshotInternal = function (options, observer) {\n var _this = this;\n var errHandler = function errHandler(err) {\n console.error('Uncaught Error in onSnapshot:', err);\n };\n if (observer.error) {\n errHandler = observer.error.bind(observer);\n }\n var asyncObserver = new AsyncObserver({\n next: function next(result) {\n if (observer.next) {\n observer.next(new database_QuerySnapshot(_this.firestore, _this._query, result));\n }\n },\n error: errHandler\n });\n var firestoreClient = this.firestore.ensureClientConfigured();\n var internalListener = firestoreClient.listen(this._query, asyncObserver, options);\n return function () {\n asyncObserver.mute();\n firestoreClient.unlisten(internalListener);\n };\n };\n Query.prototype.get = function () {\n var _this = this;\n validateExactNumberOfArgs('Query.get', arguments, 0);\n return new utils_promise[\"b\" /* PromiseImpl */](function (resolve, reject) {\n var unlisten = _this.onSnapshotInternal({\n includeDocumentMetadataChanges: false,\n includeQueryMetadataChanges: true,\n waitForSyncWhenOnline: true\n }, {\n next: function next(result) {\n // Remove query first before passing event to user to avoid\n // user actions affecting the now stale query.\n unlisten();\n resolve(result);\n },\n error: reject\n });\n });\n };\n Query.prototype.validateNewFilter = function (filter) {\n if (filter instanceof query_RelationFilter && filter.isInequality()) {\n var existingField = this._query.getInequalityFilterField();\n if (existingField !== null && !existingField.equals(filter.field)) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid query. All where filters with an inequality' + ' (<, <=, >, or >=) must be on the same field. But you have' + (\" inequality filters on '\" + existingField.toString() + \"'\") + (\" and '\" + filter.field.toString() + \"'\"));\n }\n var firstOrderByField = this._query.getFirstOrderByField();\n if (firstOrderByField !== null) {\n this.validateOrderByAndInequalityMatch(filter.field, firstOrderByField);\n }\n }\n };\n Query.prototype.validateNewOrderBy = function (orderBy) {\n if (this._query.getFirstOrderByField() === null) {\n // This is the first order by. It must match any inequality.\n var inequalityField = this._query.getInequalityFilterField();\n if (inequalityField !== null) {\n this.validateOrderByAndInequalityMatch(inequalityField, orderBy.field);\n }\n }\n };\n Query.prototype.validateOrderByAndInequalityMatch = function (inequality, orderBy) {\n if (!orderBy.equals(inequality)) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, \"Invalid query. You have a where filter with an inequality \" + (\"(<, <=, >, or >=) on field '\" + inequality.toString() + \"' \") + (\"and so you must also use '\" + inequality.toString() + \"' \") + \"as your first Query.orderBy(), but your first Query.orderBy() \" + (\"is on field '\" + orderBy.toString() + \"' instead.\"));\n }\n };\n return Query;\n}();\n\nvar database_QuerySnapshot = /** @class */function () {\n function QuerySnapshot(_firestore, _originalQuery, _snapshot) {\n this._firestore = _firestore;\n this._originalQuery = _originalQuery;\n this._snapshot = _snapshot;\n this._cachedChanges = null;\n this.metadata = {\n fromCache: _snapshot.fromCache,\n hasPendingWrites: _snapshot.hasPendingWrites\n };\n }\n Object.defineProperty(QuerySnapshot.prototype, \"docs\", {\n get: function get() {\n var result = [];\n this.forEach(function (doc) {\n return result.push(doc);\n });\n return result;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(QuerySnapshot.prototype, \"empty\", {\n get: function get() {\n return this._snapshot.docs.isEmpty();\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(QuerySnapshot.prototype, \"size\", {\n get: function get() {\n return this._snapshot.docs.size;\n },\n enumerable: true,\n configurable: true\n });\n QuerySnapshot.prototype.forEach = function (callback, thisArg) {\n var _this = this;\n validateBetweenNumberOfArgs('QuerySnapshot.forEach', arguments, 1, 2);\n validateArgType('QuerySnapshot.forEach', 'function', 1, callback);\n this._snapshot.docs.forEach(function (doc) {\n callback.call(thisArg, _this.convertToDocumentImpl(doc));\n });\n };\n Object.defineProperty(QuerySnapshot.prototype, \"query\", {\n get: function get() {\n return new database_Query(this._originalQuery, this._firestore);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(QuerySnapshot.prototype, \"docChanges\", {\n get: function get() {\n if (!this._cachedChanges) {\n this._cachedChanges = changesFromSnapshot(this._firestore, this._snapshot);\n }\n return this._cachedChanges;\n },\n enumerable: true,\n configurable: true\n });\n QuerySnapshot.prototype.convertToDocumentImpl = function (doc) {\n return new database_DocumentSnapshot(this._firestore, doc.key, doc, this.metadata.fromCache);\n };\n return QuerySnapshot;\n}();\n\nvar database_CollectionReference = /** @class */function (_super) {\n database___extends(CollectionReference, _super);\n function CollectionReference(path, firestore) {\n var _this = _super.call(this, query_Query.atPath(path), firestore) || this;\n if (path.length % 2 !== 1) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Invalid collection reference. Collection ' + 'references must have an odd number of segments, but ' + (path.canonicalString() + \" has \" + path.length));\n }\n return _this;\n }\n Object.defineProperty(CollectionReference.prototype, \"id\", {\n get: function get() {\n return this._query.path.lastSegment();\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(CollectionReference.prototype, \"parent\", {\n get: function get() {\n var parentPath = this._query.path.popLast();\n if (parentPath.isEmpty()) {\n return null;\n } else {\n return new database_DocumentReference(new document_key_DocumentKey(parentPath), this.firestore);\n }\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(CollectionReference.prototype, \"path\", {\n get: function get() {\n return this._query.path.canonicalString();\n },\n enumerable: true,\n configurable: true\n });\n CollectionReference.prototype.doc = function (pathString) {\n validateBetweenNumberOfArgs('CollectionReference.doc', arguments, 0, 1);\n validateOptionalArgType('CollectionReference.doc', 'string', 1, pathString);\n if (pathString === undefined) {\n pathString = misc_AutoId.newId();\n }\n if (typeof pathString !== 'string' || pathString === '') {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Document path must be a non-empty string');\n }\n var path = path_ResourcePath.fromString(pathString);\n return database_DocumentReference.forPath(this._query.path.child(path), this.firestore);\n };\n CollectionReference.prototype.add = function (value) {\n validateExactNumberOfArgs('CollectionReference.add', arguments, 1);\n validateArgType('CollectionReference.add', 'object', 1, value);\n var docRef = this.doc();\n return docRef.set(value).then(function () {\n return docRef;\n });\n };\n return CollectionReference;\n}(database_Query);\n\nfunction validateSetOptions(methodName, options) {\n if (options === undefined) {\n return {\n merge: false\n };\n }\n validateOptionNames(methodName, options, ['merge']);\n validateNamedOptionalType(methodName, 'boolean', 'merge', options.merge);\n return options;\n}\nfunction validateReference(methodName, documentRef, firestore) {\n if (!(documentRef instanceof database_DocumentReference)) {\n throw invalidClassError(methodName, 'DocumentReference', 1, documentRef);\n } else if (documentRef.firestore !== firestore) {\n throw new FirestoreError(Code.INVALID_ARGUMENT, 'Provided document reference is from a different Firestore instance.');\n } else {\n return documentRef;\n }\n}\n/**\r\n * Calculates the array of firestore.DocumentChange's for a given ViewSnapshot.\r\n *\r\n * Exported for testing.\r\n */\nfunction changesFromSnapshot(firestore, snapshot) {\n if (snapshot.oldDocs.isEmpty()) {\n // Special case the first snapshot because index calculation is easy and\n // fast\n var lastDoc_1;\n var index_1 = 0;\n return snapshot.docChanges.map(function (change) {\n var doc = new database_DocumentSnapshot(firestore, change.doc.key, change.doc, snapshot.fromCache);\n assert(change.type === ChangeType.Added, 'Invalid event type for first snapshot');\n assert(!lastDoc_1 || snapshot.query.docComparator(lastDoc_1, change.doc) < 0, 'Got added events in wrong order');\n lastDoc_1 = change.doc;\n return {\n type: 'added',\n doc: doc,\n oldIndex: -1,\n newIndex: index_1++\n };\n });\n } else {\n // A DocumentSet that is updated incrementally as changes are applied to use\n // to lookup the index of a document.\n var indexTracker_1 = snapshot.oldDocs;\n return snapshot.docChanges.map(function (change) {\n var doc = new database_DocumentSnapshot(firestore, change.doc.key, change.doc, snapshot.fromCache);\n var oldIndex = -1;\n var newIndex = -1;\n if (change.type !== ChangeType.Added) {\n oldIndex = indexTracker_1.indexOf(change.doc.key);\n assert(oldIndex >= 0, 'Index for document not found');\n indexTracker_1 = indexTracker_1.delete(change.doc.key);\n }\n if (change.type !== ChangeType.Removed) {\n indexTracker_1 = indexTracker_1.add(change.doc);\n newIndex = indexTracker_1.indexOf(change.doc.key);\n }\n return { type: resultChangeType(change.type), doc: doc, oldIndex: oldIndex, newIndex: newIndex };\n });\n }\n}\nfunction resultChangeType(type) {\n switch (type) {\n case ChangeType.Added:\n return 'added';\n case ChangeType.Modified:\n case ChangeType.Metadata:\n return 'modified';\n case ChangeType.Removed:\n return 'removed';\n default:\n return fail('Unknown change type: ' + type);\n }\n}\n// Export the classes with a private constructor (it will fail if invoked\n// at runtime). Note that this still allows instanceof checks.\n// We're treating the variables as class names, so disable checking for lower\n// case variable names.\n// tslint:disable:variable-name\nvar PublicFirestore = makeConstructorPrivate(database_Firestore, 'Use firebase.firestore() instead.');\nvar PublicTransaction = makeConstructorPrivate(database_Transaction, 'Use firebase.firestore().runTransaction() instead.');\nvar PublicWriteBatch = makeConstructorPrivate(database_WriteBatch, 'Use firebase.firestore().batch() instead.');\nvar PublicDocumentReference = makeConstructorPrivate(database_DocumentReference, 'Use firebase.firestore().doc() instead.');\nvar PublicDocumentSnapshot = makeConstructorPrivate(database_DocumentSnapshot);\nvar PublicQuery = makeConstructorPrivate(database_Query);\nvar PublicQuerySnapshot = makeConstructorPrivate(database_QuerySnapshot);\nvar PublicCollectionReference = makeConstructorPrivate(database_CollectionReference, 'Use firebase.firestore().collection() instead.');\n// tslint:enable:variable-name\n// CONCATENATED MODULE: ./src/firestore/platform/config.ts\n/**\r\n * Copyright 2017 Google Inc.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\n\n\n\n\n\n\nvar firestoreNamespace = {\n Firestore: PublicFirestore,\n GeoPoint: geo_point_GeoPoint,\n Blob: PublicBlob,\n Transaction: PublicTransaction,\n WriteBatch: PublicWriteBatch,\n DocumentReference: PublicDocumentReference,\n DocumentSnapshot: PublicDocumentSnapshot,\n Query: PublicQuery,\n QuerySnapshot: PublicQuerySnapshot,\n CollectionReference: PublicCollectionReference,\n FieldPath: field_path_FieldPath,\n FieldValue: PublicFieldValue,\n setLogLevel: database_Firestore.setLogLevel\n};\n/**\r\n * Configures Firestore as part of the Firebase SDK by calling registerService.\r\n */\nfunction configureForFirebase(firebase) {\n firebase.INTERNAL.registerService('firestore', function (app) {\n return new database_Firestore(app);\n }, shallowCopy(firestoreNamespace));\n}\n/**\r\n * Exports the Firestore namespace into the provided `exportObject` object under\r\n * the key 'firestore'. This is used for wrapped binary that exposes Firestore\r\n * as a goog module.\r\n */\nfunction configureForStandalone(exportObject) {\n var copiedNamespace = shallowCopy(firestoreNamespace);\n // Unlike the use with Firebase, the standalone allows the use of the\n // constructor, so export it's internal class\n copiedNamespace['Firestore'] = database_Firestore;\n exportObject['firestore'] = copiedNamespace;\n}\n// CONCATENATED MODULE: ./src/firestore.ts\n/* harmony export (immutable) */ __webpack_exports__[\"registerFirestore\"] = registerFirestore;\n/**\r\n* Copyright 2017 Google Inc.\r\n*\r\n* Licensed under the Apache License, Version 2.0 (the \"License\");\r\n* you may not use this file except in compliance with the License.\r\n* You may obtain a copy of the License at\r\n*\r\n* http://www.apache.org/licenses/LICENSE-2.0\r\n*\r\n* Unless required by applicable law or agreed to in writing, software\r\n* distributed under the License is distributed on an \"AS IS\" BASIS,\r\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n* See the License for the specific language governing permissions and\r\n* limitations under the License.\r\n*/\n\n\n\nfunction registerFirestore(instance) {\n configureForFirebase(instance);\n}\nregisterFirestore(src_app[\"default\"]);\n\n/***/ }),\n\n/***/ 67:\n/***/ (function(module, exports, __webpack_require__) {\n\n(function() {var g,goog=goog||{},k=this;function l(a){return\"string\"==typeof a}function aa(){}\nfunction ba(a){var b=typeof a;if(\"object\"==b)if(a){if(a instanceof Array)return\"array\";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(\"[object Window]\"==c)return\"object\";if(\"[object Array]\"==c||\"number\"==typeof a.length&&\"undefined\"!=typeof a.splice&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"splice\"))return\"array\";if(\"[object Function]\"==c||\"undefined\"!=typeof a.call&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"call\"))return\"function\"}else return\"null\";\nelse if(\"function\"==b&&\"undefined\"==typeof a.call)return\"object\";return b}function n(a){return\"array\"==ba(a)}function ca(a){var b=ba(a);return\"array\"==b||\"object\"==b&&\"number\"==typeof a.length}function da(a){return\"function\"==ba(a)}function p(a){var b=typeof a;return\"object\"==b&&null!=a||\"function\"==b}var q=\"closure_uid_\"+(1E9*Math.random()>>>0),ea=0;function fa(a,b,c){return a.call.apply(a.bind,arguments)}\nfunction ha(a,b,c){if(!a)throw Error();if(2b?1:0};function na(a,b){b.unshift(a);ja.call(this,ka.apply(null,b));b.shift()}u(na,ja);na.prototype.name=\"AssertionError\";function oa(a,b){throw new na(\"Failure\"+(a?\": \"+a:\"\"),Array.prototype.slice.call(arguments,1));};function w(){0!=qa&&(ra[this[q]||(this[q]=++ea)]=this);this.i=this.i;this.v=this.v}var qa=0,ra={};w.prototype.i=!1;w.prototype.Y=function(){if(!this.i&&(this.i=!0,this.w(),0!=qa)){var a=this[q]||(this[q]=++ea);delete ra[a]}};w.prototype.w=function(){if(this.v)for(;this.v.length;)this.v.shift()()};var sa=Array.prototype.indexOf?function(a,b,c){return Array.prototype.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(l(a))return l(b)&&1==b.length?a.indexOf(b,c):-1;for(;cb?null:l(a)?a.charAt(b):a[b]}function wa(a){if(!n(a))for(var b=a.length-1;0<=b;b--)delete a[b];a.length=0}function xa(a){return Array.prototype.concat.apply([],arguments)}function ya(a){var b=a.length;if(0parseFloat(Qa)){Pa=String(Ta);break a}}Pa=Qa}var Ja={};\nfunction Ua(a){return Ia(a,function(){for(var b=0,c=la(String(Pa)).split(\".\"),d=la(String(a)).split(\".\"),e=Math.max(c.length,d.length),f=0;0==b&&f=a.keyCode)a.keyCode=-1}catch(b){}};var cb=\"closure_listenable_\"+(1E6*Math.random()|0);function db(a){return!(!a||!a[cb])}var eb=0;function fb(a,b,c,d,e){this.listener=a;this.a=null;this.src=b;this.type=c;this.capture=!!d;this.da=e;this.key=++eb;this.X=this.ba=!1}function gb(a){a.X=!0;a.listener=null;a.a=null;a.src=null;a.da=null};function hb(a){this.src=a;this.a={};this.b=0}function ib(a,b,c,d,e,f){var h=b.toString();b=a.a[h];b||(b=a.a[h]=[],a.b++);var m=jb(b,c,e,f);-1d.keyCode||void 0!=d.returnValue)){a:{var e=!1;if(0==d.keyCode)try{d.keyCode=-1;break a}catch(h){e=!0}if(e||void 0==d.returnValue)d.returnValue=!0}d=[];for(e=b.a;e;e=e.parentNode)d.push(e);a=a.type;for(e=d.length-1;0<=e;e--){b.a=d[e];var f=zb(d[e],a,!0,b);c=c&&f}for(e=0;e>>0);function rb(a){if(da(a))return a;a[Bb]||(a[Bb]=function(b){return a.handleEvent(b)});return a[Bb]};function B(){w.call(this);this.c=new hb(this);this.P=this;this.J=null}u(B,w);B.prototype[cb]=!0;g=B.prototype;g.addEventListener=function(a,b,c,d){pb(this,a,b,c,d)};g.removeEventListener=function(a,b,c,d){xb(this,a,b,c,d)};\ng.dispatchEvent=function(a){var b,c=this.J;if(c)for(b=[];c;c=c.J)b.push(c);c=this.P;var d=a.type||a;if(l(a))a=new A(a,c);else if(a instanceof A)a.target=a.target||c;else{var e=a;a=new A(d,c);Ga(a,e)}e=!0;if(b)for(var f=b.length-1;0<=f;f--){var h=a.a=b[f];e=Cb(h,d,!0,a)&&e}h=a.a=c;e=Cb(h,d,!0,a)&&e;e=Cb(h,d,!1,a)&&e;if(b)for(f=0;f=lc(this).value)for(da(b)&&(b=b()),a=new dc(a,String(b),this.f),c&&(a.a=c),c=\"log:\"+a.b,(a=k.console)&&a.timeStamp&&a.timeStamp(c),(a=k.msWriteProfilerMark)&&a(c),c=this;c;)c=c.a};function F(a,b){a.log(gc,b,void 0)}function G(a,b){a.log(hc,b,void 0)}var mc={},nc=null;\nfunction oc(a){nc||(nc=new fc(\"\"),mc[\"\"]=nc,nc.c=jc);var b;if(!(b=mc[a])){b=new fc(a);var c=a.lastIndexOf(\".\"),d=a.substr(c+1);c=oc(a.substr(0,c));c.b||(c.b={});c.b[d]=b;b.a=c;mc[a]=b}return b};function pc(a,b){a&&a.log(ic,b,void 0)}function H(a,b){a&&a.log(kc,b,void 0)};function qc(){this.a=oc(\"goog.labs.net.webChannel.WebChannelDebug\")}function rc(a,b,c,d){if(c)try{var e=JSON.parse(c);if(e)for(var f=0;fh.length)){var m=h[1];if(n(m)&&!(1>m.length)){var v=m[0];if(\"noop\"!=v&&\"stop\"!=v&&\"close\"!=v)for(var Ra=1;Rab||3==b&&!Ka&&!this.a.U())){this.s||4!=b||7==c||uc();Rc(this);var d=this.a.V();this.v=d;var e=this.a.U();e||I(this.b,\"No response text for uri \"+this.g+\" status \"+d);this.c=200==d;I(this.b,\"XMLHTTP RESP (\"+this.f+\") [ attempt \"+this.S+\"]: \"+this.j+\"\\n\"+this.g+\"\\n\"+b+\" \"+d);if(this.c)this.J?(Sc(this,b,e),Ka&&this.c&&3==b&&(this.M.$(this.F,\"tick\",this.fb),this.F.start())):(rc(this.b,this.f,e,null),Tc(this,e)),4==b&&Uc(this),this.c&&\n!this.s&&(4==b?this.m.wa(this):(this.c=!1,Pc(this)));else{if(400==d&&0b.length)return Kc;b=b.substr(d,c);a.C=d+c;return b}g.cancel=function(){this.s=!0;Uc(this)};function Pc(a){a.T=t()+a.P;Xc(a,a.P)}function Xc(a,b){if(null!=a.o)throw Error(\"WatchDog timer not null\");a.o=xc(r(a.eb,a),b)}function Rc(a){a.o&&(k.clearTimeout(a.o),a.o=null)}\ng.eb=function(){this.o=null;var a=t();if(0<=a-this.T)this.c&&(a=this.b.a)&&F(a,\"Received watchdog timeout even though request loaded successfully\"),I(this.b,\"TIMEOUT: \"+this.g),2!=this.I&&(uc(),K()),Uc(this),this.i=2,Vc(this);else{var b=this.b.a;b&&G(b,\"WatchDog timer called too early\");Xc(this,this.T-a)}};function Vc(a){a.m.Ka()||a.s||a.m.wa(a)}function Uc(a){Rc(a);var b=a.G;b&&\"function\"==typeof b.Y&&b.Y();a.G=null;Yb(a.F);cc(a.M);a.a&&(b=a.a,a.a=null,b.abort(),b.Y())}\nfunction Tc(a,b){try{a.m.Na(a,b),uc()}catch(c){sc(a.b,c,\"Error in httprequest callback\")}};function Yc(a){if(a.A&&\"function\"==typeof a.A)return a.A();if(l(a))return a.split(\"\");if(ca(a)){for(var b=[],c=a.length,d=0;d2*a.c&&$c(a),!0):!1}function $c(a){if(a.c!=a.a.length){for(var b=0,c=0;bb)throw Error(\"Bad port number \"+b);a.i=b}else a.i=null}function hd(a,b,c){b instanceof kd?(a.c=b,qd(a.c,a.h)):(c||(b=ld(b,rd)),a.c=new kd(b,0,a.h))}\nfunction R(a,b,c){a.c.set(b,c)}function Qc(a,b,c){n(c)||(c=[String(c)]);sd(a.c,b,c)}function Mc(a){R(a,\"zx\",Math.floor(2147483648*Math.random()).toString(36)+Math.abs(Math.floor(2147483648*Math.random())^t()).toString(36));return a}function td(a){return a instanceof Q?M(a):new Q(a,void 0)}function ud(a,b,c,d){var e=new Q(null,void 0);a&&ed(e,a);b&&fd(e,b);c&&gd(e,c);d&&(e.a=d);return e}function jd(a,b){return a?b?decodeURI(a.replace(/%25/g,\"%2525\")):decodeURIComponent(a):\"\"}\nfunction ld(a,b,c){return l(a)?(a=encodeURI(a).replace(b,vd),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,\"%$1\")),a):null}function vd(a){a=a.charCodeAt(0);return\"%\"+(a>>4&15).toString(16)+(a&15).toString(16)}var md=/[#\\/\\?@]/g,od=/[\\#\\?:]/g,nd=/[\\#\\?]/g,rd=/[\\#\\?@]/g,pd=/#/g;function kd(a,b,c){this.b=this.a=null;this.c=a||null;this.f=!!c}\nfunction S(a){a.a||(a.a=new O,a.b=0,a.c&&dd(a.c,function(b,c){b=decodeURIComponent(b.replace(/\\+/g,\" \"));S(a);a.c=null;b=wd(a,b);var d=a.a.get(b);d||a.a.set(b,d=[]);d.push(c);a.b+=1}))}g=kd.prototype;g.u=function(){S(this);return this.b};function xd(a,b){S(a);b=wd(a,b);P(a.a.b,b)&&(a.c=null,a.b-=a.a.get(b).length,bd(a.a,b))}function yd(a,b){S(a);b=wd(a,b);return P(a.a.b,b)}g.forEach=function(a,b){S(this);this.a.forEach(function(c,d){ta(c,function(c){a.call(b,c,d,this)},this)},this)};\ng.O=function(){S(this);for(var a=this.a.A(),b=this.a.O(),c=[],d=0;d=a.c:!1}function Td(a,b){return a.b?a.b==b:a.a?a.a.contains(b):!1}function Rd(a,b){a.a?a.a.a.set(T(b),b):a.b=b}\nOd.prototype.cancel=function(){this.b?(this.b.cancel(),this.b=null):this.a&&0!=this.a.a.c&&(ta(this.a.A(),function(a){a.cancel()}),ad(this.a.a))};function Ud(a,b){this.a=a;this.b=b};function Vd(a,b){this.a=a;this.b=b}Vd.prototype.stringify=function(a){return k.JSON.stringify(a,this.a)};Vd.prototype.parse=function(a){return k.JSON.parse(a,this.b)};function Wd(){this.a=new Vd}function Xd(a,b,c){var d=c||\"\";try{Zc(a,function(a,c){var e=a;p(a)&&(e=Fb(a));b.push(d+c+\"=\"+encodeURIComponent(e))})}catch(e){throw b.push(d+\"type=\"+encodeURIComponent(\"_badmap\")),e;}};function Yd(a,b){var c=new qc;I(c,\"TestLoadImage: loading \"+a);var d=new Image;d.onload=ia(Zd,c,d,\"TestLoadImage: loaded\",!0,b);d.onerror=ia(Zd,c,d,\"TestLoadImage: error\",!1,b);d.onabort=ia(Zd,c,d,\"TestLoadImage: abort\",!1,b);d.ontimeout=ia(Zd,c,d,\"TestLoadImage: timeout\",!1,b);k.setTimeout(function(){if(d.ontimeout)d.ontimeout()},1E4);d.src=a}function Zd(a,b,c,d,e){try{I(a,c),b.onload=null,b.onerror=null,b.onabort=null,b.ontimeout=null,e(d)}catch(f){sc(a,f)}};function U(a){B.call(this);this.headers=new O;this.G=a||null;this.f=!1;this.F=this.a=null;this.M=this.s=\"\";this.j=0;this.g=\"\";this.h=this.I=this.o=this.H=!1;this.l=0;this.B=null;this.N=$d;this.C=this.m=!1}u(U,B);var $d=\"\";U.prototype.b=oc(\"goog.net.XhrIo\");var ae=/^https?$/i,be=[\"POST\",\"PUT\"];g=U.prototype;\ng.ta=function(a,b,c,d){if(this.a)throw Error(\"[goog.net.XhrIo] Object is active with another request=\"+this.s+\"; newUri=\"+a);b=b?b.toUpperCase():\"GET\";this.s=a;this.g=\"\";this.j=0;this.M=b;this.H=!1;this.f=!0;this.a=this.G?Fc(this.G):Fc(Dc);this.F=this.G?Bc(this.G):Bc(Dc);this.a.onreadystatechange=r(this.Ma,this);try{H(this.b,V(this,\"Opening Xhr\")),this.I=!0,this.a.open(b,String(a),!0),this.I=!1}catch(f){H(this.b,V(this,\"Error opening Xhr: \"+f.message));ce(this,f);return}a=c||\"\";var e=new O(this.headers);\nd&&Zc(d,function(a,b){e.set(b,a)});d=ua(e.O());c=k.FormData&&a instanceof k.FormData;!(0<=sa(be,b))||d||c||e.set(\"Content-Type\",\"application/x-www-form-urlencoded;charset=utf-8\");e.forEach(function(a,b){this.a.setRequestHeader(b,a)},this);this.N&&(this.a.responseType=this.N);\"withCredentials\"in this.a&&this.a.withCredentials!==this.m&&(this.a.withCredentials=this.m);try{de(this),0c&&(c=a.length);d=a.indexOf(\"?\");if(0>d||d>c){d=c;var e=\"\"}else e=a.substring(d+1,c);a=[a.substr(0,d),e,a.substr(c)];c=a[1];a[1]=b?c?c+\"&\"+b:b:c;a=a[0]+(a[1]?\"?\"+a[1]:\"\")+a[2]}return a}R(a,b,c);return a};function ke(a,b,c){this.za=b||0;this.Ba=0;this.h=[];this.l=[];this.a=new qc;this.J=c||new Md;this.ia=this.ya=this.H=this.ja=this.b=this.N=this.j=this.ha=this.f=this.P=this.i=null;this.Va=this.I=0;this.ka=this.C=this.s=this.m=this.o=this.c=null;this.v=this.Aa=this.S=-1;this.ga=this.B=this.G=0;this.T=a&&a.supportsCrossDomainXhr||!1;this.M=\"\";this.g=new Od(a&&a.concurrentRequestLimit);this.la=new Wd;this.F=a&&void 0!==a.backgroundChannelTest?a.backgroundChannelTest:!0;this.Ua=a&&a.fastHandshake||!1}\ng=ke.prototype;g.oa=8;g.D=1;function le(a){I(a.a,\"disconnect()\");me(a);if(3==a.D){var b=a.I++,c=M(a.H);R(c,\"SID\",a.M);R(c,\"RID\",b);R(c,\"TYPE\",\"terminate\");ne(a,c);b=new L(a,a.a,0,b,void 0);b.I=2;b.l=Mc(M(c));c=!1;k.navigator&&k.navigator.sendBeacon&&(c=k.navigator.sendBeacon(b.l.toString(),\"\"));c||((new Image).src=b.l);b.H=t();Pc(b)}oe(a)}\nfunction me(a){a.C&&(a.C.abort(),a.C=null);a.b&&(a.b.cancel(),a.b=null);a.m&&(k.clearTimeout(a.m),a.m=null);pe(a);a.g.cancel();a.o&&(k.clearTimeout(a.o),a.o=null)}function qe(a,b){if(1E3==a.h.length){var c=\"Already have 1000 queued maps upon queueing \"+Fb(b),d=a.a.a;d&&F(d,c)}a.h.push(new Ud(a.Va++,b));3==a.D&&re(a)}g.Ka=function(){return 0==this.D};function re(a){Sd(a.g)||a.o||(a.o=xc(r(a.Pa,a),0),a.G=0)}\ng.Pa=function(a){this.o=null;I(this.a,\"startForwardChannel_\");if(1==this.D)if(a)(a=this.a.a)&&F(a,\"Not supposed to retry the open\");else{I(this.a,\"open_()\");this.I=Math.floor(1E5*Math.random());a=this.I++;var b=new L(this,this.a,0,a,void 0),c=this.i;this.P&&(c?(c=Ea(c),Ga(c,this.P)):c=this.P);null===this.f&&(b.h=c);var d=se(this),e=M(this.H);R(e,\"RID\",a);0b&&this.ka&&0==this.B&&!this.s&&(this.s=xc(r(this.ab,this),6E3)));else I(this.a,\"Bad POST response data returned\"),W(this,11)}else if(this.b==a&&pe(this),!/^[\\s\\xa0]*$/.test(b))for(b=c=this.la.a.parse(b),c=0;cthis.c)throw Error(Je);this.a=new Ge;this.b=new Nd;this.g=null;this.aa()}u(Ie,w);var Je=\"[goog.structs.Pool] Min can not be greater than max\";g=Ie.prototype;g.ca=function(){var a=t();if(!(null!=this.g&&0>a-this.g)){for(var b;0this.c&&0=this.u()){for(var c=this.a,d=0;d>1,a[d].a>c.a)a[b]=a[d],b=d;else break;a[b]=c}Me.prototype.A=function(){for(var a=this.a,b=[],c=a.length,d=0;d=e)f=void 0;else{if(1==e)wa(d);else{d[0]=d.pop();d=0;c=c.a;e=c.length;for(var h=c[d];d>1;){var m=2*d+1,v=2*d+2;m=vh.a)break;c[d]=c[m];d=m}c[d]=h}f=f.b}f.apply(this,[b])}else break}};\ng.ma=function(a){Y.L.ma.call(this,a);this.ua()};g.aa=function(){Y.L.aa.call(this);this.ua()};g.w=function(){Y.L.w.call(this);k.clearTimeout(void 0);wa(this.f.a);this.f=null};function Z(a,b,c,d){this.l=a;this.j=!!d;Y.call(this,b,c)}u(Z,Y);Z.prototype.qa=function(){var a=new U,b=this.l;b&&b.forEach(function(b,d){a.headers.set(d,b)});this.j&&(a.m=!0);return a};Z.prototype.va=function(a){return!a.i&&!a.a};Be.prototype.createWebChannel=Be.prototype.a;X.prototype.send=X.prototype.l;X.prototype.open=X.prototype.j;X.prototype.close=X.prototype.close;yc.NO_ERROR=0;yc.TIMEOUT=8;yc.HTTP_ERROR=6;zc.COMPLETE=\"complete\";Dd.EventType=Ed;Ed.OPEN=\"a\";Ed.CLOSE=\"b\";Ed.ERROR=\"c\";Ed.MESSAGE=\"d\";B.prototype.listen=B.prototype.$;Z.prototype.getObject=Z.prototype.ca;Z.prototype.releaseObject=Z.prototype.hb;U.prototype.listenOnce=U.prototype.Ia;U.prototype.getLastError=U.prototype.$a;U.prototype.getLastErrorCode=U.prototype.Ga;\nU.prototype.getStatus=U.prototype.V;U.prototype.getStatusText=U.prototype.Ha;U.prototype.getResponseJson=U.prototype.Za;U.prototype.getResponseText=U.prototype.U;U.prototype.getResponseText=U.prototype.U;U.prototype.send=U.prototype.ta;module.exports={createWebChannelTransport:Fe,ErrorCode:yc,EventType:zc,WebChannel:Dd,XhrIoPool:Z};}).call(typeof window !== 'undefined' ? window : this)\n\n\n/***/ })\n\n},[66]);\n } catch(error) {\n throw new Error(\n 'Cannot instantiate firebase-firestore.js - ' +\n 'be sure to load firebase-app.js first.'\n )\n }\n\n\n// WEBPACK FOOTER //\n// firebase-firestore.js","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* tslint:disable:no-console */\n\nimport { SDK_VERSION } from '../core/version';\nimport { AnyJs } from './misc';\n\nexport enum LogLevel {\n DEBUG,\n ERROR,\n SILENT\n}\n\nlet logLevel = LogLevel.ERROR;\n\n// Helper methods are needed because variables can't be exported as read/write\nexport function getLogLevel(): LogLevel {\n return logLevel;\n}\nexport function setLogLevel(newLevel: LogLevel): void {\n logLevel = newLevel;\n}\n\nexport function debug(tag: string, msg: string, ...obj: AnyJs[]): void {\n if (logLevel <= LogLevel.DEBUG) {\n const time = new Date().toISOString();\n const args = obj.map(argToString);\n console.log(`Firestore (${SDK_VERSION}) ${time} [${tag}]: ${msg}`, ...args);\n }\n}\n\nexport function error(msg: string, ...obj: AnyJs[]): void {\n if (logLevel <= LogLevel.ERROR) {\n const time = new Date().toISOString();\n const args = obj.map(argToString);\n console.error(`Firestore (${SDK_VERSION}) ${time}: ${msg}`, ...args);\n }\n}\n\n/**\n * Converts an additional log parameter to a string representation.\n */\nfunction argToString(obj: AnyJs): string | AnyJs {\n if (typeof obj === 'string') {\n return obj;\n } else {\n try {\n return JSON.stringify(obj);\n } catch (e) {\n // Converting to JSON failed, just log the object directly\n return obj;\n }\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/log.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SDK_VERSION } from '../core/version';\n\nimport { error } from './log';\n\n/**\n * Unconditionally fails, throwing an Error with the given message.\n *\n * Returns any so it can be used in expressions:\n * @example\n * let futureVar = fail('not implemented yet');\n */\nexport function fail(failure: string): never {\n // Log the failure in addition to throw an exception, just in case the\n // exception is swallowed.\n const message =\n `FIRESTORE (${SDK_VERSION}) INTERNAL ASSERTION FAILED: ` + failure;\n error(message);\n\n // NOTE: We don't use FirestoreError here because these are internal failures\n // that cannot be handled by the user. (Also it would create a circular\n // dependency between the error and assert modules which doesn't work.)\n throw new Error(message);\n}\n\n/**\n * Fails if the given assertion condition is false, throwing an Error with the\n * given message if it did.\n */\nexport function assert(assertion: boolean, message: string) {\n if (!assertion) {\n fail(message);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/assert.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DatabaseId, DatabaseInfo } from '../core/database_info';\nimport { ProtoByteString } from '../core/types';\nimport { Connection } from '../remote/connection';\nimport { JsonProtoSerializer } from '../remote/serializer';\nimport { fail } from '../util/assert';\n\n/**\n * Provides a common interface to load anything platform dependent, e.g.\n * the connection implementation.\n *\n * An implementation of this must be provided at compile time for the platform.\n */\nexport interface Platform {\n loadConnection(databaseInfo: DatabaseInfo): Promise;\n newSerializer(databaseId: DatabaseId): JsonProtoSerializer;\n\n /** Converts a Base64 encoded string to a binary string. */\n atob(encoded: string): string;\n\n /** Converts a binary string to a Base64 encoded string. */\n btoa(raw: string): string;\n\n /** True if and only if the Base64 conversion functions are available. */\n readonly base64Available: boolean;\n\n readonly emptyByteString: ProtoByteString;\n}\n\n/**\n * Provides singleton helpers where setup code can inject a platform at runtime.\n * setPlatform needs to be set before Firestore is used and must be set exactly\n * once.\n */\nexport class PlatformSupport {\n private static platform: Platform;\n static setPlatform(platform: Platform): void {\n if (PlatformSupport.platform) {\n fail('Platform already defined');\n }\n PlatformSupport.platform = platform;\n }\n\n static getPlatform(): Platform {\n if (!PlatformSupport.platform) {\n fail('Platform not set');\n }\n return PlatformSupport.platform;\n }\n}\n\n/**\n * Returns the representation of an empty \"proto\" byte string for the\n * platform.\n */\nexport function emptyByteString(): ProtoByteString {\n return PlatformSupport.getPlatform().emptyByteString;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/platform/platform.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// We are doing some heavy reflective stuff, lots of any casting necessary\n/* tslint:disable:no-any */\n\nimport { Code, FirestoreError } from './error';\n\n/**\n * Helper function to prevent instantiation through the constructor.\n *\n * This method creates a new constructor that throws when it's invoked.\n * The prototype of that constructor is then set to the prototype of the hidden\n * \"class\" to expose all the prototype methods and allow for instanceof\n * checks.\n *\n * To also make all the static methods available, all properties of the\n * original constructor are copied to the new constructor.\n */\nexport function makeConstructorPrivate(cls: T, optionalMessage?: string): T {\n function PublicConstructor() {\n let error = 'This constructor is private.';\n if (optionalMessage) {\n error += ' ';\n error += optionalMessage;\n }\n throw new FirestoreError(Code.INVALID_ARGUMENT, error);\n }\n\n // Make sure instanceof checks work and all methods are exposed on the public\n // constructor\n PublicConstructor.prototype = (cls as any).prototype;\n\n // Copy any static methods/members\n for (const staticProperty in cls) {\n if (cls.hasOwnProperty(staticProperty)) {\n (PublicConstructor as any)[staticProperty] = (cls as any)[staticProperty];\n }\n }\n\n return PublicConstructor as any;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/api.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from './assert';\n\nexport interface Dict {\n [stringKey: string]: V;\n [numberKey: number]: V;\n}\n\nexport function contains(obj: Dict, key: string | number): boolean {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nexport function get(obj: Dict, key: string | number): V | null {\n return Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : null;\n}\n\nexport function size(obj: Dict): number {\n let count = 0;\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n count++;\n }\n }\n return count;\n}\n\n/** Returns the given value if it's defined or the defaultValue otherwise. */\nexport function defaulted(value: V | undefined, defaultValue: V): V {\n return value !== undefined ? value : defaultValue;\n}\n\nexport function forEachNumber(\n obj: Dict,\n fn: (key: number, val: V) => void\n): void {\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n const num = parseInt(key, 10);\n if (!isNaN(num)) {\n fn(num, obj[key]);\n }\n }\n }\n}\n\nexport function forEach(\n obj: Dict,\n fn: (key: string, val: V) => void\n): void {\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn(key, obj[key]);\n }\n }\n}\n\nexport function lookupOrInsert(\n obj: Dict,\n key: string | number,\n valFn: () => V\n): V {\n if (!contains(obj, key)) {\n obj[key] = valFn();\n }\n return obj[key];\n}\n\nexport function isEmpty(obj: Dict) {\n assert(\n obj != null && typeof obj === 'object',\n 'isEmpty() expects object parameter.'\n );\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return false;\n }\n }\n return true;\n}\n\nexport function shallowCopy(obj: Dict): Dict {\n assert(\n obj && typeof obj === 'object',\n 'shallowCopy() expects object parameter.'\n );\n const result: Dict = {};\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/obj.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { fail } from './assert';\nimport { Code, FirestoreError } from './error';\nimport { AnyJs } from './misc';\nimport * as obj from './obj';\n\n/**\n * Validates the invocation of functionName has the exact number of arguments.\n *\n * Forward the magic \"arguments\" variable as second parameter on which the\n * parameter validation is performed:\n * validateExactNumberOfArgs('myFunction', arguments, 2);\n */\nexport function validateExactNumberOfArgs(\n functionName: string,\n args: IArguments,\n numberOfArgs: number\n): void {\n if (args.length !== numberOfArgs) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires ` +\n formatPlural(numberOfArgs, 'argument') +\n ', but was called with ' +\n formatPlural(args.length, 'argument') +\n '.'\n );\n }\n}\n\n/**\n * Validates the invocation of functionName has at least the provided number of\n * arguments (but can have many more).\n *\n * Forward the magic \"arguments\" variable as second parameter on which the\n * parameter validation is performed:\n * validateAtLeastNumberOfArgs('myFunction', arguments, 2);\n */\nexport function validateAtLeastNumberOfArgs(\n functionName: string,\n args: IArguments,\n minNumberOfArgs: number\n): void {\n if (args.length < minNumberOfArgs) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires at least ` +\n formatPlural(minNumberOfArgs, 'argument') +\n ', but was called with ' +\n formatPlural(args.length, 'argument') +\n '.'\n );\n }\n}\n\n/**\n * Validates the invocation of functionName has number of arguments between\n * the values provided.\n *\n * Forward the magic \"arguments\" variable as second parameter on which the\n * parameter validation is performed:\n * validateBetweenNumberOfArgs('myFunction', arguments, 2, 3);\n */\nexport function validateBetweenNumberOfArgs(\n functionName: string,\n args: IArguments,\n minNumberOfArgs: number,\n maxNumberOfArgs: number\n): void {\n if (args.length < minNumberOfArgs || args.length > maxNumberOfArgs) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires between ${minNumberOfArgs} and ` +\n `${maxNumberOfArgs} arguments, but was called with ` +\n formatPlural(args.length, 'argument') +\n '.'\n );\n }\n}\n\n/**\n * Validates the provided argument is an array and has as least the expected\n * number of elements.\n */\nexport function validateNamedArrayAtLeastNumberOfElements(\n functionName: string,\n value: T[],\n name: string,\n minNumberOfElements: number\n): void {\n if (!(value instanceof Array) || value.length < minNumberOfElements) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires its ${name} argument to be an ` +\n 'array with at least ' +\n `${formatPlural(minNumberOfElements, 'element')}.`\n );\n }\n}\n\n/**\n * Validates the provided positional argument has the native JavaScript type\n * using typeof checks.\n */\nexport function validateArgType(\n functionName: string,\n type: string,\n position: number,\n argument: AnyJs\n): void {\n validateType(functionName, type, `${ordinal(position)} argument`, argument);\n}\n\n/**\n * Validates the provided argument has the native JavaScript type using\n * typeof checks or is undefined.\n */\nexport function validateOptionalArgType(\n functionName: string,\n type: string,\n position: number,\n argument: AnyJs\n): void {\n if (argument !== undefined) {\n validateArgType(functionName, type, position, argument);\n }\n}\n\n/**\n * Validates the provided named option has the native JavaScript type using\n * typeof checks.\n */\nexport function validateNamedType(\n functionName: string,\n type: string,\n optionName: string,\n argument: AnyJs\n) {\n validateType(functionName, type, `${optionName} option`, argument);\n}\n\n/**\n * Validates the provided named option has the native JavaScript type using\n * typeof checks or is undefined.\n */\nexport function validateNamedOptionalType(\n functionName: string,\n type: string,\n optionName: string,\n argument: AnyJs\n) {\n if (argument !== undefined) {\n validateNamedType(functionName, type, optionName, argument);\n }\n}\n\n/** Helper to validate the type of a provided input. */\nfunction validateType(\n functionName: string,\n type: string,\n inputName: string,\n input: AnyJs\n) {\n if (typeof input !== type || (type === 'object' && !isPlainObject(input))) {\n const description = valueDescription(input);\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires its ${inputName} ` +\n `to be of type ${type}, but it was: ${description}`\n );\n }\n}\n\n/**\n * Returns true iff it's a non-null object without a custom prototype\n * (i.e. excludes Array, Date, etc.).\n */\nexport function isPlainObject(input: AnyJs) {\n return (\n typeof input === 'object' &&\n input !== null &&\n Object.getPrototypeOf(input) === Object.prototype\n );\n}\n\n/** Returns a string describing the type / value of the provided input. */\nexport function valueDescription(input: AnyJs) {\n if (input === undefined) {\n return 'undefined';\n } else if (input === null) {\n return 'null';\n } else if (typeof input === 'string') {\n if (input.length > 20) {\n input = `${input.substring(0, 20)}...`;\n }\n return JSON.stringify(input);\n } else if (typeof input === 'number' || typeof input === 'boolean') {\n return '' + input;\n } else if (typeof input === 'object') {\n if (input instanceof Array) {\n return 'an array';\n } else {\n const customObjectName = tryGetCustomObjectType(input);\n if (customObjectName) {\n return `a custom ${customObjectName} object`;\n } else {\n return 'an object';\n }\n }\n } else if (typeof input === 'function') {\n return 'a function';\n } else {\n return fail('Unknown wrong type: ' + typeof input);\n }\n}\n\n/** Hacky method to try to get the constructor name for an object. */\nexport function tryGetCustomObjectType(input: object): string | null {\n if (input.constructor) {\n const funcNameRegex = /function\\s+([^\\s(]+)\\s*\\(/;\n const results = funcNameRegex.exec(input.constructor.toString());\n if (results && results.length > 1) {\n return results[1];\n }\n }\n return null;\n}\n\n/** Validates the provided argument is defined. */\nexport function validateDefined(\n functionName: string,\n position: number,\n argument: AnyJs\n): void {\n if (argument === undefined) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires a valid ${ordinal(position)} ` +\n `argument, but it was undefined.`\n );\n }\n}\n\n/**\n * Validates the provided positional argument is an object, and its keys and\n * values match the expected keys and types provided in optionTypes.\n */\nexport function validateOptionNames(\n functionName: string,\n options: object,\n optionNames: string[]\n) {\n obj.forEach(options as obj.Dict, (key, _) => {\n if (optionNames.indexOf(key) < 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Unknown option '${key}' passed to function ${functionName}(). ` +\n 'Available options: ' +\n optionNames.join(', ')\n );\n }\n });\n}\n\n/**\n * Helper method to throw an error that the provided argument did not pass\n * an instanceof check.\n */\nexport function invalidClassError(\n functionName: string,\n type: string,\n position: number,\n argument: AnyJs\n): Error {\n const description = valueDescription(argument);\n return new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${functionName}() requires its ${ordinal(position)} ` +\n `argument to be a ${type}, but it was: ${description}`\n );\n}\n\n/** Converts a number to its english word representation */\nfunction ordinal(num: number) {\n switch (num) {\n case 1:\n return 'first';\n case 2:\n return 'second';\n case 3:\n return 'third';\n default:\n return num + 'th';\n }\n}\n\n/**\n * Formats the given word as plural conditionally given the preceding number.\n */\nfunction formatPlural(num: number, str: string) {\n return `${num} ${str}` + (num === 1 ? '' : 's');\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/input_validation.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from './assert';\n\nexport type EventHandler = (value: E) => void;\n\n/**\n * A union of all of the standard JS types, useful for cases where the type is\n * unknown. Unlike \"any\" this doesn't lose all type-safety, since the consuming\n * code must still cast to a particular type before using it.\n */\nexport type AnyJs = null | undefined | boolean | number | string | object;\n\n// TODO(b/66916745): AnyDuringMigration was used to suppress type check failures\n// that were found during the upgrade to TypeScript 2.4. They need to be audited\n// and fixed.\n// tslint:disable-next-line:no-any\nexport type AnyDuringMigration = any;\n\n// tslint:disable-next-line:class-as-namespace\nexport class AutoId {\n static newId(): string {\n // Alphanumeric characters\n const chars =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let autoId = '';\n for (let i = 0; i < 20; i++) {\n autoId += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n assert(autoId.length === 20, 'Invalid auto ID: ' + autoId);\n return autoId;\n }\n}\n\nexport function primitiveComparator(left: T, right: T): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\n/** Duck-typed interface for objects that have an equals() method. */\nexport interface Equatable {\n equals(other: T): boolean;\n}\n\n/** Helper to compare nullable (or undefined-able) objects using equals(). */\nexport function equals(\n left: Equatable | null | undefined,\n right: T | null | undefined\n): boolean {\n if (left !== null && left !== undefined) {\n return !!(right && left.equals(right));\n } else {\n // HACK: Explicitly cast since TypeScript's type narrowing apparently isn't\n // smart enough.\n return (left as null | undefined) === right;\n }\n}\n\n/** Helper to compare arrays using equals(). */\nexport function arrayEquals(left: Array>, right: T[]): boolean {\n if (left.length !== right.length) {\n return false;\n }\n\n for (let i = 0; i < left.length; i++) {\n if (!left[i].equals(right[i])) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Returns the largest lexicographically smaller string of equal or smaller\n * length. Returns an empty string if there is no such predecessor (if the input\n * is empty).\n *\n * Strings returned from this method can be invalid UTF-16 but this is sufficent\n * in use for indexeddb because that depends on lexicographical ordering but\n * shouldn't be used elsewhere.\n */\nexport function immediatePredecessor(s: string): string {\n // We can decrement the last character in the string and be done\n // unless that character is 0 (0x0000), in which case we have to erase the\n // last character.\n const lastIndex = s.length - 1;\n if (s.length === 0) {\n // Special case the empty string.\n return '';\n } else if (s.charAt(lastIndex) === '\\0') {\n return s.substring(0, lastIndex);\n } else {\n return (\n s.substring(0, lastIndex) +\n String.fromCharCode(s.charCodeAt(lastIndex) - 1)\n );\n }\n}\n\n/**\n * Returns the immediate lexicographically-following string. This is useful to\n * construct an inclusive range for indexeddb iterators.\n */\nexport function immediateSuccessor(s: string): string {\n // Return the input string, with an additional NUL byte appended.\n return s + '\\0';\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/misc.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PlatformSupport } from '../platform/platform';\nimport { makeConstructorPrivate } from '../util/api';\nimport { Code, FirestoreError } from '../util/error';\nimport {\n invalidClassError,\n validateArgType,\n validateExactNumberOfArgs\n} from '../util/input_validation';\nimport { primitiveComparator } from '../util/misc';\n\n/** Helper function to assert Uint8Array is available at runtime. */\nfunction assertUint8ArrayAvailable() {\n if (typeof Uint8Array === 'undefined') {\n throw new FirestoreError(\n Code.UNIMPLEMENTED,\n 'Uint8Arrays are not available in this environment.'\n );\n }\n}\n\n/** Helper function to assert Base64 functions are available at runtime. */\nfunction assertBase64Available() {\n if (!PlatformSupport.getPlatform().base64Available) {\n throw new FirestoreError(\n Code.UNIMPLEMENTED,\n 'Blobs are unavailable in Firestore in this environment.'\n );\n }\n}\n\n/**\n * Immutable class holding a blob (binary data).\n * This class is directly exposed in the public API.\n *\n * Note that while you can't hide the constructor in JavaScript code, we are\n * using the hack above to make sure no-one outside this module can call it.\n */\nexport class Blob {\n // Prefix with underscore to signal this is a private variable in JS and\n // prevent it showing up for autocompletion.\n // A binary string is a string with each char as Unicode code point in the\n // range of [0, 255], essentially simulating a byte array.\n private _binaryString: string;\n\n private constructor(binaryString: string) {\n assertBase64Available();\n this._binaryString = binaryString;\n }\n\n static fromBase64String(base64: string): Blob {\n validateExactNumberOfArgs('Blob.fromBase64String', arguments, 1);\n validateArgType('Blob.fromBase64String', 'string', 1, base64);\n assertBase64Available();\n try {\n const binaryString = PlatformSupport.getPlatform().atob(base64);\n return new Blob(binaryString);\n } catch (e) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Failed to construct Blob from Base64 string: ' + e\n );\n }\n }\n\n static fromUint8Array(array: Uint8Array): Blob {\n validateExactNumberOfArgs('Blob.fromUint8Array', arguments, 1);\n assertUint8ArrayAvailable();\n if (!(array instanceof Uint8Array)) {\n throw invalidClassError('Blob.fromUint8Array', 'Uint8Array', 1, array);\n }\n // We can't call array.map directly because it expects the return type to\n // be a Uint8Array, whereas we can convert it to a regular array by invoking\n // map on the Array prototype.\n const binaryString = Array.prototype.map\n .call(array, (char: number) => {\n return String.fromCharCode(char);\n })\n .join('');\n return new Blob(binaryString);\n }\n\n public toBase64(): string {\n validateExactNumberOfArgs('Blob.toBase64', arguments, 0);\n assertBase64Available();\n return PlatformSupport.getPlatform().btoa(this._binaryString);\n }\n\n public toUint8Array(): Uint8Array {\n validateExactNumberOfArgs('Blob.toUint8Array', arguments, 0);\n assertUint8ArrayAvailable();\n const buffer = new Uint8Array(this._binaryString.length);\n for (let i = 0; i < this._binaryString.length; i++) {\n buffer[i] = this._binaryString.charCodeAt(i);\n }\n return buffer;\n }\n\n public toString(): string {\n return 'Blob(base64: ' + this.toBase64() + ')';\n }\n\n /**\n * Actually private to JS consumers of our API, so this function is prefixed\n * with an underscore.\n */\n public _equals(other: Blob): boolean {\n return this._binaryString === other._binaryString;\n }\n\n /**\n * Actually private to JS consumers of our API, so this function is prefixed\n * with an underscore.\n */\n public _compareTo(other: Blob): number {\n return primitiveComparator(this._binaryString, other._binaryString);\n }\n}\n\n// Public instance that disallows construction at runtime. This constructor is\n// used when exporting Blob on firebase.firestore.Blob and will be called Blob\n// publicly. Internally we still use Blob which has a type checked private\n// constructor. Note that Blob and PublicBlob can be used interchangeably in\n// instanceof checks.\n// For our internal TypeScript code PublicBlob doesn't exist as a type, and so\n// we need to use Blob as type and export it too.\n// tslint:disable-next-line:variable-name We're treating this as a class name.\nexport let PublicBlob = makeConstructorPrivate(\n Blob,\n 'Use Blob.fromUint8Array() or Blob.fromBase64String() instead.'\n);\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/blob.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Blob } from '../api/blob';\nimport { GeoPoint } from '../api/geo_point';\nimport { DatabaseId } from '../core/database_info';\nimport { Timestamp } from '../core/timestamp';\nimport { assert, fail } from '../util/assert';\nimport { AnyJs, primitiveComparator } from '../util/misc';\nimport * as objUtils from '../util/obj';\nimport { SortedMap } from '../util/sorted_map';\nimport * as typeUtils from '../util/types';\n\nimport { DocumentKey } from './document_key';\nimport { FieldPath } from './path';\n\n/**\n * Supported data value types:\n * - Null\n * - Boolean\n * - Long\n * - Double\n * - String\n * - Object\n * - Array\n * - Binary\n * - Timestamp\n * - ServerTimestamp (a sentinel used in uncommitted writes)\n * - GeoPoint\n * - (Document) References\n */\n\nexport interface JsonObject {\n [name: string]: T;\n}\n\nexport enum TypeOrder {\n // This order is defined by the backend.\n NullValue = 0,\n BooleanValue = 1,\n NumberValue = 2,\n TimestampValue = 3,\n StringValue = 4,\n BlobValue = 5,\n RefValue = 6,\n GeoPointValue = 7,\n ArrayValue = 8,\n ObjectValue = 9\n}\n\n/**\n * Potential types returned by FieldValue.value(). This could be stricter\n * (instead of using {}), but there's little benefit.\n *\n * Note that currently we use AnyJs (which is identical except includes\n * undefined) for incoming user data as a convenience to the calling code (but\n * we'll throw if the data contains undefined). This should probably be changed\n * to use FieldType, but all consuming code will have to be updated to\n * explicitly handle undefined and then cast to FieldType or similar. Perhaps\n * we should tackle this when adding robust argument validation to the API.\n */\nexport type FieldType = null | boolean | number | string | {};\n\n/**\n * A field value represents a datatype as stored by Firestore.\n */\nexport abstract class FieldValue {\n readonly typeOrder: TypeOrder;\n\n abstract value(): FieldType;\n abstract equals(other: FieldValue): boolean;\n abstract compareTo(other: FieldValue): number;\n\n toString(): string {\n const val = this.value();\n return val === null ? 'null' : val.toString();\n }\n\n defaultCompareTo(other: FieldValue): number {\n assert(\n this.typeOrder !== other.typeOrder,\n 'Default compareTo should not be used for values of same type.'\n );\n const cmp = primitiveComparator(this.typeOrder, other.typeOrder);\n return cmp;\n }\n}\n\nexport class NullValue extends FieldValue {\n typeOrder = TypeOrder.NullValue;\n\n // internalValue is unused but we add it to work around\n // https://github.com/Microsoft/TypeScript/issues/15585\n readonly internalValue = null;\n\n private constructor() {\n super();\n }\n\n value(): FieldType {\n return null;\n }\n\n equals(other: FieldValue): boolean {\n return other instanceof NullValue;\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof NullValue) {\n return 0;\n }\n return this.defaultCompareTo(other);\n }\n\n static INSTANCE = new NullValue();\n}\n\nexport class BooleanValue extends FieldValue {\n typeOrder = TypeOrder.BooleanValue;\n\n private constructor(readonly internalValue: boolean) {\n super();\n }\n\n value(): boolean {\n return this.internalValue;\n }\n\n equals(other: FieldValue): boolean {\n return (\n other instanceof BooleanValue &&\n this.internalValue === other.internalValue\n );\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof BooleanValue) {\n return primitiveComparator(this, other);\n }\n return this.defaultCompareTo(other);\n }\n\n static of(value: boolean): BooleanValue {\n return value ? BooleanValue.TRUE : BooleanValue.FALSE;\n }\n\n static TRUE = new BooleanValue(true);\n static FALSE = new BooleanValue(false);\n}\n\n/** Base class for IntegerValue and DoubleValue. */\nexport abstract class NumberValue extends FieldValue {\n typeOrder = TypeOrder.NumberValue;\n\n constructor(readonly internalValue: number) {\n super();\n }\n\n value(): number {\n return this.internalValue;\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof NumberValue) {\n return numericComparator(this.internalValue, other.internalValue);\n }\n return this.defaultCompareTo(other);\n }\n}\n\n/** Utility function to compare doubles (using Firestore semantics for NaN). */\nfunction numericComparator(left: number, right: number): number {\n if (left < right) {\n return -1;\n } else if (left > right) {\n return 1;\n } else if (left === right) {\n return 0;\n } else {\n // one or both are NaN.\n if (isNaN(left)) {\n return isNaN(right) ? 0 : -1;\n } else {\n return 1;\n }\n }\n}\n\n/**\n * Utility function to check numbers for equality using Firestore semantics\n * (NaN === NaN, -0.0 !== 0.0).\n */\nfunction numericEquals(left: number, right: number): boolean {\n // Implemented based on Object.is() polyfill from\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n if (left === right) {\n // +0 != -0\n return left !== 0 || 1 / left === 1 / right;\n } else {\n // NaN == NaN\n return left !== left && right !== right;\n }\n}\n\nexport class IntegerValue extends NumberValue {\n constructor(internalValue: number) {\n super(internalValue);\n }\n\n equals(other: FieldValue): boolean {\n // NOTE: DoubleValue and IntegerValue instances may compareTo() the same,\n // but that doesn't make them equal via equals().\n if (other instanceof IntegerValue) {\n return numericEquals(this.internalValue, other.internalValue);\n } else {\n return false;\n }\n }\n\n // NOTE: compareTo() is implemented in NumberValue.\n}\n\nexport class DoubleValue extends NumberValue {\n constructor(readonly internalValue: number) {\n super(internalValue);\n }\n\n static NAN = new DoubleValue(NaN);\n static POSITIVE_INFINITY = new DoubleValue(Infinity);\n static NEGATIVE_INFINITY = new DoubleValue(-Infinity);\n\n equals(other: FieldValue): boolean {\n // NOTE: DoubleValue and IntegerValue instances may compareTo() the same,\n // but that doesn't make them equal via equals().\n if (other instanceof DoubleValue) {\n return numericEquals(this.internalValue, other.internalValue);\n } else {\n return false;\n }\n }\n\n // NOTE: compareTo() is implemented in NumberValue.\n}\n\n// TODO(b/37267885): Add truncation support\nexport class StringValue extends FieldValue {\n typeOrder = TypeOrder.StringValue;\n\n constructor(readonly internalValue: string) {\n super();\n }\n\n value(): string {\n return this.internalValue;\n }\n\n equals(other: FieldValue): boolean {\n return (\n other instanceof StringValue && this.internalValue === other.internalValue\n );\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof StringValue) {\n return primitiveComparator(this.internalValue, other.internalValue);\n }\n return this.defaultCompareTo(other);\n }\n}\n\nexport class TimestampValue extends FieldValue {\n typeOrder = TypeOrder.TimestampValue;\n\n constructor(readonly internalValue: Timestamp) {\n super();\n }\n\n value(): Date {\n return this.internalValue.toDate();\n }\n\n equals(other: FieldValue): boolean {\n return (\n other instanceof TimestampValue &&\n this.internalValue.equals(other.internalValue)\n );\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof TimestampValue) {\n return this.internalValue.compareTo(other.internalValue);\n } else if (other instanceof ServerTimestampValue) {\n // Concrete timestamps come before server timestamps.\n return -1;\n } else {\n return this.defaultCompareTo(other);\n }\n }\n}\n\n/**\n * Represents a locally-applied ServerTimestamp.\n *\n * Notes:\n * - ServerTimestampValue instances are created as the result of applying a\n * TransformMutation (see TransformMutation.applyTo()). They can only exist in\n * the local view of a document. Therefore they do not need to be parsed or\n * serialized.\n * - When evaluated locally (e.g. for snapshot.data()), they evaluate to null.\n * - With respect to other ServerTimestampValues, they sort by their\n * localWriteTime.\n */\nexport class ServerTimestampValue extends FieldValue {\n typeOrder = TypeOrder.TimestampValue;\n\n constructor(readonly localWriteTime: Timestamp) {\n super();\n }\n\n value(): null {\n return null;\n }\n\n equals(other: FieldValue): boolean {\n return (\n other instanceof ServerTimestampValue &&\n this.localWriteTime.equals(other.localWriteTime)\n );\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof ServerTimestampValue) {\n return this.localWriteTime.compareTo(other.localWriteTime);\n } else if (other instanceof TimestampValue) {\n // Server timestamps come after all concrete timestamps.\n return 1;\n } else {\n return this.defaultCompareTo(other);\n }\n }\n\n toString(): string {\n return '';\n }\n}\n\nexport class BlobValue extends FieldValue {\n typeOrder = TypeOrder.BlobValue;\n\n constructor(readonly internalValue: Blob) {\n super();\n }\n\n value(): Blob {\n return this.internalValue;\n }\n\n equals(other: FieldValue): boolean {\n return (\n other instanceof BlobValue &&\n this.internalValue._equals(other.internalValue)\n );\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof BlobValue) {\n return this.internalValue._compareTo(other.internalValue);\n }\n return this.defaultCompareTo(other);\n }\n}\n\nexport class RefValue extends FieldValue {\n typeOrder = TypeOrder.RefValue;\n\n constructor(readonly databaseId: DatabaseId, readonly key: DocumentKey) {\n super();\n }\n\n value(): DocumentKey {\n return this.key;\n }\n\n equals(other: FieldValue): boolean {\n if (other instanceof RefValue) {\n return (\n this.key.equals(other.key) && this.databaseId.equals(other.databaseId)\n );\n } else {\n return false;\n }\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof RefValue) {\n const cmp = this.databaseId.compareTo(other.databaseId);\n return cmp !== 0 ? cmp : DocumentKey.comparator(this.key, other.key);\n }\n return this.defaultCompareTo(other);\n }\n}\n\nexport class GeoPointValue extends FieldValue {\n typeOrder = TypeOrder.GeoPointValue;\n\n constructor(readonly internalValue: GeoPoint) {\n super();\n }\n\n value(): GeoPoint {\n return this.internalValue;\n }\n\n equals(other: FieldValue): boolean {\n return (\n other instanceof GeoPointValue &&\n this.internalValue._equals(other.internalValue)\n );\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof GeoPointValue) {\n return this.internalValue._compareTo(other.internalValue);\n }\n return this.defaultCompareTo(other);\n }\n}\n\nexport class ObjectValue extends FieldValue {\n typeOrder = TypeOrder.ObjectValue;\n\n constructor(readonly internalValue: SortedMap) {\n super();\n }\n\n value(): JsonObject {\n const result: JsonObject = {};\n this.internalValue.inorderTraversal((key, val) => {\n result[key] = val.value();\n });\n return result;\n }\n\n forEach(action: (key: string, value: FieldValue) => void): void {\n this.internalValue.inorderTraversal(action);\n }\n\n equals(other: FieldValue): boolean {\n if (other instanceof ObjectValue) {\n const it1 = this.internalValue.getIterator();\n const it2 = other.internalValue.getIterator();\n while (it1.hasNext() && it2.hasNext()) {\n const next1: { key: string; value: FieldValue } = it1.getNext();\n const next2: { key: string; value: FieldValue } = it2.getNext();\n if (next1.key !== next2.key || !next1.value.equals(next2.value)) {\n return false;\n }\n }\n\n return !it1.hasNext() && !it2.hasNext();\n }\n\n return false;\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof ObjectValue) {\n const it1 = this.internalValue.getIterator();\n const it2 = other.internalValue.getIterator();\n while (it1.hasNext() && it2.hasNext()) {\n const next1: { key: string; value: FieldValue } = it1.getNext();\n const next2: { key: string; value: FieldValue } = it2.getNext();\n const cmp =\n primitiveComparator(next1.key, next2.key) ||\n next1.value.compareTo(next2.value);\n if (cmp) {\n return cmp;\n }\n }\n\n // Only equal if both iterators are exhausted\n return primitiveComparator(it1.hasNext(), it2.hasNext());\n } else {\n return this.defaultCompareTo(other);\n }\n }\n\n set(path: FieldPath, to: FieldValue): ObjectValue {\n assert(!path.isEmpty(), 'Cannot set field for empty path on ObjectValue');\n if (path.length === 1) {\n return this.setChild(path.firstSegment(), to);\n } else {\n let child = this.child(path.firstSegment());\n if (!(child instanceof ObjectValue)) {\n child = ObjectValue.EMPTY;\n }\n const newChild = (child as ObjectValue).set(path.popFirst(), to);\n return this.setChild(path.firstSegment(), newChild);\n }\n }\n\n delete(path: FieldPath): ObjectValue {\n assert(\n !path.isEmpty(),\n 'Cannot delete field for empty path on ObjectValue'\n );\n if (path.length === 1) {\n return new ObjectValue(this.internalValue.remove(path.firstSegment()));\n } else {\n // nested field\n const child = this.child(path.firstSegment());\n if (child instanceof ObjectValue) {\n const newChild = child.delete(path.popFirst());\n return new ObjectValue(\n this.internalValue.insert(path.firstSegment(), newChild)\n );\n } else {\n // Don't actually change a primitive value to an object for a delete\n return this;\n }\n }\n }\n\n contains(path: FieldPath): boolean {\n return this.field(path) !== undefined;\n }\n\n field(path: FieldPath): FieldValue {\n assert(!path.isEmpty(), \"Can't get field of empty path\");\n let field: FieldValue | undefined = this;\n path.forEach((pathSegment: string) => {\n if (field instanceof ObjectValue) {\n field = field.internalValue.get(pathSegment) || undefined;\n } else {\n field = undefined;\n }\n });\n return field;\n }\n\n toString(): string {\n return JSON.stringify(this.value());\n }\n\n private child(childName: string): FieldValue | undefined {\n return this.internalValue.get(childName) || undefined;\n }\n\n private setChild(childName: string, value: FieldValue): ObjectValue {\n return new ObjectValue(this.internalValue.insert(childName, value));\n }\n\n static EMPTY = new ObjectValue(\n new SortedMap(primitiveComparator)\n );\n}\n\nexport class ArrayValue extends FieldValue {\n typeOrder = TypeOrder.ArrayValue;\n\n constructor(readonly internalValue: FieldValue[]) {\n super();\n }\n\n value(): FieldType[] {\n return this.internalValue.map(v => v.value());\n }\n\n forEach(action: (value: FieldValue) => void): void {\n this.internalValue.forEach(action);\n }\n\n equals(other: FieldValue): boolean {\n if (other instanceof ArrayValue) {\n if (this.internalValue.length !== other.internalValue.length) {\n return false;\n }\n\n for (let i = 0; i < this.internalValue.length; i++) {\n if (!this.internalValue[i].equals(other.internalValue[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n }\n\n compareTo(other: FieldValue): number {\n if (other instanceof ArrayValue) {\n const minLength = Math.min(\n this.internalValue.length,\n other.internalValue.length\n );\n\n for (let i = 0; i < minLength; i++) {\n const cmp = this.internalValue[i].compareTo(other.internalValue[i]);\n\n if (cmp) {\n return cmp;\n }\n }\n\n return primitiveComparator(\n this.internalValue.length,\n other.internalValue.length\n );\n } else {\n return this.defaultCompareTo(other);\n }\n }\n\n toString(): string {\n return JSON.stringify(this.value());\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/field_value.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AnyJs } from './misc';\n\n// Untyped Number alias we can use to check for ES6 methods / properties.\n// tslint:disable-next-line:no-any variable-name\nconst NumberAsAny = Number as any;\n\n/**\n * Minimum safe integer in Javascript because of floating point precision.\n * Added to not rely on ES6 features.\n */\nexport let MIN_SAFE_INTEGER: number =\n NumberAsAny.MIN_SAFE_INTEGER || -(Math.pow(2, 53) - 1);\n\n/**\n * Maximum safe integer in Javascript because of floating point precision.\n * Added to not rely on ES6 features.\n */\nexport let MAX_SAFE_INTEGER: number =\n NumberAsAny.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1;\n\n/**\n * Returns whether an number is an integer, uses native implementation if\n * available.\n * Added to not rely on ES6 features.\n * @param value The value to test for being an integer\n */\nexport let isInteger: (value: AnyJs) => boolean =\n NumberAsAny.isInteger ||\n (value =>\n typeof value === 'number' &&\n isFinite(value) &&\n Math.floor(value) === value);\n\n/**\n * Returns whether a variable is either undefined or null.\n */\nexport function isNullOrUndefined(value: AnyJs): boolean {\n return value === null || value === undefined;\n}\n\n/**\n * Returns whether a value is an integer and in the safe integer range\n * @param value The value to test for being an integer and in the safe range\n */\nexport function isSafeInteger(value: AnyJs): boolean {\n return (\n isInteger(value) &&\n (value as number) <= MAX_SAFE_INTEGER &&\n (value as number) >= MIN_SAFE_INTEGER\n );\n}\n\n/**\n * Safely checks if the number is NaN.\n */\nexport function safeIsNaN(value: AnyJs): boolean {\n if (NumberAsAny.IsNaN) {\n return NumberAsAny.IsNaN(value);\n } else {\n return typeof value === 'number' && isNaN(value);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/types.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Document } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport {\n DoubleValue,\n FieldValue,\n NullValue,\n RefValue\n} from '../model/field_value';\nimport { FieldPath, ResourcePath } from '../model/path';\nimport { assert, fail } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport { isNullOrUndefined } from '../util/types';\n\nexport class Query {\n static atPath(path: ResourcePath): Query {\n return new Query(path);\n }\n\n private memoizedCanonicalId: string | null = null;\n private memoizedOrderBy: OrderBy[] | null = null;\n\n constructor(\n readonly path: ResourcePath,\n readonly explicitOrderBy: OrderBy[] = [],\n readonly filters: Filter[] = [],\n readonly limit: number | null = null,\n readonly startAt: Bound | null = null,\n readonly endAt: Bound | null = null\n ) {\n if (this.startAt) {\n this.assertValidBound(this.startAt);\n }\n if (this.endAt) {\n this.assertValidBound(this.endAt);\n }\n }\n\n get orderBy(): OrderBy[] {\n if (this.memoizedOrderBy === null) {\n const inequalityField = this.getInequalityFilterField();\n const firstOrderByField = this.getFirstOrderByField();\n if (inequalityField !== null && firstOrderByField === null) {\n // In order to implicitly add key ordering, we must also add the\n // inequality filter field for it to be a valid query.\n // Note that the default inequality field and key ordering is ascending.\n if (inequalityField.isKeyField()) {\n this.memoizedOrderBy = [KEY_ORDERING_ASC];\n } else {\n this.memoizedOrderBy = [\n new OrderBy(inequalityField),\n KEY_ORDERING_ASC\n ];\n }\n } else {\n assert(\n inequalityField === null ||\n (firstOrderByField !== null &&\n inequalityField.equals(firstOrderByField)),\n 'First orderBy should match inequality field.'\n );\n this.memoizedOrderBy = [];\n let foundKeyOrdering = false;\n for (const orderBy of this.explicitOrderBy) {\n this.memoizedOrderBy.push(orderBy);\n if (orderBy.field.isKeyField()) {\n foundKeyOrdering = true;\n }\n }\n if (!foundKeyOrdering) {\n // The order of the implicit key ordering always matches the last\n // explicit order by\n const lastDirection =\n this.explicitOrderBy.length > 0\n ? this.explicitOrderBy[this.explicitOrderBy.length - 1].dir\n : Direction.ASCENDING;\n this.memoizedOrderBy.push(\n lastDirection === Direction.ASCENDING\n ? KEY_ORDERING_ASC\n : KEY_ORDERING_DESC\n );\n }\n }\n }\n return this.memoizedOrderBy;\n }\n\n addFilter(filter: Filter): Query {\n assert(\n this.getInequalityFilterField() == null ||\n !(filter instanceof RelationFilter) ||\n !filter.isInequality() ||\n filter.field.equals(this.getInequalityFilterField()!),\n 'Query must only have one inequality field.'\n );\n\n assert(\n !DocumentKey.isDocumentKey(this.path),\n 'No filtering allowed for document query'\n );\n const newFilters = this.filters.concat([filter]);\n return new Query(\n this.path,\n this.explicitOrderBy.slice(),\n newFilters,\n this.limit,\n this.startAt,\n this.endAt\n );\n }\n\n addOrderBy(orderBy: OrderBy): Query {\n assert(\n !DocumentKey.isDocumentKey(this.path),\n 'No ordering allowed for document query'\n );\n assert(!this.startAt && !this.endAt, 'Bounds must be set after orderBy');\n // TODO(dimond): validate that orderBy does not list the same key twice.\n const newOrderBy = this.explicitOrderBy.concat([orderBy]);\n return new Query(\n this.path,\n newOrderBy,\n this.filters.slice(),\n this.limit,\n this.startAt,\n this.endAt\n );\n }\n\n withLimit(limit: number | null): Query {\n return new Query(\n this.path,\n this.explicitOrderBy.slice(),\n this.filters.slice(),\n limit,\n this.startAt,\n this.endAt\n );\n }\n\n withStartAt(bound: Bound): Query {\n return new Query(\n this.path,\n this.explicitOrderBy.slice(),\n this.filters.slice(),\n this.limit,\n bound,\n this.endAt\n );\n }\n\n withEndAt(bound: Bound): Query {\n return new Query(\n this.path,\n this.explicitOrderBy.slice(),\n this.filters.slice(),\n this.limit,\n this.startAt,\n bound\n );\n }\n\n // TODO(b/29183165): This is used to get a unique string from a query to, for\n // example, use as a dictionary key, but the implementation is subject to\n // collisions. Make it collision-free.\n canonicalId(): string {\n if (this.memoizedCanonicalId === null) {\n let canonicalId = this.path.canonicalString();\n canonicalId += '|f:';\n for (const filter of this.filters) {\n canonicalId += filter.canonicalId();\n canonicalId += ',';\n }\n canonicalId += '|ob:';\n // TODO(dimond): make this collision resistant\n for (const orderBy of this.orderBy) {\n canonicalId += orderBy.canonicalId();\n canonicalId += ',';\n }\n if (!isNullOrUndefined(this.limit)) {\n canonicalId += '|l:';\n canonicalId += this.limit!;\n }\n if (this.startAt) {\n canonicalId += '|lb:';\n canonicalId += this.startAt.canonicalId();\n }\n if (this.endAt) {\n canonicalId += '|ub:';\n canonicalId += this.endAt.canonicalId();\n }\n this.memoizedCanonicalId = canonicalId;\n }\n return this.memoizedCanonicalId;\n }\n\n toString(): string {\n let str = 'Query(' + this.path.canonicalString();\n if (this.filters.length > 0) {\n str += `, filters: [${this.filters.join(', ')}]`;\n }\n if (!isNullOrUndefined(this.limit)) {\n str += ', limit: ' + this.limit;\n }\n if (this.explicitOrderBy.length > 0) {\n str += `, orderBy: [${this.explicitOrderBy.join(', ')}]`;\n }\n if (this.startAt) {\n str += ', startAt: ' + this.startAt.canonicalId();\n }\n if (this.endAt) {\n str += ', endAt: ' + this.endAt.canonicalId();\n }\n\n return str + ')';\n }\n\n equals(other: Query): boolean {\n if (this.limit !== other.limit) {\n return false;\n }\n\n if (this.orderBy.length !== other.orderBy.length) {\n return false;\n }\n\n for (let i = 0; i < this.orderBy.length; i++) {\n if (!this.orderBy[i].equals(other.orderBy[i])) {\n return false;\n }\n }\n\n if (this.filters.length !== other.filters.length) {\n return false;\n }\n\n for (let i = 0; i < this.filters.length; i++) {\n if (!this.filters[i].equals(other.filters[i])) {\n return false;\n }\n }\n\n if (!this.path.equals(other.path)) {\n return false;\n }\n\n if (\n this.startAt !== null\n ? !this.startAt.equals(other.startAt)\n : other.startAt !== null\n ) {\n return false;\n }\n\n return this.endAt !== null\n ? this.endAt.equals(other.endAt)\n : other.endAt === null;\n }\n\n docComparator(d1: Document, d2: Document): number {\n let comparedOnKeyField = false;\n for (const orderBy of this.orderBy) {\n const comp = orderBy.compare(d1, d2);\n if (comp !== 0) return comp;\n comparedOnKeyField = comparedOnKeyField || orderBy.field.isKeyField();\n }\n // Assert that we actually compared by key\n assert(\n comparedOnKeyField,\n \"orderBy used that doesn't compare on key field\"\n );\n return 0;\n }\n\n matches(doc: Document): boolean {\n return (\n this.matchesAncestor(doc) &&\n this.matchesOrderBy(doc) &&\n this.matchesFilters(doc) &&\n this.matchesBounds(doc)\n );\n }\n\n hasLimit(): boolean {\n return !isNullOrUndefined(this.limit);\n }\n\n getFirstOrderByField(): FieldPath | null {\n return this.explicitOrderBy.length > 0\n ? this.explicitOrderBy[0].field\n : null;\n }\n\n getInequalityFilterField(): FieldPath | null {\n for (const filter of this.filters) {\n if (filter instanceof RelationFilter && filter.isInequality()) {\n return filter.field;\n }\n }\n return null;\n }\n\n isDocumentQuery(): boolean {\n return DocumentKey.isDocumentKey(this.path) && this.filters.length === 0;\n }\n\n private matchesAncestor(doc: Document): boolean {\n const docPath = doc.key.path;\n if (DocumentKey.isDocumentKey(this.path)) {\n // exact match for document queries\n return this.path.equals(docPath);\n } else {\n // shallow ancestor queries by default\n return (\n this.path.isPrefixOf(docPath) && this.path.length === docPath.length - 1\n );\n }\n }\n\n /**\n * A document must have a value for every ordering clause in order to show up\n * in the results.\n */\n private matchesOrderBy(doc: Document): boolean {\n for (const orderBy of this.explicitOrderBy) {\n // order by key always matches\n if (\n !orderBy.field.isKeyField() &&\n doc.field(orderBy.field) === undefined\n ) {\n return false;\n }\n }\n return true;\n }\n\n private matchesFilters(doc: Document): boolean {\n for (const filter of this.filters) {\n if (!filter.matches(doc)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Makes sure a document is within the bounds, if provided.\n */\n private matchesBounds(doc: Document): boolean {\n if (this.startAt && !this.startAt.sortsBeforeDocument(this.orderBy, doc)) {\n return false;\n }\n if (this.endAt && this.endAt.sortsBeforeDocument(this.orderBy, doc)) {\n return false;\n }\n return true;\n }\n\n private assertValidBound(bound: Bound): void {\n assert(\n bound.position.length <= this.orderBy.length,\n 'Bound is longer than orderBy'\n );\n }\n}\n\nexport interface Filter {\n matches(doc: Document): boolean;\n canonicalId(): string;\n equals(filter: Filter): boolean;\n}\n\nexport class RelationOp {\n static LESS_THAN = new RelationOp('<');\n static LESS_THAN_OR_EQUAL = new RelationOp('<=');\n static EQUAL = new RelationOp('==');\n static GREATER_THAN = new RelationOp('>');\n static GREATER_THAN_OR_EQUAL = new RelationOp('>=');\n\n static fromString(op: string): RelationOp {\n switch (op) {\n case '<':\n return RelationOp.LESS_THAN;\n case '<=':\n return RelationOp.LESS_THAN_OR_EQUAL;\n case '==':\n return RelationOp.EQUAL;\n case '>=':\n return RelationOp.GREATER_THAN_OR_EQUAL;\n case '>':\n return RelationOp.GREATER_THAN;\n default:\n return fail('Unknown relation: ' + op);\n }\n }\n\n constructor(public name: string) {}\n\n toString(): string {\n return this.name;\n }\n\n equals(other: RelationOp): boolean {\n return this.name === other.name;\n }\n}\n\nexport class RelationFilter implements Filter {\n constructor(\n public field: FieldPath,\n public op: RelationOp,\n public value: FieldValue\n ) {}\n\n matches(doc: Document): boolean {\n if (this.field.isKeyField()) {\n assert(\n this.value instanceof RefValue,\n 'Comparing on key, but filter value not a RefValue'\n );\n const refValue = this.value as RefValue;\n const comparison = DocumentKey.comparator(doc.key, refValue.key);\n return this.matchesComparison(comparison);\n } else {\n const val = doc.field(this.field);\n return val !== undefined && this.matchesValue(val);\n }\n }\n\n private matchesValue(value: FieldValue): boolean {\n // Only compare types with matching backend order (such as double and int).\n if (this.value.typeOrder !== value.typeOrder) {\n return false;\n }\n return this.matchesComparison(value.compareTo(this.value));\n }\n\n private matchesComparison(comparison: number) {\n switch (this.op) {\n case RelationOp.LESS_THAN:\n return comparison < 0;\n case RelationOp.LESS_THAN_OR_EQUAL:\n return comparison <= 0;\n case RelationOp.EQUAL:\n return comparison === 0;\n case RelationOp.GREATER_THAN:\n return comparison > 0;\n case RelationOp.GREATER_THAN_OR_EQUAL:\n return comparison >= 0;\n default:\n return fail('Unknown relation op' + this.op);\n }\n }\n\n isInequality(): boolean {\n return this.op !== RelationOp.EQUAL;\n }\n\n canonicalId(): string {\n // TODO(b/29183165): Technically, this won't be unique if two values have\n // the same description, such as the int 3 and the string \"3\". So we should\n // add the types in here somehow, too.\n return (\n this.field.canonicalString() + this.op.toString() + this.value.toString()\n );\n }\n\n equals(other: Filter): boolean {\n if (other instanceof RelationFilter) {\n return (\n this.op.equals(other.op) &&\n this.field.equals(other.field) &&\n this.value.equals(other.value)\n );\n } else {\n return false;\n }\n }\n\n toString(): string {\n return `${this.field.canonicalString()} ${this.op} ${this.value.value()}`;\n }\n}\n\n/**\n * Filter that matches 'null' values.\n */\nexport class NullFilter implements Filter {\n constructor(public field: FieldPath) {}\n\n matches(doc: Document): boolean {\n const val = doc.field(this.field);\n return val !== undefined && val.value() === null;\n }\n\n canonicalId(): string {\n return this.field.canonicalString() + ' IS null';\n }\n\n toString(): string {\n return `${this.field.canonicalString()} IS null`;\n }\n\n equals(other: Filter): boolean {\n if (other instanceof NullFilter) {\n return this.field.equals(other.field);\n } else {\n return false;\n }\n }\n}\n\n/**\n * Filter that matches 'NaN' values.\n */\nexport class NanFilter implements Filter {\n constructor(public field: FieldPath) {}\n\n matches(doc: Document): boolean {\n const val = doc.field(this.field).value();\n return typeof val === 'number' && isNaN(val);\n }\n\n canonicalId(): string {\n return this.field.canonicalString() + ' IS NaN';\n }\n\n toString(): string {\n return `${this.field.canonicalString()} IS NaN`;\n }\n\n equals(other: Filter): boolean {\n if (other instanceof NanFilter) {\n return this.field.equals(other.field);\n } else {\n return false;\n }\n }\n}\n\n/**\n * Creates a filter based on the provided arguments.\n */\nexport function fieldFilter(\n field: FieldPath,\n op: RelationOp,\n value: FieldValue\n) {\n if (value.equals(NullValue.INSTANCE)) {\n if (op !== RelationOp.EQUAL) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid query. You can only perform equals ' + 'comparisons on null.'\n );\n }\n return new NullFilter(field);\n } else if (value.equals(DoubleValue.NAN)) {\n if (op !== RelationOp.EQUAL) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid query. You can only perform equals ' + 'comparisons on NaN.'\n );\n }\n return new NanFilter(field);\n } else {\n return new RelationFilter(field, op, value);\n }\n}\n\n/**\n * The direction of sorting in an order by.\n */\nexport class Direction {\n static ASCENDING = new Direction('asc');\n static DESCENDING = new Direction('desc');\n\n private constructor(public name: string) {}\n\n toString(): string {\n return this.name;\n }\n}\n\n/**\n * Represents a bound of a query.\n *\n * The bound is specified with the given components representing a position and\n * whether it's just before or just after the position (relative to whatever the\n * query order is).\n *\n * The position represents a logical index position for a query. It's a prefix\n * of values for the (potentially implicit) order by clauses of a query.\n *\n * Bound provides a function to determine whether a document comes before or\n * after a bound. This is influenced by whether the position is just before or\n * just after the provided values.\n */\nexport class Bound {\n constructor(readonly position: FieldValue[], readonly before: boolean) {}\n\n canonicalId(): string {\n // TODO(b/29183165): Make this collision robust.\n let canonicalId = this.before ? 'b:' : 'a:';\n for (const component of this.position) {\n canonicalId += component.toString();\n }\n return canonicalId;\n }\n\n /**\n * Returns true if a document sorts before a bound using the provided sort\n * order.\n */\n sortsBeforeDocument(orderBy: OrderBy[], doc: Document): boolean {\n assert(\n this.position.length <= orderBy.length,\n \"Bound has more components than query's orderBy\"\n );\n let comparison = 0;\n for (let i = 0; i < this.position.length; i++) {\n const orderByComponent = orderBy[i];\n const component = this.position[i];\n if (orderByComponent.field.isKeyField()) {\n assert(\n component instanceof RefValue,\n 'Bound has a non-key value where the key path is being used.'\n );\n comparison = DocumentKey.comparator(\n (component as RefValue).key,\n doc.key\n );\n } else {\n const docValue = doc.field(orderByComponent.field);\n assert(\n docValue !== undefined,\n 'Field should exist since document matched the orderBy already.'\n );\n comparison = component.compareTo(docValue);\n }\n if (orderByComponent.dir === Direction.DESCENDING) {\n comparison = comparison * -1;\n }\n if (comparison !== 0) {\n break;\n }\n }\n return this.before ? comparison <= 0 : comparison < 0;\n }\n\n equals(other: Bound | null): boolean {\n if (other === null) {\n return false;\n }\n if (\n this.before !== other.before ||\n this.position.length !== other.position.length\n ) {\n return false;\n }\n for (let i = 0; i < this.position.length; i++) {\n const thisPosition = this.position[i];\n const otherPosition = other.position[i];\n return thisPosition.equals(otherPosition);\n }\n return true;\n }\n}\n\n/**\n * An ordering on a field, in some Direction. Direction defaults to ASCENDING.\n */\nexport class OrderBy {\n readonly dir: Direction;\n private readonly isKeyOrderBy: boolean;\n\n constructor(public readonly field: FieldPath, dir?: Direction) {\n if (dir === undefined) {\n dir = Direction.ASCENDING;\n }\n this.dir = dir;\n this.isKeyOrderBy = field.isKeyField();\n }\n\n compare(d1: Document, d2: Document): number {\n const comparison = this.isKeyOrderBy\n ? Document.compareByKey(d1, d2)\n : Document.compareByField(this.field, d1, d2);\n switch (this.dir) {\n case Direction.ASCENDING:\n return comparison;\n case Direction.DESCENDING:\n return -1 * comparison;\n default:\n return fail('Unknown direction: ' + this.dir);\n }\n }\n\n canonicalId(): string {\n // TODO(b/29183165): Make this collision robust.\n return this.field.canonicalString() + this.dir.toString();\n }\n\n toString(): string {\n return `${this.field.canonicalString()} (${this.dir})`;\n }\n\n equals(other: OrderBy): boolean {\n return this.dir === other.dir && this.field.equals(other.field);\n }\n}\n\nconst KEY_ORDERING_ASC = new OrderBy(FieldPath.keyField(), Direction.ASCENDING);\nconst KEY_ORDERING_DESC = new OrderBy(\n FieldPath.keyField(),\n Direction.DESCENDING\n);\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/query.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { fail } from '../util/assert';\nimport { Code } from '../util/error';\n\n/**\n * Error Codes describing the different ways GRPC can fail. These are copied\n * directly from GRPC's sources here:\n *\n * https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h\n *\n * Important! The names of these identifiers matter because the string forms\n * are used for reverse lookups from the webchannel stream. Do NOT change the\n * names of these identifiers.\n */\nenum RpcCode {\n OK = 0,\n CANCELLED = 1,\n UNKNOWN = 2,\n INVALID_ARGUMENT = 3,\n DEADLINE_EXCEEDED = 4,\n NOT_FOUND = 5,\n ALREADY_EXISTS = 6,\n PERMISSION_DENIED = 7,\n UNAUTHENTICATED = 16,\n RESOURCE_EXHAUSTED = 8,\n FAILED_PRECONDITION = 9,\n ABORTED = 10,\n OUT_OF_RANGE = 11,\n UNIMPLEMENTED = 12,\n INTERNAL = 13,\n UNAVAILABLE = 14,\n DATA_LOSS = 15\n}\n\nexport function isPermanentError(code: Code): boolean {\n switch (code) {\n case Code.OK:\n return fail('Treated status OK as error');\n case Code.CANCELLED:\n case Code.UNKNOWN:\n case Code.DEADLINE_EXCEEDED:\n case Code.RESOURCE_EXHAUSTED:\n case Code.INTERNAL:\n case Code.UNAVAILABLE:\n // Unauthenticated means something went wrong with our token and we need\n // to retry with new credentials which will happen automatically.\n // TODO(b/37325376): Give up after second unauthenticated error.\n case Code.UNAUTHENTICATED:\n return false;\n case Code.INVALID_ARGUMENT:\n case Code.NOT_FOUND:\n case Code.ALREADY_EXISTS:\n case Code.PERMISSION_DENIED:\n case Code.FAILED_PRECONDITION:\n // Aborted might be retried in some scenarios, but that is dependant on\n // the context and should handled individually by the calling code.\n // See https://cloud.google.com/apis/design/errors.\n case Code.ABORTED:\n case Code.OUT_OF_RANGE:\n case Code.UNIMPLEMENTED:\n case Code.DATA_LOSS:\n return true;\n default:\n return fail('Unknown status code: ' + code);\n }\n}\n\n/**\n * Maps an error Code from a GRPC status identifier like 'NOT_FOUND'.\n *\n * @returns The Code equivalent to the given status string or undefined if\n * there is no match.\n */\nexport function mapCodeFromRpcStatus(status: string): Code | undefined {\n // tslint:disable-next-line:no-any lookup by string\n const code: RpcCode = RpcCode[status as any] as any;\n if (code === undefined) {\n return undefined;\n }\n\n return mapCodeFromRpcCode(code);\n}\n\n/**\n * Maps an error Code from GRPC status code number, like 0, 1, or 14. These\n * are not the same as HTTP status codes.\n *\n * @returns The Code equivalent to the given GRPC status code. Fails if there\n * is no match.\n */\nexport function mapCodeFromRpcCode(code: number): Code {\n switch (code) {\n case RpcCode.OK:\n return Code.OK;\n case RpcCode.CANCELLED:\n return Code.CANCELLED;\n case RpcCode.UNKNOWN:\n return Code.UNKNOWN;\n case RpcCode.DEADLINE_EXCEEDED:\n return Code.DEADLINE_EXCEEDED;\n case RpcCode.RESOURCE_EXHAUSTED:\n return Code.RESOURCE_EXHAUSTED;\n case RpcCode.INTERNAL:\n return Code.INTERNAL;\n case RpcCode.UNAVAILABLE:\n return Code.UNAVAILABLE;\n case RpcCode.UNAUTHENTICATED:\n return Code.UNAUTHENTICATED;\n case RpcCode.INVALID_ARGUMENT:\n return Code.INVALID_ARGUMENT;\n case RpcCode.NOT_FOUND:\n return Code.NOT_FOUND;\n case RpcCode.ALREADY_EXISTS:\n return Code.ALREADY_EXISTS;\n case RpcCode.PERMISSION_DENIED:\n return Code.PERMISSION_DENIED;\n case RpcCode.FAILED_PRECONDITION:\n return Code.FAILED_PRECONDITION;\n case RpcCode.ABORTED:\n return Code.ABORTED;\n case RpcCode.OUT_OF_RANGE:\n return Code.OUT_OF_RANGE;\n case RpcCode.UNIMPLEMENTED:\n return Code.UNIMPLEMENTED;\n case RpcCode.DATA_LOSS:\n return Code.DATA_LOSS;\n default:\n return fail('Unknown status code: ' + code);\n }\n}\n\n/**\n * Maps an RPC code from a Code. This is the reverse operation from\n * mapCodeFromRpcCode and should really only be used in tests.\n */\nexport function mapRpcCodeFromCode(code: Code | undefined): number {\n if (code === undefined) {\n return RpcCode.OK;\n }\n\n switch (code) {\n case Code.OK:\n return RpcCode.OK;\n case Code.CANCELLED:\n return RpcCode.CANCELLED;\n case Code.UNKNOWN:\n return RpcCode.UNKNOWN;\n case Code.DEADLINE_EXCEEDED:\n return RpcCode.DEADLINE_EXCEEDED;\n case Code.RESOURCE_EXHAUSTED:\n return RpcCode.RESOURCE_EXHAUSTED;\n case Code.INTERNAL:\n return RpcCode.INTERNAL;\n case Code.UNAVAILABLE:\n return RpcCode.UNAVAILABLE;\n case Code.UNAUTHENTICATED:\n return RpcCode.UNAUTHENTICATED;\n case Code.INVALID_ARGUMENT:\n return RpcCode.INVALID_ARGUMENT;\n case Code.NOT_FOUND:\n return RpcCode.NOT_FOUND;\n case Code.ALREADY_EXISTS:\n return RpcCode.ALREADY_EXISTS;\n case Code.PERMISSION_DENIED:\n return RpcCode.PERMISSION_DENIED;\n case Code.FAILED_PRECONDITION:\n return RpcCode.FAILED_PRECONDITION;\n case Code.ABORTED:\n return RpcCode.ABORTED;\n case Code.OUT_OF_RANGE:\n return RpcCode.OUT_OF_RANGE;\n case Code.UNIMPLEMENTED:\n return RpcCode.UNIMPLEMENTED;\n case Code.DATA_LOSS:\n return RpcCode.DATA_LOSS;\n default:\n return fail('Unknown status code: ' + code);\n }\n}\n\n/**\n * Converts an HTTP Status Code to the equivalent error code.\n *\n * @param status An HTTP Status Code, like 200, 404, 503, etc.\n * @returns The equivalent Code. Unknown status codes are mapped to\n * Code.UNKNOWN.\n */\nexport function mapCodeFromHttpStatus(status: number): Code {\n // The canonical error codes for Google APIs [1] specify mapping onto HTTP\n // status codes but the mapping is not bijective. In each case of ambiguity\n // this function chooses a primary error.\n //\n // [1]\n // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto\n switch (status) {\n case 200: // OK\n return Code.OK;\n\n case 400: // Bad Request\n return Code.INVALID_ARGUMENT;\n // Other possibilities based on the forward mapping\n // return Code.FAILED_PRECONDITION;\n // return Code.OUT_OF_RANGE;\n\n case 401: // Unauthorized\n return Code.UNAUTHENTICATED;\n\n case 403: // Forbidden\n return Code.PERMISSION_DENIED;\n\n case 404: // Not Found\n return Code.NOT_FOUND;\n\n case 409: // Conflict\n return Code.ABORTED;\n // Other possibilities:\n // return Code.ALREADY_EXISTS;\n\n case 416: // Range Not Satisfiable\n return Code.OUT_OF_RANGE;\n\n case 429: // Too Many Requests\n return Code.RESOURCE_EXHAUSTED;\n\n case 499: // Client Closed Request\n return Code.CANCELLED;\n\n case 500: // Internal Server Error\n return Code.UNKNOWN;\n // Other possibilities:\n // return Code.INTERNAL;\n // return Code.DATA_LOSS;\n\n case 501: // Unimplemented\n return Code.UNIMPLEMENTED;\n\n case 503: // Service Unavailable\n return Code.UNAVAILABLE;\n\n case 504: // Gateway Timeout\n return Code.DEADLINE_EXCEEDED;\n\n default:\n if (status >= 200 && status < 300) return Code.OK;\n if (status >= 400 && status < 500) return Code.FAILED_PRECONDITION;\n if (status >= 500 && status < 600) return Code.INTERNAL;\n return Code.UNKNOWN;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/rpc_error.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { SortedMap } from '../util/sorted_map';\nimport { SortedSet } from '../util/sorted_set';\n\nimport { Document, MaybeDocument } from './document';\nimport { DocumentKey } from './document_key';\n\n/** Miscellaneous collection types / constants. */\n\nexport type MaybeDocumentMap = SortedMap;\nconst EMPTY_MAYBE_DOCUMENT_MAP = new SortedMap(\n DocumentKey.comparator\n);\nexport function maybeDocumentMap() {\n return EMPTY_MAYBE_DOCUMENT_MAP;\n}\n\nexport type DocumentMap = SortedMap;\nconst EMPTY_DOCUMENT_MAP = new SortedMap(\n DocumentKey.comparator\n);\nexport function documentMap() {\n return EMPTY_DOCUMENT_MAP;\n}\n\nexport type DocumentVersionMap = SortedMap;\nconst EMPTY_DOCUMENT_VERSION_MAP = new SortedMap(\n DocumentKey.comparator\n);\nexport function documentVersionMap() {\n return EMPTY_DOCUMENT_VERSION_MAP;\n}\n\nexport type DocumentKeySet = SortedSet;\nconst EMPTY_DOCUMENT_KEY_SET = new SortedSet(DocumentKey.comparator);\nexport function documentKeySet() {\n return EMPTY_DOCUMENT_KEY_SET;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/collections.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { ProtoByteString, TargetId } from '../core/types';\nimport { QueryData } from '../local/query_data';\nimport { maybeDocumentMap } from '../model/collections';\nimport { Document, NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { emptyByteString } from '../platform/platform';\nimport { assert, fail } from '../util/assert';\nimport { FirestoreError } from '../util/error';\nimport * as objUtils from '../util/obj';\n\nimport { ExistenceFilter } from './existence_filter';\nimport {\n CurrentStatusUpdate,\n RemoteEvent,\n ResetMapping,\n TargetChange,\n UpdateMapping\n} from './remote_event';\n\n/**\n * Internal representation of the watcher API protocol buffers.\n */\nexport type WatchChange =\n | DocumentWatchChange\n | WatchTargetChange\n | ExistenceFilterChange;\n\n/**\n * Represents a changed document and a list of target ids to which this change\n * applies.\n *\n * If document has been deleted NoDocument will be provided.\n */\nexport class DocumentWatchChange {\n constructor(\n /** The new document applies to all of these targets. */\n public updatedTargetIds: TargetId[],\n /** The new document is removed from all of these targets. */\n public removedTargetIds: TargetId[],\n /** The key of the document for this change. */\n public key: DocumentKey,\n /**\n * The new document or NoDocument if it was deleted. Is null if the\n * document went out of view without the server sending a new document.\n */\n public newDoc: Document | NoDocument | null\n ) {}\n}\n\nexport class ExistenceFilterChange {\n constructor(\n public targetId: TargetId,\n public existenceFilter: ExistenceFilter\n ) {}\n}\n\nexport enum WatchTargetChangeState {\n NoChange,\n Added,\n Removed,\n Current,\n Reset\n}\n\nexport class WatchTargetChange {\n constructor(\n /** What kind of change occurred to the watch target. */\n public state: WatchTargetChangeState,\n /** The target IDs that were added/removed/set. */\n public targetIds: TargetId[],\n /**\n * An opaque, server-assigned token that allows watching a query to be\n * resumed after disconnecting without retransmitting all the data that\n * matches the query. The resume token essentially identifies a point in\n * time from which the server should resume sending results.\n */\n public resumeToken: ProtoByteString = emptyByteString(),\n /** An RPC error indicating why the watch failed. */\n public cause: FirestoreError | null = null\n ) {}\n}\n\n/**\n * A helper class to accumulate watch changes into a RemoteEvent and other\n * target information.\n */\nexport class WatchChangeAggregator {\n constructor(\n private snapshotVersion: SnapshotVersion,\n private readonly listenTargets: { [targetId: number]: QueryData },\n pendingTargetResponses: { [targetId: number]: number }\n ) {\n this.pendingTargetResponses = objUtils.shallowCopy(pendingTargetResponses);\n }\n\n /** The existence filter - if any - for the given target IDs. */\n readonly existenceFilters: { [targetId: number]: ExistenceFilter } = {};\n\n /** The number of pending responses that we are waiting on from watch. */\n readonly pendingTargetResponses: { [targetId: number]: number };\n\n /** Keeps track of the current target mappings */\n private targetChanges: { [targetId: number]: TargetChange } = {};\n\n /** Keeps track of document to update */\n private documentUpdates = maybeDocumentMap();\n\n /** Whether this aggregator was frozen and can no longer be modified */\n private frozen = false;\n\n /** Aggregates a watch change into the current state */\n add(watchChange: WatchChange): void {\n assert(!this.frozen, 'Trying to modify frozen WatchChangeAggregator.');\n if (watchChange instanceof DocumentWatchChange) {\n this.addDocumentChange(watchChange);\n } else if (watchChange instanceof WatchTargetChange) {\n this.addTargetChange(watchChange);\n } else if (watchChange instanceof ExistenceFilterChange) {\n this.addExistenceFilterChange(watchChange);\n } else {\n fail('Unknown watch change: ' + watchChange);\n }\n }\n\n /** Aggregates all provided watch changes to the current state in order */\n addChanges(watchChanges: WatchChange[]): void {\n assert(!this.frozen, 'Trying to modify frozen WatchChangeAggregator.');\n watchChanges.forEach(change => this.add(change));\n }\n\n /**\n * Converts the current state into a remote event with the snapshot version\n * provided via the constructor.\n */\n createRemoteEvent(): RemoteEvent {\n const targetChanges = this.targetChanges;\n\n // Remove all the non-active targets from the remote event.\n objUtils.forEachNumber(this.targetChanges, targetId => {\n if (!this.isActiveTarget(targetId)) {\n delete targetChanges[targetId];\n }\n });\n\n // Mark this aggregator as frozen so no further modifications are made\n this.frozen = true;\n return new RemoteEvent(\n this.snapshotVersion,\n targetChanges,\n this.documentUpdates\n );\n }\n\n private ensureTargetChange(targetId: TargetId): TargetChange {\n let change = this.targetChanges[targetId];\n if (!change) {\n // Create an UpdateMapping by default, since resets are always explicit.\n change = {\n currentStatusUpdate: CurrentStatusUpdate.None,\n snapshotVersion: this.snapshotVersion,\n mapping: new UpdateMapping(),\n resumeToken: emptyByteString()\n };\n this.targetChanges[targetId] = change;\n }\n return change;\n }\n\n /**\n * We need to wait for watch to ack targets before we process those events,\n * so to know if a target is active, there must be no pending acks we're\n * waiting for and it must be in the current list of targets that the client\n * cares about.\n *\n * This method is visible for testing.\n */\n protected isActiveTarget(targetId: TargetId): boolean {\n return (\n !objUtils.contains(this.pendingTargetResponses, targetId) &&\n objUtils.contains(this.listenTargets, targetId)\n );\n }\n\n private addDocumentChange(docChange: DocumentWatchChange) {\n let relevant = false;\n\n for (const targetId of docChange.updatedTargetIds) {\n if (this.isActiveTarget(targetId)) {\n const change = this.ensureTargetChange(targetId);\n change.mapping.add(docChange.key);\n relevant = true;\n }\n }\n\n for (const targetId of docChange.removedTargetIds) {\n if (this.isActiveTarget(targetId)) {\n const change = this.ensureTargetChange(targetId);\n change.mapping.delete(docChange.key);\n relevant = true;\n }\n }\n\n // Only update the document if there is a new document to replace to an\n // active target that is being listened to, this might be just a target\n // update instead.\n if (docChange.newDoc && relevant) {\n this.documentUpdates = this.documentUpdates.insert(\n docChange.key,\n docChange.newDoc\n );\n }\n }\n\n private addTargetChange(targetChange: WatchTargetChange) {\n targetChange.targetIds.forEach(targetId => {\n const change = this.ensureTargetChange(targetId);\n switch (targetChange.state) {\n case WatchTargetChangeState.NoChange:\n if (this.isActiveTarget(targetId)) {\n // Creating the change above satisfies the semantics of no-change.\n applyResumeToken(change, targetChange.resumeToken);\n }\n break;\n case WatchTargetChangeState.Added:\n // We need to decrement the number of pending acks needed from watch\n // for this targetId.\n this.recordTargetResponse(targetId);\n if (!objUtils.contains(this.pendingTargetResponses, targetId)) {\n // We have a freshly added target, so we need to reset any state\n // that we had previously This can happen e.g. when remove and add\n // back a target for existence filter mismatches.\n change.mapping = new UpdateMapping();\n change.currentStatusUpdate = CurrentStatusUpdate.None;\n delete this.existenceFilters[targetId];\n }\n applyResumeToken(change, targetChange.resumeToken);\n break;\n case WatchTargetChangeState.Removed:\n // We need to keep track of removed targets to we can\n // post-filter and remove any target changes.\n // We need to decrement the number of pending acks needed from watch\n // for this targetId.\n this.recordTargetResponse(targetId);\n assert(\n !targetChange.cause,\n 'WatchChangeAggregator does not handle errored targets'\n );\n break;\n case WatchTargetChangeState.Current:\n if (this.isActiveTarget(targetId)) {\n change.currentStatusUpdate = CurrentStatusUpdate.MarkCurrent;\n applyResumeToken(change, targetChange.resumeToken);\n }\n break;\n case WatchTargetChangeState.Reset:\n if (this.isActiveTarget(targetId)) {\n // Overwrite any existing target mapping with a reset\n // mapping. Every subsequent update will modify the reset\n // mapping, not an update mapping.\n change.mapping = new ResetMapping();\n applyResumeToken(change, targetChange.resumeToken);\n }\n break;\n default:\n fail('Unknown target watch change state: ' + targetChange.state);\n }\n });\n }\n\n /**\n * Record that we get a watch target add/remove by decrementing the number of\n * pending target responses that we have.\n */\n private recordTargetResponse(targetId: TargetId): void {\n const newCount = (this.pendingTargetResponses[targetId] || 0) - 1;\n if (newCount === 0) {\n delete this.pendingTargetResponses[targetId];\n } else {\n this.pendingTargetResponses[targetId] = newCount;\n }\n }\n\n private addExistenceFilterChange(change: ExistenceFilterChange): void {\n if (this.isActiveTarget(change.targetId)) {\n this.existenceFilters[change.targetId] = change.existenceFilter;\n }\n }\n}\n\n/**\n * Applies the resume token to the TargetChange, but only when it has a new\n * value. null and empty resumeTokens are discarded.\n */\nfunction applyResumeToken(\n change: TargetChange,\n resumeToken: ProtoByteString\n): void {\n if (resumeToken.length > 0) {\n change.resumeToken = resumeToken;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/watch_change.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '../protos/firestore_proto_api';\nimport { Blob } from '../api/blob';\nimport { GeoPoint } from '../api/geo_point';\nimport { DatabaseId } from '../core/database_info';\nimport {\n Bound,\n Direction,\n Filter,\n NanFilter,\n NullFilter,\n OrderBy,\n Query,\n RelationFilter,\n RelationOp\n} from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { Timestamp } from '../core/timestamp';\nimport { ProtoByteString, TargetId } from '../core/types';\nimport { QueryData, QueryPurpose } from '../local/query_data';\nimport { Document, MaybeDocument, NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport * as fieldValue from '../model/field_value';\nimport {\n DeleteMutation,\n FieldMask,\n FieldTransform,\n Mutation,\n MutationResult,\n PatchMutation,\n Precondition,\n ServerTimestampTransform,\n SetMutation,\n TransformMutation\n} from '../model/mutation';\nimport { FieldPath, ResourcePath } from '../model/path';\nimport { assert, fail } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport { AnyJs } from '../util/misc';\nimport * as obj from '../util/obj';\nimport * as typeUtils from '../util/types';\n\nimport { ExistenceFilter } from './existence_filter';\nimport { mapCodeFromRpcCode, mapRpcCodeFromCode } from './rpc_error';\nimport {\n DocumentWatchChange,\n ExistenceFilterChange,\n WatchChange,\n WatchTargetChange,\n WatchTargetChangeState\n} from './watch_change';\nimport { ApiClientObjectMap } from '../protos/firestore_proto_api';\n\nconst DIRECTIONS = (() => {\n const dirs: { [dir: string]: api.OrderDirection } = {};\n dirs[Direction.ASCENDING.name] = 'ASCENDING';\n dirs[Direction.DESCENDING.name] = 'DESCENDING';\n return dirs;\n})();\n\nconst OPERATORS = (() => {\n const ops: { [op: string]: api.FieldFilterOp } = {};\n ops[RelationOp.LESS_THAN.name] = 'LESS_THAN';\n ops[RelationOp.LESS_THAN_OR_EQUAL.name] = 'LESS_THAN_OR_EQUAL';\n ops[RelationOp.GREATER_THAN.name] = 'GREATER_THAN';\n ops[RelationOp.GREATER_THAN_OR_EQUAL.name] = 'GREATER_THAN_OR_EQUAL';\n ops[RelationOp.EQUAL.name] = 'EQUAL';\n return ops;\n})();\n\nfunction assertPresent(value: AnyJs, description: string) {\n assert(!typeUtils.isNullOrUndefined(value), description + ' is missing');\n}\n\nfunction parseInt64(value: number | string): number {\n // TODO(bjornick): Handle int64 greater than 53 bits.\n if (typeof value === 'number') {\n return value;\n } else if (typeof value === 'string') {\n return parseInt(value, 10);\n } else {\n return fail(\"can't parse \" + value);\n }\n}\n\n// This is a supplement to the generated proto interfaces, which fail to account\n// for the fact that a timestamp may be encoded as either a string OR this.\ninterface TimestampProto {\n seconds?: string;\n nanos?: number;\n}\n\nexport interface SerializerOptions {\n /**\n * The serializer supports both Protobuf.js and Proto3 JSON formats. By\n * setting this flag to true, the serializer will use the Proto3 JSON format.\n *\n * For a description of the Proto3 JSON format check\n * https://developers.google.com/protocol-buffers/docs/proto3#json\n */\n useProto3Json: boolean;\n}\n\n/**\n * Generates JsonObject values for the Datastore API suitable for sending to\n * either GRPC stub methods or via the JSON/HTTP REST API.\n * TODO(klimt): We can remove the databaseId argument if we keep the full\n * resource name in documents.\n */\nexport class JsonProtoSerializer {\n constructor(\n private databaseId: DatabaseId,\n private options: SerializerOptions\n ) {}\n\n private emptyByteString(): ProtoByteString {\n if (this.options.useProto3Json) {\n return '';\n } else {\n return new Uint8Array(0);\n }\n }\n\n private unsafeCastProtoByteString(byteString: ProtoByteString): string {\n // byteStrings can be either string or UInt8Array, but the typings say\n // it's always a string. Cast as string to avoid type check failing\n return byteString as string;\n }\n\n fromRpcStatus(status: api.Status): FirestoreError {\n const code =\n status.code === undefined\n ? Code.UNKNOWN\n : mapCodeFromRpcCode(status.code);\n return new FirestoreError(code, status.message || '');\n }\n\n /**\n * Returns a value for a Date that's appropriate to put into a proto.\n * DO NOT USE THIS FOR ANYTHING ELSE.\n * This method cheats. It's typed as returning \"string\" because that's what\n * our generated proto interfaces say dates must be. But it's easier and safer\n * to actually return a Timestamp proto.\n */\n private toTimestamp(timestamp: Timestamp): string {\n return {\n seconds: timestamp.seconds,\n nanos: timestamp.nanos\n // tslint:disable-next-line:no-any\n } as any;\n }\n\n private fromTimestamp(date: string | TimestampProto): Timestamp {\n // The json interface (for the browser) will return an iso timestamp string,\n // while the proto js library (for node) will return a\n // google.protobuf.Timestamp instance.\n if (typeof date === 'string') {\n // TODO(b/37282237): Use strings for Proto3 timestamps\n // assert(this.options.useProto3Json,\n // 'The timestamp string format requires Proto3.');\n return Timestamp.fromISOString(date);\n } else {\n assert(!!date, 'Cannot deserialize null or undefined timestamp.');\n // TODO(b/37282237): Use strings for Proto3 timestamps\n // assert(!this.options.useProto3Json,\n // 'The timestamp instance format requires Proto JS.');\n const seconds = parseInt64(date.seconds || '0');\n const nanos = date.nanos || 0;\n return new Timestamp(seconds, nanos);\n }\n }\n\n /**\n * Returns a value for bytes that's appropriate to put in a proto.\n * DO NOT USE THIS FOR ANYTHING ELSE.\n * This method cheats. It's typed as returning \"string\" because that's what\n * our generated proto interfaces say bytes must be. But it should return\n * an Uint8Array in Node.\n */\n private toBytes(bytes: Blob): string {\n if (this.options.useProto3Json) {\n return bytes.toBase64();\n } else {\n // The typings say it's a string, but it needs to be a Uint8Array in Node.\n return this.unsafeCastProtoByteString(bytes.toUint8Array());\n }\n }\n\n /**\n * Parse the blob from the protos into the internal Blob class. Note that the\n * typings assume all blobs are strings, but they are actually Uint8Arrays\n * on Node.\n */\n private fromBlob(blob: string | Uint8Array): Blob {\n if (typeof blob === 'string') {\n assert(\n this.options.useProto3Json,\n 'Expected bytes to be passed in as Uint8Array, but got a string instead.'\n );\n return Blob.fromBase64String(blob);\n } else {\n assert(\n !this.options.useProto3Json,\n 'Expected bytes to be passed in as string, but got something else instead.'\n );\n return Blob.fromUint8Array(blob);\n }\n }\n\n toVersion(version: SnapshotVersion): string {\n return this.toTimestamp(version.toTimestamp());\n }\n\n fromVersion(version: string): SnapshotVersion {\n assert(!!version, \"Trying to deserialize version that isn't set\");\n return SnapshotVersion.fromTimestamp(this.fromTimestamp(version));\n }\n\n toResourceName(databaseId: DatabaseId, path: ResourcePath): string {\n return this.fullyQualifiedPrefixPath(databaseId)\n .child('documents')\n .child(path)\n .canonicalString();\n }\n\n fromResourceName(name: string): ResourcePath {\n const resource = ResourcePath.fromString(name);\n assert(\n this.isValidResourceName(resource),\n 'Tried to deserialize invalid key ' + resource.toString()\n );\n return resource;\n }\n\n toName(key: DocumentKey): string {\n return this.toResourceName(this.databaseId, key.path);\n }\n\n fromName(name: string): DocumentKey {\n const resource = this.fromResourceName(name);\n assert(\n resource.get(1) === this.databaseId.projectId,\n 'Tried to deserialize key from different project: ' +\n resource.get(1) +\n ' vs ' +\n this.databaseId.projectId\n );\n assert(\n (!resource.get(3) && !this.databaseId.database) ||\n resource.get(3) === this.databaseId.database,\n 'Tried to deserialize key from different database: ' +\n resource.get(3) +\n ' vs ' +\n this.databaseId.database\n );\n return new DocumentKey(this.extractLocalPathFromResourceName(resource));\n }\n\n toQueryPath(path: ResourcePath): string {\n if (path.length === 0) {\n // If the path is empty, the backend requires we leave off the /documents\n // at the end.\n return this.encodedDatabaseId;\n }\n return this.toResourceName(this.databaseId, path);\n }\n\n fromQueryPath(name: string): ResourcePath {\n const resourceName = this.fromResourceName(name);\n if (resourceName.length === 4) {\n return ResourcePath.EMPTY_PATH;\n }\n return this.extractLocalPathFromResourceName(resourceName);\n }\n\n get encodedDatabaseId(): string {\n const path = new ResourcePath([\n 'projects',\n this.databaseId.projectId,\n 'databases',\n this.databaseId.database\n ]);\n return path.canonicalString();\n }\n\n private fullyQualifiedPrefixPath(databaseId: DatabaseId): ResourcePath {\n return new ResourcePath([\n 'projects',\n databaseId.projectId,\n 'databases',\n databaseId.database\n ]);\n }\n\n private extractLocalPathFromResourceName(\n resourceName: ResourcePath\n ): ResourcePath {\n assert(\n resourceName.length > 4 && resourceName.get(4) === 'documents',\n 'tried to deserialize invalid key ' + resourceName.toString()\n );\n return resourceName.popFirst(5);\n }\n\n private isValidResourceName(path: ResourcePath): boolean {\n // Resource names have at least 4 components (project ID, database ID)\n return (\n path.length >= 4 &&\n path.get(0) === 'projects' &&\n path.get(2) === 'databases'\n );\n }\n\n toValue(val: fieldValue.FieldValue): api.Value {\n if (val instanceof fieldValue.NullValue) {\n return { nullValue: 'NULL_VALUE' };\n } else if (val instanceof fieldValue.BooleanValue) {\n return { booleanValue: val.value() };\n } else if (val instanceof fieldValue.IntegerValue) {\n return { integerValue: '' + val.value() };\n } else if (val instanceof fieldValue.DoubleValue) {\n const doubleValue = val.value();\n if (this.options.useProto3Json) {\n // Proto 3 let's us encode NaN and Infinity as string values as\n // expected by the backend. This is currently not checked by our unit\n // tests because they rely on protobuf.js.\n if (isNaN(doubleValue)) {\n return { doubleValue: 'NaN' } as {};\n } else if (doubleValue === Infinity) {\n return { doubleValue: 'Infinity' } as {};\n } else if (doubleValue === -Infinity) {\n return { doubleValue: '-Infinity' } as {};\n }\n }\n return { doubleValue: val.value() };\n } else if (val instanceof fieldValue.StringValue) {\n return { stringValue: val.value() };\n } else if (val instanceof fieldValue.ObjectValue) {\n return { mapValue: this.toMapValue(val) };\n } else if (val instanceof fieldValue.ArrayValue) {\n return { arrayValue: this.toArrayValue(val) };\n } else if (val instanceof fieldValue.TimestampValue) {\n return {\n timestampValue: this.toTimestamp(val.internalValue)\n };\n } else if (val instanceof fieldValue.GeoPointValue) {\n return {\n geoPointValue: {\n latitude: val.value().latitude,\n longitude: val.value().longitude\n }\n };\n } else if (val instanceof fieldValue.BlobValue) {\n return {\n bytesValue: this.toBytes(val.value())\n };\n } else if (val instanceof fieldValue.RefValue) {\n return {\n referenceValue: this.toResourceName(val.databaseId, val.key.path)\n };\n } else {\n return fail('Unknown FieldValue ' + JSON.stringify(val));\n }\n }\n\n fromValue(obj: api.Value): fieldValue.FieldValue {\n // tslint:disable-next-line:no-any\n const type = (obj as any)['value_type'];\n if (hasTag(obj, type, 'nullValue')) {\n return fieldValue.NullValue.INSTANCE;\n } else if (hasTag(obj, type, 'booleanValue')) {\n return fieldValue.BooleanValue.of(obj.booleanValue!);\n } else if (hasTag(obj, type, 'integerValue')) {\n return new fieldValue.IntegerValue(parseInt64(obj.integerValue!));\n } else if (hasTag(obj, type, 'doubleValue')) {\n if (this.options.useProto3Json) {\n // Proto 3 uses the string values 'NaN' and 'Infinity'.\n if ((obj.doubleValue as {}) === 'NaN') {\n return fieldValue.DoubleValue.NAN;\n } else if ((obj.doubleValue as {}) === 'Infinity') {\n return fieldValue.DoubleValue.POSITIVE_INFINITY;\n } else if ((obj.doubleValue as {}) === '-Infinity') {\n return fieldValue.DoubleValue.NEGATIVE_INFINITY;\n }\n }\n\n return new fieldValue.DoubleValue(obj.doubleValue!);\n } else if (hasTag(obj, type, 'stringValue')) {\n return new fieldValue.StringValue(obj.stringValue!);\n } else if (hasTag(obj, type, 'mapValue')) {\n return this.fromFields(obj.mapValue!.fields || {});\n } else if (hasTag(obj, type, 'arrayValue')) {\n // \"values\" is not present if the array is empty\n assertPresent(obj.arrayValue, 'arrayValue');\n const values = obj.arrayValue!.values || [];\n return new fieldValue.ArrayValue(values.map(v => this.fromValue(v)));\n } else if (hasTag(obj, type, 'timestampValue')) {\n assertPresent(obj.timestampValue, 'timestampValue');\n return new fieldValue.TimestampValue(\n this.fromTimestamp(obj.timestampValue!)\n );\n } else if (hasTag(obj, type, 'geoPointValue')) {\n assertPresent(obj.geoPointValue, 'geoPointValue');\n const latitude = obj.geoPointValue!.latitude || 0;\n const longitude = obj.geoPointValue!.longitude || 0;\n return new fieldValue.GeoPointValue(new GeoPoint(latitude, longitude));\n } else if (hasTag(obj, type, 'bytesValue')) {\n assertPresent(obj.bytesValue, 'bytesValue');\n const blob = this.fromBlob(obj.bytesValue!);\n return new fieldValue.BlobValue(blob);\n } else if (hasTag(obj, type, 'referenceValue')) {\n assertPresent(obj.referenceValue, 'referenceValue');\n const resourceName = this.fromResourceName(obj.referenceValue!);\n const dbId = new DatabaseId(resourceName.get(1), resourceName.get(3));\n const key = new DocumentKey(\n this.extractLocalPathFromResourceName(resourceName)\n );\n return new fieldValue.RefValue(dbId, key);\n } else {\n return fail('Unknown Value proto ' + JSON.stringify(obj));\n }\n }\n\n /** Creates an api.Document from key and fields (but no create/update time) */\n toMutationDocument(\n key: DocumentKey,\n fields: fieldValue.ObjectValue\n ): api.Document {\n return {\n name: this.toName(key),\n fields: this.toFields(fields)\n };\n }\n\n toDocument(document: Document): api.Document {\n assert(\n !document.hasLocalMutations,\n \"Can't serialize documents with mutations.\"\n );\n return {\n name: this.toName(document.key),\n fields: this.toFields(document.data),\n updateTime: this.toTimestamp(document.version.toTimestamp())\n };\n }\n\n fromDocument(document: api.Document): Document {\n return new Document(\n this.fromName(document.name!),\n this.fromVersion(document.updateTime!),\n this.fromFields(document.fields || {}),\n { hasLocalMutations: false }\n );\n }\n\n toFields(fields: fieldValue.ObjectValue): { [key: string]: api.Value } {\n const result: { [key: string]: api.Value } = {};\n fields.forEach((key, value) => {\n result[key] = this.toValue(value);\n });\n return result;\n }\n\n fromFields(object: {}): fieldValue.ObjectValue {\n // Proto map gets mapped to Object, so cast it.\n const map = object as { [key: string]: api.Value };\n let result = fieldValue.ObjectValue.EMPTY;\n obj.forEach(map, (key, value) => {\n result = result.set(new FieldPath([key]), this.fromValue(value));\n });\n return result;\n }\n\n toMapValue(map: fieldValue.ObjectValue): api.MapValue {\n return {\n fields: this.toFields(map)\n };\n }\n\n toArrayValue(array: fieldValue.ArrayValue): api.ArrayValue {\n const result: api.Value[] = [];\n array.forEach(value => {\n result.push(this.toValue(value));\n });\n return { values: result };\n }\n\n private fromFound(doc: api.BatchGetDocumentsResponse): Document {\n assert(\n !!doc.found,\n 'Tried to deserialize a found document from a missing document.'\n );\n assertPresent(doc.found!.name, 'doc.found.name');\n assertPresent(doc.found!.updateTime, 'doc.found.updateTime');\n const key = this.fromName(doc.found!.name!);\n const version = this.fromVersion(doc.found!.updateTime!);\n const fields = this.fromFields(doc.found!.fields || {});\n return new Document(key, version, fields, { hasLocalMutations: false });\n }\n\n private fromMissing(result: api.BatchGetDocumentsResponse): NoDocument {\n assert(\n !!result.missing,\n 'Tried to deserialize a missing document from a found document.'\n );\n assert(\n !!result.readTime,\n 'Tried to deserialize a missing document without a read time.'\n );\n const key = this.fromName(result.missing!);\n const version = this.fromVersion(result.readTime!);\n return new NoDocument(key, version);\n }\n\n fromMaybeDocument(result: api.BatchGetDocumentsResponse): MaybeDocument {\n // tslint:disable-next-line:no-any\n const type = (result as any)['result_type'];\n if (hasTag(result, type, 'found')) {\n return this.fromFound(result);\n } else if (hasTag(result, type, 'missing')) {\n return this.fromMissing(result);\n }\n return fail('invalid batch get response: ' + JSON.stringify(result));\n }\n\n private toWatchTargetChangeState(\n state: WatchTargetChangeState\n ): api.TargetChangeTargetChangeType {\n switch (state) {\n case WatchTargetChangeState.Added:\n return 'ADD';\n case WatchTargetChangeState.Current:\n return 'CURRENT';\n case WatchTargetChangeState.NoChange:\n return 'NO_CHANGE';\n case WatchTargetChangeState.Removed:\n return 'REMOVE';\n case WatchTargetChangeState.Reset:\n return 'RESET';\n default:\n return fail('Unknown WatchTargetChangeState: ' + state);\n }\n }\n\n toTestWatchChange(watchChange: WatchChange): api.ListenResponse {\n if (watchChange instanceof ExistenceFilterChange) {\n return {\n filter: {\n count: watchChange.existenceFilter.count,\n targetId: watchChange.targetId\n }\n };\n }\n if (watchChange instanceof DocumentWatchChange) {\n if (watchChange.newDoc instanceof Document) {\n const doc = watchChange.newDoc;\n return {\n documentChange: {\n document: {\n name: this.toName(doc.key),\n fields: this.toFields(doc.data),\n updateTime: this.toVersion(doc.version)\n },\n targetIds: watchChange.updatedTargetIds,\n removedTargetIds: watchChange.removedTargetIds\n }\n };\n } else if (watchChange.newDoc instanceof NoDocument) {\n const doc = watchChange.newDoc;\n return {\n documentDelete: {\n document: this.toName(doc.key),\n readTime: this.toVersion(doc.version),\n removedTargetIds: watchChange.removedTargetIds\n }\n };\n } else if (watchChange.newDoc === null) {\n return {\n documentRemove: {\n document: this.toName(watchChange.key),\n removedTargetIds: watchChange.removedTargetIds\n }\n };\n }\n }\n if (watchChange instanceof WatchTargetChange) {\n let cause: api.Status | undefined = undefined;\n if (watchChange.cause) {\n cause = {\n code: mapRpcCodeFromCode(watchChange.cause.code),\n message: watchChange.cause.message\n };\n }\n return {\n targetChange: {\n targetChangeType: this.toWatchTargetChangeState(watchChange.state),\n targetIds: watchChange.targetIds,\n resumeToken: this.unsafeCastProtoByteString(watchChange.resumeToken),\n cause\n }\n };\n }\n return fail('Unrecognized watch change: ' + JSON.stringify(watchChange));\n }\n\n fromWatchChange(change: api.ListenResponse): WatchChange {\n // tslint:disable-next-line:no-any\n const type = (change as any)['change_type'];\n let watchChange: WatchChange;\n if (hasTag(change, type, 'targetChange')) {\n assertPresent(change.targetChange, 'targetChange');\n // proto3 default value is unset in JSON (undefined), so use 'NO_CHANGE'\n // if unset\n const state = this.fromWatchTargetChangeState(\n change.targetChange!.targetChangeType || 'NO_CHANGE'\n );\n const targetIds: TargetId[] = change.targetChange!.targetIds || [];\n const resumeToken =\n change.targetChange!.resumeToken || this.emptyByteString();\n const causeProto = change.targetChange!.cause;\n const cause = causeProto && this.fromRpcStatus(causeProto);\n watchChange = new WatchTargetChange(\n state,\n targetIds,\n resumeToken,\n cause || null\n );\n } else if (hasTag(change, type, 'documentChange')) {\n assertPresent(change.documentChange, 'documentChange');\n assertPresent(change.documentChange!.document, 'documentChange.name');\n assertPresent(\n change.documentChange!.document!.name,\n 'documentChange.document.name'\n );\n assertPresent(\n change.documentChange!.document!.updateTime,\n 'documentChange.document.updateTime'\n );\n const entityChange = change.documentChange!;\n const key = this.fromName(entityChange.document!.name!);\n const version = this.fromVersion(entityChange.document!.updateTime!);\n const fields = this.fromFields(entityChange.document!.fields || {});\n const doc = new Document(key, version, fields, {\n hasLocalMutations: false\n });\n const updatedTargetIds = entityChange.targetIds || [];\n const removedTargetIds = entityChange.removedTargetIds || [];\n watchChange = new DocumentWatchChange(\n updatedTargetIds,\n removedTargetIds,\n doc.key,\n doc\n );\n } else if (hasTag(change, type, 'documentDelete')) {\n assertPresent(change.documentDelete, 'documentDelete');\n assertPresent(change.documentDelete!.document, 'documentDelete.document');\n const docDelete = change.documentDelete!;\n const key = this.fromName(docDelete.document!);\n const version = docDelete.readTime\n ? this.fromVersion(docDelete.readTime)\n : SnapshotVersion.forDeletedDoc();\n const doc = new NoDocument(key, version);\n const removedTargetIds = docDelete.removedTargetIds || [];\n watchChange = new DocumentWatchChange([], removedTargetIds, doc.key, doc);\n } else if (hasTag(change, type, 'documentRemove')) {\n assertPresent(change.documentRemove, 'documentRemove');\n assertPresent(change.documentRemove!.document, 'documentRemove');\n const docRemove = change.documentRemove!;\n const key = this.fromName(docRemove.document!);\n const removedTargetIds = docRemove.removedTargetIds || [];\n watchChange = new DocumentWatchChange([], removedTargetIds, key, null);\n } else if (hasTag(change, type, 'filter')) {\n // TODO(dimond): implement existence filter parsing with strategy.\n assertPresent(change.filter, 'filter');\n assertPresent(change.filter!.targetId, 'filter.targetId');\n const filter = change.filter;\n const count = filter!.count || 0;\n const existenceFilter = new ExistenceFilter(count);\n const targetId = filter!.targetId!;\n watchChange = new ExistenceFilterChange(targetId, existenceFilter);\n } else {\n return fail('Unknown change type ' + JSON.stringify(change));\n }\n return watchChange;\n }\n\n fromWatchTargetChangeState(\n state: api.TargetChangeTargetChangeType\n ): WatchTargetChangeState {\n if (state === 'NO_CHANGE') {\n return WatchTargetChangeState.NoChange;\n } else if (state === 'ADD') {\n return WatchTargetChangeState.Added;\n } else if (state === 'REMOVE') {\n return WatchTargetChangeState.Removed;\n } else if (state === 'CURRENT') {\n return WatchTargetChangeState.Current;\n } else if (state === 'RESET') {\n return WatchTargetChangeState.Reset;\n } else {\n return fail('Got unexpected TargetChange.state: ' + state);\n }\n }\n\n versionFromListenResponse(change: api.ListenResponse): SnapshotVersion {\n // We have only reached a consistent snapshot for the entire stream if there\n // is a read_time set and it applies to all targets (i.e. the list of\n // targets is empty). The backend is guaranteed to send such responses.\n // tslint:disable-next-line:no-any\n const type = (change as any)['response_type'];\n if (!hasTag(change, type, 'targetChange')) {\n return SnapshotVersion.MIN;\n }\n const targetChange = change.targetChange!;\n if (targetChange.targetIds && targetChange.targetIds.length) {\n return SnapshotVersion.MIN;\n }\n if (!targetChange.readTime) {\n return SnapshotVersion.MIN;\n }\n return this.fromVersion(targetChange.readTime);\n }\n\n toMutation(mutation: Mutation): api.Write {\n let result: api.Write;\n if (mutation instanceof SetMutation) {\n result = {\n update: this.toMutationDocument(mutation.key, mutation.value)\n };\n } else if (mutation instanceof DeleteMutation) {\n result = { delete: this.toName(mutation.key) };\n } else if (mutation instanceof PatchMutation) {\n result = {\n update: this.toMutationDocument(mutation.key, mutation.data),\n updateMask: this.toDocumentMask(mutation.fieldMask)\n };\n } else if (mutation instanceof TransformMutation) {\n result = {\n transform: {\n document: this.toName(mutation.key),\n fieldTransforms: mutation.fieldTransforms.map(transform =>\n this.toFieldTransform(transform)\n )\n }\n };\n } else {\n return fail('Unknown mutation type ' + mutation.type);\n }\n\n if (!mutation.precondition.isNone) {\n result.currentDocument = this.toPrecondition(mutation.precondition);\n }\n\n return result;\n }\n\n fromMutation(proto: api.Write): Mutation {\n const precondition = proto.currentDocument\n ? this.fromPrecondition(proto.currentDocument)\n : Precondition.NONE;\n\n if (proto.update) {\n assertPresent(proto.update.name, 'name');\n const key = this.fromName(proto.update.name!);\n const value = this.fromFields(proto.update.fields || {});\n if (proto.updateMask) {\n const fieldMask = this.fromDocumentMask(proto.updateMask);\n return new PatchMutation(key, value, fieldMask, precondition);\n } else {\n return new SetMutation(key, value, precondition);\n }\n } else if (proto.delete) {\n const key = this.fromName(proto.delete);\n return new DeleteMutation(key, precondition);\n } else if (proto.transform) {\n const key = this.fromName(proto.transform.document!);\n const fieldTransforms = proto.transform.fieldTransforms!.map(transform =>\n this.fromFieldTransform(transform)\n );\n assert(\n precondition.exists === true,\n 'Transforms only support precondition \"exists == true\"'\n );\n return new TransformMutation(key, fieldTransforms);\n } else {\n return fail('unknown mutation proto: ' + JSON.stringify(proto));\n }\n }\n\n private toPrecondition(precondition: Precondition): api.Precondition {\n assert(!precondition.isNone, \"Can't serialize an empty precondition\");\n if (precondition.updateTime !== undefined) {\n return {\n updateTime: this.toVersion(precondition.updateTime)\n };\n } else if (precondition.exists !== undefined) {\n return { exists: precondition.exists };\n } else {\n return fail('Unknown precondition');\n }\n }\n\n private fromPrecondition(precondition: api.Precondition): Precondition {\n if (precondition.updateTime !== undefined) {\n return Precondition.updateTime(this.fromVersion(precondition.updateTime));\n } else if (precondition.exists !== undefined) {\n return Precondition.exists(precondition.exists);\n } else {\n return Precondition.NONE;\n }\n }\n\n private fromWriteResult(proto: api.WriteResult): MutationResult {\n // NOTE: Deletes don't have an updateTime.\n const version = proto.updateTime\n ? this.fromVersion(proto.updateTime)\n : null;\n let transformResults: fieldValue.FieldValue[] | null = null;\n if (proto.transformResults) {\n transformResults = proto.transformResults.map(result =>\n this.fromValue(result)\n );\n }\n return new MutationResult(version, transformResults);\n }\n\n fromWriteResults(protos: api.WriteResult[] | undefined): MutationResult[] {\n return (protos || []).map(proto => this.fromWriteResult(proto));\n }\n\n private toFieldTransform(fieldTransform: FieldTransform): api.FieldTransform {\n assert(\n fieldTransform.transform instanceof ServerTimestampTransform,\n 'Unknown transform: ' + fieldTransform.transform\n );\n return {\n fieldPath: fieldTransform.field.canonicalString(),\n setToServerValue: 'REQUEST_TIME'\n };\n }\n\n private fromFieldTransform(proto: api.FieldTransform): FieldTransform {\n assert(\n proto.setToServerValue! === 'REQUEST_TIME',\n 'Unknown transform proto: ' + JSON.stringify(proto)\n );\n const fieldPath = FieldPath.fromServerFormat(proto.fieldPath!);\n return new FieldTransform(fieldPath, ServerTimestampTransform.instance);\n }\n\n toDocumentsTarget(query: Query): api.DocumentsTarget {\n return { documents: [this.toQueryPath(query.path)] };\n }\n\n fromDocumentsTarget(documentsTarget: api.DocumentsTarget): Query {\n const count = documentsTarget.documents!.length;\n assert(\n count === 1,\n 'DocumentsTarget contained other than 1 document: ' + count\n );\n const name = documentsTarget.documents![0];\n return Query.atPath(this.fromQueryPath(name));\n }\n\n toQueryTarget(query: Query): api.QueryTarget {\n // Dissect the path into parent, collectionId, and optional key filter.\n const result: api.QueryTarget = { structuredQuery: {} };\n if (query.path.isEmpty()) {\n result.parent = this.toQueryPath(ResourcePath.EMPTY_PATH);\n } else {\n const path = query.path;\n assert(\n path.length % 2 !== 0,\n 'Document queries with filters are not supported.'\n );\n result.parent = this.toQueryPath(path.popLast());\n result.structuredQuery!.from = [{ collectionId: path.lastSegment() }];\n }\n\n const where = this.toFilter(query.filters);\n if (where) {\n result.structuredQuery!.where = where;\n }\n\n const orderBy = this.toOrder(query.orderBy);\n if (orderBy) {\n result.structuredQuery!.orderBy = orderBy;\n }\n\n const limit = this.toLimit(query.limit);\n if (limit !== undefined) {\n result.structuredQuery!.limit = limit;\n }\n\n if (query.startAt) {\n result.structuredQuery!.startAt = this.toCursor(query.startAt);\n }\n if (query.endAt) {\n result.structuredQuery!.endAt = this.toCursor(query.endAt);\n }\n\n return result;\n }\n\n fromQueryTarget(target: api.QueryTarget): Query {\n let path = this.fromQueryPath(target.parent!);\n\n const query = target.structuredQuery!;\n const fromCount = query.from ? query.from.length : 0;\n if (fromCount > 0) {\n assert(\n fromCount === 1,\n 'StructuredQuery.from with more than one collection is not supported.'\n );\n const from = query.from![0];\n path = path.child(from.collectionId!);\n }\n\n let filterBy: Filter[] = [];\n if (query.where) {\n filterBy = this.fromFilter(query.where);\n }\n\n let orderBy: OrderBy[] = [];\n if (query.orderBy) {\n orderBy = this.fromOrder(query.orderBy);\n }\n\n let limit: number | null = null;\n if (query.limit) {\n limit = query.limit;\n }\n\n let startAt: Bound | null = null;\n if (query.startAt) {\n startAt = this.fromCursor(query.startAt);\n }\n\n let endAt: Bound | null = null;\n if (query.endAt) {\n endAt = this.fromCursor(query.endAt);\n }\n\n return new Query(path, orderBy, filterBy, limit, startAt, endAt);\n }\n\n toListenRequestLabels(\n queryData: QueryData\n ): ApiClientObjectMap | null {\n const value = this.toLabel(queryData.purpose);\n if (value == null) {\n return null;\n } else {\n return {\n 'goog-listen-tags': value\n };\n }\n }\n\n private toLabel(purpose: QueryPurpose): string | null {\n switch (purpose) {\n case QueryPurpose.Listen:\n return null;\n case QueryPurpose.ExistenceFilterMismatch:\n return 'existence-filter-mismatch';\n case QueryPurpose.LimboResolution:\n return 'limbo-document';\n default:\n return fail('Unrecognized query purpose: ' + purpose);\n }\n }\n\n toTarget(queryData: QueryData): api.Target {\n let result: api.Target;\n const query = queryData.query;\n\n if (query.isDocumentQuery()) {\n result = { documents: this.toDocumentsTarget(query) };\n } else {\n result = { query: this.toQueryTarget(query) };\n }\n\n result.targetId = queryData.targetId;\n\n if (queryData.resumeToken.length > 0) {\n result.resumeToken = this.unsafeCastProtoByteString(\n queryData.resumeToken\n );\n }\n\n return result;\n }\n\n private toFilter(filters: Filter[]): api.Filter | undefined {\n if (filters.length === 0) return;\n const protos = filters.map(\n filter =>\n filter instanceof RelationFilter\n ? this.toRelationFilter(filter)\n : this.toUnaryFilter(filter)\n );\n if (protos.length === 1) {\n return protos[0];\n }\n return { compositeFilter: { op: 'AND', filters: protos } };\n }\n\n private fromFilter(filter: api.Filter | undefined): Filter[] {\n if (!filter) {\n return [];\n } else if (filter.unaryFilter !== undefined) {\n return [this.fromUnaryFilter(filter)];\n } else if (filter.fieldFilter !== undefined) {\n return [this.fromRelationFilter(filter)];\n } else if (filter.compositeFilter !== undefined) {\n return filter.compositeFilter.filters!\n .map(f => this.fromFilter(f))\n .reduce((accum, current) => accum.concat(current));\n } else {\n return fail('Unknown filter: ' + JSON.stringify(filter));\n }\n }\n\n private toOrder(orderBys: OrderBy[]): api.Order[] | undefined {\n if (orderBys.length === 0) return;\n return orderBys.map(order => this.toPropertyOrder(order));\n }\n\n private fromOrder(orderBys: api.Order[]): OrderBy[] {\n return orderBys.map(order => this.fromPropertyOrder(order));\n }\n\n private toLimit(limit: number | null): number | undefined {\n if (!typeUtils.isNullOrUndefined(limit)) {\n return limit!;\n }\n return;\n }\n\n private toCursor(cursor: Bound): api.Cursor {\n return {\n before: cursor.before,\n values: cursor.position.map(component => this.toValue(component))\n };\n }\n\n private fromCursor(cursor: api.Cursor): Bound {\n const before = !!cursor.before;\n const position = cursor.values!.map(component => this.fromValue(component));\n return new Bound(position, before);\n }\n\n // visible for testing\n toDirection(dir: Direction): api.OrderDirection {\n return DIRECTIONS[dir.name];\n }\n\n // visible for testing\n fromDirection(dir: api.OrderDirection | undefined): Direction | undefined {\n switch (dir) {\n case 'ASCENDING':\n return Direction.ASCENDING;\n case 'DESCENDING':\n return Direction.DESCENDING;\n default:\n return undefined;\n }\n }\n\n // visible for testing\n toOperatorName(op: RelationOp): api.FieldFilterOp {\n return OPERATORS[op.name];\n }\n\n fromOperatorName(op: api.FieldFilterOp): RelationOp {\n switch (op) {\n case 'EQUAL':\n return RelationOp.EQUAL;\n case 'GREATER_THAN':\n return RelationOp.GREATER_THAN;\n case 'GREATER_THAN_OR_EQUAL':\n return RelationOp.GREATER_THAN_OR_EQUAL;\n case 'LESS_THAN':\n return RelationOp.LESS_THAN;\n case 'LESS_THAN_OR_EQUAL':\n return RelationOp.LESS_THAN_OR_EQUAL;\n case 'OPERATOR_UNSPECIFIED':\n return fail('Unspecified relation');\n default:\n return fail('Unknown relation');\n }\n }\n\n toFieldPathReference(path: FieldPath): api.FieldReference {\n return { fieldPath: path.canonicalString() };\n }\n\n fromFieldPathReference(fieldReference: api.FieldReference): FieldPath {\n return FieldPath.fromServerFormat(fieldReference.fieldPath!);\n }\n\n // visible for testing\n toPropertyOrder(orderBy: OrderBy): api.Order {\n return {\n field: this.toFieldPathReference(orderBy.field),\n direction: this.toDirection(orderBy.dir)\n };\n }\n\n fromPropertyOrder(orderBy: api.Order): OrderBy {\n return new OrderBy(\n this.fromFieldPathReference(orderBy.field!),\n this.fromDirection(orderBy.direction)\n );\n }\n\n // visible for testing\n toRelationFilter(filter: Filter): api.Filter {\n if (filter instanceof RelationFilter) {\n return {\n fieldFilter: {\n field: this.toFieldPathReference(filter.field),\n op: this.toOperatorName(filter.op),\n value: this.toValue(filter.value)\n }\n };\n } else {\n return fail('Unrecognized filter: ' + JSON.stringify(filter));\n }\n }\n\n fromRelationFilter(filter: api.Filter): Filter {\n return new RelationFilter(\n this.fromFieldPathReference(filter.fieldFilter!.field!),\n this.fromOperatorName(filter.fieldFilter!.op!),\n this.fromValue(filter.fieldFilter!.value!)\n );\n }\n\n // visible for testing\n toUnaryFilter(filter: Filter): api.Filter {\n if (filter instanceof NanFilter) {\n return {\n unaryFilter: {\n field: this.toFieldPathReference(filter.field),\n op: 'IS_NAN'\n }\n };\n } else if (filter instanceof NullFilter) {\n return {\n unaryFilter: {\n field: this.toFieldPathReference(filter.field),\n op: 'IS_NULL'\n }\n };\n } else {\n return fail('Unrecognized filter: ' + JSON.stringify(filter));\n }\n }\n\n fromUnaryFilter(filter: api.Filter): Filter {\n switch (filter.unaryFilter!.op!) {\n case 'IS_NAN':\n const nanField = this.fromFieldPathReference(\n filter.unaryFilter!.field!\n );\n return new NanFilter(nanField);\n case 'IS_NULL':\n const nullField = this.fromFieldPathReference(\n filter.unaryFilter!.field!\n );\n return new NullFilter(nullField);\n case 'OPERATOR_UNSPECIFIED':\n return fail('Unspecified filter');\n default:\n return fail('Unknown filter');\n }\n }\n\n toDocumentMask(fieldMask: FieldMask): api.DocumentMask {\n return {\n fieldPaths: fieldMask.fields.map(field => field.canonicalString())\n };\n }\n\n fromDocumentMask(proto: api.DocumentMask): FieldMask {\n const paths = proto.fieldPaths || [];\n const fields = paths.map(path => FieldPath.fromServerFormat(path));\n return new FieldMask(fields);\n }\n}\n\n/**\n * Checks for a specific oneof tag in a protocol buffer message.\n *\n * This intentionally accommodates two distinct cases:\n *\n * 1) Messages containing a type tag: these are the format produced by GRPC in\n * return values. These may contain default-value mappings for all tags in the\n * oneof but the type tag specifies which one was actually set.\n *\n * 2) Messages that don't contain a type tag: these are the format required by\n * GRPC as inputs. If we emitted objects with type tags, ProtoBuf.js would\n * choke claiming that the tags aren't fields in the Message.\n *\n * Allowing both formats here makes the serializer able to consume the outputs\n * it produces: for all messages it supports, fromX(toX(value)) == value.\n *\n * Note that case 2 suffers from ambiguity: if multiple tags are present\n * without a type tag then the callers are structured in such a way that the\n * first invocation will win. Since we only parse in this mode when parsing\n * the output of a serialize method this works, but it's not a general\n * solution.\n *\n * Unfortunately there is no general solution here because proto3 makes it\n * impossible to distinguish unset from explicitly set fields: both have the\n * default value for the type. Without the type tag but multiple value tags\n * it's possible to have default values for each tag in the oneof and not be\n * able to know which was actually in effect.\n */\nfunction hasTag(obj: {}, type: string, tag: string): boolean {\n return type === tag || (!type && tag in obj);\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/serializer.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as firestore from 'firestore';\n\nimport { FieldPath as InternalFieldPath } from '../model/path';\nimport { Code, FirestoreError } from '../util/error';\nimport {\n validateArgType,\n validateNamedArrayAtLeastNumberOfElements\n} from '../util/input_validation';\n\n// The objects that are a part of this API are exposed to third-parties as\n// compiled javascript so we want to flag our private members with a leading\n// underscore to discourage their use.\n// tslint:disable:strip-private-property-underscore\n\n/**\n * A FieldPath refers to a field in a document. The path may consist of a single\n * field name (referring to a top-level field in the document), or a list of\n * field names (referring to a nested field in the document).\n */\nexport class FieldPath implements firestore.FieldPath {\n /** Internal representation of a Firestore field path. */\n _internalPath: InternalFieldPath;\n\n /**\n * Creates a FieldPath from the provided field names. If more than one field\n * name is provided, the path will point to a nested field in a document.\n *\n * @param fieldNames A list of field names.\n */\n constructor(...fieldNames: string[]) {\n validateNamedArrayAtLeastNumberOfElements(\n 'FieldPath',\n fieldNames,\n 'fieldNames',\n 1\n );\n\n for (let i = 0; i < fieldNames.length; ++i) {\n validateArgType('FieldPath', 'string', i, fieldNames[i]);\n if (fieldNames[i].length === 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid field name at argument $(i + 1). ` +\n 'Field names must not be empty.'\n );\n }\n }\n\n this._internalPath = new InternalFieldPath(fieldNames);\n }\n\n /**\n * Internal Note: The backend doesn't technically support querying by\n * document ID. Instead it queries by the entire document name (full path\n * included), but in the cases we currently support documentId(), the net\n * effect is the same.\n */\n private static readonly _DOCUMENT_ID = new FieldPath(\n InternalFieldPath.keyField().canonicalString()\n );\n\n public static documentId(): FieldPath {\n return FieldPath._DOCUMENT_ID;\n }\n}\n\n/**\n * Matches any characters in a field path string that are reserved.\n */\nconst RESERVED = new RegExp('[~\\\\*/\\\\[\\\\]]');\n\n/**\n * Parses a field path string into a FieldPath, treating dots as separators.\n */\nexport function fromDotSeparatedString(path: string): FieldPath {\n const found = path.search(RESERVED);\n if (found >= 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid field path (${path}). Paths must not contain ` +\n `'~', '*', '/', '[', or ']'`\n );\n }\n try {\n return new FieldPath(...path.split('.'));\n } catch (e) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid field path (${path}). Paths must not be empty, ` +\n `begin with '.', end with '.', or contain '..'`\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/field_path.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n documentKeySet,\n DocumentKeySet,\n MaybeDocumentMap\n} from '../model/collections';\nimport { Document, MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { DocumentSet } from '../model/document_set';\nimport {\n CurrentStatusUpdate,\n ResetMapping,\n TargetChange,\n UpdateMapping\n} from '../remote/remote_event';\nimport { assert, fail } from '../util/assert';\n\nimport { Query } from './query';\nimport {\n ChangeType,\n DocumentChangeSet,\n SyncState,\n ViewSnapshot\n} from './view_snapshot';\n\nexport type LimboDocumentChange = AddedLimboDocument | RemovedLimboDocument;\nexport class AddedLimboDocument {\n constructor(public key: DocumentKey) {}\n}\nexport class RemovedLimboDocument {\n constructor(public key: DocumentKey) {}\n}\n\n/** The result of applying a set of doc changes to a view. */\nexport interface ViewDocumentChanges {\n /** The new set of docs that should be in the view. */\n documentSet: DocumentSet;\n /** The diff of this these docs with the previous set of docs. */\n changeSet: DocumentChangeSet;\n /**\n * Whether the set of documents passed in was not sufficient to calculate the\n * new state of the view and there needs to be another pass based on the\n * local cache.\n */\n needsRefill: boolean;\n\n mutatedKeys: DocumentKeySet;\n}\n\nexport interface ViewChange {\n snapshot?: ViewSnapshot;\n limboChanges: LimboDocumentChange[];\n}\n\n/**\n * View is responsible for computing the final merged truth of what docs are in\n * a query. It gets notified of local and remote changes to docs, and applies\n * the query filters and limits to determine the most correct possible results.\n */\nexport class View {\n private syncState: SyncState | null = null;\n /**\n * A flag whether the view is current with the backend. A view is considered\n * current after it has seen the current flag from the backend and did not\n * lose consistency within the watch stream (e.g. because of an existence\n * filter mismatch).\n */\n private current = false;\n private documentSet: DocumentSet;\n /** Documents in the view but not in the remote target */\n private limboDocuments = documentKeySet();\n /** Document Keys that have local changes */\n private mutatedKeys = documentKeySet();\n\n constructor(\n private query: Query,\n /** Documents included in the remote target */\n private syncedDocuments: DocumentKeySet\n ) {\n this.documentSet = new DocumentSet(query.docComparator.bind(query));\n }\n\n /**\n * Iterates over a set of doc changes, applies the query limit, and computes\n * what the new results should be, what the changes were, and whether we may\n * need to go back to the local cache for more results. Does not make any\n * changes to the view.\n * @param docChanges The doc changes to apply to this view.\n * @param previousChanges If this is being called with a refill, then start\n * with this set of docs and changes instead of the current view.\n * @return a new set of docs, changes, and refill flag.\n */\n computeDocChanges(\n docChanges: MaybeDocumentMap,\n previousChanges?: ViewDocumentChanges\n ): ViewDocumentChanges {\n const changeSet = previousChanges\n ? previousChanges.changeSet\n : new DocumentChangeSet();\n const oldDocumentSet = previousChanges\n ? previousChanges.documentSet\n : this.documentSet;\n let newMutatedKeys = previousChanges\n ? previousChanges.mutatedKeys\n : this.mutatedKeys;\n let newDocumentSet = oldDocumentSet;\n let needsRefill = false;\n\n // Track the last doc in a (full) limit. This is necessary, because some\n // update (a delete, or an update moving a doc past the old limit) might\n // mean there is some other document in the local cache that either should\n // come (1) between the old last limit doc and the new last document, in the\n // case of updates, or (2) after the new last document, in the case of\n // deletes. So we keep this doc at the old limit to compare the updates to.\n //\n // Note that this should never get used in a refill (when previousChanges is\n // set), because there will only be adds -- no deletes or updates.\n const lastDocInLimit =\n this.query.hasLimit() && oldDocumentSet.size === this.query.limit\n ? oldDocumentSet.last()\n : null;\n\n docChanges.inorderTraversal(\n (key: DocumentKey, newMaybeDoc: MaybeDocument) => {\n const oldDoc = oldDocumentSet.get(key);\n let newDoc = newMaybeDoc instanceof Document ? newMaybeDoc : null;\n if (newDoc) {\n assert(\n key.equals(newDoc.key),\n 'Mismatching keys found in document changes: ' +\n key +\n ' != ' +\n newDoc.key\n );\n newDoc = this.query.matches(newDoc) ? newDoc : null;\n }\n if (newDoc) {\n newDocumentSet = newDocumentSet.add(newDoc);\n if (newDoc.hasLocalMutations) {\n newMutatedKeys = newMutatedKeys.add(key);\n } else {\n newMutatedKeys = newMutatedKeys.delete(key);\n }\n } else {\n newDocumentSet = newDocumentSet.delete(key);\n newMutatedKeys = newMutatedKeys.delete(key);\n }\n\n // Calculate change\n if (oldDoc && newDoc) {\n const docsEqual = oldDoc.data.equals(newDoc.data);\n if (\n !docsEqual ||\n oldDoc.hasLocalMutations !== newDoc.hasLocalMutations\n ) {\n // only report a change if document actually changed\n if (docsEqual) {\n changeSet.track({ type: ChangeType.Metadata, doc: newDoc });\n } else {\n changeSet.track({ type: ChangeType.Modified, doc: newDoc });\n }\n\n if (\n lastDocInLimit &&\n this.query.docComparator(newDoc, lastDocInLimit) > 0\n ) {\n // This doc moved from inside the limit to after the limit.\n // That means there may be some doc in the local cache that's\n // actually less than this one.\n needsRefill = true;\n }\n }\n } else if (!oldDoc && newDoc) {\n changeSet.track({ type: ChangeType.Added, doc: newDoc });\n } else if (oldDoc && !newDoc) {\n changeSet.track({ type: ChangeType.Removed, doc: oldDoc });\n if (lastDocInLimit) {\n // A doc was removed from a full limit query. We'll need to\n // requery from the local cache to see if we know about some other\n // doc that should be in the results.\n needsRefill = true;\n }\n }\n }\n );\n if (this.query.hasLimit()) {\n // TODO(klimt): Make DocumentSet size be constant time.\n while (newDocumentSet.size > this.query.limit!) {\n const oldDoc = newDocumentSet.last();\n newDocumentSet = newDocumentSet.delete(oldDoc!.key);\n changeSet.track({ type: ChangeType.Removed, doc: oldDoc! });\n }\n }\n assert(\n !needsRefill || !previousChanges,\n 'View was refilled using docs that themselves needed refilling.'\n );\n return {\n documentSet: newDocumentSet,\n changeSet,\n needsRefill,\n mutatedKeys: newMutatedKeys\n };\n }\n\n /**\n * Updates the view with the given ViewDocumentChanges and updates limbo docs\n * and sync state from the given (optional) target change.\n * @param docChanges The set of changes to make to the view's docs.\n * @param targetChange A target change to apply for computing limbo docs and\n * sync state.\n * @return A new ViewChange with the given docs, changes, and sync state.\n */\n applyChanges(\n docChanges: ViewDocumentChanges,\n targetChange?: TargetChange\n ): ViewChange {\n assert(!docChanges.needsRefill, 'Cannot apply changes that need a refill');\n const oldDocs = this.documentSet;\n this.documentSet = docChanges.documentSet;\n this.mutatedKeys = docChanges.mutatedKeys;\n // Sort changes based on type and query comparator\n const changes = docChanges.changeSet.getChanges();\n changes.sort((c1, c2) => {\n return (\n compareChangeType(c1.type, c2.type) ||\n this.query.docComparator(c1.doc, c2.doc)\n );\n });\n\n const limboChanges = this.applyTargetChange(targetChange);\n const synced = this.limboDocuments.size === 0 && this.current;\n const newSyncState = synced ? SyncState.Synced : SyncState.Local;\n const syncStateChanged = newSyncState !== this.syncState;\n this.syncState = newSyncState;\n\n if (changes.length === 0 && !syncStateChanged) {\n // no changes\n return { limboChanges };\n } else {\n return {\n snapshot: {\n query: this.query,\n docs: docChanges.documentSet,\n oldDocs,\n docChanges: changes,\n fromCache: newSyncState === SyncState.Local,\n syncStateChanged,\n hasPendingWrites: !docChanges.mutatedKeys.isEmpty()\n },\n limboChanges\n };\n }\n }\n\n /**\n * Returns whether the doc for the given key should be in limbo.\n */\n private shouldBeInLimbo(key: DocumentKey): boolean {\n // If the remote end says it's part of this query, it's not in limbo.\n if (this.syncedDocuments.has(key)) {\n return false;\n }\n // The local store doesn't think it's a result, so it shouldn't be in limbo.\n if (!this.documentSet.has(key)) {\n return false;\n }\n // If there are local changes to the doc, they might explain why the server\n // doesn't know that it's part of the query. So don't put it in limbo.\n // TODO(klimt): Ideally, we would only consider changes that might actually\n // affect this specific query.\n if (this.documentSet.get(key)!.hasLocalMutations) {\n return false;\n }\n // Everything else is in limbo.\n return true;\n }\n\n /**\n * Updates syncedDocuments, current, and limbo docs based on the given change.\n * Returns the list of changes to which docs are in limbo.\n */\n private applyTargetChange(\n targetChange?: TargetChange\n ): LimboDocumentChange[] {\n if (targetChange) {\n const targetMapping = targetChange.mapping;\n if (targetMapping instanceof ResetMapping) {\n this.syncedDocuments = targetMapping.documents;\n } else if (targetMapping instanceof UpdateMapping) {\n this.syncedDocuments = targetMapping.applyToKeySet(\n this.syncedDocuments\n );\n }\n\n switch (targetChange.currentStatusUpdate) {\n case CurrentStatusUpdate.MarkCurrent:\n this.current = true;\n break;\n case CurrentStatusUpdate.MarkNotCurrent:\n this.current = false;\n break;\n case CurrentStatusUpdate.None:\n break;\n default:\n fail(\n 'Unknown current status update: ' + targetChange.currentStatusUpdate\n );\n }\n }\n\n // Recompute the set of limbo docs.\n // TODO(klimt): Do this incrementally so that it's not quadratic when\n // updating many documents.\n const oldLimboDocuments = this.limboDocuments;\n this.limboDocuments = documentKeySet();\n if (this.current) {\n this.documentSet.forEach(doc => {\n if (this.shouldBeInLimbo(doc.key)) {\n this.limboDocuments = this.limboDocuments.add(doc.key);\n }\n });\n }\n\n // Diff the new limbo docs with the old limbo docs.\n const changes: LimboDocumentChange[] = [];\n oldLimboDocuments.forEach(key => {\n if (!this.limboDocuments.has(key)) {\n changes.push(new RemovedLimboDocument(key));\n }\n });\n this.limboDocuments.forEach(key => {\n if (!oldLimboDocuments.has(key)) {\n changes.push(new AddedLimboDocument(key));\n }\n });\n return changes;\n }\n}\n\nfunction compareChangeType(c1: ChangeType, c2: ChangeType): number {\n const order = (change: ChangeType) => {\n switch (change) {\n case ChangeType.Added:\n return 1;\n case ChangeType.Modified:\n return 2;\n case ChangeType.Metadata:\n // A metadata change is converted to a modified change at the public\n // api layer. Since we sort by document key and then change type,\n // metadata and modified changes must be sorted equivalently.\n return 2;\n case ChangeType.Removed:\n return 0;\n default:\n return fail('Unknown ChangeType: ' + change);\n }\n };\n\n return order(c1) - order(c2);\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/view.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ResourcePath } from '../model/path';\nimport { assert, fail } from '../util/assert';\n\n/**\n * Helpers for dealing with resource paths stored in IndexedDB.\n *\n * Resource paths in their canonical string form do not sort as the server\n * sorts them. Specifically the server splits paths into segments first and then\n * sorts, putting end-of-segment before any character. In a UTF-8 string\n * encoding the slash ('/') that denotes the end-of-segment naturally comes\n * after other characters so the intent here is to encode the path delimiters in\n * such a way that the resulting strings sort naturally.\n *\n * Resource paths are also used for prefix scans so it's important to\n * distinguish whole segments from any longer segments of which they might be a\n * prefix. For example, it's important to make it possible to scan documents in\n * a collection \"foo\" without encountering documents in a collection \"foobar\".\n *\n * Separate from the concerns about resource path ordering and separation,\n * On Android, SQLite imposes additional restrictions since it does not handle\n * keys with embedded NUL bytes particularly well. Rather than change the\n * implementation we keep the encoding identical to keep the ports similar.\n *\n * Taken together this means resource paths when encoded for storage in\n * IndexedDB have the following characteristics:\n *\n * * Segment separators (\"/\") sort before everything else.\n * * All paths have a trailing separator.\n * * NUL bytes do not exist in the output, since IndexedDB doesn't treat them\n * well.\n *\n * Therefore resource paths are encoded into string form using the following\n * rules:\n *\n * * '\\x01' is used as an escape character.\n * * Path separators are encoded as \"\\x01\\x01\"\n * * NUL bytes are encoded as \"\\x01\\x10\"\n * * '\\x01' is encoded as \"\\x01\\x11\"\n *\n * This encoding leaves some room between path separators and the NUL byte\n * just in case we decide to support integer document ids after all.\n *\n * Note that characters treated specially by the backend ('.', '/', and '~')\n * are not treated specially here. This class assumes that any unescaping of\n * resource path strings into actual ResourcePath objects will handle these\n * characters there.\n */\nexport type EncodedResourcePath = string;\n\nconst escapeChar = '\\u0001';\nconst encodedSeparatorChar = '\\u0001';\nconst encodedNul = '\\u0010';\nconst encodedEscape = '\\u0011';\n\n/**\n * Encodes a resource path into a IndexedDb-compatible string form.\n */\nexport function encode(path: ResourcePath): EncodedResourcePath {\n let result = '';\n for (let i = 0; i < path.length; i++) {\n if (result.length > 0) {\n result = encodeSeparator(result);\n }\n result = encodeSegment(path.get(i), result);\n }\n return encodeSeparator(result);\n}\n\n/** Encodes a single segment of a resource path into the given result */\nfunction encodeSegment(segment: string, resultBuf: string) {\n let result = resultBuf;\n const length = segment.length;\n for (let i = 0; i < length; i++) {\n const c = segment.charAt(i);\n switch (c) {\n case '\\0':\n result += escapeChar + encodedNul;\n break;\n case escapeChar:\n result += escapeChar + encodedEscape;\n break;\n default:\n result += c;\n }\n }\n return result;\n}\n\n/** Encodes a path separator into the given result */\nfunction encodeSeparator(result: string): string {\n return result + escapeChar + encodedSeparatorChar;\n}\n\n/**\n * Decodes the given IndexedDb-compatible string form of a resource path into\n * a ResourcePath instance. Note that this method is not suitable for use with\n * decoding resource names from the server; those are One Platform format\n * strings.\n */\nexport function decode(path: EncodedResourcePath): ResourcePath {\n // Event the empty path must encode as a path of at least length 2. A path\n // with exactly 2 must be the empty path.\n const length = path.length;\n assert(length >= 2, 'Invalid path ' + path);\n if (length === 2) {\n assert(\n path.charAt(0) === escapeChar && path.charAt(1) === encodedSeparatorChar,\n 'Non-empty path ' + path + ' had length 2'\n );\n return ResourcePath.EMPTY_PATH;\n }\n\n // Escape characters cannot exist past the second-to-last position in the\n // source value.\n const lastReasonableEscapeIndex = length - 2;\n\n const segments: string[] = [];\n let segmentBuilder = '';\n\n for (let start = 0; start < length; ) {\n // The last two characters of a valid encoded path must be a separator, so\n // there must be an end to this segment.\n const end = path.indexOf(escapeChar, start);\n if (end < 0 || end > lastReasonableEscapeIndex) {\n fail('Invalid encoded resource path: \"' + path + '\"');\n }\n\n const next = path.charAt(end + 1);\n switch (next) {\n case encodedSeparatorChar:\n const currentPiece = path.substring(start, end);\n let segment;\n if (segmentBuilder.length === 0) {\n // Avoid copying for the common case of a segment that excludes \\0\n // and \\001\n segment = currentPiece;\n } else {\n segmentBuilder += currentPiece;\n segment = segmentBuilder;\n segmentBuilder = '';\n }\n segments.push(segment);\n break;\n case encodedNul:\n segmentBuilder += path.substring(start, end);\n segmentBuilder += '\\0';\n break;\n case encodedEscape:\n // The escape character can be used in the output to encode itself.\n segmentBuilder += path.substring(start, end + 1);\n break;\n default:\n fail('Invalid encoded resource path: \"' + path + '\"');\n }\n\n start = end + 2;\n }\n\n return new ResourcePath(segments);\n}\n\n/**\n * Computes the prefix successor of the given path, computed by encode above.\n * A prefix successor is the first key that cannot be prefixed by the given\n * path. It's useful for defining the end of a prefix scan such that all keys\n * in the scan have the same prefix.\n *\n * Note that this is not a general prefix successor implementation, which is\n * tricky to get right with Strings, given that they encode down to UTF-8.\n * Instead this relies on the fact that all paths encoded by this class are\n * always terminated with a separator, and so a successor can always be\n * cheaply computed by incrementing the last character of the path.\n */\nexport function prefixSuccessor(path: EncodedResourcePath) {\n const c = path.charCodeAt(path.length - 1);\n // TODO(mcg): this really should be a general thing, but not worth it right\n // now\n assert(c === 1, 'successor may only operate on paths generated by encode');\n return path.substring(0, path.length - 1) + String.fromCharCode(c + 1);\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/encoded_resource_path.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '../protos/firestore_proto_api';\nimport { BatchId } from '../core/types';\nimport { TargetId } from '../core/types';\nimport { ResourcePath } from '../model/path';\nimport { assert } from '../util/assert';\n\nimport { encode, EncodedResourcePath } from './encoded_resource_path';\n\nexport const SCHEMA_VERSION = 1;\n\n/** Performs database creation and (in the future) upgrades between versions. */\nexport function createOrUpgradeDb(db: IDBDatabase, oldVersion: number): void {\n assert(oldVersion === 0, 'Unexpected upgrade from version ' + oldVersion);\n\n db.createObjectStore(DbMutationQueue.store, {\n keyPath: DbMutationQueue.keyPath\n });\n\n // TODO(mikelehen): Get rid of \"as any\" if/when TypeScript fixes their\n // types. https://github.com/Microsoft/TypeScript/issues/14322\n db.createObjectStore(\n // tslint:disable-next-line:no-any\n DbMutationBatch.store,\n { keyPath: DbMutationBatch.keyPath as any }\n );\n\n const targetDocumentsStore = db.createObjectStore(\n // tslint:disable-next-line:no-any\n DbTargetDocument.store,\n { keyPath: DbTargetDocument.keyPath as any }\n );\n targetDocumentsStore.createIndex(\n DbTargetDocument.documentTargetsIndex,\n DbTargetDocument.documentTargetsKeyPath,\n { unique: true }\n );\n\n const targetStore = db.createObjectStore(DbTarget.store, {\n keyPath: DbTarget.keyPath\n });\n // NOTE: This is unique only because the TargetId is the suffix.\n targetStore.createIndex(\n DbTarget.queryTargetsIndexName,\n DbTarget.queryTargetsKeyPath,\n { unique: true }\n );\n\n // NOTE: keys for these stores are specified explicitly rather than using a\n // keyPath.\n db.createObjectStore(DbDocumentMutation.store);\n db.createObjectStore(DbRemoteDocument.store);\n db.createObjectStore(DbOwner.store);\n db.createObjectStore(DbTargetGlobal.store);\n}\n\n/**\n * Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.\n */\nexport class DbTimestamp {\n constructor(public seconds: number, public nanos: number) {}\n}\n\n// The key for the singleton object in the 'owner' store is 'owner'.\nexport type DbOwnerKey = 'owner';\n\n/**\n * A singleton object to be stored in the 'owner' store in IndexedDb.\n *\n * A given database can be owned by a single tab at a given time. That tab\n * must validate that it is still the owner before every write operation and\n * should regularly write an updated timestamp to prevent other tabs from\n * \"stealing\" ownership of the db.\n */\nexport class DbOwner {\n /** Name of the IndexedDb object store. */\n static store = 'owner';\n\n constructor(public ownerId: string, public leaseTimestampMs: number) {}\n}\n\n/** Object keys in the 'mutationQueues' store are userId strings. */\nexport type DbMutationQueueKey = string;\n\n/**\n * An object to be stored in the 'mutationQueues' store in IndexedDb.\n *\n * Each user gets a single queue of MutationBatches to apply to the server.\n * DbMutationQueue tracks the metadata about the queue.\n */\nexport class DbMutationQueue {\n /** Name of the IndexedDb object store. */\n static store = 'mutationQueues';\n\n /** Keys are automatically assigned via the userId property. */\n static keyPath = 'userId';\n\n constructor(\n /**\n * The normalized user ID to which this queue belongs.\n */\n public userId: string,\n /**\n * An identifier for the highest numbered batch that has been acknowledged\n * by the server. All MutationBatches in this queue with batchIds less\n * than or equal to this value are considered to have been acknowledged by\n * the server.\n */\n public lastAcknowledgedBatchId: number,\n /**\n * A stream token that was previously sent by the server.\n *\n * See StreamingWriteRequest in datastore.proto for more details about\n * usage.\n *\n * After sending this token, earlier tokens may not be used anymore so\n * only a single stream token is retained.\n */\n public lastStreamToken: string\n ) {}\n}\n\n/** keys in the 'mutations' object store are [userId, batchId] pairs. */\nexport type DbMutationBatchKey = [string, BatchId];\n\n/**\n * An object to be stored in the 'mutations' store in IndexedDb.\n *\n * Represents a batch of user-level mutations intended to be sent to the server\n * in a single write. Each user-level batch gets a separate DbMutationBatch\n * with a new batchId.\n */\nexport class DbMutationBatch {\n /** Name of the IndexedDb object store. */\n static store = 'mutations';\n\n /** Keys are automatically assigned via the userId, batchId properties. */\n static keyPath = ['userId', 'batchId'];\n\n constructor(\n /**\n * The normalized user ID to which this batch belongs.\n */\n public userId: string,\n /**\n * An identifier for this batch, allocated by the mutation queue in a\n * monotonically increasing manner.\n */\n public batchId: BatchId,\n /**\n * The local write time of the batch, stored as milliseconds since the\n * epoch.\n */\n public localWriteTimeMs: number,\n /**\n * A list of mutations to apply. All mutations will be applied atomically.\n *\n * Mutations are serialized via JsonProtoSerializer.toMutation().\n */\n public mutations: api.Write[]\n ) {}\n}\n\n/**\n * The key for a db document mutation, which is made up of a userID, path, and\n * batchId. Note that the path must be serialized into a form that indexedDB can\n * sort.\n */\nexport type DbDocumentMutationKey = [string, EncodedResourcePath, BatchId];\n\n/**\n * An object to be stored in the 'documentMutations' store in IndexedDb.\n *\n * A manually maintained index of all the mutation batches that affect a given\n * document key. The rows in this table are references based on the contents of\n * DbMutationBatch.mutations.\n */\nexport class DbDocumentMutation {\n static store = 'documentMutations';\n\n /**\n * Creates a [userId] key for use in the DbDocumentMutations index to iterate\n * over all of a user's document mutations.\n */\n static prefixForUser(userId: string): [string] {\n return [userId];\n }\n\n /**\n * Creates a [userId, encodedPath] key for use in the DbDocumentMutations\n * index to iterate over all at document mutations for a given path or lower.\n */\n static prefixForPath(\n userId: string,\n path: ResourcePath\n ): [string, EncodedResourcePath] {\n return [userId, encode(path)];\n }\n\n /**\n * Creates a full index key of [userId, encodedPath, batchId] for inserting\n * and deleting into the DbDocumentMutations index.\n */\n static key(\n userId: string,\n path: ResourcePath,\n batchId: BatchId\n ): DbDocumentMutationKey {\n return [userId, encode(path), batchId];\n }\n\n /**\n * Because we store all the useful information for this store in the key,\n * there is no useful information to store as the value. The raw (unencoded)\n * path cannot be stored because IndexedDb doesn't store prototype\n * information.\n */\n static PLACEHOLDER = new DbDocumentMutation();\n\n private constructor() {}\n}\n\n/**\n * A key in the 'remoteDocuments' object store is a string array containing the\n * segments that make up the path.\n */\nexport type DbRemoteDocumentKey = string[];\n\n/**\n * Represents the known absence of a document at a particular version.\n * Stored in IndexedDb as part of a DbRemoteDocument object.\n */\nexport class DbNoDocument {\n constructor(public path: string[], public readTime: DbTimestamp) {}\n}\n\n/**\n * An object to be stored in the 'remoteDocuments' store in IndexedDb. It\n * represents either a cached document (if it exists) or a cached \"no-document\"\n * (if it is known to not exist).\n *\n * Note: This is the persisted equivalent of a MaybeDocument and could perhaps\n * be made more general if necessary.\n */\nexport class DbRemoteDocument {\n static store = 'remoteDocuments';\n\n constructor(\n /**\n * Set to an instance of a DbNoDocument if it is known that no document\n * exists.\n */\n public noDocument: DbNoDocument | null,\n /**\n * Set to an instance of a Document if there's a cached version of the\n * document.\n */\n public document: api.Document | null\n ) {}\n}\n\n/**\n * A key in the 'targets' object store is a targetId of the query.\n */\nexport type DbTargetKey = TargetId;\n\n/**\n * The persisted type for a query nested with in the 'targets' store in\n * IndexedDb. We use the proto definitions for these two kinds of queries in\n * order to avoid writing extra serialization logic.\n */\nexport type DbQuery = api.QueryTarget | api.DocumentsTarget;\n\n/**\n * An object to be stored in the 'targets' store in IndexedDb.\n *\n * This is based on and should be kept in sync with the proto used in the iOS\n * client.\n *\n * Each query the client listens to against the server is tracked on disk so\n * that the query can be efficiently resumed on restart.\n */\nexport class DbTarget {\n static store = 'targets';\n\n /** Keys are automatically assigned via the targetId property. */\n static keyPath = 'targetId';\n\n /** The name of the queryTargets index. */\n static queryTargetsIndexName = 'queryTargetsIndex';\n\n /**\n * The index of all canonicalIds to the targets that they match. This is not\n * a unique mapping because canonicalId does not promise a unique name for all\n * possible queries, so we append the targetId to make the mapping unique.\n */\n static queryTargetsKeyPath = ['canonicalId', 'targetId'];\n\n constructor(\n /**\n * An auto-generated sequential numeric identifier for the query.\n *\n * Queries are stored using their canonicalId as the key, but these\n * canonicalIds can be quite long so we additionally assign a unique\n * queryId which can be used by referenced data structures (e.g.\n * indexes) to minimize the on-disk cost.\n */\n public targetId: TargetId,\n /**\n * The canonical string representing this query. This is not unique.\n */\n public canonicalId: string,\n /**\n * The last readTime received from the Watch Service for this query.\n *\n * This is the same value as TargetChange.read_time in the protos.\n */\n public readTime: DbTimestamp,\n /**\n * An opaque, server-assigned token that allows watching a query to be\n * resumed after disconnecting without retransmitting all the data\n * that matches the query. The resume token essentially identifies a\n * point in time from which the server should resume sending results.\n *\n * This is related to the snapshotVersion in that the resumeToken\n * effectively also encodes that value, but the resumeToken is opaque\n * and sometimes encodes additional information.\n *\n * A consequence of this is that the resumeToken should be used when\n * asking the server to reason about where this client is in the watch\n * stream, but the client should use the snapshotVersion for its own\n * purposes.\n *\n * This is the same value as TargetChange.resume_token in the protos.\n */\n public resumeToken: string,\n /**\n * A sequence number representing the last time this query was\n * listened to, used for garbage collection purposes.\n *\n * Conventionally this would be a timestamp value, but device-local\n * clocks are unreliable and they must be able to create new listens\n * even while disconnected. Instead this should be a monotonically\n * increasing number that's incremented on each listen call.\n *\n * This is different from the queryId since the queryId is an\n * immutable identifier assigned to the Query on first use while\n * lastListenSequenceNumber is updated every time the query is\n * listened to.\n */\n public lastListenSequenceNumber: number,\n /**\n * The query for this target.\n *\n * Because canonical ids are not unique we must store the actual query. We\n * use the proto to have an object we can persist without having to\n * duplicate translation logic to and from a `Query` object.\n */\n public query: DbQuery\n ) {}\n}\n\n/**\n * The key for a DbTargetDocument, containing a targetId and an encoded resource\n * path.\n */\nexport type DbTargetDocumentKey = [TargetId, EncodedResourcePath];\n\n/**\n * An object representing an association between a target and a document.\n * Stored in the targetDocument object store to store the documents tracked by a\n * particular target.\n */\nexport class DbTargetDocument {\n /** Name of the IndexedDb object store. */\n static store = 'targetDocuments';\n\n /** Keys are automatically assigned via the targetId, path properties. */\n static keyPath = ['targetId', 'path'];\n\n /** The index name for the reverse index. */\n static documentTargetsIndex = 'documentTargetsIndex';\n\n /** We also need to create the reverse index for these properties. */\n static documentTargetsKeyPath = ['path', 'targetId'];\n\n constructor(\n /**\n * The targetId identifying a target.\n */\n public targetId: TargetId,\n /**\n * The path to the document, as encoded in the key.\n */\n public path: EncodedResourcePath\n ) {}\n}\n\n/**\n * The type to represent the single allowed key for the DbTargetGlobal store.\n */\nexport type DbTargetGlobalKey = typeof DbTargetGlobal.key;\n\n/**\n * A record of global state tracked across all Targets, tracked separately\n * to avoid the need for extra indexes.\n *\n * This should be kept in-sync with the proto used in the iOS client.\n */\nexport class DbTargetGlobal {\n /**\n * The key string used for the single object that exists in the\n * DbTargetGlobal store.\n */\n static key = 'targetGlobalKey';\n static store = 'targetGlobal';\n\n constructor(\n /**\n * The highest numbered target id across all targets.\n *\n * See DbTarget.targetId.\n */\n public highestTargetId: TargetId,\n /**\n * The highest numbered lastListenSequenceNumber across all targets.\n *\n * See DbTarget.lastListenSequenceNumber.\n */\n public highestListenSequenceNumber: number,\n /**\n * A global snapshot version representing the last consistent snapshot we\n * received from the backend. This is monotonically increasing and any\n * snapshots received from the backend prior to this version (e.g. for\n * targets resumed with a resumeToken) should be suppressed (buffered)\n * until the backend has caught up to this snapshot version again. This\n * prevents our cache from ever going backwards in time.\n */\n public lastRemoteSnapshotVersion: DbTimestamp\n ) {}\n}\n\n/**\n * The list of all IndexedDB stored used by the SDK. This is used when creating\n * transactions so that access across all stores is done atomically.\n */\nexport const ALL_STORES = [\n DbMutationQueue.store,\n DbMutationBatch.store,\n DbDocumentMutation.store,\n DbRemoteDocument.store,\n DbTarget.store,\n DbOwner.store,\n DbTargetGlobal.store,\n DbTargetDocument.store\n];\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/indexeddb_schema.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from '../util/assert';\nimport { debug } from '../util/log';\nimport { AnyDuringMigration } from '../util/misc';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { PersistencePromise } from './persistence_promise';\n\nconst LOG_TAG = 'SimpleDb';\n\n/**\n * Provides a wrapper around IndexedDb with a simplified interface that uses\n * Promise-like return values to chain operations. Real promises cannot be used\n * since .then() continuations are executed asynchronously (e.g. via\n * .setImmediate), which would cause IndexedDB to end the transaction.\n * See PersistencePromise for more details.\n */\nexport class SimpleDb {\n /** Opens the specified database, creating or upgrading it if necessary. */\n static openOrCreate(\n name: string,\n version: number,\n runUpgrade: (db: IDBDatabase, oldVersion: number) => void\n ): Promise {\n assert(\n SimpleDb.isAvailable(),\n 'IndexedDB not supported in current environment.'\n );\n debug(LOG_TAG, 'Opening database:', name);\n return new PersistencePromise((resolve, reject) => {\n // TODO(mikelehen): Investigate browser compatibility.\n // https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB\n // suggests IE9 and older WebKit browsers handle upgrade\n // differently.\n const request = window.indexedDB.open(name, version);\n\n request.onsuccess = (event: Event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n resolve(new SimpleDb(db));\n };\n\n request.onerror = (event: ErrorEvent) => {\n reject((event.target as IDBOpenDBRequest).error);\n };\n\n request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\n debug(\n LOG_TAG,\n 'Database \"' + name + '\" requires upgrade from version:',\n event.oldVersion\n );\n // TODO(mikelehen): If/when we need to do an actual data\n // migration, we'll want to wrap db in a SimpleDb and have the\n // runUpgrade function return a PersistencePromise, since we'll\n // likely need to do async reads and writes. For now we're\n // cheating and just passing the raw IndexedDB in, since\n // createObjectStore(), etc. are synchronous.\n const db = (event.target as IDBOpenDBRequest).result;\n runUpgrade(db, event.oldVersion);\n };\n }).toPromise();\n }\n\n /** Deletes the specified database. */\n static delete(name: string): Promise {\n debug(LOG_TAG, 'Removing database:', name);\n return wrapRequest(window.indexedDB.deleteDatabase(name)).toPromise();\n }\n\n /** Returns true if IndexedDB is available in the current environment. */\n static isAvailable(): boolean {\n if (typeof window === 'undefined' || window.indexedDB == null) {\n return false;\n }\n // We extensively use indexed array values and compound keys,\n // which IE and Edge do not support. However, they still have indexedDB\n // defined on the window, so we need to check for them here and make sure\n // to return that persistence is not enabled for those browsers.\n // For tracking support of this feature, see here:\n // https://developer.microsoft.com/en-us/microsoft-edge/platform/status/indexeddbarraysandmultientrysupport/\n\n // Check the UA string to find out the browser.\n const ua = window.navigator.userAgent;\n\n // IE 10\n // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';\n\n // IE 11\n // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';\n\n // Edge\n // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,\n // like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';\n\n if (\n ua.indexOf('MSIE ') > 0 ||\n ua.indexOf('Trident/') > 0 ||\n ua.indexOf('Edge/') > 0\n ) {\n return false;\n } else {\n return true;\n }\n }\n\n constructor(private db: IDBDatabase) {}\n\n runTransaction(\n mode: 'readonly' | 'readwrite',\n objectStores: string[],\n transactionFn: (transaction: SimpleDbTransaction) => PersistencePromise\n ): Promise {\n const transaction = new SimpleDbTransaction(this.db, mode, objectStores);\n const transactionFnResult = transactionFn(transaction)\n .catch(error => {\n // Abort the transaction if there was an\n // error.\n transaction.abort();\n return PersistencePromise.reject(error);\n })\n .toPromise();\n\n // Wait for the transaction to complete (i.e. IndexedDb's onsuccess event to\n // fire), but still return the original transactionFnResult back to the\n // caller.\n return transaction.completionPromise.then(\n () => transactionFnResult\n ) as AnyDuringMigration;\n }\n\n close() {\n this.db.close();\n }\n}\n\n/**\n * A controller for iterating over a key range or index. It allows an iterate\n * callback to delete the currently-referenced object, or jump to a new key\n * within the key range or index.\n */\nexport class IterationController {\n private shouldStop = false;\n private nextKey: IDBValidKey | IDBKeyRange | null = null;\n\n constructor(private dbCursor: IDBCursorWithValue) {}\n\n get isDone(): boolean {\n return this.shouldStop;\n }\n\n get skipToKey(): IDBValidKey | IDBKeyRange | null {\n return this.nextKey;\n }\n\n set cursor(value: IDBCursorWithValue) {\n this.dbCursor = value;\n }\n\n /**\n * This function can be called to stop iteration at any point.\n */\n done(): void {\n this.shouldStop = true;\n }\n\n /**\n * This function can be called to skip to that next key, which could be\n * an index or a primary key.\n */\n skip(key: IDBValidKey | IDBKeyRange): void {\n this.nextKey = key;\n }\n\n /**\n * Delete the current cursor value from the object store.\n *\n * NOTE: You CANNOT do this with a keysOnly query.\n */\n delete(): PersistencePromise {\n return wrapRequest(this.dbCursor.delete());\n }\n}\n\n/**\n * Callback used with iterate() method.\n */\nexport type IterateCallback = (\n key: KeyType,\n value: ValueType,\n control: IterationController\n) => void | PersistencePromise;\n\n/** Options available to the iterate() method. */\nexport interface IterateOptions {\n /** Index to iterate over (else primary keys will be iterated) */\n index?: string;\n\n /** IndxedDB Range to iterate over (else entire store will be iterated) */\n range?: IDBKeyRange;\n\n /** If true, values aren't read while iterating. */\n keysOnly?: boolean;\n\n /** If true, iterate over the store in reverse. */\n reverse?: boolean;\n}\n\n/**\n * Wraps an IDBTransaction and exposes a store() method to get a handle to a\n * specific object store.\n */\nexport class SimpleDbTransaction {\n private transaction: IDBTransaction;\n private aborted = false;\n\n /**\n * A promise that resolves with the result of the IndexedDb transaction.\n *\n * Note: A transaction explicitly aborted via abort() is considered successful\n * and this promise will resolve as successful.\n */\n readonly completionPromise: Promise;\n\n constructor(db: IDBDatabase, mode: string, objectStoresNames: string[]) {\n this.transaction = db.transaction(\n objectStoresNames,\n mode as AnyDuringMigration\n );\n\n this.completionPromise = new Promise((resolve, reject) => {\n // We consider aborting to be \"normal\" and just resolve the promise.\n // May need to revisit if/when we actually need to abort transactions.\n this.transaction.onabort = this.transaction.oncomplete = event => {\n resolve();\n };\n this.transaction.onerror = (event: Event) => {\n reject((event.target as IDBRequest).error);\n };\n });\n }\n\n abort(): void {\n if (!this.aborted) {\n debug(LOG_TAG, 'Aborting transaction.');\n this.aborted = true;\n this.transaction.abort();\n }\n }\n\n /**\n * Returns a SimpleDbStore for the specified store. All\n * operations performed on the SimpleDbStore happen within the context of this\n * transaction and it cannot be used anymore once the transaction is\n * completed.\n *\n * Note that we can't actually enforce that the KeyType and ValueType are\n * correct, but they allow type safety through the rest of the consuming code.\n */\n store(\n storeName: string\n ): SimpleDbStore {\n const store = this.transaction.objectStore(storeName);\n assert(!!store, 'Object store not part of transaction: ' + storeName);\n return new SimpleDbStore(store);\n }\n}\n\n/**\n * A wrapper around an IDBObjectStore providing an API that:\n *\n * 1) Has generic KeyType / ValueType parameters to provide strongly-typed\n * methods for acting against the object store.\n * 2) Deals with IndexedDB's onsuccess / onerror event callbacks, making every\n * method return a PersistencePromise instead.\n * 3) Provides a higher-level API to avoid needing to do excessive wrapping of\n * intermediate IndexedDB types (IDBCursorWithValue, etc.)\n */\nexport class SimpleDbStore {\n constructor(private store: IDBObjectStore) {}\n\n /**\n * Writes a value into the Object Store.\n *\n * @param key Optional explicit key to use when writing the object, else the\n * key will be auto-assigned (e.g. via the defined keyPath for the store).\n * @param value The object to write.\n */\n put(value: ValueType): PersistencePromise;\n put(key: KeyType, value: ValueType): PersistencePromise;\n put(\n keyOrValue: KeyType | ValueType,\n value?: ValueType\n ): PersistencePromise {\n let request;\n if (value !== undefined) {\n debug(LOG_TAG, 'PUT', this.store.name, keyOrValue, value);\n request = this.store.put(value, keyOrValue as KeyType);\n } else {\n debug(LOG_TAG, 'PUT', this.store.name, '', keyOrValue);\n request = this.store.put(keyOrValue as ValueType);\n }\n return wrapRequest(request);\n }\n\n /**\n * Gets the object with the specified key from the specified store, or null\n * if no object exists with the specified key.\n *\n * @key The key of the object to get.\n * @return The object with the specified key or null if no object exists.\n */\n get(key: KeyType): PersistencePromise {\n const request = this.store.get(key);\n // tslint:disable-next-line:no-any We're doing an unsafe cast to ValueType.\n return wrapRequest(request).next(result => {\n // Normalize nonexistence to null.\n if (result === undefined) {\n result = null;\n }\n debug(LOG_TAG, 'GET', this.store.name, key, result);\n return result;\n });\n }\n\n delete(key: KeyType | IDBKeyRange): PersistencePromise {\n debug(LOG_TAG, 'DELETE', this.store.name, key);\n const request = this.store.delete(key);\n return wrapRequest(request);\n }\n\n loadAll(): PersistencePromise;\n loadAll(range: IDBKeyRange): PersistencePromise;\n loadAll(index: string, range: IDBKeyRange): PersistencePromise;\n loadAll(\n indexOrRange?: string | IDBKeyRange,\n range?: IDBKeyRange\n ): PersistencePromise {\n const cursor = this.cursor(this.options(indexOrRange, range));\n const results: ValueType[] = [];\n return this.iterateCursor(cursor, (key, value) => {\n results.push(value);\n }).next(() => {\n return results;\n });\n }\n\n deleteAll(): PersistencePromise;\n deleteAll(range: IDBKeyRange): PersistencePromise;\n deleteAll(index: string, range: IDBKeyRange): PersistencePromise;\n deleteAll(\n indexOrRange?: string | IDBKeyRange,\n range?: IDBKeyRange\n ): PersistencePromise {\n debug(LOG_TAG, 'DELETE ALL', this.store.name);\n const options = this.options(indexOrRange, range);\n options.keysOnly = false;\n const cursor = this.cursor(options);\n return this.iterateCursor(cursor, (key, value, control) => {\n // NOTE: Calling delete() on a cursor is documented as more efficient than\n // calling delete() on an object store with a single key\n // (https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/delete),\n // however, this requires us *not* to use a keysOnly cursor\n // (https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor/delete). We\n // may want to compare the performance of each method.\n return control.delete();\n });\n }\n\n /**\n * Iterates over keys and values in an object store.\n *\n * @param options Options specifying how to iterate the objects in the store.\n * @param callback will be called for each iterated object. Iteration can be\n * canceled at any point by calling the doneFn passed to the callback.\n * The callback can return a PersistencePromise if it performs async\n * operations but note that iteration will continue without waiting for them\n * to complete.\n * @returns A PersistencePromise that resolves once all PersistencePromises\n * returned by callbacks resolve.\n */\n iterate(\n callback: IterateCallback\n ): PersistencePromise;\n iterate(\n options: IterateOptions,\n callback: IterateCallback\n ): PersistencePromise;\n iterate(\n optionsOrCallback: IterateOptions | IterateCallback,\n callback?: IterateCallback\n ): PersistencePromise {\n let options;\n if (!callback) {\n options = {};\n callback = optionsOrCallback as IterateCallback;\n } else {\n options = optionsOrCallback;\n }\n const cursor = this.cursor(options);\n return this.iterateCursor(cursor, callback);\n }\n\n private iterateCursor(\n cursorRequest: IDBRequest,\n fn: IterateCallback\n ): PersistencePromise {\n const results: Array> = [];\n return new PersistencePromise((resolve, reject) => {\n cursorRequest.onerror = (event: Event) => {\n reject((event.target as IDBRequest).error);\n };\n cursorRequest.onsuccess = (event: Event) => {\n const cursor: IDBCursorWithValue = (event.target as IDBRequest).result;\n if (!cursor) {\n resolve();\n return;\n }\n const controller = new IterationController(cursor);\n const userResult = fn(cursor.primaryKey, cursor.value, controller);\n if (userResult instanceof PersistencePromise) {\n results.push(userResult);\n }\n if (controller.isDone) {\n resolve();\n } else if (controller.skipToKey === null) {\n cursor.continue();\n } else {\n cursor.continue(controller.skipToKey);\n }\n };\n }).next(() => {\n return PersistencePromise.waitFor(results);\n });\n }\n\n private options(\n indexOrRange?: string | IDBKeyRange,\n range?: IDBKeyRange\n ): IterateOptions {\n let indexName: string | undefined = undefined;\n if (indexOrRange !== undefined) {\n if (typeof indexOrRange === 'string') {\n indexName = indexOrRange;\n } else {\n assert(\n range === undefined,\n '3rd argument must not be defined if 2nd is a range.'\n );\n range = indexOrRange;\n }\n }\n return { index: indexName, range };\n }\n\n private cursor(options: IterateOptions): IDBRequest {\n let direction = 'next';\n if (options.reverse) {\n direction = 'prev';\n }\n if (options.index) {\n const index = this.store.index(options.index);\n if (options.keysOnly) {\n return index.openKeyCursor(\n options.range,\n direction as AnyDuringMigration\n );\n } else {\n return index.openCursor(options.range, direction as AnyDuringMigration);\n }\n } else {\n return this.store.openCursor(\n options.range,\n direction as AnyDuringMigration\n );\n }\n }\n}\n\n/**\n * Wraps an IDBRequest in a PersistencePromise, using the onsuccess / onerror\n * handlers to resolve / reject the PersistencePromise as appropriate.\n */\nfunction wrapRequest(request: IDBRequest): PersistencePromise {\n return new PersistencePromise((resolve, reject) => {\n request.onsuccess = (event: Event) => {\n const result = (event.target as IDBRequest).result;\n resolve(result);\n };\n\n request.onerror = (event: Event) => {\n reject((event.target as IDBRequest).error);\n };\n });\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/simple_db.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { Query } from '../core/query';\nimport { Timestamp } from '../core/timestamp';\nimport { BatchId, ProtoByteString } from '../core/types';\nimport { DocumentKey } from '../model/document_key';\nimport { Mutation } from '../model/mutation';\nimport { BATCHID_UNKNOWN, MutationBatch } from '../model/mutation_batch';\nimport { ResourcePath } from '../model/path';\nimport { assert, fail } from '../util/assert';\nimport { immediatePredecessor, primitiveComparator } from '../util/misc';\nimport { SortedSet } from '../util/sorted_set';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport * as EncodedResourcePath from './encoded_resource_path';\nimport { GarbageCollector } from './garbage_collector';\nimport {\n DbDocumentMutation,\n DbDocumentMutationKey,\n DbMutationBatch,\n DbMutationBatchKey,\n DbMutationQueue,\n DbMutationQueueKey\n} from './indexeddb_schema';\nimport { LocalSerializer } from './local_serializer';\nimport { MutationQueue } from './mutation_queue';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { SimpleDbStore, SimpleDbTransaction } from './simple_db';\n\n/** A mutation queue for a specific user, backed by IndexedDB. */\nexport class IndexedDbMutationQueue implements MutationQueue {\n /**\n * Next value to use when assigning sequential IDs to each mutation batch.\n *\n * NOTE: There can only be one IndexedDbMutationQueue for a given db at a\n * time, hence it is safe to track nextBatchID as an instance-level property.\n * Should we ever relax this constraint we'll need to revisit this.\n */\n private nextBatchId: BatchId;\n\n /**\n * A write-through cache copy of the metadata describing the current queue.\n */\n private metadata: DbMutationQueue;\n\n private garbageCollector: GarbageCollector | null = null;\n\n constructor(\n /**\n * The normalized userId (e.g. null UID => \"\" userId) used to store /\n * retrieve mutations.\n */\n private userId: string,\n private serializer: LocalSerializer\n ) {}\n\n /**\n * Creates a new mutation queue for the given user.\n * @param user The user for which to create a mutation queue.\n * @param serializer The serializer to use when persisting to IndexedDb.\n */\n static forUser(user: User, serializer: LocalSerializer) {\n // TODO(mcg): Figure out what constraints there are on userIDs\n // In particular, are there any reserved characters? are empty ids allowed?\n // For the moment store these together in the same mutations table assuming\n // that empty userIDs aren't allowed.\n assert(user.uid !== '', 'UserID must not be an empty string.');\n const userId = user.isUnauthenticated() ? '' : user.uid!;\n return new IndexedDbMutationQueue(userId, serializer);\n }\n\n start(transaction: PersistenceTransaction): PersistencePromise {\n return IndexedDbMutationQueue.loadNextBatchIdFromDb(transaction)\n .next(nextBatchId => {\n this.nextBatchId = nextBatchId;\n return mutationQueuesStore(transaction).get(this.userId);\n })\n .next((metadata: DbMutationQueue | null) => {\n if (!metadata) {\n metadata = new DbMutationQueue(\n this.userId,\n BATCHID_UNKNOWN,\n /*lastStreamToken=*/ ''\n );\n }\n this.metadata = metadata;\n\n // On restart, nextBatchId may end up lower than\n // lastAcknowledgedBatchId since it's computed from the queue\n // contents, and there may be no mutations in the queue. In this\n // case, we need to reset lastAcknowledgedBatchId (which is safe\n // since the queue must be empty).\n if (this.metadata.lastAcknowledgedBatchId >= this.nextBatchId) {\n return this.checkEmpty(transaction).next(empty => {\n assert(\n empty,\n 'Reset nextBatchID is only possible when the queue is empty'\n );\n\n this.metadata.lastAcknowledgedBatchId = BATCHID_UNKNOWN;\n return mutationQueuesStore(transaction).put(this.metadata);\n });\n } else {\n return PersistencePromise.resolve();\n }\n });\n }\n\n /**\n * Returns one larger than the largest batch ID that has been stored. If there\n * are no mutations returns 0. Note that batch IDs are global.\n */\n static loadNextBatchIdFromDb(\n txn: PersistenceTransaction\n ): PersistencePromise {\n let maxBatchId = BATCHID_UNKNOWN;\n return mutationsStore(txn)\n .iterate({ reverse: true }, (key, batch, control) => {\n const [userId, batchId] = key;\n if (batchId > maxBatchId) {\n maxBatchId = batch.batchId;\n }\n\n if (userId === '') {\n // We can't compute a predecessor for the empty string, since it\n // is lexographically first. That also means that no other\n // userIds can come before this one, so we can just exit early.\n control.done();\n } else {\n const nextUser = immediatePredecessor(userId);\n control.skip([nextUser]);\n }\n })\n .next(() => maxBatchId + 1);\n }\n\n checkEmpty(transaction: PersistenceTransaction): PersistencePromise {\n let empty = true;\n const range = IDBKeyRange.bound(\n this.keyForBatchId(Number.NEGATIVE_INFINITY),\n this.keyForBatchId(Number.POSITIVE_INFINITY)\n );\n return mutationsStore(transaction)\n .iterate({ range }, (key, value, control) => {\n empty = false;\n control.done();\n })\n .next(() => empty);\n }\n\n getNextBatchId(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(this.nextBatchId);\n }\n\n getHighestAcknowledgedBatchId(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(this.metadata.lastAcknowledgedBatchId);\n }\n\n acknowledgeBatch(\n transaction: PersistenceTransaction,\n batch: MutationBatch,\n streamToken: ProtoByteString\n ): PersistencePromise {\n const batchId = batch.batchId;\n assert(\n batchId > this.metadata.lastAcknowledgedBatchId,\n 'Mutation batchIDs must be acknowledged in order'\n );\n\n this.metadata.lastAcknowledgedBatchId = batchId;\n this.metadata.lastStreamToken = validateStreamToken(streamToken);\n\n return mutationQueuesStore(transaction).put(this.metadata);\n }\n\n getLastStreamToken(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(this.metadata.lastStreamToken);\n }\n\n setLastStreamToken(\n transaction: PersistenceTransaction,\n streamToken: ProtoByteString\n ): PersistencePromise {\n this.metadata.lastStreamToken = validateStreamToken(streamToken);\n return mutationQueuesStore(transaction).put(this.metadata);\n }\n\n addMutationBatch(\n transaction: PersistenceTransaction,\n localWriteTime: Timestamp,\n mutations: Mutation[]\n ): PersistencePromise {\n const batchId = this.nextBatchId;\n this.nextBatchId++;\n const batch = new MutationBatch(batchId, localWriteTime, mutations);\n\n const dbBatch = this.serializer.toDbMutationBatch(this.userId, batch);\n\n return mutationsStore(transaction)\n .put(dbBatch)\n .next(() => {\n const promises: Array> = [];\n for (const mutation of mutations) {\n const encodedPath = EncodedResourcePath.encode(mutation.key.path);\n const indexKey = DbDocumentMutation.key(\n this.userId,\n mutation.key.path,\n batchId\n );\n documentMutationsStore(transaction).put(\n indexKey,\n DbDocumentMutation.PLACEHOLDER\n );\n }\n return PersistencePromise.waitFor(promises);\n })\n .next(() => {\n return batch;\n });\n }\n\n lookupMutationBatch(\n transaction: PersistenceTransaction,\n batchId: BatchId\n ): PersistencePromise {\n return mutationsStore(transaction)\n .get(this.keyForBatchId(batchId))\n .next(\n dbBatch =>\n dbBatch ? this.serializer.fromDbMutationBatch(dbBatch) : null\n );\n }\n\n getNextMutationBatchAfterBatchId(\n transaction: PersistenceTransaction,\n batchId: BatchId\n ): PersistencePromise {\n const range = IDBKeyRange.lowerBound(this.keyForBatchId(batchId + 1));\n let foundBatch: MutationBatch | null = null;\n return mutationsStore(transaction)\n .iterate({ range }, (key, dbBatch, control) => {\n if (dbBatch.userId === this.userId) {\n assert(\n dbBatch.batchId > batchId,\n 'Should have found mutation after ' + batchId\n );\n foundBatch = this.serializer.fromDbMutationBatch(dbBatch);\n }\n control.done();\n })\n .next(() => foundBatch);\n }\n\n getAllMutationBatches(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n const range = IDBKeyRange.bound(\n this.keyForBatchId(BATCHID_UNKNOWN),\n this.keyForBatchId(Number.POSITIVE_INFINITY)\n );\n return mutationsStore(transaction)\n .loadAll(range)\n .next(dbBatches =>\n dbBatches.map(dbBatch => this.serializer.fromDbMutationBatch(dbBatch))\n );\n }\n\n getAllMutationBatchesThroughBatchId(\n transaction: PersistenceTransaction,\n batchId: BatchId\n ): PersistencePromise {\n const range = IDBKeyRange.bound(\n this.keyForBatchId(BATCHID_UNKNOWN),\n this.keyForBatchId(batchId)\n );\n return mutationsStore(transaction)\n .loadAll(range)\n .next(dbBatches =>\n dbBatches.map(dbBatch => this.serializer.fromDbMutationBatch(dbBatch))\n );\n }\n\n getAllMutationBatchesAffectingDocumentKey(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n // Scan the document-mutation index starting with a prefix starting with\n // the given documentKey.\n const indexPrefix = DbDocumentMutation.prefixForPath(\n this.userId,\n documentKey.path\n );\n const indexStart = IDBKeyRange.lowerBound(indexPrefix);\n\n const results: MutationBatch[] = [];\n return documentMutationsStore(transaction)\n .iterate({ range: indexStart }, (indexKey, _, control) => {\n const [userID, encodedPath, batchID] = indexKey;\n\n // Only consider rows matching exactly the specific key of\n // interest. Note that because we order by path first, and we\n // order terminators before path separators, we'll encounter all\n // the index rows for documentKey contiguously. In particular, all\n // the rows for documentKey will occur before any rows for\n // documents nested in a subcollection beneath documentKey so we\n // can stop as soon as we hit any such row.\n const path = EncodedResourcePath.decode(encodedPath);\n if (userID !== this.userId || !documentKey.path.equals(path)) {\n control.done();\n return;\n }\n const mutationKey = this.keyForBatchId(batchID);\n // Look up the mutation batch in the store.\n // PORTING NOTE: because iteration is callback driven in the web,\n // we just look up the key instead of keeping an open iterator\n // like iOS.\n return mutationsStore(transaction)\n .get(mutationKey)\n .next(dbBatch => {\n if (dbBatch === null) {\n fail(\n 'Dangling document-mutation reference found: ' +\n indexKey +\n ' which points to ' +\n mutationKey\n );\n }\n results.push(this.serializer.fromDbMutationBatch(dbBatch!));\n });\n })\n .next(() => results);\n }\n\n getAllMutationBatchesAffectingQuery(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n assert(\n !query.isDocumentQuery(),\n \"Document queries shouldn't go down this path\"\n );\n\n const queryPath = query.path;\n const immediateChildrenLength = queryPath.length + 1;\n\n // TODO(mcg): Actually implement a single-collection query\n //\n // This is actually executing an ancestor query, traversing the whole\n // subtree below the collection which can be horrifically inefficient for\n // some structures. The right way to solve this is to implement the full\n // value index, but that's not in the cards in the near future so this is\n // the best we can do for the moment.\n //\n // Since we don't yet index the actual properties in the mutations, our\n // current approach is to just return all mutation batches that affect\n // documents in the collection being queried.\n const indexPrefix = DbDocumentMutation.prefixForPath(\n this.userId,\n queryPath\n );\n const encodedQueryPath = indexPrefix[1];\n const indexStart = IDBKeyRange.lowerBound(indexPrefix);\n\n // Collect up unique batchIDs encountered during a scan of the index. Use a\n // SortedSet to accumulate batch IDs so they can be traversed in order in a\n // scan of the main table.\n let uniqueBatchIDs = new SortedSet(primitiveComparator);\n return documentMutationsStore(transaction)\n .iterate({ range: indexStart }, (indexKey, _, control) => {\n const [userID, encodedPath, batchID] = indexKey;\n const path = EncodedResourcePath.decode(encodedPath);\n if (userID !== this.userId || !queryPath.isPrefixOf(path)) {\n control.done();\n return;\n }\n // Rows with document keys more than one segment longer than the\n // query path can't be matches. For example, a query on 'rooms'\n // can't match the document /rooms/abc/messages/xyx.\n // TODO(mcg): we'll need a different scanner when we implement\n // ancestor queries.\n if (path.length !== immediateChildrenLength) {\n return;\n }\n uniqueBatchIDs = uniqueBatchIDs.add(batchID);\n })\n .next(() => {\n const results: MutationBatch[] = [];\n const promises: Array> = [];\n // TODO(rockwood): Implement this using iterate.\n uniqueBatchIDs.forEach(batchID => {\n const mutationKey = this.keyForBatchId(batchID);\n promises.push(\n mutationsStore(transaction)\n .get(mutationKey)\n .next(mutation => {\n if (mutation === null) {\n fail(\n 'Dangling document-mutation reference found, ' +\n 'which points to ' +\n mutationKey\n );\n }\n results.push(this.serializer.fromDbMutationBatch(mutation!));\n })\n );\n });\n return PersistencePromise.waitFor(promises).next(() => results);\n });\n }\n\n removeMutationBatches(\n transaction: PersistenceTransaction,\n batches: MutationBatch[]\n ): PersistencePromise {\n const txn = mutationsStore(transaction);\n const indexTxn = documentMutationsStore(transaction);\n const promises: Array> = [];\n\n for (const batch of batches) {\n const range = IDBKeyRange.only(this.keyForBatchId(batch.batchId));\n let numDeleted = 0;\n const removePromise = txn.iterate({ range }, (key, value, control) => {\n numDeleted++;\n return control.delete();\n });\n promises.push(\n removePromise.next(() => {\n assert(\n numDeleted === 1,\n 'Dangling document-mutation reference found: Missing batch ' +\n batch.batchId\n );\n })\n );\n for (const mutation of batch.mutations) {\n const indexKey = DbDocumentMutation.key(\n this.userId,\n mutation.key.path,\n batch.batchId\n );\n promises.push(indexTxn.delete(indexKey));\n if (this.garbageCollector !== null) {\n this.garbageCollector.addPotentialGarbageKey(mutation.key);\n }\n }\n }\n return PersistencePromise.waitFor(promises);\n }\n\n performConsistencyCheck(\n txn: PersistenceTransaction\n ): PersistencePromise {\n return this.checkEmpty(txn).next(empty => {\n if (!empty) {\n return PersistencePromise.resolve();\n }\n\n // Verify that there are no entries in the documentMutations index if\n // the queue is empty.\n const startRange = IDBKeyRange.lowerBound(\n DbDocumentMutation.prefixForUser(this.userId)\n );\n const danglingMutationReferences: ResourcePath[] = [];\n return documentMutationsStore(txn)\n .iterate({ range: startRange }, (key, _, control) => {\n const userID = key[0];\n if (userID !== this.userId) {\n control.done();\n return;\n } else {\n const path = EncodedResourcePath.decode(key[1]);\n danglingMutationReferences.push(path);\n }\n })\n .next(() => {\n assert(\n danglingMutationReferences.length === 0,\n 'Document leak -- detected dangling mutation references when queue is empty. Dangling keys: ' +\n danglingMutationReferences.map(p => p.canonicalString())\n );\n });\n });\n }\n\n setGarbageCollector(gc: GarbageCollector | null): void {\n this.garbageCollector = gc;\n }\n\n containsKey(\n txn: PersistenceTransaction,\n key: DocumentKey\n ): PersistencePromise {\n const indexKey = DbDocumentMutation.prefixForPath(this.userId, key.path);\n const encodedPath = indexKey[1];\n const startRange = IDBKeyRange.lowerBound(indexKey);\n let containsKey = false;\n return documentMutationsStore(txn)\n .iterate({ range: startRange, keysOnly: true }, (key, _, control) => {\n const [userID, keyPath, batchID] = key;\n if (userID === this.userId && keyPath === encodedPath) {\n containsKey = true;\n }\n control.done();\n })\n .next(() => containsKey);\n }\n\n /**\n * Creates a [userId, batchId] key for use with the DbMutationQueue object\n * store.\n */\n private keyForBatchId(batchId: BatchId): DbMutationBatchKey {\n return [this.userId, batchId];\n }\n}\n\nfunction validateStreamToken(token: ProtoByteString): string {\n assert(\n typeof token === 'string',\n 'Persisting non-string stream token not supported.'\n );\n return token as string;\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the mutations object store.\n */\nfunction mutationsStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n return getStore(\n txn,\n DbMutationBatch.store\n );\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the mutationQueues object store.\n */\nfunction documentMutationsStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n return getStore(\n txn,\n DbDocumentMutation.store\n );\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the mutationQueues object store.\n */\nfunction mutationQueuesStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n return getStore(\n txn,\n DbMutationQueue.store\n );\n}\n\n/**\n * Helper to get a typed SimpleDbStore from a transaction.\n */\nfunction getStore(\n txn: PersistenceTransaction,\n store: string\n): SimpleDbStore {\n if (txn instanceof SimpleDbTransaction) {\n return txn.store(store);\n } else {\n return fail('Invalid transaction object provided!');\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/indexeddb_mutation_queue.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '../protos/firestore_proto_api';\nimport { Query } from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { Timestamp } from '../core/timestamp';\nimport { TargetId } from '../core/types';\nimport { DocumentKeySet, documentKeySet } from '../model/collections';\nimport { DocumentKey } from '../model/document_key';\nimport { assert, fail } from '../util/assert';\nimport { immediateSuccessor } from '../util/misc';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport * as EncodedResourcePath from './encoded_resource_path';\nimport { GarbageCollector } from './garbage_collector';\nimport {\n DbQuery,\n DbTarget,\n DbTargetDocument,\n DbTargetDocumentKey,\n DbTargetGlobal,\n DbTargetGlobalKey,\n DbTargetKey,\n DbTimestamp\n} from './indexeddb_schema';\nimport { LocalSerializer } from './local_serializer';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { QueryCache } from './query_cache';\nimport { QueryData } from './query_data';\nimport { SimpleDbStore, SimpleDbTransaction } from './simple_db';\n\nexport class IndexedDbQueryCache implements QueryCache {\n constructor(private serializer: LocalSerializer) {}\n\n /**\n * The last received snapshot version. We store this seperately from the\n * metadata to avoid the extra conversion to/from DbTimestamp.\n */\n private lastRemoteSnapshotVersion = SnapshotVersion.MIN;\n\n /**\n * A cached copy of the metadata for the query cache.\n */\n private metadata = new DbTargetGlobal(\n /*highestTargetId=*/ 0,\n /*lastListenSequenceNumber=*/ 0,\n SnapshotVersion.MIN.toTimestamp()\n );\n\n /** The garbage collector to notify about potential garbage keys. */\n private garbageCollector: GarbageCollector | null = null;\n\n start(transaction: PersistenceTransaction): PersistencePromise {\n return globalTargetStore(transaction)\n .get(DbTargetGlobal.key)\n .next(metadata => {\n if (metadata !== null) {\n this.metadata = metadata;\n const lastSavedVersion = metadata.lastRemoteSnapshotVersion;\n this.lastRemoteSnapshotVersion = SnapshotVersion.fromTimestamp(\n new Timestamp(lastSavedVersion.seconds, lastSavedVersion.nanos)\n );\n }\n return PersistencePromise.resolve();\n });\n }\n\n getHighestTargetId(): TargetId {\n return this.metadata.highestTargetId;\n }\n\n getLastRemoteSnapshotVersion(): SnapshotVersion {\n return this.lastRemoteSnapshotVersion;\n }\n\n setLastRemoteSnapshotVersion(\n transaction: PersistenceTransaction,\n snapshotVersion: SnapshotVersion\n ): PersistencePromise {\n this.lastRemoteSnapshotVersion = snapshotVersion;\n this.metadata.lastRemoteSnapshotVersion = snapshotVersion.toTimestamp();\n return globalTargetStore(transaction).put(\n DbTargetGlobal.key,\n this.metadata\n );\n }\n\n addQueryData(\n transaction: PersistenceTransaction,\n queryData: QueryData\n ): PersistencePromise {\n const targetId = queryData.targetId;\n const addedQueryPromise = targetsStore(transaction).put(\n this.serializer.toDbTarget(queryData)\n );\n if (targetId > this.metadata.highestTargetId) {\n this.metadata.highestTargetId = targetId;\n return addedQueryPromise.next(() =>\n globalTargetStore(transaction).put(DbTargetGlobal.key, this.metadata)\n );\n } else {\n return addedQueryPromise;\n }\n }\n\n removeQueryData(\n transaction: PersistenceTransaction,\n queryData: QueryData\n ): PersistencePromise {\n return this.removeMatchingKeysForTargetId(\n transaction,\n queryData.targetId\n ).next(() => {\n targetsStore(transaction).delete(queryData.targetId);\n });\n }\n\n getQueryData(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n // Iterating by the canonicalId may yield more than one result because\n // canonicalId values are not required to be unique per target. This query\n // depends on the queryTargets index to be efficent.\n const canonicalId = query.canonicalId();\n const range = IDBKeyRange.bound(\n [canonicalId, Number.NEGATIVE_INFINITY],\n [canonicalId, Number.POSITIVE_INFINITY]\n );\n let result: QueryData | null = null;\n return targetsStore(transaction)\n .iterate(\n { range, index: DbTarget.queryTargetsIndexName },\n (key, value, control) => {\n const found = this.serializer.fromDbTarget(value);\n // After finding a potential match, check that the query is\n // actually equal to the requested query.\n if (query.equals(found.query)) {\n result = found;\n control.done();\n }\n }\n )\n .next(() => result);\n }\n\n addMatchingKeys(\n txn: PersistenceTransaction,\n keys: DocumentKeySet,\n targetId: TargetId\n ): PersistencePromise {\n // PORTING NOTE: The reverse index (documentsTargets) is maintained by\n // Indexeddb.\n const promises: Array> = [];\n const store = documentTargetStore(txn);\n keys.forEach(key => {\n const path = EncodedResourcePath.encode(key.path);\n promises.push(store.put(new DbTargetDocument(targetId, path)));\n });\n return PersistencePromise.waitFor(promises);\n }\n\n removeMatchingKeys(\n txn: PersistenceTransaction,\n keys: DocumentKeySet,\n targetId: TargetId\n ): PersistencePromise {\n // PORTING NOTE: The reverse index (documentsTargets) is maintained by\n // IndexedDb.\n const promises: Array> = [];\n const store = documentTargetStore(txn);\n keys.forEach(key => {\n const path = EncodedResourcePath.encode(key.path);\n promises.push(store.delete([targetId, path]));\n if (this.garbageCollector !== null) {\n this.garbageCollector.addPotentialGarbageKey(key);\n }\n });\n return PersistencePromise.waitFor(promises);\n }\n\n removeMatchingKeysForTargetId(\n txn: PersistenceTransaction,\n targetId: TargetId\n ): PersistencePromise {\n const store = documentTargetStore(txn);\n const range = IDBKeyRange.bound(\n [targetId],\n [targetId + 1],\n /*lowerOpen=*/ false,\n /*upperOpen=*/ true\n );\n return this.notifyGCForRemovedKeys(txn, range).next(() =>\n store.delete(range)\n );\n }\n\n private notifyGCForRemovedKeys(\n txn: PersistenceTransaction,\n range: IDBKeyRange\n ): PersistencePromise {\n const store = documentTargetStore(txn);\n if (this.garbageCollector !== null && this.garbageCollector.isEager) {\n // In order to generate garbage events properly, we need to read these\n // keys before deleting.\n return store.iterate({ range, keysOnly: true }, (key, _, control) => {\n const path = EncodedResourcePath.decode(key[1]);\n const docKey = new DocumentKey(path);\n // Paranoid assertion in case the the collector is set to null\n // during the iteration.\n assert(\n this.garbageCollector !== null,\n 'GarbageCollector for query cache set to null during key removal.'\n );\n this.garbageCollector!.addPotentialGarbageKey(docKey);\n });\n } else {\n return PersistencePromise.resolve();\n }\n }\n\n getMatchingKeysForTargetId(\n txn: PersistenceTransaction,\n targetId: TargetId\n ): PersistencePromise {\n const promises: Array> = [];\n const range = IDBKeyRange.bound(\n [targetId],\n [targetId + 1],\n /*lowerOpen=*/ false,\n /*upperOpen=*/ true\n );\n const store = documentTargetStore(txn);\n let result = documentKeySet();\n\n return store\n .iterate({ range, keysOnly: true }, (key, _, control) => {\n const path = EncodedResourcePath.decode(key[1]);\n const docKey = new DocumentKey(path);\n result = result.add(docKey);\n })\n .next(() => result);\n }\n\n setGarbageCollector(gc: GarbageCollector | null): void {\n this.garbageCollector = gc;\n }\n\n containsKey(\n txn: PersistenceTransaction | null,\n key: DocumentKey\n ): PersistencePromise {\n assert(\n txn !== null,\n 'Persistence Transaction cannot be null for query cache containsKey'\n );\n const path = EncodedResourcePath.encode(key.path);\n const range = IDBKeyRange.bound(\n [path],\n [immediateSuccessor(path)],\n /*lowerOpen=*/ false,\n /*upperOpen=*/ true\n );\n let count = 0;\n return documentTargetStore(txn!)\n .iterate(\n {\n index: DbTargetDocument.documentTargetsIndex,\n keysOnly: true,\n range\n },\n (key, _, control) => {\n count++;\n control.done();\n }\n )\n .next(() => count > 0);\n }\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the queries object store.\n */\nfunction targetsStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n return getStore(txn, DbTarget.store);\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the target globals object store.\n */\nfunction globalTargetStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n return getStore(txn, DbTargetGlobal.store);\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the document target object store.\n */\nfunction documentTargetStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n return getStore(\n txn,\n DbTargetDocument.store\n );\n}\n\n/**\n * Helper to get a typed SimpleDbStore from a transaction.\n */\nfunction getStore(\n txn: PersistenceTransaction,\n store: string\n): SimpleDbStore {\n if (txn instanceof SimpleDbTransaction) {\n return txn.store(store);\n } else {\n return fail('Invalid transaction object provided!');\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/indexeddb_query_cache.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport { DocumentMap, documentMap } from '../model/collections';\nimport { Document, MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { fail } from '../util/assert';\n\nimport { DbRemoteDocument, DbRemoteDocumentKey } from './indexeddb_schema';\nimport { LocalSerializer } from './local_serializer';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { RemoteDocumentCache } from './remote_document_cache';\nimport { SimpleDbStore, SimpleDbTransaction } from './simple_db';\n\nexport class IndexedDbRemoteDocumentCache implements RemoteDocumentCache {\n constructor(private serializer: LocalSerializer) {}\n\n addEntry(\n transaction: PersistenceTransaction,\n maybeDocument: MaybeDocument\n ): PersistencePromise {\n return remoteDocumentsStore(transaction).put(\n dbKey(maybeDocument.key),\n this.serializer.toDbRemoteDocument(maybeDocument)\n );\n }\n\n removeEntry(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n return remoteDocumentsStore(transaction).delete(dbKey(documentKey));\n }\n\n getEntry(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n return remoteDocumentsStore(transaction)\n .get(dbKey(documentKey))\n .next(dbRemoteDoc => {\n return dbRemoteDoc\n ? this.serializer.fromDbRemoteDocument(dbRemoteDoc)\n : null;\n });\n }\n\n getDocumentsMatchingQuery(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n let results = documentMap();\n\n // Documents are ordered by key, so we can use a prefix scan to narrow down\n // the documents we need to match the query against.\n const startKey = query.path.toArray();\n const range = IDBKeyRange.lowerBound(startKey);\n return remoteDocumentsStore(transaction)\n .iterate({ range }, (key, dbRemoteDoc, control) => {\n const maybeDoc = this.serializer.fromDbRemoteDocument(dbRemoteDoc);\n if (!query.path.isPrefixOf(maybeDoc.key.path)) {\n control.done();\n } else if (maybeDoc instanceof Document && query.matches(maybeDoc)) {\n results = results.insert(maybeDoc.key, maybeDoc);\n }\n })\n .next(() => results);\n }\n}\n\n/**\n * Helper to get a typed SimpleDbStore for the remoteDocuments object store.\n */\nfunction remoteDocumentsStore(\n txn: PersistenceTransaction\n): SimpleDbStore {\n if (txn instanceof SimpleDbTransaction) {\n return txn.store(\n DbRemoteDocument.store\n );\n } else {\n return fail('Invalid transaction object provided!');\n }\n}\n\nfunction dbKey(docKey: DocumentKey): DbRemoteDocumentKey {\n return docKey.path.toArray();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/indexeddb_remote_document_cache.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '../protos/firestore_proto_api';\nimport { Query } from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { Timestamp } from '../core/timestamp';\nimport { Document, MaybeDocument, NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { MutationBatch } from '../model/mutation_batch';\nimport { JsonProtoSerializer } from '../remote/serializer';\nimport { assert, fail } from '../util/assert';\n\nimport {\n DbMutationBatch,\n DbNoDocument,\n DbQuery,\n DbRemoteDocument,\n DbTarget,\n DbTimestamp\n} from './indexeddb_schema';\nimport { QueryData, QueryPurpose } from './query_data';\n\n/** Serializer for values stored in the LocalStore. */\nexport class LocalSerializer {\n constructor(private remoteSerializer: JsonProtoSerializer) {}\n\n /** Decodes a remote document from storage locally to a Document. */\n fromDbRemoteDocument(remoteDoc: DbRemoteDocument): MaybeDocument {\n if (remoteDoc.document) {\n return this.remoteSerializer.fromDocument(remoteDoc.document);\n } else if (remoteDoc.noDocument) {\n const key = DocumentKey.fromSegments(remoteDoc.noDocument.path);\n const readTime = remoteDoc.noDocument.readTime;\n const timestamp = new Timestamp(readTime.seconds, readTime.nanos);\n return new NoDocument(key, SnapshotVersion.fromTimestamp(timestamp));\n } else {\n return fail('Unexpected DbRemoteDocument');\n }\n }\n\n /** Encodes a document for storage locally. */\n toDbRemoteDocument(maybeDoc: MaybeDocument): DbRemoteDocument {\n if (maybeDoc instanceof Document) {\n const doc = this.remoteSerializer.toDocument(maybeDoc);\n return new DbRemoteDocument(null, doc);\n } else {\n const path = maybeDoc.key.path.toArray();\n const timestamp = maybeDoc.version.toTimestamp();\n const readTime = new DbTimestamp(timestamp.seconds, timestamp.nanos);\n return new DbRemoteDocument(new DbNoDocument(path, readTime), null);\n }\n }\n\n /** Encodes a batch of mutations into a DbMutationBatch for local storage. */\n toDbMutationBatch(userId: string, batch: MutationBatch): DbMutationBatch {\n const serializedMutations = batch.mutations.map(m =>\n this.remoteSerializer.toMutation(m)\n );\n return new DbMutationBatch(\n userId,\n batch.batchId,\n batch.localWriteTime.toEpochMilliseconds(),\n serializedMutations\n );\n }\n\n /** Decodes a DbMutationBatch into a MutationBatch */\n fromDbMutationBatch(dbBatch: DbMutationBatch): MutationBatch {\n const mutations = dbBatch.mutations.map(m =>\n this.remoteSerializer.fromMutation(m)\n );\n const timestamp = Timestamp.fromEpochMilliseconds(dbBatch.localWriteTimeMs);\n return new MutationBatch(dbBatch.batchId, timestamp, mutations);\n }\n\n /** Decodes a DbTarget into QueryData */\n fromDbTarget(dbTarget: DbTarget): QueryData {\n const readTime = new Timestamp(\n dbTarget.readTime.seconds,\n dbTarget.readTime.nanos\n );\n const version = SnapshotVersion.fromTimestamp(readTime);\n let query: Query;\n if (isDocumentQuery(dbTarget.query)) {\n query = this.remoteSerializer.fromDocumentsTarget(dbTarget.query);\n } else {\n query = this.remoteSerializer.fromQueryTarget(dbTarget.query);\n }\n return new QueryData(\n query,\n dbTarget.targetId,\n QueryPurpose.Listen,\n version,\n dbTarget.resumeToken\n );\n }\n\n /** Encodes QueryData into a DbTarget for storage locally. */\n toDbTarget(queryData: QueryData): DbTarget {\n assert(\n QueryPurpose.Listen === queryData.purpose,\n 'Only queries with purpose ' +\n QueryPurpose.Listen +\n ' may be stored, got ' +\n queryData.purpose\n );\n const timestamp = queryData.snapshotVersion.toTimestamp();\n const dbTimestamp = new DbTimestamp(timestamp.seconds, timestamp.nanos);\n let queryProto: DbQuery;\n if (queryData.query.isDocumentQuery()) {\n queryProto = this.remoteSerializer.toDocumentsTarget(queryData.query);\n } else {\n queryProto = this.remoteSerializer.toQueryTarget(queryData.query);\n }\n assert(\n typeof queryData.resumeToken === 'string',\n 'Persisting non-string resume token not supported.'\n );\n const resumeToken = queryData.resumeToken as string;\n\n // lastListenSequenceNumber is always 0 until we do real GC.\n return new DbTarget(\n queryData.targetId,\n queryData.query.canonicalId(),\n dbTimestamp,\n resumeToken,\n 0,\n queryProto\n );\n }\n}\n\n/**\n * A helper function for figuring out what kind of query has been stored.\n */\nfunction isDocumentQuery(dbQuery: DbQuery): dbQuery is api.DocumentsTarget {\n return (dbQuery as api.DocumentsTarget).documents !== undefined;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/local_serializer.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { assert, fail } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport { AnyJs } from '../util/misc';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\n// TODO(mikelehen): This should be split into multiple files and probably\n// moved to an auth/ folder to match other platforms.\n\nexport interface FirstPartyCredentialsSettings {\n type: 'gapi';\n client: Gapi;\n sessionIndex: string;\n}\n\nexport interface GoogleAuthCredentialsSettings {\n type: 'google-auth';\n client: GoogleAuthClient;\n}\n\nexport interface ProviderCredentialsSettings {\n type: 'provider';\n client: CredentialsProvider;\n}\n\n/** Settings for private credentials */\nexport type CredentialsSettings =\n | FirstPartyCredentialsSettings\n | GoogleAuthCredentialsSettings\n | ProviderCredentialsSettings;\n\nexport type TokenType = 'OAuth' | 'FirstParty';\nexport interface Token {\n /** Type of token. */\n type: TokenType;\n\n /**\n * The user with which the token is associated (used for persisting user\n * state on disk, etc.).\n */\n user: User;\n\n /** Extra header values to be passed along with a request */\n authHeaders: { [header: string]: string };\n}\n\nexport class OAuthToken implements Token {\n type = 'OAuth' as TokenType;\n authHeaders: { [header: string]: string };\n constructor(value: string, public user: User) {\n this.authHeaders = { Authorization: `Bearer ${value}` };\n }\n}\n\n/**\n * A Listener for user change events.\n */\nexport type UserListener = (user: User) => void;\n\n/**\n * Provides methods for getting the uid and token for the current user and\n * listening for changes.\n */\nexport interface CredentialsProvider {\n /**\n * Requests a token for the current user, optionally forcing a refreshed\n * token to be fetched.\n */\n getToken(forceRefresh: boolean): Promise;\n\n /**\n * Specifies a listener to be notified of user changes (sign-in / sign-out).\n * It immediately called once with the initial user.\n */\n setUserChangeListener(listener: UserListener): void;\n\n /** Removes the previously-set user change listener. */\n removeUserChangeListener(): void;\n}\n\n/** A CredentialsProvider that always yields an empty token. */\nexport class EmptyCredentialsProvider implements CredentialsProvider {\n /**\n * Stores the User listener registered with setUserChangeListener()\n * This isn't actually necessary since the UID never changes, but we use this\n * to verify the listen contract is adhered to in tests.\n */\n private userListener: UserListener | null = null;\n\n constructor() {}\n\n getToken(forceRefresh: boolean): Promise {\n return Promise.resolve(null);\n }\n\n setUserChangeListener(listener: UserListener): void {\n assert(!this.userListener, 'Can only call setUserChangeListener() once.');\n this.userListener = listener;\n // Fire with initial user.\n listener(User.UNAUTHENTICATED);\n }\n\n removeUserChangeListener(): void {\n assert(\n this.userListener !== null,\n 'removeUserChangeListener() when no listener registered'\n );\n this.userListener = null;\n }\n}\n\nexport class FirebaseCredentialsProvider implements CredentialsProvider {\n /**\n * The auth token listener registered with FirebaseApp, retained here so we\n * can unregister it.\n */\n private tokenListener: ((token: string | null) => void) | null = null;\n\n /** Tracks the current User. */\n private currentUser: User;\n\n /**\n * Counter used to detect if the user changed while a getToken request was\n * outstanding.\n */\n private userCounter = 0;\n\n /** The User listener registered with setUserChangeListener(). */\n private userListener: UserListener | null = null;\n\n constructor(private readonly app: firebase.app.App) {\n // We listen for token changes but all we really care about is knowing when\n // the uid may have changed.\n this.tokenListener = () => {\n const newUser = this.getUser();\n if (!this.currentUser || !newUser.equals(this.currentUser)) {\n this.currentUser = newUser;\n this.userCounter++;\n if (this.userListener) {\n this.userListener(this.currentUser);\n }\n }\n };\n\n this.userCounter = 0;\n\n // Will fire at least once where we set this.currentUser\n this.app.INTERNAL.addAuthTokenListener(this.tokenListener);\n }\n\n getToken(forceRefresh: boolean): Promise {\n assert(\n this.tokenListener != null,\n 'getToken cannot be called after listener removed.'\n );\n\n // Take note of the current value of the userCounter so that this method can\n // fail (with an ABORTED error) if there is a user change while the request\n // is outstanding.\n const initialUserCounter = this.userCounter;\n return this.app.INTERNAL.getToken(forceRefresh).then(tokenData => {\n // Cancel the request since the user changed while the request was\n // outstanding so the response is likely for a previous user (which\n // user, we can't be sure).\n if (this.userCounter !== initialUserCounter) {\n throw new FirestoreError(\n Code.ABORTED,\n 'getToken aborted due to uid change.'\n );\n } else {\n if (tokenData) {\n assert(\n typeof tokenData.accessToken === 'string',\n 'Invalid tokenData returned from getToken():' + tokenData\n );\n return new OAuthToken(tokenData.accessToken, this.currentUser);\n } else {\n return null;\n }\n }\n });\n }\n\n setUserChangeListener(listener: UserListener): void {\n assert(!this.userListener, 'Can only call setUserChangeListener() once.');\n this.userListener = listener;\n\n // Fire the initial event, but only if we received the initial user\n if (this.currentUser) {\n listener(this.currentUser);\n }\n }\n\n removeUserChangeListener(): void {\n assert(\n this.tokenListener != null,\n 'removeUserChangeListener() called twice'\n );\n assert(\n this.userListener !== null,\n 'removeUserChangeListener() called when no listener registered'\n );\n this.app.INTERNAL.removeAuthTokenListener(this.tokenListener!);\n this.tokenListener = null;\n this.userListener = null;\n }\n\n private getUser(): User {\n // TODO(mikelehen): Remove this check once we're shipping with firebase.js.\n if (typeof this.app.INTERNAL.getUid !== 'function') {\n fail(\n 'This version of the Firestore SDK requires at least version' +\n ' 3.7.0 of firebase.js.'\n );\n }\n const currentUid = this.app.INTERNAL.getUid();\n assert(\n currentUid === null || typeof currentUid === 'string',\n 'Received invalid UID: ' + currentUid\n );\n return new User(currentUid);\n }\n}\n\n// Wrap a google-auth-library client as a CredentialsProvider.\n// NOTE: grpc-connection can natively accept a google-auth-library\n// client via createFromGoogleCredential(), but we opt to plumb the tokens\n// through our CredentialsProvider interface, at least for now.\nexport class GoogleCredentialsProvider implements CredentialsProvider {\n constructor(private authClient: GoogleAuthClient) {}\n\n getToken(forceRefresh: boolean): Promise {\n return new Promise((resolve, reject) => {\n // TODO(b/32935141): ideally this would be declared as an extern\n this.authClient[\n 'getAccessToken'\n ]((error: AnyJs, tokenLiteral: string) => {\n if (error) {\n reject(error);\n } else {\n resolve(new OAuthToken(tokenLiteral, User.GOOGLE_CREDENTIALS));\n }\n });\n });\n }\n\n // NOTE: A google-auth-library client represents an immutable \"user\", so\n // once we fire the initial event, it'll never change.\n setUserChangeListener(listener: UserListener): void {\n // Fire with initial uid.\n listener(User.GOOGLE_CREDENTIALS);\n }\n\n removeUserChangeListener(): void {}\n}\n\n/**\n * Very incomplete typing for an auth client from\n * https://github.com/google/google-auth-library-nodejs/\n */\nexport interface GoogleAuthClient {\n getAccessToken(callback: (error?: Error, token?: string) => void): void;\n}\n// TODO(b/32935141): Ideally gapi type would be declared as an extern\n// tslint:disable-next-line:no-any\nexport type Gapi = any;\n\n/*\n * FirstPartyToken provides a fresh token each time its value\n * is requested, because if the token is too old, requests will be rejected.\n * TODO(b/33147818) this implementation violates the current assumption that\n * tokens are immutable. We need to either revisit this assumption or come\n * up with some way for FPA to use the listen/unlisten interface.\n */\nexport class FirstPartyToken implements Token {\n type = 'FirstParty' as TokenType;\n user = User.FIRST_PARTY;\n\n constructor(private gapi: Gapi, private sessionIndex: string) {\n assert(\n this.gapi &&\n this.gapi['auth'] &&\n this.gapi['auth']['getAuthHeaderValueForFirstParty'],\n 'unexpected gapi interface'\n );\n }\n\n get authHeaders(): { [header: string]: string } {\n return {\n Authorization: this.gapi['auth']['getAuthHeaderValueForFirstParty']([]),\n 'X-Goog-AuthUser': this.sessionIndex\n };\n }\n}\n\n/*\n * Provides user credentials required for the Firestore JavaScript SDK\n * to authenticate the user, using technique that is only available\n * to applications hosted by Google.\n */\nexport class FirstPartyCredentialsProvider implements CredentialsProvider {\n constructor(private gapi: Gapi, private sessionIndex: string) {\n assert(\n this.gapi &&\n this.gapi['auth'] &&\n this.gapi['auth']['getAuthHeaderValueForFirstParty'],\n 'unexpected gapi interface'\n );\n }\n\n getToken(forceRefresh: boolean): Promise {\n return Promise.resolve(new FirstPartyToken(this.gapi, this.sessionIndex));\n }\n\n // TODO(33108925): can someone switch users w/o a page refresh?\n // TODO(33110621): need to understand token/session lifecycle\n setUserChangeListener(listener: UserListener): void {\n // Fire with initial uid.\n listener(User.FIRST_PARTY);\n }\n\n removeUserChangeListener(): void {}\n}\n\n/**\n * Builds a CredentialsProvider depending on the type of\n * the credentials passed in.\n */\nexport function makeCredentialsProvider(credentials?: CredentialsSettings) {\n if (!credentials) {\n return new EmptyCredentialsProvider();\n }\n\n switch (credentials.type) {\n case 'google-auth':\n return new GoogleCredentialsProvider(credentials.client);\n\n case 'gapi':\n return new FirstPartyCredentialsProvider(\n credentials.client,\n credentials.sessionIndex || '0'\n );\n\n case 'provider':\n return credentials.client;\n\n default:\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'makeCredentialsProvider failed due to invalid credential type'\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/credentials.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AnyJs } from '../util/misc';\nimport { JsonObject } from '../model/field_value';\n\n/**\n * Observer/Subscribe interfaces.\n */\nexport type NextFn = (value: T) => void;\nexport type ErrorFn = (error: Error) => void;\nexport type CompleteFn = () => void;\n\n// Allow for any of the Observer methods to be undefined.\nexport interface PartialObserver {\n next?: NextFn;\n error?: ErrorFn;\n complete?: CompleteFn;\n}\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport function isPartialObserver(obj: AnyJs): boolean {\n return implementsAnyMethods(obj, ['next', 'error', 'complete']);\n}\n\n/**\n * Returns true if obj is an object and contains at least one of the specified\n * methods.\n */\nfunction implementsAnyMethods(obj: AnyJs, methods: string[]): boolean {\n if (typeof obj !== 'object' || obj === null) {\n return false;\n }\n\n const object = obj as JsonObject;\n for (const method of methods) {\n if (method in object && typeof object[method] === 'function') {\n return true;\n }\n }\n return false;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/observer.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as firestore from 'firestore';\n\nimport { DatabaseId } from '../core/database_info';\nimport { Timestamp } from '../core/timestamp';\nimport { DocumentKey } from '../model/document_key';\nimport { FieldValue, ObjectValue } from '../model/field_value';\nimport {\n ArrayValue,\n BlobValue,\n BooleanValue,\n DoubleValue,\n GeoPointValue,\n IntegerValue,\n NullValue,\n RefValue,\n StringValue,\n TimestampValue\n} from '../model/field_value';\nimport {\n FieldMask,\n FieldTransform,\n Mutation,\n PatchMutation,\n Precondition,\n ServerTimestampTransform,\n SetMutation,\n TransformMutation\n} from '../model/mutation';\nimport { FieldPath } from '../model/path';\nimport { assert, fail } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport { isPlainObject, valueDescription } from '../util/input_validation';\nimport { AnyJs, primitiveComparator } from '../util/misc';\nimport * as objUtils from '../util/obj';\nimport { Dict } from '../util/obj';\nimport { SortedMap } from '../util/sorted_map';\nimport * as typeUtils from '../util/types';\n\nimport { Blob } from './blob';\nimport {\n FieldPath as ExternalFieldPath,\n fromDotSeparatedString\n} from './field_path';\nimport {\n DeleteFieldValueImpl,\n FieldValueImpl,\n ServerTimestampFieldValueImpl\n} from './field_value';\nimport { GeoPoint } from './geo_point';\n\nconst RESERVED_FIELD_REGEX = /^__.*__$/;\n\n/** The result of parsing document data (e.g. for a setData call). */\nexport class ParsedSetData {\n constructor(\n readonly data: ObjectValue,\n readonly fieldMask: FieldMask | null,\n readonly fieldTransforms: FieldTransform[]\n ) {}\n\n toMutations(key: DocumentKey, precondition: Precondition): Mutation[] {\n const mutations = [] as Mutation[];\n if (this.fieldMask !== null) {\n mutations.push(\n new PatchMutation(key, this.data, this.fieldMask, precondition)\n );\n } else {\n mutations.push(new SetMutation(key, this.data, precondition));\n }\n if (this.fieldTransforms.length > 0) {\n mutations.push(new TransformMutation(key, this.fieldTransforms));\n }\n return mutations;\n }\n}\n\n/** The result of parsing \"update\" data (i.e. for an updateData call). */\nexport class ParsedUpdateData {\n constructor(\n readonly data: ObjectValue,\n readonly fieldMask: FieldMask,\n readonly fieldTransforms: FieldTransform[]\n ) {}\n\n toMutations(key: DocumentKey, precondition: Precondition): Mutation[] {\n const mutations = [\n new PatchMutation(key, this.data, this.fieldMask, precondition)\n ] as Mutation[];\n if (this.fieldTransforms.length > 0) {\n mutations.push(new TransformMutation(key, this.fieldTransforms));\n }\n return mutations;\n }\n}\n\n/*\n * Represents what type of API method provided the data being parsed; useful\n * for determining which error conditions apply during parsing and providing\n * better error messages.\n */\nenum UserDataSource {\n Set,\n Update,\n QueryValue // from a where clause or cursor bound\n}\n\n/** A \"context\" object passed around while parsing user data. */\nclass ParseContext {\n readonly fieldTransforms: FieldTransform[];\n readonly fieldMask: FieldPath[];\n /**\n * Initializes a ParseContext with the given source and path.\n *\n * @param dataSource Indicates what kind of API method this data came from.\n * @param path A path within the object being parsed. This could be an empty\n * path (in which case the context represents the root of the data being\n * parsed), or a nonempty path (indicating the context represents a nested\n * location within the data).\n *\n * TODO(b/34871131): We don't support array paths right now, so path can be\n * null to indicate the context represents any location within an array (in\n * which case certain features will not work and errors will be somewhat\n * compromised).\n * @param fieldTransforms A mutable list of field transforms encountered while\n * parsing the data.\n * @param fieldMask A mutable list of field paths encountered while parsing \n * the data.\n */\n constructor(\n readonly dataSource: UserDataSource,\n readonly methodName: string,\n readonly path: FieldPath | null,\n fieldTransforms?: FieldTransform[],\n fieldMask?: FieldPath[]\n ) {\n // Minor hack: If fieldTransforms is undefined, we assume this is an\n // external call and we need to validate the entire path.\n if (fieldTransforms === undefined) {\n this.validatePath();\n }\n this.fieldTransforms = fieldTransforms || [];\n this.fieldMask = fieldMask || [];\n }\n\n childContext(field: string | FieldPath | number): ParseContext {\n let childPath: FieldPath | null;\n if (typeof field === 'number') {\n // TODO(b/34871131): We don't support array paths right now; so make path\n // null.\n childPath = null;\n } else {\n childPath = this.path == null ? null : this.path.child(field);\n }\n const context = new ParseContext(\n this.dataSource,\n this.methodName,\n childPath,\n this.fieldTransforms,\n this.fieldMask\n );\n if (typeof field === 'string') {\n // We only need to validate the new segment.\n context.validatePathSegment(field);\n } else if (typeof field === 'object' && field instanceof FieldPath) {\n // Validate the whole path.\n context.validatePath();\n }\n return context;\n }\n\n createError(reason: string): Error {\n const fieldDescription =\n this.path === null || this.path.isEmpty()\n ? ''\n : ` (found in field ${this.path.toString()})`;\n return new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${this.methodName}() called with invalid data. ` +\n reason +\n fieldDescription\n );\n }\n\n private validatePath() {\n // TODO(b/34871131): Remove null check once we have proper paths for fields\n // within arrays.\n if (this.path === null) {\n return;\n }\n for (let i = 0; i < this.path.length; i++) {\n this.validatePathSegment(this.path.get(i));\n }\n }\n\n private validatePathSegment(segment: string) {\n if (this.isWrite() && RESERVED_FIELD_REGEX.test(segment)) {\n throw this.createError('Document fields cannot begin and end with __');\n }\n }\n\n private isWrite(): boolean {\n return (\n this.dataSource === UserDataSource.Set ||\n this.dataSource === UserDataSource.Update\n );\n }\n}\n/**\n * An interface that allows arbitrary pre-converting of user data. This\n * abstraction allows for, e.g.:\n * * The public API to convert DocumentReference objects to DocRef objects,\n * avoiding a circular dependency between user_data_converter.ts and\n * database.ts\n * * Tests to convert test-only sentinels (e.g. '') into types\n * compatible with UserDataConverter.\n *\n * Returns the converted value (can return back the input to act as a no-op).\n *\n * It can also throw an Error which will be wrapped into a friendly message.\n */\nexport type DataPreConverter = (input: AnyJs) => AnyJs;\n\n/**\n * A placeholder object for DocumentReferences in this file, in order to\n * avoid a circular dependency. See the comments for `DataPreConverter` for\n * the full context.\n */\nexport class DocumentKeyReference {\n constructor(public databaseId: DatabaseId, public key: DocumentKey) {}\n}\n\n/**\n * Helper for parsing raw user input (provided via the API) into internal model\n * classes.\n */\nexport class UserDataConverter {\n constructor(private preConverter: DataPreConverter) {}\n\n /** Parse document data (e.g. from a set() call). */\n parseSetData(\n methodName: string,\n input: AnyJs,\n options: firestore.SetOptions\n ): ParsedSetData {\n const context = new ParseContext(\n UserDataSource.Set,\n methodName,\n FieldPath.EMPTY_PATH\n );\n validatePlainObject('Data must be an object, but it was:', context, input);\n\n const merge = options.merge !== undefined ? options.merge : false;\n\n let updateData = ObjectValue.EMPTY;\n\n objUtils.forEach(input as Dict, (key, value) => {\n const path = new ExternalFieldPath(key)._internalPath;\n\n const childContext = context.childContext(path);\n value = this.runPreConverter(value, childContext);\n\n const parsedValue = this.parseData(value, childContext);\n if (parsedValue) {\n updateData = updateData.set(path, parsedValue);\n }\n });\n\n const fieldMask = merge ? new FieldMask(context.fieldMask) : null;\n return new ParsedSetData(updateData, fieldMask, context.fieldTransforms);\n }\n\n /** Parse update data (e.g. from an update() call). */\n parseUpdateData(methodName: string, input: AnyJs): ParsedUpdateData {\n const context = new ParseContext(\n UserDataSource.Update,\n methodName,\n FieldPath.EMPTY_PATH\n );\n validatePlainObject('Data must be an object, but it was:', context, input);\n\n const fieldMaskPaths = [] as FieldPath[];\n let updateData = ObjectValue.EMPTY;\n objUtils.forEach(input as Dict, (key, value) => {\n const path = fieldPathFromDotSeparatedString(methodName, key);\n\n const childContext = context.childContext(path);\n value = this.runPreConverter(value, childContext);\n if (value instanceof DeleteFieldValueImpl) {\n // Add it to the field mask, but don't add anything to updateData.\n fieldMaskPaths.push(path);\n } else {\n const parsedValue = this.parseData(value, childContext);\n if (parsedValue != null) {\n fieldMaskPaths.push(path);\n updateData = updateData.set(path, parsedValue);\n }\n }\n });\n\n const mask = new FieldMask(fieldMaskPaths);\n return new ParsedUpdateData(updateData, mask, context.fieldTransforms);\n }\n\n /** Parse update data from a list of field/value arguments. */\n parseUpdateVarargs(\n methodName: string,\n field: string | ExternalFieldPath,\n value: AnyJs,\n moreFieldsAndValues: AnyJs[]\n ): ParsedUpdateData {\n const context = new ParseContext(\n UserDataSource.Update,\n methodName,\n FieldPath.EMPTY_PATH\n );\n const keys = [fieldPathFromArgument(methodName, field)];\n const values = [value];\n\n if (moreFieldsAndValues.length % 2 !== 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${methodName}() needs to be called with an even number ` +\n 'of arguments that alternate between field names and values.'\n );\n }\n\n for (let i = 0; i < moreFieldsAndValues.length; i += 2) {\n keys.push(\n fieldPathFromArgument(methodName, moreFieldsAndValues[i] as\n | string\n | ExternalFieldPath)\n );\n values.push(moreFieldsAndValues[i + 1]);\n }\n\n const fieldMaskPaths = [] as FieldPath[];\n let updateData = ObjectValue.EMPTY;\n\n for (let i = 0; i < keys.length; ++i) {\n const path = keys[i];\n const childContext = context.childContext(path);\n const value = this.runPreConverter(values[i], childContext);\n if (value instanceof DeleteFieldValueImpl) {\n // Add it to the field mask, but don't add anything to updateData.\n fieldMaskPaths.push(path);\n } else {\n const parsedValue = this.parseData(value, childContext);\n if (parsedValue != null) {\n fieldMaskPaths.push(path);\n updateData = updateData.set(path, parsedValue);\n }\n }\n }\n\n const mask = new FieldMask(fieldMaskPaths);\n return new ParsedUpdateData(updateData, mask, context.fieldTransforms);\n }\n\n /**\n * Parse a \"query value\" (e.g. value in a where filter or a value in a cursor\n * bound).\n */\n parseQueryValue(methodName: string, input: AnyJs): FieldValue {\n const context = new ParseContext(\n UserDataSource.QueryValue,\n methodName,\n FieldPath.EMPTY_PATH\n );\n const parsed = this.parseData(input, context);\n assert(parsed != null, 'Parsed data should not be null.');\n assert(\n context.fieldTransforms.length === 0,\n 'Field transforms should have been disallowed.'\n );\n return parsed!;\n }\n\n /** Sends data through this.preConverter, handling any thrown errors. */\n private runPreConverter(input: AnyJs, context: ParseContext): AnyJs {\n try {\n return this.preConverter(input);\n } catch (e) {\n const message = errorMessage(e);\n throw context.createError(message);\n }\n }\n\n /**\n * Internal helper for parsing user data.\n *\n * @param input Data to be parsed.\n * @param context A context object representing the current path being parsed,\n * the source of the data being parsed, etc.\n * @return The parsed value, or null if the value was a FieldValue sentinel\n * that should not be included in the resulting parsed data.\n */\n private parseData(input: AnyJs, context: ParseContext): FieldValue | null {\n input = this.runPreConverter(input, context);\n if (input instanceof Array) {\n // TODO(b/34871131): We may need a different way to detect nested arrays\n // once we support array paths (at which point we should include the path\n // containing the array in the error message).\n if (!context.path) {\n throw context.createError('Nested arrays are not supported');\n }\n // We don't support field mask paths more granular than the top-level\n // array.\n context.fieldMask.push(context.path);\n return this.parseArray(input as AnyJs[], context);\n } else if (looksLikeJsonObject(input)) {\n validatePlainObject('Unsupported field value:', context, input);\n return this.parseObject(input as Dict, context);\n } else {\n // If context.path is null, we are inside an array and we should have\n // already added the root of the array to the field mask.\n if (context.path) {\n context.fieldMask.push(context.path);\n }\n return this.parseScalarValue(input, context);\n }\n }\n\n private parseArray(array: AnyJs[], context: ParseContext): FieldValue {\n const result = [] as FieldValue[];\n let entryIndex = 0;\n for (const entry of array) {\n let parsedEntry = this.parseData(entry, context.childContext(entryIndex));\n if (parsedEntry == null) {\n // Just include nulls in the array for fields being replaced with a\n // sentinel.\n parsedEntry = NullValue.INSTANCE;\n }\n result.push(parsedEntry);\n entryIndex++;\n }\n return new ArrayValue(result);\n }\n\n private parseObject(obj: Dict, context: ParseContext): FieldValue {\n let result = new SortedMap(primitiveComparator);\n objUtils.forEach(obj, (key: string, val: AnyJs) => {\n const parsedValue = this.parseData(val, context.childContext(key));\n if (parsedValue != null) {\n result = result.insert(key, parsedValue);\n }\n });\n return new ObjectValue(result);\n }\n\n /**\n * Helper to parse a scalar value (i.e. not an Object or Array)\n *\n * @return The parsed value, or null if the value was a FieldValue sentinel\n * that should not be included in the resulting parsed data.\n */\n private parseScalarValue(\n value: AnyJs,\n context: ParseContext\n ): FieldValue | null {\n if (value === null) {\n return NullValue.INSTANCE;\n } else if (typeof value === 'number') {\n if (typeUtils.isSafeInteger(value)) {\n return new IntegerValue(value);\n } else {\n return new DoubleValue(value);\n }\n } else if (typeof value === 'boolean') {\n return BooleanValue.of(value);\n } else if (typeof value === 'string') {\n return new StringValue(value);\n } else if (value instanceof Date) {\n return new TimestampValue(Timestamp.fromDate(value));\n } else if (value instanceof GeoPoint) {\n return new GeoPointValue(value);\n } else if (value instanceof Blob) {\n return new BlobValue(value);\n } else if (value instanceof DocumentKeyReference) {\n return new RefValue(value.databaseId, value.key);\n } else if (value instanceof FieldValueImpl) {\n if (value instanceof DeleteFieldValueImpl) {\n // We shouldn't encounter delete sentinels here. Provide a good error.\n if (context.dataSource !== UserDataSource.Update) {\n throw context.createError(\n 'FieldValue.delete() can only be used with update()'\n );\n } else {\n assert(\n context.path == null || context.path.length > 0,\n 'FieldValue.delete() at the top level should have already' +\n ' been handled.'\n );\n throw context.createError(\n 'FieldValue.delete() can only appear at the top level ' +\n 'of your update data'\n );\n }\n } else if (value instanceof ServerTimestampFieldValueImpl) {\n if (\n context.dataSource !== UserDataSource.Set &&\n context.dataSource !== UserDataSource.Update\n ) {\n throw context.createError(\n 'FieldValue.serverTimestamp() can only be used with set()' +\n ' and update()'\n );\n }\n if (context.path === null) {\n throw context.createError(\n 'FieldValue.serverTimestamp() is not currently' +\n ' supported inside arrays'\n );\n }\n context.fieldTransforms.push(\n new FieldTransform(context.path, ServerTimestampTransform.instance)\n );\n\n // Return null so this value is omitted from the parsed result.\n return null;\n } else {\n return fail('Unknown FieldValue type: ' + value);\n }\n } else {\n throw context.createError(\n `Unsupported field value: ${valueDescription(value)}`\n );\n }\n }\n}\n\n/**\n * Checks whether an object looks like a JSON object that should be converted\n * into a struct. Normal class/prototype instances are considered to look like\n * JSON objects since they should be converted to a struct value. Arrays, Dates,\n * GeoPoints, etc. are not considered to look like JSON objects since they map\n * to specific FieldValue types other than ObjectValue.\n */\nfunction looksLikeJsonObject(input: AnyJs): boolean {\n return (\n typeof input === 'object' &&\n input !== null &&\n !(input instanceof Array) &&\n !(input instanceof Date) &&\n !(input instanceof GeoPoint) &&\n !(input instanceof Blob) &&\n !(input instanceof DocumentKeyReference) &&\n !(input instanceof FieldValueImpl)\n );\n}\n\nfunction validatePlainObject(\n message: string,\n context: ParseContext,\n input: AnyJs\n) {\n if (!looksLikeJsonObject(input) || !isPlainObject(input)) {\n const description = valueDescription(input);\n if (description === 'an object') {\n // Massage the error if it was an object.\n throw context.createError(message + ' a custom object');\n } else {\n throw context.createError(message + ' ' + description);\n }\n }\n}\n\n/**\n * Helper that calls fromDotSeparatedString() but wraps any error thrown.\n */\nexport function fieldPathFromArgument(\n methodName: string,\n path: string | ExternalFieldPath\n): FieldPath {\n if (path instanceof ExternalFieldPath) {\n return path._internalPath;\n } else if (typeof path === 'string') {\n return fieldPathFromDotSeparatedString(methodName, path);\n } else {\n const message = 'Field path arguments must be of type string or FieldPath.';\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${methodName}() called with invalid data. ${message}`\n );\n }\n}\n\n/**\n * Wraps fromDotSeparatedString with an error message about the method that\n * was thrown.\n * @param methodName The publicly visible method name\n * @param path The dot-separated string form of a field path which will be split\n * on dots.\n */\nfunction fieldPathFromDotSeparatedString(\n methodName: string,\n path: string\n): FieldPath {\n try {\n return fromDotSeparatedString(path)._internalPath;\n } catch (e) {\n const message = errorMessage(e);\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function ${methodName}() called with invalid data. ${message}`\n );\n }\n}\n\n/**\n * Extracts the message from a caught exception, which should be an Error object\n * though JS doesn't guarantee that.\n */\nfunction errorMessage(error: Error | object): string {\n return error instanceof Error ? error.message : error.toString();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/user_data_converter.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as firestore from 'firestore';\n\nimport { FieldPath as ExternalFieldPath } from './field_path';\nimport { DatabaseId, DatabaseInfo } from '../core/database_info';\nimport { ListenOptions } from '../core/event_manager';\nimport { FirestoreClient } from '../core/firestore_client';\nimport {\n Bound,\n Direction,\n fieldFilter,\n Filter,\n OrderBy,\n Query as InternalQuery,\n RelationFilter,\n RelationOp\n} from '../core/query';\nimport { Transaction as InternalTransaction } from '../core/transaction';\nimport { ChangeType, ViewSnapshot } from '../core/view_snapshot';\nimport { Document, MaybeDocument, NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport {\n ArrayValue,\n FieldValue,\n ObjectValue,\n RefValue\n} from '../model/field_value';\nimport { DeleteMutation, Mutation, Precondition } from '../model/mutation';\nimport { FieldPath, ResourcePath } from '../model/path';\nimport { PlatformSupport } from '../platform/platform';\nimport { makeConstructorPrivate } from '../util/api';\nimport { assert, fail } from '../util/assert';\nimport { AsyncObserver } from '../util/async_observer';\nimport { AsyncQueue } from '../util/async_queue';\nimport { Code, FirestoreError } from '../util/error';\nimport {\n invalidClassError,\n validateArgType,\n validateAtLeastNumberOfArgs,\n validateBetweenNumberOfArgs,\n validateDefined,\n validateExactNumberOfArgs,\n validateNamedOptionalType,\n validateNamedType,\n validateOptionalArgType,\n validateOptionNames,\n valueDescription\n} from '../util/input_validation';\nimport * as log from '../util/log';\nimport { LogLevel } from '../util/log';\nimport { AnyJs, AutoId } from '../util/misc';\nimport * as objUtils from '../util/obj';\nimport { Rejecter, Resolver } from '../util/promise';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport {\n CredentialsProvider,\n CredentialsSettings,\n EmptyCredentialsProvider,\n FirebaseCredentialsProvider,\n makeCredentialsProvider\n} from './credentials';\nimport {\n CompleteFn,\n ErrorFn,\n isPartialObserver,\n NextFn,\n PartialObserver,\n Unsubscribe\n} from './observer';\nimport {\n DocumentKeyReference,\n fieldPathFromArgument,\n UserDataConverter\n} from './user_data_converter';\n\n// The objects that are a part of this API are exposed to third-parties as\n// compiled javascript so we want to flag our private members with a leading\n// underscore to discourage their use.\n// tslint:disable:strip-private-property-underscore\n\nconst DEFAULT_HOST = 'firestore.googleapis.com';\nconst DEFAULT_SSL = true;\n\n/** Undocumented, private additional settings not exposed in our public API. */\ninterface PrivateSettings extends firestore.Settings {\n // Can be a google-auth-library or gapi client.\n credentials?: CredentialsSettings;\n}\n\n/**\n * Options that can be provided in the Firestore constructor when not using\n * Firebase (aka standalone mode).\n */\nexport interface FirestoreDatabase {\n projectId: string;\n database?: string;\n}\n\n/**\n * A concrete type describing all the values that can be applied via a\n * user-supplied firestore.Settings object. This is a separate type so that\n * defaults can be supplied and the value can be checked for equality.\n */\nclass FirestoreSettings {\n /** The hostname to connect to. */\n host: string;\n\n /** Whether to use SSL when connecting. */\n ssl: boolean;\n\n // Can be a google-auth-library or gapi client.\n // tslint:disable-next-line:no-any\n credentials?: any;\n\n constructor(settings: PrivateSettings) {\n if (settings.host === undefined) {\n if (settings.ssl !== undefined) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n \"Can't provide ssl option if host option is not set\"\n );\n }\n this.host = DEFAULT_HOST;\n this.ssl = DEFAULT_SSL;\n } else {\n validateNamedType('settings', 'string', 'host', settings.host);\n this.host = settings.host;\n\n validateNamedOptionalType('settings', 'boolean', 'ssl', settings.ssl);\n this.ssl = objUtils.defaulted(settings.ssl, DEFAULT_SSL);\n }\n validateOptionNames('settings', settings, ['host', 'ssl', 'credentials']);\n\n validateNamedOptionalType(\n 'settings',\n 'object',\n 'credentials',\n settings.credentials\n );\n this.credentials = settings.credentials;\n }\n\n equals(other: FirestoreSettings): boolean {\n return (\n this.host === other.host &&\n this.ssl === other.ssl &&\n this.credentials === other.credentials\n );\n }\n}\n\nclass FirestoreConfig {\n databaseId: DatabaseId;\n persistenceKey: string;\n credentials: CredentialsProvider;\n firebaseApp: firebase.app.App;\n settings: FirestoreSettings;\n persistence: boolean;\n}\n\n/**\n * The root reference to the database.\n */\nexport class Firestore implements firestore.Firestore, FirebaseService {\n private _config: FirestoreConfig;\n\n // The firestore client instance. This will be available as soon as\n // configureClient is called, but any calls against it will block until\n // setup has completed.\n //\n // Operations on the _firestoreClient don't block on _firestoreReady. Those\n // are already set to synchronize on the async queue.\n private _firestoreClient: FirestoreClient | undefined;\n public _dataConverter: UserDataConverter;\n\n public get _databaseId(): DatabaseId {\n return this._config.databaseId;\n }\n\n constructor(databaseIdOrApp: FirestoreDatabase | firebase.app.App) {\n const config = new FirestoreConfig();\n if (typeof (databaseIdOrApp as firebase.app.App).options === 'object') {\n // This is very likely a Firebase app object\n // TODO(b/34177605): Can we somehow use instanceof?\n const app = databaseIdOrApp as firebase.app.App;\n config.firebaseApp = app;\n config.databaseId = Firestore.databaseIdFromApp(app);\n config.persistenceKey = config.firebaseApp.name;\n config.credentials = new FirebaseCredentialsProvider(app);\n } else {\n const external = databaseIdOrApp as FirestoreDatabase;\n if (!external.projectId) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Must provide projectId'\n );\n }\n\n config.databaseId = new DatabaseId(external.projectId, external.database);\n // Use a default persistenceKey that lines up with firebase.app.App.\n config.persistenceKey = '[DEFAULT]';\n config.credentials = new EmptyCredentialsProvider();\n }\n\n config.settings = new FirestoreSettings({});\n this._config = config;\n }\n\n settings(settingsLiteral: firestore.Settings): void {\n validateExactNumberOfArgs('Firestore.settings', arguments, 1);\n validateArgType('Firestore.settings', 'object', 1, settingsLiteral);\n\n if (\n objUtils.contains(settingsLiteral as objUtils.Dict<{}>, 'persistence')\n ) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n '\"persistence\" is now specified with a separate call to ' +\n 'firestore.enablePersistence().'\n );\n }\n\n const newSettings = new FirestoreSettings(settingsLiteral);\n if (this._firestoreClient && !this._config.settings.equals(newSettings)) {\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'Firestore has already been started and its settings can no longer ' +\n 'be changed. You can only call settings() before calling any other ' +\n 'methods on a Firestore object.'\n );\n }\n\n this._config.settings = newSettings;\n if (newSettings.credentials !== undefined) {\n this._config.credentials = makeCredentialsProvider(\n newSettings.credentials\n );\n }\n }\n\n enablePersistence(): Promise {\n if (this._firestoreClient) {\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'Firestore has already been started and persistence can no longer ' +\n 'be enabled. You can only call enablePersistence() before calling ' +\n 'any other methods on a Firestore object.'\n );\n }\n\n return this.configureClient(/* persistence= */ true);\n }\n\n ensureClientConfigured(): FirestoreClient {\n if (!this._firestoreClient) {\n this.configureClient(/* persistence= */ false);\n }\n return this._firestoreClient as FirestoreClient;\n }\n\n private configureClient(persistence: boolean): Promise {\n assert(\n !!this._config.settings.host,\n 'FirestoreSettings.host cannot be falsey'\n );\n\n assert(!this._firestoreClient, 'configureClient() called multiple times');\n\n const databaseInfo = new DatabaseInfo(\n this._config.databaseId,\n this._config.persistenceKey,\n this._config.settings.host,\n this._config.settings.ssl\n );\n\n const preConverter = (value: AnyJs) => {\n if (value instanceof DocumentReference) {\n const thisDb = this._config.databaseId;\n const otherDb = value.firestore._config.databaseId;\n if (!otherDb.equals(thisDb)) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Document reference is for database ' +\n `${otherDb.projectId}/${otherDb.database} but should be ` +\n `for database ${thisDb.projectId}/${thisDb.database}`\n );\n }\n return new DocumentKeyReference(this._config.databaseId, value._key);\n } else {\n return value;\n }\n };\n this._dataConverter = new UserDataConverter(preConverter);\n\n this._firestoreClient = new FirestoreClient(\n PlatformSupport.getPlatform(),\n databaseInfo,\n this._config.credentials,\n new AsyncQueue()\n );\n return this._firestoreClient.start(persistence);\n }\n\n private static databaseIdFromApp(app: firebase.app.App): DatabaseId {\n const options = app.options as objUtils.Dict<{}>;\n if (!objUtils.contains(options, 'projectId')) {\n // TODO(b/62673263): We can safely remove the special handling of\n // 'firestoreId' once alpha testers have upgraded.\n if (objUtils.contains(options, 'firestoreId')) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n '\"firestoreId\" is now specified as \"projectId\" in ' +\n 'firebase.initializeApp.'\n );\n }\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n '\"projectId\" not provided in firebase.initializeApp.'\n );\n }\n\n if (objUtils.contains(options, 'firestoreOptions')) {\n // TODO(b/62673263): We can safely remove the special handling of\n // 'firestoreOptions' once alpha testers have upgraded.\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n '\"firestoreOptions\" values are now specified with ' +\n 'Firestore.settings()'\n );\n }\n\n const projectId = options['projectId'];\n if (!projectId || typeof projectId !== 'string') {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'projectId must be a string in firebase.app.App.options'\n );\n }\n return new DatabaseId(projectId);\n }\n\n get app(): firebase.app.App {\n if (!this._config.firebaseApp) {\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n \"Firestore was not initialized using the Firebase SDK. 'app' is \" +\n 'not available'\n );\n }\n return this._config.firebaseApp;\n }\n\n INTERNAL = {\n delete: (): Promise => {\n if (this._firestoreClient) {\n return this._firestoreClient.shutdown();\n } else {\n return Promise.resolve();\n }\n }\n };\n\n collection(pathString: string): firestore.CollectionReference {\n validateExactNumberOfArgs('Firestore.collection', arguments, 1);\n validateArgType('Firestore.collection', 'string', 1, pathString);\n if (!pathString) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Must provide a non-empty collection path to collection()'\n );\n }\n\n this.ensureClientConfigured();\n return new CollectionReference(ResourcePath.fromString(pathString), this);\n }\n\n doc(pathString: string): firestore.DocumentReference {\n validateExactNumberOfArgs('Firestore.doc', arguments, 1);\n validateArgType('Firestore.doc', 'string', 1, pathString);\n if (!pathString) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Must provide a non-empty document path to doc()'\n );\n }\n this.ensureClientConfigured();\n return DocumentReference.forPath(ResourcePath.fromString(pathString), this);\n }\n\n runTransaction(\n updateFunction: (transaction: firestore.Transaction) => Promise\n ): Promise {\n validateExactNumberOfArgs('Firestore.runTransaction', arguments, 1);\n validateArgType('Firestore.runTransaction', 'function', 1, updateFunction);\n return this.ensureClientConfigured().transaction(\n (transaction: InternalTransaction) => {\n return updateFunction(new Transaction(this, transaction));\n }\n );\n }\n\n batch(): firestore.WriteBatch {\n this.ensureClientConfigured();\n\n return new WriteBatch(this);\n }\n\n static get logLevel(): firestore.LogLevel {\n switch (log.getLogLevel()) {\n case LogLevel.DEBUG:\n return 'debug';\n case LogLevel.ERROR:\n return 'error';\n case LogLevel.SILENT:\n return 'silent';\n default:\n return fail('Unknown log level: ' + log.getLogLevel());\n }\n }\n\n static setLogLevel(level: firestore.LogLevel) {\n validateExactNumberOfArgs('Firestore.setLogLevel', arguments, 1);\n validateArgType('Firestore.setLogLevel', 'string', 1, level);\n switch (level) {\n case 'debug':\n log.setLogLevel(log.LogLevel.DEBUG);\n break;\n case 'error':\n log.setLogLevel(log.LogLevel.ERROR);\n break;\n case 'silent':\n log.setLogLevel(log.LogLevel.SILENT);\n break;\n default:\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid log level: ' + level\n );\n }\n }\n}\n\n/**\n * A reference to a transaction.\n */\nexport class Transaction implements firestore.Transaction {\n constructor(\n private _firestore: Firestore,\n private _transaction: InternalTransaction\n ) {}\n\n get(\n documentRef: firestore.DocumentReference\n ): Promise {\n validateExactNumberOfArgs('Transaction.get', arguments, 1);\n const ref = validateReference(\n 'Transaction.get',\n documentRef,\n this._firestore\n );\n return this._transaction\n .lookup([ref._key])\n .then((docs: MaybeDocument[]) => {\n if (!docs || docs.length !== 1) {\n return fail('Mismatch in docs returned from document lookup.');\n }\n const doc = docs[0];\n if (doc instanceof NoDocument) {\n return new DocumentSnapshot(this._firestore, ref._key, null, false);\n }\n return new DocumentSnapshot(this._firestore, ref._key, doc, false);\n });\n }\n\n set(\n documentRef: firestore.DocumentReference,\n value: firestore.DocumentData,\n options?: firestore.SetOptions\n ): Transaction {\n validateBetweenNumberOfArgs('Transaction.set', arguments, 2, 3);\n const ref = validateReference(\n 'Transaction.set',\n documentRef,\n this._firestore\n );\n options = validateSetOptions('Transaction.set', options);\n const parsed = this._firestore._dataConverter.parseSetData(\n 'Transaction.set',\n value,\n options\n );\n this._transaction.set(ref._key, parsed);\n return this;\n }\n\n update(\n documentRef: firestore.DocumentReference,\n value: firestore.UpdateData\n ): Transaction;\n update(\n documentRef: firestore.DocumentReference,\n field: string | ExternalFieldPath,\n value: AnyJs,\n ...moreFieldsAndValues: AnyJs[]\n ): Transaction;\n update(\n documentRef: firestore.DocumentReference,\n fieldOrUpdateData: string | ExternalFieldPath | firestore.UpdateData,\n value?: AnyJs,\n ...moreFieldsAndValues: AnyJs[]\n ): Transaction {\n let ref;\n let parsed;\n\n if (\n typeof fieldOrUpdateData === 'string' ||\n fieldOrUpdateData instanceof ExternalFieldPath\n ) {\n validateAtLeastNumberOfArgs('Transaction.update', arguments, 3);\n ref = validateReference(\n 'Transaction.update',\n documentRef,\n this._firestore\n );\n parsed = this._firestore._dataConverter.parseUpdateVarargs(\n 'Transaction.update',\n fieldOrUpdateData,\n value,\n moreFieldsAndValues\n );\n } else {\n validateExactNumberOfArgs('Transaction.update', arguments, 2);\n ref = validateReference(\n 'Transaction.update',\n documentRef,\n this._firestore\n );\n parsed = this._firestore._dataConverter.parseUpdateData(\n 'Transaction.update',\n fieldOrUpdateData\n );\n }\n\n this._transaction.update(ref._key, parsed);\n return this;\n }\n\n delete(documentRef: firestore.DocumentReference): Transaction {\n validateExactNumberOfArgs('Transaction.delete', arguments, 1);\n const ref = validateReference(\n 'Transaction.delete',\n documentRef,\n this._firestore\n );\n this._transaction.delete(ref._key);\n return this;\n }\n}\n\nexport class WriteBatch implements firestore.WriteBatch {\n private _mutations = [] as Mutation[];\n private _committed = false;\n\n constructor(private _firestore: Firestore) {}\n\n set(\n documentRef: firestore.DocumentReference,\n value: firestore.DocumentData,\n options?: firestore.SetOptions\n ): WriteBatch {\n validateBetweenNumberOfArgs('WriteBatch.set', arguments, 2, 3);\n this.verifyNotCommitted();\n const ref = validateReference(\n 'WriteBatch.set',\n documentRef,\n this._firestore\n );\n options = validateSetOptions('WriteBatch.set', options);\n const parsed = this._firestore._dataConverter.parseSetData(\n 'WriteBatch.set',\n value,\n options\n );\n this._mutations = this._mutations.concat(\n parsed.toMutations(ref._key, Precondition.NONE)\n );\n return this;\n }\n\n update(\n documentRef: firestore.DocumentReference,\n value: firestore.UpdateData\n ): WriteBatch;\n update(\n documentRef: firestore.DocumentReference,\n field: string | ExternalFieldPath,\n value: AnyJs,\n ...moreFieldsAndValues: AnyJs[]\n ): WriteBatch;\n update(\n documentRef: firestore.DocumentReference,\n fieldOrUpdateData: string | ExternalFieldPath | firestore.UpdateData,\n value?: AnyJs,\n ...moreFieldsAndValues: AnyJs[]\n ): WriteBatch {\n this.verifyNotCommitted();\n\n let ref;\n let parsed;\n\n if (\n typeof fieldOrUpdateData === 'string' ||\n fieldOrUpdateData instanceof ExternalFieldPath\n ) {\n validateAtLeastNumberOfArgs('WriteBatch.update', arguments, 3);\n ref = validateReference(\n 'WriteBatch.update',\n documentRef,\n this._firestore\n );\n parsed = this._firestore._dataConverter.parseUpdateVarargs(\n 'WriteBatch.update',\n fieldOrUpdateData,\n value,\n moreFieldsAndValues\n );\n } else {\n validateExactNumberOfArgs('WriteBatch.update', arguments, 2);\n ref = validateReference(\n 'WriteBatch.update',\n documentRef,\n this._firestore\n );\n parsed = this._firestore._dataConverter.parseUpdateData(\n 'WriteBatch.update',\n fieldOrUpdateData\n );\n }\n\n this._mutations = this._mutations.concat(\n parsed.toMutations(ref._key, Precondition.exists(true))\n );\n return this;\n }\n\n delete(documentRef: firestore.DocumentReference): WriteBatch {\n validateExactNumberOfArgs('WriteBatch.delete', arguments, 1);\n this.verifyNotCommitted();\n const ref = validateReference(\n 'WriteBatch.delete',\n documentRef,\n this._firestore\n );\n this._mutations = this._mutations.concat(\n new DeleteMutation(ref._key, Precondition.NONE)\n );\n return this;\n }\n\n commit(): Promise {\n this.verifyNotCommitted();\n this._committed = true;\n if (this._mutations.length > 0) {\n return this._firestore.ensureClientConfigured().write(this._mutations);\n } else {\n return Promise.resolve();\n }\n }\n\n private verifyNotCommitted() {\n if (this._committed) {\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'A write batch can no longer be used after commit() ' +\n 'has been called.'\n );\n }\n }\n}\n\n/**\n * A reference to a particular document in a collection in the database.\n */\nexport class DocumentReference implements firestore.DocumentReference {\n private _firestoreClient: FirestoreClient;\n\n constructor(public _key: DocumentKey, readonly firestore: Firestore) {\n this._firestoreClient = this.firestore.ensureClientConfigured();\n }\n\n static forPath(path: ResourcePath, firestore: Firestore) {\n if (path.length % 2 !== 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid document reference. Document ' +\n 'references must have an even number of segments, but ' +\n `${path.canonicalString()} has ${path.length}`\n );\n }\n return new DocumentReference(new DocumentKey(path), firestore);\n }\n\n get id(): string {\n return this._key.path.lastSegment();\n }\n\n get parent(): firestore.CollectionReference {\n return new CollectionReference(this._key.path.popLast(), this.firestore);\n }\n\n get path(): string {\n return this._key.path.canonicalString();\n }\n\n collection(pathString: string): firestore.CollectionReference {\n validateExactNumberOfArgs('DocumentReference.collection', arguments, 1);\n validateArgType('DocumentReference.collection', 'string', 1, pathString);\n if (!pathString) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Must provide a non-empty collection name to collection()'\n );\n }\n const path = ResourcePath.fromString(pathString);\n return new CollectionReference(this._key.path.child(path), this.firestore);\n }\n\n set(\n value: firestore.DocumentData,\n options?: firestore.SetOptions\n ): Promise {\n validateBetweenNumberOfArgs('DocumentReference.set', arguments, 1, 2);\n options = validateSetOptions('DocumentReference.set', options);\n\n const parsed = this.firestore._dataConverter.parseSetData(\n 'DocumentReference.set',\n value,\n options\n );\n return this._firestoreClient.write(\n parsed.toMutations(this._key, Precondition.NONE)\n );\n }\n\n update(value: firestore.UpdateData): Promise;\n update(\n field: string | ExternalFieldPath,\n value: AnyJs,\n ...moreFieldsAndValues: AnyJs[]\n ): Promise;\n update(\n fieldOrUpdateData: string | ExternalFieldPath | firestore.UpdateData,\n value?: AnyJs,\n ...moreFieldsAndValues: AnyJs[]\n ): Promise {\n let parsed;\n\n if (\n typeof fieldOrUpdateData === 'string' ||\n fieldOrUpdateData instanceof ExternalFieldPath\n ) {\n validateAtLeastNumberOfArgs('DocumentReference.update', arguments, 2);\n parsed = this.firestore._dataConverter.parseUpdateVarargs(\n 'DocumentReference.update',\n fieldOrUpdateData,\n value,\n moreFieldsAndValues\n );\n } else {\n validateExactNumberOfArgs('DocumentReference.update', arguments, 1);\n parsed = this.firestore._dataConverter.parseUpdateData(\n 'DocumentReference.update',\n fieldOrUpdateData\n );\n }\n\n return this._firestoreClient.write(\n parsed.toMutations(this._key, Precondition.exists(true))\n );\n }\n\n delete(): Promise {\n validateExactNumberOfArgs('DocumentReference.delete', arguments, 0);\n return this._firestoreClient.write([\n new DeleteMutation(this._key, Precondition.NONE)\n ]);\n }\n\n onSnapshot(\n observer: PartialObserver\n ): Unsubscribe;\n onSnapshot(\n options: firestore.DocumentListenOptions,\n observer: PartialObserver\n ): Unsubscribe;\n onSnapshot(\n onNext: NextFn,\n onError?: ErrorFn,\n onCompletion?: CompleteFn\n ): Unsubscribe;\n onSnapshot(\n options: firestore.DocumentListenOptions,\n onNext: NextFn,\n onError?: ErrorFn,\n onCompletion?: CompleteFn\n ): Unsubscribe;\n\n onSnapshot(...args: AnyJs[]): Unsubscribe {\n validateBetweenNumberOfArgs(\n 'DocumentReference.onSnapshot',\n arguments,\n 1,\n 4\n );\n let options: firestore.DocumentListenOptions = {\n includeMetadataChanges: false\n };\n let observer: PartialObserver;\n let currArg = 0;\n if (\n typeof args[currArg] === 'object' &&\n !isPartialObserver(args[currArg])\n ) {\n options = args[currArg] as firestore.DocumentListenOptions;\n validateOptionNames('DocumentReference.onSnapshot', options, [\n 'includeMetadataChanges'\n ]);\n validateNamedOptionalType(\n 'DocumentReference.onSnapshot',\n 'boolean',\n 'includeMetadataChanges',\n options.includeMetadataChanges\n );\n currArg++;\n }\n\n const internalOptions = {\n includeDocumentMetadataChanges: options.includeMetadataChanges,\n includeQueryMetadataChanges: options.includeMetadataChanges\n };\n\n if (isPartialObserver(args[currArg])) {\n observer = args[currArg] as PartialObserver;\n } else {\n validateArgType(\n 'DocumentReference.onSnapshot',\n 'function',\n currArg,\n args[currArg]\n );\n validateOptionalArgType(\n 'DocumentReference.onSnapshot',\n 'function',\n currArg + 1,\n args[currArg + 1]\n );\n validateOptionalArgType(\n 'DocumentReference.onSnapshot',\n 'function',\n currArg + 2,\n args[currArg + 2]\n );\n observer = {\n next: args[currArg] as NextFn,\n error: args[currArg + 1] as ErrorFn,\n complete: args[currArg + 2] as CompleteFn\n };\n }\n return this.onSnapshotInternal(internalOptions, observer);\n }\n\n private onSnapshotInternal(\n options: ListenOptions,\n observer: PartialObserver\n ): Unsubscribe {\n let errHandler = (err: Error) => {\n console.error('Uncaught Error in onSnapshot:', err);\n };\n if (observer.error) {\n errHandler = observer.error.bind(observer);\n }\n\n const asyncObserver = new AsyncObserver({\n next: snapshot => {\n if (observer.next) {\n assert(\n snapshot.docs.size <= 1,\n 'Too many documents returned on a document query'\n );\n const doc = snapshot.docs.get(this._key);\n\n observer.next(\n new DocumentSnapshot(\n this.firestore,\n this._key,\n doc,\n snapshot.fromCache\n )\n );\n }\n },\n error: errHandler\n });\n const internalListener = this._firestoreClient.listen(\n InternalQuery.atPath(this._key.path),\n asyncObserver,\n options\n );\n\n return () => {\n asyncObserver.mute();\n this._firestoreClient.unlisten(internalListener);\n };\n }\n\n get(): Promise {\n validateExactNumberOfArgs('DocumentReference.get', arguments, 0);\n return new Promise(\n (resolve: Resolver, reject: Rejecter) => {\n const unlisten = this.onSnapshotInternal(\n {\n includeQueryMetadataChanges: true,\n includeDocumentMetadataChanges: true,\n waitForSyncWhenOnline: true\n },\n {\n next: (snap: firestore.DocumentSnapshot) => {\n // Remove query first before passing event to user to avoid\n // user actions affecting the now stale query.\n unlisten();\n\n if (!snap.exists && snap.metadata.fromCache) {\n // TODO(dimond): If we're online and the document doesn't\n // exist then we resolve with a doc.exists set to false. If\n // we're offline however, we reject the Promise in this\n // case. Two options: 1) Cache the negative response from\n // the server so we can deliver that even when you're\n // offline 2) Actually reject the Promise in the online case\n // if the document doesn't exist.\n reject(\n new FirestoreError(\n Code.ABORTED,\n 'Failed to get document because the client is ' + 'offline.'\n )\n );\n } else {\n resolve(snap);\n }\n },\n error: reject\n }\n );\n }\n );\n }\n}\n\nexport class DocumentSnapshot implements firestore.DocumentSnapshot {\n constructor(\n private _firestore: Firestore,\n private _key: DocumentKey,\n public _document: Document | null,\n private _fromCache: boolean\n ) {}\n\n data(): firestore.DocumentData {\n validateExactNumberOfArgs('DocumentSnapshot.data', arguments, 0);\n if (!this._document) {\n throw new FirestoreError(\n Code.NOT_FOUND,\n \"This document doesn't exist. Check doc.exists to make sure \" +\n 'the document exists before calling doc.data().'\n );\n }\n return this.convertObject(this._document.data);\n }\n\n get(fieldPath: string | ExternalFieldPath): AnyJs {\n validateExactNumberOfArgs('DocumentSnapshot.get', arguments, 1);\n if (!this._document) {\n throw new FirestoreError(\n Code.NOT_FOUND,\n \"This document doesn't exist. Check doc.exists to make sure \" +\n 'the document exists before calling doc.get().'\n );\n }\n const value = this._document.data.field(\n fieldPathFromArgument('DocumentSnapshot.get', fieldPath)\n );\n return value === undefined ? undefined : this.convertValue(value);\n }\n\n get id(): string {\n return this._key.path.lastSegment();\n }\n\n get ref(): firestore.DocumentReference {\n return new DocumentReference(this._key, this._firestore);\n }\n\n get exists(): boolean {\n return this._document !== null;\n }\n\n get metadata(): firestore.SnapshotMetadata {\n return {\n hasPendingWrites:\n this._document !== null && this._document.hasLocalMutations,\n fromCache: this._fromCache\n };\n }\n\n private convertObject(data: ObjectValue): firestore.DocumentData {\n const result: firestore.DocumentData = {};\n data.forEach((key, value) => {\n result[key] = this.convertValue(value);\n });\n return result;\n }\n\n private convertValue(value: FieldValue): AnyJs {\n if (value instanceof ObjectValue) {\n return this.convertObject(value);\n } else if (value instanceof ArrayValue) {\n return this.convertArray(value);\n } else if (value instanceof RefValue) {\n const key = value.value();\n const database = this._firestore.ensureClientConfigured().databaseId();\n if (!value.databaseId.equals(database)) {\n // TODO(b/64130202): Somehow support foreign references.\n log.error(\n `Document ${this._key.path} contains a document ` +\n `reference within a different database (` +\n `${value.databaseId.projectId}/${value.databaseId\n .database}) which is not ` +\n `supported. It will be treated as a reference in the current ` +\n `database (${database.projectId}/${database.database}) ` +\n `instead.`\n );\n }\n return new DocumentReference(key, this._firestore);\n } else {\n return value.value();\n }\n }\n\n private convertArray(data: ArrayValue): AnyJs[] {\n return data.internalValue.map(value => {\n return this.convertValue(value);\n });\n }\n}\n\nexport class Query implements firestore.Query {\n constructor(public _query: InternalQuery, readonly firestore: Firestore) {}\n\n where(\n field: string | ExternalFieldPath,\n opStr: firestore.WhereFilterOp,\n value: AnyJs\n ): firestore.Query {\n validateExactNumberOfArgs('Query.where', arguments, 3);\n validateArgType('Query.where', 'string', 2, opStr);\n validateDefined('Query.where', 3, value);\n let fieldValue;\n const fieldPath = fieldPathFromArgument('Query.where', field);\n if (fieldPath.isKeyField()) {\n if (typeof value === 'string') {\n if (value.indexOf('/') !== -1) {\n // TODO(dimond): Allow slashes once ancestor queries are supported\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Function Query.where() requires its third parameter to be a ' +\n 'valid document ID if the first parameter is ' +\n 'FieldPath.documentId(), but it contains a slash.'\n );\n }\n if (value === '') {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Function Query.where() requires its third parameter to be a ' +\n 'valid document ID if the first parameter is ' +\n 'FieldPath.documentId(), but it was an empty string.'\n );\n }\n const path = this._query.path.child(new ResourcePath([value]));\n assert(path.length % 2 === 0, 'Path should be a document key');\n fieldValue = new RefValue(\n this.firestore._databaseId,\n new DocumentKey(path)\n );\n } else if (value instanceof DocumentReference) {\n const ref = value as DocumentReference;\n fieldValue = new RefValue(this.firestore._databaseId, ref._key);\n } else {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function Query.where() requires its third parameter to be a ` +\n `string or a DocumentReference if the first parameter is ` +\n `FieldPath.documentId(), but it was: ` +\n `${valueDescription(value)}.`\n );\n }\n } else {\n fieldValue = this.firestore._dataConverter.parseQueryValue(\n 'Query.where',\n value\n );\n }\n const filter = fieldFilter(\n fieldPath,\n RelationOp.fromString(opStr),\n fieldValue\n );\n this.validateNewFilter(filter);\n return new Query(this._query.addFilter(filter), this.firestore);\n }\n\n orderBy(\n field: string | ExternalFieldPath,\n directionStr?: firestore.OrderByDirection\n ): firestore.Query {\n validateBetweenNumberOfArgs('Query.orderBy', arguments, 1, 2);\n validateOptionalArgType('Query.orderBy', 'string', 2, directionStr);\n let direction: Direction;\n if (directionStr === undefined || directionStr === 'asc') {\n direction = Direction.ASCENDING;\n } else if (directionStr === 'desc') {\n direction = Direction.DESCENDING;\n } else {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Function Query.orderBy() has unknown direction '${directionStr}', ` +\n `expected 'asc' or 'desc'.`\n );\n }\n if (this._query.startAt !== null) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid query. You must not call Query.startAt() or ' +\n 'Query.startAfter() before calling Query.orderBy().'\n );\n }\n if (this._query.endAt !== null) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid query. You must not call Query.endAt() or ' +\n 'Query.endBefore() before calling Query.orderBy().'\n );\n }\n const fieldPath = fieldPathFromArgument('Query.orderBy', field);\n const orderBy = new OrderBy(fieldPath, direction);\n this.validateNewOrderBy(orderBy);\n return new Query(this._query.addOrderBy(orderBy), this.firestore);\n }\n\n limit(n: number): firestore.Query {\n validateExactNumberOfArgs('Query.limit', arguments, 1);\n validateArgType('Query.limit', 'number', 1, n);\n if (n <= 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid Query. Query limit (${n}) is invalid. Limit must be ` +\n 'positive.'\n );\n }\n return new Query(this._query.withLimit(n), this.firestore);\n }\n\n startAt(\n docOrField: AnyJs | firestore.DocumentSnapshot,\n ...fields: AnyJs[]\n ): firestore.Query {\n validateAtLeastNumberOfArgs('Query.startAt', arguments, 1);\n const bound = this.boundFromDocOrFields(\n 'Query.startAt',\n docOrField,\n fields,\n /*before=*/ true\n );\n return new Query(this._query.withStartAt(bound), this.firestore);\n }\n\n startAfter(\n docOrField: AnyJs | firestore.DocumentSnapshot,\n ...fields: AnyJs[]\n ): firestore.Query {\n validateAtLeastNumberOfArgs('Query.startAfter', arguments, 1);\n const bound = this.boundFromDocOrFields(\n 'Query.startAfter',\n docOrField,\n fields,\n /*before=*/ false\n );\n return new Query(this._query.withStartAt(bound), this.firestore);\n }\n\n endBefore(\n docOrField: AnyJs | firestore.DocumentSnapshot,\n ...fields: AnyJs[]\n ): firestore.Query {\n validateAtLeastNumberOfArgs('Query.endBefore', arguments, 1);\n const bound = this.boundFromDocOrFields(\n 'Query.endBefore',\n docOrField,\n fields,\n /*before=*/ true\n );\n return new Query(this._query.withEndAt(bound), this.firestore);\n }\n\n endAt(\n docOrField: AnyJs | firestore.DocumentSnapshot,\n ...fields: AnyJs[]\n ): firestore.Query {\n validateAtLeastNumberOfArgs('Query.endAt', arguments, 1);\n const bound = this.boundFromDocOrFields(\n 'Query.endAt',\n docOrField,\n fields,\n /*before=*/ false\n );\n return new Query(this._query.withEndAt(bound), this.firestore);\n }\n\n /** Helper function to create a bound from a document or fields */\n private boundFromDocOrFields(\n methodName: string,\n docOrField: AnyJs | firestore.DocumentSnapshot,\n fields: AnyJs[],\n before: boolean\n ): Bound {\n validateDefined(methodName, 1, docOrField);\n if (docOrField instanceof DocumentSnapshot) {\n if (fields.length > 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Too many arguments provided to ${methodName}().`\n );\n }\n const snap = docOrField;\n if (!snap.exists) {\n throw new FirestoreError(\n Code.NOT_FOUND,\n `Can't use a DocumentSnapshot that doesn't exist for ` +\n `${methodName}().`\n );\n }\n return this.boundFromDocument(methodName, snap._document!, before);\n } else {\n const allFields = [docOrField].concat(fields);\n return this.boundFromFields(methodName, allFields, before);\n }\n }\n\n /**\n * Create a Bound from a query and a document.\n *\n * Note that the Bound will always include the key of the document\n * and so only the provided document will compare equal to the returned\n * position.\n *\n * Will throw if the document does not contain all fields of the order by\n * of the query.\n */\n private boundFromDocument(\n methodName: string,\n doc: Document,\n before: boolean\n ): Bound {\n const components: FieldValue[] = [];\n\n // Because people expect to continue/end a query at the exact document\n // provided, we need to use the implicit sort order rather than the explicit\n // sort order, because it's guaranteed to contain the document key. That way\n // the position becomes unambiguous and the query continues/ends exactly at\n // the provided document. Without the key (by using the explicit sort\n // orders), multiple documents could match the position, yielding duplicate\n // results.\n for (const orderBy of this._query.orderBy) {\n if (orderBy.field.isKeyField()) {\n components.push(new RefValue(this.firestore._databaseId, doc.key));\n } else {\n const value = doc.field(orderBy.field);\n if (value !== undefined) {\n components.push(value);\n } else {\n const field = orderBy.field.canonicalString();\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid query. You are trying to start or end a query using a ` +\n `document for which the field '${field}' (used as the ` +\n `orderBy) does not exist.`\n );\n }\n }\n }\n return new Bound(components, before);\n }\n\n /**\n * Converts a list of field values to a Bound for the given query.\n */\n private boundFromFields(\n methodName: string,\n values: AnyJs[],\n before: boolean\n ): Bound {\n // Use explicit order by's because it has to match the query the user made\n const orderBy = this._query.explicitOrderBy;\n if (values.length > orderBy.length) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Too many arguments provided to ${methodName}(). ` +\n `The number of arguments must be less than or equal to the ` +\n `number of Query.orderBy() clauses`\n );\n }\n\n const components: FieldValue[] = [];\n for (let i = 0; i < values.length; i++) {\n const rawValue = values[i];\n const orderByComponent = orderBy[i];\n if (orderByComponent.field.isKeyField()) {\n if (typeof rawValue !== 'string') {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid query. Expected a string for document ID in ` +\n `${methodName}(), but got a ${typeof rawValue}`\n );\n }\n if (rawValue.indexOf('/') !== -1) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid query. Document ID '${rawValue}' contains a slash in ` +\n `${methodName}()`\n );\n }\n const key = new DocumentKey(this._query.path.child(rawValue));\n components.push(new RefValue(this.firestore._databaseId, key));\n } else {\n const wrapped = this.firestore._dataConverter.parseQueryValue(\n methodName,\n rawValue\n );\n components.push(wrapped);\n }\n }\n\n return new Bound(components, before);\n }\n\n onSnapshot(observer: PartialObserver): Unsubscribe;\n onSnapshot(\n options: firestore.QueryListenOptions,\n observer: PartialObserver\n ): Unsubscribe;\n onSnapshot(\n onNext: NextFn,\n onError?: ErrorFn,\n onCompletion?: CompleteFn\n ): Unsubscribe;\n onSnapshot(\n options: firestore.QueryListenOptions,\n onNext: NextFn,\n onError?: ErrorFn,\n onCompletion?: CompleteFn\n ): Unsubscribe;\n\n onSnapshot(...args: AnyJs[]): Unsubscribe {\n validateBetweenNumberOfArgs('Query.onSnapshot', arguments, 1, 4);\n let options: firestore.QueryListenOptions = {};\n let observer: PartialObserver;\n let currArg = 0;\n if (\n typeof args[currArg] === 'object' &&\n !isPartialObserver(args[currArg])\n ) {\n options = args[currArg] as firestore.QueryListenOptions;\n validateOptionNames('Query.onSnapshot', options, [\n 'includeQueryMetadataChanges',\n 'includeDocumentMetadataChanges'\n ]);\n validateNamedOptionalType(\n 'Query.onSnapshot',\n 'boolean',\n 'includeDocumentMetadataChanges',\n options.includeDocumentMetadataChanges\n );\n validateNamedOptionalType(\n 'Query.onSnapshot',\n 'boolean',\n 'includeQueryMetadataChanges',\n options.includeQueryMetadataChanges\n );\n currArg++;\n }\n\n if (isPartialObserver(args[currArg])) {\n observer = args[currArg] as PartialObserver;\n } else {\n validateArgType('Query.onSnapshot', 'function', currArg, args[currArg]);\n validateOptionalArgType(\n 'Query.onSnapshot',\n 'function',\n currArg + 1,\n args[currArg + 1]\n );\n validateOptionalArgType(\n 'Query.onSnapshot',\n 'function',\n currArg + 2,\n args[currArg + 2]\n );\n observer = {\n next: args[currArg] as NextFn,\n error: args[currArg + 1] as ErrorFn,\n complete: args[currArg + 2] as CompleteFn\n };\n }\n return this.onSnapshotInternal(options, observer);\n }\n\n private onSnapshotInternal(\n options: ListenOptions,\n observer: PartialObserver\n ): Unsubscribe {\n let errHandler = (err: Error) => {\n console.error('Uncaught Error in onSnapshot:', err);\n };\n if (observer.error) {\n errHandler = observer.error.bind(observer);\n }\n\n const asyncObserver = new AsyncObserver({\n next: (result: ViewSnapshot): void => {\n if (observer.next) {\n observer.next(new QuerySnapshot(this.firestore, this._query, result));\n }\n },\n error: errHandler\n });\n\n const firestoreClient = this.firestore.ensureClientConfigured();\n const internalListener = firestoreClient.listen(\n this._query,\n asyncObserver,\n options\n );\n return () => {\n asyncObserver.mute();\n firestoreClient.unlisten(internalListener);\n };\n }\n\n get(): Promise {\n validateExactNumberOfArgs('Query.get', arguments, 0);\n return new Promise(\n (resolve: Resolver, reject: Rejecter) => {\n const unlisten = this.onSnapshotInternal(\n {\n includeDocumentMetadataChanges: false,\n includeQueryMetadataChanges: true,\n waitForSyncWhenOnline: true\n },\n {\n next: (result: firestore.QuerySnapshot) => {\n // Remove query first before passing event to user to avoid\n // user actions affecting the now stale query.\n unlisten();\n\n resolve(result);\n },\n error: reject\n }\n );\n }\n );\n }\n\n private validateNewFilter(filter: Filter): void {\n if (filter instanceof RelationFilter && filter.isInequality()) {\n const existingField = this._query.getInequalityFilterField();\n if (existingField !== null && !existingField.equals(filter.field)) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid query. All where filters with an inequality' +\n ' (<, <=, >, or >=) must be on the same field. But you have' +\n ` inequality filters on '${existingField.toString()}'` +\n ` and '${filter.field.toString()}'`\n );\n }\n\n const firstOrderByField = this._query.getFirstOrderByField();\n if (firstOrderByField !== null) {\n this.validateOrderByAndInequalityMatch(filter.field, firstOrderByField);\n }\n }\n }\n\n private validateNewOrderBy(orderBy: OrderBy): void {\n if (this._query.getFirstOrderByField() === null) {\n // This is the first order by. It must match any inequality.\n const inequalityField = this._query.getInequalityFilterField();\n if (inequalityField !== null) {\n this.validateOrderByAndInequalityMatch(inequalityField, orderBy.field);\n }\n }\n }\n\n private validateOrderByAndInequalityMatch(\n inequality: FieldPath,\n orderBy: FieldPath\n ): void {\n if (!orderBy.equals(inequality)) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid query. You have a where filter with an inequality ` +\n `(<, <=, >, or >=) on field '${inequality.toString()}' ` +\n `and so you must also use '${inequality.toString()}' ` +\n `as your first Query.orderBy(), but your first Query.orderBy() ` +\n `is on field '${orderBy.toString()}' instead.`\n );\n }\n }\n}\n\nexport class QuerySnapshot implements firestore.QuerySnapshot {\n private _cachedChanges: firestore.DocumentChange[] | null = null;\n\n readonly metadata: firestore.SnapshotMetadata;\n\n constructor(\n private _firestore: Firestore,\n private _originalQuery: InternalQuery,\n private _snapshot: ViewSnapshot\n ) {\n this.metadata = {\n fromCache: _snapshot.fromCache,\n hasPendingWrites: _snapshot.hasPendingWrites\n };\n }\n\n get docs(): firestore.DocumentSnapshot[] {\n const result: firestore.DocumentSnapshot[] = [];\n this.forEach(doc => result.push(doc));\n return result;\n }\n\n get empty(): boolean {\n return this._snapshot.docs.isEmpty();\n }\n\n get size(): number {\n return this._snapshot.docs.size;\n }\n\n forEach(\n callback: (result: firestore.DocumentSnapshot) => void,\n thisArg?: AnyJs\n ): void {\n validateBetweenNumberOfArgs('QuerySnapshot.forEach', arguments, 1, 2);\n validateArgType('QuerySnapshot.forEach', 'function', 1, callback);\n this._snapshot.docs.forEach(doc => {\n callback.call(thisArg, this.convertToDocumentImpl(doc));\n });\n }\n\n get query(): firestore.Query {\n return new Query(this._originalQuery, this._firestore);\n }\n\n get docChanges(): firestore.DocumentChange[] {\n if (!this._cachedChanges) {\n this._cachedChanges = changesFromSnapshot(\n this._firestore,\n this._snapshot\n );\n }\n return this._cachedChanges;\n }\n\n private convertToDocumentImpl(doc: Document): DocumentSnapshot {\n return new DocumentSnapshot(\n this._firestore,\n doc.key,\n doc,\n this.metadata.fromCache\n );\n }\n}\n\nexport class CollectionReference extends Query\n implements firestore.CollectionReference {\n constructor(path: ResourcePath, firestore: Firestore) {\n super(InternalQuery.atPath(path), firestore);\n if (path.length % 2 !== 1) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Invalid collection reference. Collection ' +\n 'references must have an odd number of segments, but ' +\n `${path.canonicalString()} has ${path.length}`\n );\n }\n }\n\n get id(): string {\n return this._query.path.lastSegment();\n }\n\n get parent(): firestore.DocumentReference | null {\n const parentPath = this._query.path.popLast();\n if (parentPath.isEmpty()) {\n return null;\n } else {\n return new DocumentReference(new DocumentKey(parentPath), this.firestore);\n }\n }\n\n get path(): string {\n return this._query.path.canonicalString();\n }\n\n doc(pathString?: string): firestore.DocumentReference {\n validateBetweenNumberOfArgs('CollectionReference.doc', arguments, 0, 1);\n validateOptionalArgType('CollectionReference.doc', 'string', 1, pathString);\n if (pathString === undefined) {\n pathString = AutoId.newId();\n }\n if (typeof pathString !== 'string' || pathString === '') {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Document path must be a non-empty string'\n );\n }\n const path = ResourcePath.fromString(pathString);\n return DocumentReference.forPath(\n this._query.path.child(path),\n this.firestore\n );\n }\n\n add(value: firestore.DocumentData): Promise {\n validateExactNumberOfArgs('CollectionReference.add', arguments, 1);\n validateArgType('CollectionReference.add', 'object', 1, value);\n const docRef = this.doc();\n return docRef.set(value).then(() => docRef);\n }\n}\n\nfunction validateSetOptions(\n methodName: string,\n options: firestore.SetOptions | undefined\n): firestore.SetOptions {\n if (options === undefined) {\n return {\n merge: false\n };\n }\n\n validateOptionNames(methodName, options, ['merge']);\n validateNamedOptionalType(methodName, 'boolean', 'merge', options.merge);\n return options;\n}\n\nfunction validateReference(\n methodName: string,\n documentRef: firestore.DocumentReference,\n firestore: Firestore\n): DocumentReference {\n if (!(documentRef instanceof DocumentReference)) {\n throw invalidClassError(methodName, 'DocumentReference', 1, documentRef);\n } else if (documentRef.firestore !== firestore) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Provided document reference is from a different Firestore instance.'\n );\n } else {\n return documentRef;\n }\n}\n\n/**\n * Calculates the array of firestore.DocumentChange's for a given ViewSnapshot.\n *\n * Exported for testing.\n */\nexport function changesFromSnapshot(\n firestore: Firestore,\n snapshot: ViewSnapshot\n): firestore.DocumentChange[] {\n if (snapshot.oldDocs.isEmpty()) {\n // Special case the first snapshot because index calculation is easy and\n // fast\n let lastDoc: Document;\n let index = 0;\n return snapshot.docChanges.map(change => {\n const doc = new DocumentSnapshot(\n firestore,\n change.doc.key,\n change.doc,\n snapshot.fromCache\n );\n assert(\n change.type === ChangeType.Added,\n 'Invalid event type for first snapshot'\n );\n assert(\n !lastDoc || snapshot.query.docComparator(lastDoc, change.doc) < 0,\n 'Got added events in wrong order'\n );\n lastDoc = change.doc;\n return {\n type: 'added' as firestore.DocumentChangeType,\n doc,\n oldIndex: -1,\n newIndex: index++\n };\n });\n } else {\n // A DocumentSet that is updated incrementally as changes are applied to use\n // to lookup the index of a document.\n let indexTracker = snapshot.oldDocs;\n return snapshot.docChanges.map(change => {\n const doc = new DocumentSnapshot(\n firestore,\n change.doc.key,\n change.doc,\n snapshot.fromCache\n );\n let oldIndex = -1;\n let newIndex = -1;\n if (change.type !== ChangeType.Added) {\n oldIndex = indexTracker.indexOf(change.doc.key);\n assert(oldIndex >= 0, 'Index for document not found');\n indexTracker = indexTracker.delete(change.doc.key);\n }\n if (change.type !== ChangeType.Removed) {\n indexTracker = indexTracker.add(change.doc);\n newIndex = indexTracker.indexOf(change.doc.key);\n }\n return { type: resultChangeType(change.type), doc, oldIndex, newIndex };\n });\n }\n}\n\nfunction resultChangeType(type: ChangeType): firestore.DocumentChangeType {\n switch (type) {\n case ChangeType.Added:\n return 'added';\n case ChangeType.Modified:\n case ChangeType.Metadata:\n return 'modified';\n case ChangeType.Removed:\n return 'removed';\n default:\n return fail('Unknown change type: ' + type);\n }\n}\n\n// Export the classes with a private constructor (it will fail if invoked\n// at runtime). Note that this still allows instanceof checks.\n\n// We're treating the variables as class names, so disable checking for lower\n// case variable names.\n// tslint:disable:variable-name\nexport const PublicFirestore = makeConstructorPrivate(\n Firestore,\n 'Use firebase.firestore() instead.'\n);\nexport const PublicTransaction = makeConstructorPrivate(\n Transaction,\n 'Use firebase.firestore().runTransaction() instead.'\n);\nexport const PublicWriteBatch = makeConstructorPrivate(\n WriteBatch,\n 'Use firebase.firestore().batch() instead.'\n);\nexport const PublicDocumentReference = makeConstructorPrivate(\n DocumentReference,\n 'Use firebase.firestore().doc() instead.'\n);\nexport const PublicDocumentSnapshot = makeConstructorPrivate(DocumentSnapshot);\nexport const PublicQuery = makeConstructorPrivate(Query);\nexport const PublicQuerySnapshot = makeConstructorPrivate(QuerySnapshot);\nexport const PublicCollectionReference = makeConstructorPrivate(\n CollectionReference,\n 'Use firebase.firestore().collection() instead.'\n);\n// tslint:enable:variable-name\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/database.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as firestore from 'firestore';\n\nimport { PublicBlob } from '../api/blob';\nimport {\n Firestore,\n PublicCollectionReference,\n PublicDocumentReference,\n PublicDocumentSnapshot,\n PublicFirestore,\n PublicQuery,\n PublicQuerySnapshot,\n PublicTransaction,\n PublicWriteBatch\n} from '../api/database';\nimport { FieldPath } from '../api/field_path';\nimport { PublicFieldValue } from '../api/field_value';\nimport { GeoPoint } from '../api/geo_point';\nimport { shallowCopy } from '../util/obj';\n\nconst firestoreNamespace = {\n Firestore: PublicFirestore,\n GeoPoint: GeoPoint,\n Blob: PublicBlob,\n Transaction: PublicTransaction,\n WriteBatch: PublicWriteBatch,\n DocumentReference: PublicDocumentReference,\n DocumentSnapshot: PublicDocumentSnapshot,\n Query: PublicQuery,\n QuerySnapshot: PublicQuerySnapshot,\n CollectionReference: PublicCollectionReference,\n FieldPath: FieldPath,\n FieldValue: PublicFieldValue,\n setLogLevel: Firestore.setLogLevel\n};\n\n/**\n * Configures Firestore as part of the Firebase SDK by calling registerService.\n */\nexport function configureForFirebase(firebase: FirebaseNamespace): void {\n firebase.INTERNAL.registerService(\n 'firestore',\n (app: firebase.app.App) => new Firestore(app),\n shallowCopy(firestoreNamespace)\n );\n}\n\n/**\n * Exports the Firestore namespace into the provided `exportObject` object under\n * the key 'firestore'. This is used for wrapped binary that exposes Firestore\n * as a goog module.\n */\nexport function configureForStandalone(exportObject: {\n [key: string]: {};\n}): void {\n const copiedNamespace = shallowCopy(firestoreNamespace);\n // Unlike the use with Firebase, the standalone allows the use of the\n // constructor, so export it's internal class\n copiedNamespace['Firestore'] = Firestore;\n exportObject['firestore'] = copiedNamespace;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/platform/config.ts","/**\n* Copyright 2017 Google Inc.\n*\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*\n* http://www.apache.org/licenses/LICENSE-2.0\n*\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\nimport firebase from './app';\nimport './firestore/platform_browser/browser_init';\nimport { Firestore } from './firestore/api/database';\nimport { configureForFirebase } from './firestore/platform/config';\n\nexport function registerFirestore(instance) {\n configureForFirebase(instance);\n}\n\nregisterFirestore(firebase);\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport firebase from '../../app';\n\n/** The semver (www.semver.org) version of the SDK. */\nexport const SDK_VERSION = firebase.SDK_VERSION;\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/version.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as firestore from 'firestore';\n\n/**\n * Error Codes describing the different ways Firestore can fail. These come\n * directly from GRPC.\n */\nexport type Code = firestore.FirestoreErrorCode;\n\n// TODO(mcg): Change to a string enum once we've upgraded to typescript 2.4.\n// tslint:disable-next-line:variable-name Intended to look like a TS 2.4 enum\nexport const Code = {\n // Causes are copied from:\n // https://github.com/grpc/grpc/blob/bceec94ea4fc5f0085d81235d8e1c06798dc341a/include/grpc%2B%2B/impl/codegen/status_code_enum.h\n /** Not an error; returned on success. */\n OK: 'ok' as Code,\n\n /** The operation was cancelled (typically by the caller). */\n CANCELLED: 'cancelled' as Code,\n\n /** Unknown error or an error from a different error domain. */\n UNKNOWN: 'unknown' as Code,\n\n /**\n * Client specified an invalid argument. Note that this differs from\n * FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are\n * problematic regardless of the state of the system (e.g., a malformed file\n * name).\n */\n INVALID_ARGUMENT: 'invalid-argument' as Code,\n\n /**\n * Deadline expired before operation could complete. For operations that\n * change the state of the system, this error may be returned even if the\n * operation has completed successfully. For example, a successful response\n * from a server could have been delayed long enough for the deadline to\n * expire.\n */\n DEADLINE_EXCEEDED: 'deadline-exceeded' as Code,\n\n /** Some requested entity (e.g., file or directory) was not found. */\n NOT_FOUND: 'not-found' as Code,\n\n /**\n * Some entity that we attempted to create (e.g., file or directory) already\n * exists.\n */\n ALREADY_EXISTS: 'already-exists' as Code,\n\n /**\n * The caller does not have permission to execute the specified operation.\n * PERMISSION_DENIED must not be used for rejections caused by exhausting\n * some resource (use RESOURCE_EXHAUSTED instead for those errors).\n * PERMISSION_DENIED must not be used if the caller can not be identified\n * (use UNAUTHENTICATED instead for those errors).\n */\n PERMISSION_DENIED: 'permission-denied' as Code,\n\n /**\n * The request does not have valid authentication credentials for the\n * operation.\n */\n UNAUTHENTICATED: 'unauthenticated' as Code,\n\n /**\n * Some resource has been exhausted, perhaps a per-user quota, or perhaps the\n * entire file system is out of space.\n */\n RESOURCE_EXHAUSTED: 'resource-exhausted' as Code,\n\n /**\n * Operation was rejected because the system is not in a state required for\n * the operation's execution. For example, directory to be deleted may be\n * non-empty, an rmdir operation is applied to a non-directory, etc.\n *\n * A litmus test that may help a service implementor in deciding\n * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:\n * (a) Use UNAVAILABLE if the client can retry just the failing call.\n * (b) Use ABORTED if the client should retry at a higher-level\n * (e.g., restarting a read-modify-write sequence).\n * (c) Use FAILED_PRECONDITION if the client should not retry until\n * the system state has been explicitly fixed. E.g., if an \"rmdir\"\n * fails because the directory is non-empty, FAILED_PRECONDITION\n * should be returned since the client should not retry unless\n * they have first fixed up the directory by deleting files from it.\n * (d) Use FAILED_PRECONDITION if the client performs conditional\n * REST Get/Update/Delete on a resource and the resource on the\n * server does not match the condition. E.g., conflicting\n * read-modify-write on the same resource.\n */\n FAILED_PRECONDITION: 'failed-precondition' as Code,\n\n /**\n * The operation was aborted, typically due to a concurrency issue like\n * sequencer check failures, transaction aborts, etc.\n *\n * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,\n * and UNAVAILABLE.\n */\n ABORTED: 'aborted' as Code,\n\n /**\n * Operation was attempted past the valid range. E.g., seeking or reading\n * past end of file.\n *\n * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed\n * if the system state changes. For example, a 32-bit file system will\n * generate INVALID_ARGUMENT if asked to read at an offset that is not in the\n * range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from\n * an offset past the current file size.\n *\n * There is a fair bit of overlap between FAILED_PRECONDITION and\n * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)\n * when it applies so that callers who are iterating through a space can\n * easily look for an OUT_OF_RANGE error to detect when they are done.\n */\n OUT_OF_RANGE: 'out-of-range' as Code,\n\n /** Operation is not implemented or not supported/enabled in this service. */\n UNIMPLEMENTED: 'unimplemented' as Code,\n\n /**\n * Internal errors. Means some invariants expected by underlying System has\n * been broken. If you see one of these errors, Something is very broken.\n */\n INTERNAL: 'internal' as Code,\n\n /**\n * The service is currently unavailable. This is a most likely a transient\n * condition and may be corrected by retrying with a backoff.\n *\n * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,\n * and UNAVAILABLE.\n */\n UNAVAILABLE: 'unavailable' as Code,\n\n /** Unrecoverable data loss or corruption. */\n DATA_LOSS: 'data-loss' as Code\n};\n\n/**\n * An error class used for Firestore-generated errors. Ideally we should be\n * using FirebaseError, but integrating with it is overly arduous at the moment,\n * so we define our own compatible error class (with a `name` of 'FirebaseError'\n * and compatible `code` and `message` fields.)\n */\nexport class FirestoreError extends Error implements firestore.FirestoreError {\n name = 'FirebaseError';\n stack?: string;\n\n constructor(readonly code: Code, readonly message: string) {\n super(message);\n\n // HACK: We write a toString property directly because Error is not a real\n // class and so inheritance does not work correctly. We could alternatively\n // do the same \"back-door inheritance\" trick that FirebaseError does.\n this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/error.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Code, FirestoreError } from '../util/error';\nimport {\n validateArgType,\n validateExactNumberOfArgs\n} from '../util/input_validation';\nimport { primitiveComparator } from '../util/misc';\n\n/**\n * Immutable class representing a geo point as latitude-longitude pair.\n * This class is directly exposed in the public API, including its constructor.\n */\nexport class GeoPoint {\n // Prefix with underscore to signal this is a private variable in JS and\n // prevent it showing up for autocompletion when typing latitude or longitude.\n private _lat: number;\n private _long: number;\n\n constructor(latitude: number, longitude: number) {\n validateExactNumberOfArgs('GeoPoint', arguments, 2);\n validateArgType('GeoPoint', 'number', 1, latitude);\n validateArgType('GeoPoint', 'number', 2, longitude);\n if (!isFinite(latitude) || latitude < -90 || latitude > 90) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Latitude must be a number between -90 and 90, but was: ' + latitude\n );\n }\n if (!isFinite(longitude) || longitude < -180 || longitude > 180) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Longitude must be a number between -180 and 180, but was: ' + longitude\n );\n }\n\n this._lat = latitude;\n this._long = longitude;\n }\n\n /**\n * Returns the latitude of this geo point, a number between -90 and 90.\n */\n get latitude(): number {\n return this._lat;\n }\n\n /**\n * Returns the longitude of this geo point, a number between -180 and 180.\n */\n get longitude(): number {\n return this._long;\n }\n\n /**\n * Actually private to JS consumers of our API, so this function is prefixed\n * with an underscore.\n */\n public _equals(other: GeoPoint): boolean {\n return this._lat === other._lat && this._long === other._long;\n }\n\n /**\n * Actually private to JS consumers of our API, so this function is prefixed\n * with an underscore.\n */\n public _compareTo(other: GeoPoint): number {\n return (\n primitiveComparator(this._lat, other._lat) ||\n primitiveComparator(this._long, other._long)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/geo_point.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { primitiveComparator } from '../util/misc';\n\nexport class DatabaseInfo {\n /**\n * Constructs a DatabaseInfo using the provided host, databaseId and\n * persistenceKey.\n *\n * @param databaseId The database to use.\n * @param persistenceKey A unique identifier for this Firestore's local\n * storage (used in conjunction with the databaseId).\n * @param host The Firestore backend host to connect to.\n * @param ssl Whether to use SSL when connecting.\n */\n constructor(\n readonly databaseId: DatabaseId,\n readonly persistenceKey: string,\n readonly host: string,\n readonly ssl: boolean\n ) {}\n}\n\n/** The default database name for a project. */\nconst DEFAULT_DATABASE_NAME = '(default)';\n\n/** Represents the database ID a Firestore client is associated with. */\nexport class DatabaseId {\n readonly database: string;\n constructor(readonly projectId: string, database?: string) {\n this.database = database ? database : DEFAULT_DATABASE_NAME;\n }\n\n get isDefaultDatabase(): boolean {\n return this.database === DEFAULT_DATABASE_NAME;\n }\n\n equals(other: {}): boolean {\n return (\n other instanceof DatabaseId &&\n other.projectId === this.projectId &&\n other.database === this.database\n );\n }\n\n compareTo(other: DatabaseId): number {\n return (\n primitiveComparator(this.projectId, other.projectId) ||\n primitiveComparator(this.database, other.database)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/database_info.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert, fail } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\n\nexport const DOCUMENT_KEY_NAME = '__name__';\n\n/**\n * Path represents an ordered sequence of string segments.\n */\nexport abstract class Path {\n private segments: string[];\n private offset: number;\n private len: number;\n\n public constructor(segments: string[], offset?: number, length?: number) {\n this.init(segments, offset, length);\n }\n\n /**\n * An initialization method that can be called from outside the constructor.\n * We need this so that we can have a non-static construct method that returns\n * the polymorphic `this` type.\n */\n private init(segments: string[], offset?: number, length?: number) {\n if (offset === undefined) {\n offset = 0;\n } else if (offset > segments.length) {\n fail('offset ' + offset + ' out of range ' + segments.length);\n }\n\n if (length === undefined) {\n length = segments.length - offset;\n } else if (length > segments.length - offset) {\n fail('length ' + length + ' out of range ' + (segments.length - offset));\n }\n this.segments = segments;\n this.offset = offset;\n this.len = length;\n }\n\n /**\n * Constructs a new instance of Path using the same concrete type as `this`.\n * We need this instead of using the normal constructor, because polymorphic\n * `this` doesn't work on static methods.\n */\n private construct(\n segments: string[],\n offset?: number,\n length?: number\n ): this {\n const path: this = Object.create(Object.getPrototypeOf(this));\n path.init(segments, offset, length);\n return path;\n }\n\n get length(): number {\n return this.len;\n }\n\n equals(other: Path): boolean {\n return Path.comparator(this, other) === 0;\n }\n\n child(nameOrPath: string | this): this {\n const segments = this.segments.slice(this.offset, this.limit());\n if (nameOrPath instanceof Path) {\n nameOrPath.forEach(segment => {\n segments.push(segment);\n });\n } else if (typeof nameOrPath === 'string') {\n segments.push(nameOrPath);\n } else {\n fail('Unknown parameter type for Path.child(): ' + nameOrPath);\n }\n return this.construct(segments);\n }\n\n /** The index of one past the last segment of the path. */\n private limit(): number {\n return this.offset + this.length;\n }\n\n popFirst(size?: number): this {\n size = size === undefined ? 1 : size;\n assert(this.length >= size, \"Can't call popFirst() with less segments\");\n return this.construct(\n this.segments,\n this.offset + size,\n this.length - size\n );\n }\n\n popLast(): this {\n assert(!this.isEmpty(), \"Can't call popLast() on empty path\");\n return this.construct(this.segments, this.offset, this.length - 1);\n }\n\n firstSegment(): string {\n assert(!this.isEmpty(), \"Can't call firstSegment() on empty path\");\n return this.segments[this.offset];\n }\n\n lastSegment(): string {\n assert(!this.isEmpty(), \"Can't call lastSegment() on empty path\");\n return this.segments[this.limit() - 1];\n }\n\n get(index: number): string {\n assert(index < this.length, 'Index out of range');\n return this.segments[this.offset + index];\n }\n\n isEmpty(): boolean {\n return this.length === 0;\n }\n\n isPrefixOf(other: this): boolean {\n if (other.length < this.length) {\n return false;\n }\n\n for (let i = 0; i < this.length; i++) {\n if (this.get(i) !== other.get(i)) {\n return false;\n }\n }\n\n return true;\n }\n\n forEach(fn: (segment: string) => void): void {\n for (let i = this.offset, end = this.limit(); i < end; i++) {\n fn(this.segments[i]);\n }\n }\n\n toArray(): string[] {\n return this.segments.slice(this.offset, this.limit());\n }\n\n static comparator(p1: Path, p2: Path): number {\n const len = Math.min(p1.length, p2.length);\n for (let i = 0; i < len; i++) {\n const left = p1.get(i);\n const right = p2.get(i);\n if (left < right) return -1;\n if (left > right) return 1;\n }\n if (p1.length < p2.length) return -1;\n if (p1.length > p2.length) return 1;\n return 0;\n }\n}\n\n/**\n * A slash-separated path for navigating resources (documents and collections)\n * within Firestore.\n */\nexport class ResourcePath extends Path {\n canonicalString(): string {\n // NOTE: The client is ignorant of any path segments containing escape\n // sequences (e.g. __id123__) and just passes them through raw (they exist\n // for legacy reasons and should not be used frequently).\n\n return this.toArray().join('/');\n }\n\n toString(): string {\n return this.canonicalString();\n }\n\n /**\n * Creates a resource path from the given slash-delimited string.\n */\n static fromString(path: string): ResourcePath {\n // NOTE: The client is ignorant of any path segments containing escape\n // sequences (e.g. __id123__) and just passes them through raw (they exist\n // for legacy reasons and should not be used frequently).\n\n if (path.indexOf('//') >= 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid path (${path}). Paths must not contain // in them.`\n );\n }\n\n // We may still have an empty segment at the beginning or end if they had a\n // leading or trailing slash (which we allow).\n const segments = path.split('/').filter(segment => segment.length > 0);\n\n return new ResourcePath(segments);\n }\n\n static EMPTY_PATH = new ResourcePath([]);\n}\n\nconst identifierRegExp = /^[_a-zA-Z][_a-zA-Z0-9]*$/;\n\n/** A dot-separated path for navigating sub-objects within a document. */\nexport class FieldPath extends Path {\n /**\n * Returns true if the string could be used as a segment in a field path\n * without escaping.\n */\n private static isValidIdentifier(segment: string) {\n return identifierRegExp.test(segment);\n }\n\n canonicalString(): string {\n return this.toArray()\n .map(str => {\n str = str.replace('\\\\', '\\\\\\\\').replace('`', '\\\\`');\n if (!FieldPath.isValidIdentifier(str)) {\n str = '`' + str + '`';\n }\n return str;\n })\n .join('.');\n }\n\n toString(): string {\n return this.canonicalString();\n }\n\n /**\n * Returns true if this field references the key of a document.\n */\n isKeyField(): boolean {\n return this.length === 1 && this.get(0) === DOCUMENT_KEY_NAME;\n }\n\n /**\n * The field designating the key of a document.\n */\n static keyField(): FieldPath {\n return new FieldPath([DOCUMENT_KEY_NAME]);\n }\n\n /**\n * Parses a field string from the given server-formatted string.\n *\n * - Splitting the empty string is not allowed (for now at least).\n * - Empty segments within the string (e.g. if there are two consecutive\n * separators) are not allowed.\n *\n * TODO(b/37244157): we should make this more strict. Right now, it allows\n * non-identifier path components, even if they aren't escaped.\n */\n static fromServerFormat(path: string): FieldPath {\n const segments: string[] = [];\n let current = '';\n let i = 0;\n\n const addCurrentSegment = () => {\n if (current.length === 0) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n `Invalid field path (${path}). Paths must not be empty, begin ` +\n `with '.', end with '.', or contain '..'`\n );\n }\n segments.push(current);\n current = '';\n };\n\n let inBackticks = false;\n\n while (i < path.length) {\n const c = path[i];\n if (c === '\\\\') {\n if (i + 1 === path.length) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Path has trailing escape character: ' + path\n );\n }\n const next = path[i + 1];\n if (!(next === '\\\\' || next === '.' || next === '`')) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Path has invalid escape sequence: ' + path\n );\n }\n current += next;\n i += 2;\n } else if (c === '`') {\n inBackticks = !inBackticks;\n i++;\n } else if (c === '.' && !inBackticks) {\n addCurrentSegment();\n i++;\n } else {\n current += c;\n i++;\n }\n }\n addCurrentSegment();\n\n if (inBackticks) {\n throw new FirestoreError(\n Code.INVALID_ARGUMENT,\n 'Unterminated ` in path: ' + path\n );\n }\n\n return new FieldPath(segments);\n }\n\n static EMPTY_PATH = new FieldPath([]);\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/path.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from '../util/assert';\n\nimport { ResourcePath } from './path';\n\nexport class DocumentKey {\n constructor(readonly path: ResourcePath) {\n assert(\n DocumentKey.isDocumentKey(path),\n 'Invalid DocumentKey with an odd number of segments: ' +\n path.toArray().join('/')\n );\n }\n\n equals(other: DocumentKey | null): boolean {\n return (\n other !== null && ResourcePath.comparator(this.path, other.path) === 0\n );\n }\n\n toString(): string {\n return this.path.toString();\n }\n\n static EMPTY = new DocumentKey(new ResourcePath([]));\n\n static comparator(k1: DocumentKey, k2: DocumentKey): number {\n return ResourcePath.comparator(k1.path, k2.path);\n }\n\n static isDocumentKey(path: ResourcePath): boolean {\n return path.length % 2 === 0;\n }\n\n /**\n * Creates and returns a new document key with the given segments.\n *\n * @param path The segments of the path to the document\n * @return A new instance of DocumentKey\n */\n static fromSegments(segments: string[]): DocumentKey {\n return new DocumentKey(new ResourcePath(segments.slice()));\n }\n\n /**\n * Creates and returns a new document key using '/' to split the string into\n * segments.\n *\n * @param path The slash-separated path string to the document\n * @return A new instance of DocumentKey\n */\n static fromPathString(path: string): DocumentKey {\n return new DocumentKey(ResourcePath.fromString(path));\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/document_key.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { fail } from '../util/assert';\nimport { AnyJs } from '../util/misc';\n\nimport { DocumentKey } from './document_key';\nimport { FieldValue, JsonObject, ObjectValue } from './field_value';\nimport { FieldPath } from './path';\n\nexport interface DocumentOptions {\n hasLocalMutations: boolean;\n}\n\nexport class Document {\n readonly hasLocalMutations: boolean;\n\n constructor(\n readonly key: DocumentKey,\n readonly version: SnapshotVersion,\n readonly data: ObjectValue,\n options: DocumentOptions\n ) {\n this.hasLocalMutations = options.hasLocalMutations;\n }\n\n field(path: FieldPath): FieldValue {\n return this.data.field(path);\n }\n\n fieldValue(path: FieldPath): AnyJs {\n const field = this.field(path);\n return field ? field.value() : undefined;\n }\n\n value(): JsonObject {\n return this.data.value();\n }\n\n equals(other: Document | null | undefined): boolean {\n return (\n other instanceof Document &&\n this.key.equals(other.key) &&\n this.version.equals(other.version) &&\n this.data.equals(other.data) &&\n this.hasLocalMutations === other.hasLocalMutations\n );\n }\n\n toString(): string {\n return (\n `Document(${this.key}, ${this.version}, ${this.data.toString()}, ` +\n `{hasLocalMutations: ${this.hasLocalMutations}})`\n );\n }\n\n static compareByKey(d1: MaybeDocument, d2: MaybeDocument): number {\n return DocumentKey.comparator(d1.key, d2.key);\n }\n\n static compareByField(field: FieldPath, d1: Document, d2: Document): number {\n const v1 = d1.field(field);\n const v2 = d2.field(field);\n if (v1 !== undefined && v2 !== undefined) {\n return v1.compareTo(v2);\n } else {\n return fail(\"Trying to compare documents on fields that don't exist\");\n }\n }\n}\n\n/**\n * A class representing a deleted document.\n * Version is set to 0 if we don't point to any specific time, otherwise it\n * denotes time we know it didn't exist at.\n */\nexport class NoDocument {\n constructor(readonly key: DocumentKey, readonly version: SnapshotVersion) {}\n\n toString(): string {\n return `NoDocument(${this.key}, ${this.version})`;\n }\n\n public equals(other: NoDocument): boolean {\n return (\n other && other.version.equals(this.version) && other.key.equals(this.key)\n );\n }\n\n static compareByKey(d1: MaybeDocument, d2: MaybeDocument): number {\n return DocumentKey.comparator(d1.key, d2.key);\n }\n}\n\n/**\n * A union type representing either a full document or a deleted document.\n * The NoDocument is used when it doesn't exist on the server.\n */\nexport type MaybeDocument = Document | NoDocument;\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/document.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert, fail } from './assert';\nimport { AnyJs } from './misc';\n\n/*\n * Implementation of an immutable SortedMap using a Left-leaning\n * Red-Black Tree, adapted from the implementation in Mugs\n * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen\n * (mads379@gmail.com).\n *\n * Original paper on Left-leaning Red-Black Trees:\n * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf\n *\n * Invariant 1: No red node has a red child\n * Invariant 2: Every leaf path has the same number of black nodes\n * Invariant 3: Only the left child can be red (left leaning)\n */\n\nexport type Comparator = (key1: K, key2: K) => number;\n\nexport interface Entry {\n key: K;\n value: V;\n}\n\n// An immutable sorted map implementation, based on a Left-leaning Red-Black\n// tree.\nexport class SortedMap {\n // visible for testing\n root: LLRBNode | LLRBEmptyNode;\n\n constructor(public comparator: Comparator, root?: LLRBNode) {\n this.root = root ? root : LLRBNode.EMPTY;\n }\n\n // Returns a copy of the map, with the specified key/value added or replaced.\n insert(key: K, value: V): SortedMap {\n return new SortedMap(\n this.comparator,\n this.root\n .insert(key, value, this.comparator)\n .copy(null, null, LLRBNode.BLACK, null, null)\n );\n }\n\n // Returns a copy of the map, with the specified key removed.\n remove(key: K): SortedMap {\n return new SortedMap(\n this.comparator,\n this.root\n .remove(key, this.comparator)\n .copy(null, null, LLRBNode.BLACK, null, null)\n );\n }\n\n // Returns the value of the node with the given key, or null.\n get(key: K): V | null {\n let node = this.root;\n while (!node.isEmpty()) {\n const cmp = this.comparator(key, node.key);\n if (cmp === 0) {\n return node.value;\n } else if (cmp < 0) {\n node = node.left;\n } else if (cmp > 0) {\n node = node.right;\n }\n }\n return null;\n }\n\n // Returns the key of the item *before* the specified key, or null if key is\n // the first item.\n getPredecessorKey(key: K): K | null {\n let node = this.root;\n let rightParent: LLRBNode | LLRBEmptyNode | null = null;\n while (!node.isEmpty()) {\n const cmp = this.comparator(key, node.key);\n if (cmp === 0) {\n if (!node.left.isEmpty()) {\n node = node.left;\n while (!node.right.isEmpty()) node = node.right;\n return node.key;\n } else if (rightParent) {\n return rightParent.key;\n } else {\n return null; // first item.\n }\n } else if (cmp < 0) {\n node = node.left;\n } else if (cmp > 0) {\n rightParent = node;\n node = node.right;\n }\n }\n\n throw fail(\n 'Attempted to find predecessor key for a nonexistent key.' +\n ' What gives?'\n );\n }\n\n // Returns the index of the element in this sorted map, or -1 if it doesn't\n // exist.\n indexOf(key: K): number {\n // Number of nodes that were pruned when descending right\n let prunedNodes = 0;\n let node = this.root;\n while (!node.isEmpty()) {\n const cmp = this.comparator(key, node.key);\n if (cmp === 0) {\n return prunedNodes + node.left.size;\n } else if (cmp < 0) {\n node = node.left;\n } else {\n // Count all nodes left of the node plus the node itself\n prunedNodes += node.left.size + 1;\n node = node.right;\n }\n }\n // Node not found\n return -1;\n }\n\n isEmpty(): boolean {\n return this.root.isEmpty();\n }\n\n // Returns the total number of nodes in the map.\n get size(): number {\n return this.root.size;\n }\n\n // Returns the minimum key in the map.\n minKey(): K | null {\n return this.root.minKey();\n }\n\n // Returns the maximum key in the map.\n maxKey(): K | null {\n return this.root.maxKey();\n }\n\n // Traverses the map in key order and calls the specified action function\n // for each key/value pair. If action returns true, traversal is aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n inorderTraversal(action: (k: K, v: V) => T): T {\n return (this.root as LLRBNode).inorderTraversal(action);\n }\n\n forEach(fn: (k: K, v: V) => void) {\n this.inorderTraversal((k, v) => {\n fn(k, v);\n return false;\n });\n }\n\n // Traverses the map in reverse key order and calls the specified action\n // function for each key/value pair. If action returns true, traversal is\n // aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n reverseTraversal(action: (k: K, v: V) => T): T {\n return (this.root as LLRBNode).reverseTraversal(action);\n }\n\n // Returns an iterator over the SortedMap.\n getIterator(): SortedMapIterator>;\n getIterator(\n resultGenerator: (k: K, v: V) => T\n ): SortedMapIterator;\n getIterator(\n resultGenerator?: (k: K, v: V) => T\n ): SortedMapIterator {\n return new SortedMapIterator(\n this.root,\n null,\n this.comparator,\n false,\n resultGenerator\n );\n }\n\n getIteratorFrom(key: K): SortedMapIterator>;\n getIteratorFrom(\n key: K,\n resultGenerator: (k: K, v: V) => T\n ): SortedMapIterator;\n getIteratorFrom(\n key: K,\n resultGenerator?: (k: K, v: V) => T\n ): SortedMapIterator {\n return new SortedMapIterator(\n this.root,\n key,\n this.comparator,\n false,\n resultGenerator\n );\n }\n\n getReverseIterator(): SortedMapIterator>;\n getReverseIterator(\n resultGenerator: (k: K, v: V) => T\n ): SortedMapIterator;\n getReverseIterator(\n resultGenerator?: (k: K, v: V) => T\n ): SortedMapIterator {\n return new SortedMapIterator(\n this.root,\n null,\n this.comparator,\n true,\n resultGenerator\n );\n }\n\n getReverseIteratorFrom(key: K): SortedMapIterator>;\n getReverseIteratorFrom(\n key: K,\n resultGenerator: (k: K, v: V) => T\n ): SortedMapIterator;\n getReverseIteratorFrom(\n key: K,\n resultGenerator?: (k: K, v: V) => T\n ): SortedMapIterator {\n return new SortedMapIterator(\n this.root,\n key,\n this.comparator,\n true,\n resultGenerator\n );\n }\n} // end SortedMap\n\n// An iterator over an LLRBNode.\nexport class SortedMapIterator {\n private resultGenerator: ((k: K, v: V) => T) | null;\n private isReverse: boolean;\n private nodeStack: Array | LLRBEmptyNode>;\n\n constructor(\n node: LLRBNode | LLRBEmptyNode,\n startKey: K | null,\n comparator: Comparator,\n isReverse: boolean,\n resultGenerator?: (k: K, v: V) => T\n ) {\n this.resultGenerator = resultGenerator || null;\n this.isReverse = isReverse;\n this.nodeStack = [];\n\n let cmp = 1;\n while (!node.isEmpty()) {\n cmp = startKey ? comparator(node.key, startKey) : 1;\n // flip the comparison if we're going in reverse\n if (isReverse) cmp *= -1;\n\n if (cmp < 0) {\n // This node is less than our start key. ignore it\n if (this.isReverse) {\n node = node.left;\n } else {\n node = node.right;\n }\n } else if (cmp === 0) {\n // This node is exactly equal to our start key. Push it on the stack,\n // but stop iterating;\n this.nodeStack.push(node);\n break;\n } else {\n // This node is greater than our start key, add it to the stack and move\n // to the next one\n this.nodeStack.push(node);\n if (this.isReverse) {\n node = node.right;\n } else {\n node = node.left;\n }\n }\n }\n }\n\n getNext(): T {\n assert(\n this.nodeStack.length > 0,\n 'getNext() called on iterator when hasNext() is false.'\n );\n\n let node = this.nodeStack.pop()!;\n let result: any;\n if (this.resultGenerator)\n result = this.resultGenerator(node.key, node.value);\n else result = { key: node.key, value: node.value };\n\n if (this.isReverse) {\n node = node.left;\n while (!node.isEmpty()) {\n this.nodeStack.push(node);\n node = node.right;\n }\n } else {\n node = node.right;\n while (!node.isEmpty()) {\n this.nodeStack.push(node);\n node = node.left;\n }\n }\n\n return result;\n }\n\n hasNext(): boolean {\n return this.nodeStack.length > 0;\n }\n\n peek(): any {\n if (this.nodeStack.length === 0) return null;\n\n const node = this.nodeStack[this.nodeStack.length - 1];\n if (this.resultGenerator) {\n return this.resultGenerator(node.key, node.value);\n } else {\n return { key: node.key, value: node.value };\n }\n }\n} // end SortedMapIterator\n\n// Represents a node in a Left-leaning Red-Black tree.\nexport class LLRBNode {\n readonly color: boolean;\n readonly left: LLRBNode | LLRBEmptyNode;\n readonly right: LLRBNode | LLRBEmptyNode;\n readonly size: number;\n\n static EMPTY: LLRBEmptyNode = null as any;\n\n static RED = true;\n static BLACK = false;\n\n constructor(\n public key: K,\n public value: V,\n color?: boolean,\n left?: LLRBNode | LLRBEmptyNode,\n right?: LLRBNode | LLRBEmptyNode\n ) {\n this.color = color != null ? color : LLRBNode.RED;\n this.left = left != null ? left : LLRBNode.EMPTY;\n this.right = right != null ? right : LLRBNode.EMPTY;\n this.size = this.left.size + 1 + this.right.size;\n }\n\n // Returns a copy of the current node, optionally replacing pieces of it.\n copy(\n key: K | null,\n value: V | null,\n color: boolean | null,\n left: LLRBNode | LLRBEmptyNode | null,\n right: LLRBNode | LLRBEmptyNode | null\n ): any {\n return new LLRBNode(\n key != null ? key : this.key,\n value != null ? value : this.value,\n color != null ? color : this.color,\n left != null ? left : this.left,\n right != null ? right : this.right\n );\n }\n\n isEmpty(): boolean {\n return false;\n }\n\n // Traverses the tree in key order and calls the specified action function\n // for each node. If action returns true, traversal is aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n inorderTraversal(action: (k: K, v: V) => T): T {\n return (\n (this.left as LLRBNode).inorderTraversal(action) ||\n action(this.key, this.value) ||\n (this.right as LLRBNode).inorderTraversal(action)\n );\n }\n\n // Traverses the tree in reverse key order and calls the specified action\n // function for each node. If action returns true, traversal is aborted.\n // Returns the first truthy value returned by action, or the last falsey\n // value returned by action.\n reverseTraversal(action: (k: K, v: V) => T): T {\n return (\n (this.right as LLRBNode).reverseTraversal(action) ||\n action(this.key, this.value) ||\n (this.left as LLRBNode).reverseTraversal(action)\n );\n }\n\n // Returns the minimum node in the tree.\n private min(): LLRBNode {\n if (this.left.isEmpty()) {\n return this;\n } else {\n return (this.left as LLRBNode).min();\n }\n }\n\n // Returns the maximum key in the tree.\n minKey(): K | null {\n return this.min().key;\n }\n\n // Returns the maximum key in the tree.\n maxKey(): K | null {\n if (this.right.isEmpty()) {\n return this.key;\n } else {\n return this.right.maxKey();\n }\n }\n\n // Returns new tree, with the key/value added.\n insert(key: K, value: V, comparator: Comparator): LLRBNode {\n let n = this;\n const cmp = comparator(key, n.key);\n if (cmp < 0) {\n n = n.copy(null, null, null, n.left.insert(key, value, comparator), null);\n } else if (cmp === 0) {\n n = n.copy(null, value, null, null, null);\n } else {\n n = n.copy(\n null,\n null,\n null,\n null,\n n.right.insert(key, value, comparator)\n );\n }\n return n.fixUp();\n }\n\n private removeMin(): LLRBNode | LLRBEmptyNode {\n if (this.left.isEmpty()) {\n return LLRBNode.EMPTY;\n }\n let n: LLRBNode = this;\n if (!n.left.isRed() && !n.left.left.isRed()) n = n.moveRedLeft();\n n = n.copy(null, null, null, (n.left as LLRBNode).removeMin(), null);\n return n.fixUp();\n }\n\n // Returns new tree, with the specified item removed.\n remove(\n key: K,\n comparator: Comparator\n ): LLRBNode | LLRBEmptyNode {\n let smallest: LLRBNode;\n let n: LLRBNode = this;\n if (comparator(key, n.key) < 0) {\n if (!n.left.isEmpty() && !n.left.isRed() && !n.left.left.isRed()) {\n n = n.moveRedLeft();\n }\n n = n.copy(null, null, null, n.left.remove(key, comparator), null);\n } else {\n if (n.left.isRed()) n = n.rotateRight();\n if (!n.right.isEmpty() && !n.right.isRed() && !n.right.left.isRed()) {\n n = n.moveRedRight();\n }\n if (comparator(key, n.key) === 0) {\n if (n.right.isEmpty()) {\n return LLRBNode.EMPTY;\n } else {\n smallest = (n.right as LLRBNode).min();\n n = n.copy(\n smallest.key,\n smallest.value,\n null,\n null,\n (n.right as LLRBNode).removeMin()\n );\n }\n }\n n = n.copy(null, null, null, null, n.right.remove(key, comparator));\n }\n return n.fixUp();\n }\n\n isRed(): boolean {\n return this.color;\n }\n\n // Returns new tree after performing any needed rotations.\n private fixUp(): LLRBNode {\n let n: LLRBNode = this;\n if (n.right.isRed() && !n.left.isRed()) n = n.rotateLeft();\n if (n.left.isRed() && n.left.left.isRed()) n = n.rotateRight();\n if (n.left.isRed() && n.right.isRed()) n = n.colorFlip();\n return n;\n }\n\n private moveRedLeft(): LLRBNode {\n let n = this.colorFlip();\n if (n.right.left.isRed()) {\n n = n.copy(\n null,\n null,\n null,\n null,\n (n.right as LLRBNode).rotateRight()\n );\n n = n.rotateLeft();\n n = n.colorFlip();\n }\n return n;\n }\n\n private moveRedRight(): LLRBNode {\n let n = this.colorFlip();\n if (n.left.left.isRed()) {\n n = n.rotateRight();\n n = n.colorFlip();\n }\n return n;\n }\n\n private rotateLeft(): LLRBNode {\n const nl = this.copy(null, null, LLRBNode.RED, null, this.right.left);\n return this.right.copy(null, null, this.color, nl, null);\n }\n\n private rotateRight(): LLRBNode {\n const nr = this.copy(null, null, LLRBNode.RED, this.left.right, null);\n return this.left.copy(null, null, this.color, null, nr);\n }\n\n private colorFlip(): LLRBNode {\n const left = this.left.copy(null, null, !this.left.color, null, null);\n const right = this.right.copy(null, null, !this.right.color, null, null);\n return this.copy(null, null, !this.color, left, right);\n }\n\n // For testing.\n checkMaxDepth(): boolean {\n const blackDepth = this.check();\n if (Math.pow(2.0, blackDepth) <= this.size + 1) {\n return true;\n } else {\n return false;\n }\n }\n\n // In a balanced RB tree, the black-depth (number of black nodes) from root to\n // leaves is equal on both sides. This function verifies that or asserts.\n private check(): number {\n if (this.isRed() && this.left.isRed()) {\n throw fail('Red node has red child(' + this.key + ',' + this.value + ')');\n }\n if (this.right.isRed()) {\n throw fail('Right child of (' + this.key + ',' + this.value + ') is red');\n }\n const blackDepth = (this.left as LLRBNode).check();\n if (blackDepth !== (this.right as LLRBNode).check()) {\n throw fail('Black depths differ');\n } else {\n return blackDepth + (this.isRed() ? 0 : 1);\n }\n }\n} // end LLRBNode\n\n// Represents an empty node (a leaf node in the Red-Black Tree).\nexport class LLRBEmptyNode {\n key: K;\n value: V;\n color: boolean;\n left: LLRBNode;\n right: LLRBNode;\n size = 0;\n\n constructor() {}\n\n // Returns a copy of the current node.\n copy(\n key: K | null,\n value: V | null,\n color: boolean | null,\n left: LLRBNode | LLRBEmptyNode | null,\n right: LLRBNode | LLRBEmptyNode | null\n ): LLRBEmptyNode {\n return this;\n }\n\n // Returns a copy of the tree, with the specified key/value added.\n insert(key: K, value: V, comparator: Comparator): LLRBNode {\n return new LLRBNode(key, value);\n }\n\n // Returns a copy of the tree, with the specified key removed.\n remove(key: K, comparator: Comparator): LLRBEmptyNode {\n return this;\n }\n\n isEmpty(): boolean {\n return true;\n }\n\n inorderTraversal(action: (k: K, v: V) => boolean): boolean {\n return false;\n }\n\n reverseTraversal(action: (k: K, v: V) => boolean): boolean {\n return false;\n }\n\n minKey(): K | null {\n return null;\n }\n\n maxKey(): K | null {\n return null;\n }\n\n isRed(): boolean {\n return false;\n }\n\n // For testing.\n checkMaxDepth(): boolean {\n return true;\n }\n\n private check() {\n return 0;\n }\n} // end LLRBEmptyNode\n\nLLRBNode.EMPTY = new LLRBEmptyNode();\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/sorted_map.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { ProtoByteString, TargetId } from '../core/types';\nimport { emptyByteString } from '../platform/platform';\n\n/** An enumeration of the different purposes we have for queries. */\nexport enum QueryPurpose {\n /** A regular, normal query. */\n Listen,\n\n /**\n * The query was used to refill a query after an existence filter mismatch.\n */\n ExistenceFilterMismatch,\n\n /** The query was used to resolve a limbo document. */\n LimboResolution\n}\n\n/**\n * An immutable set of metadata that the local store tracks for each query.\n */\nexport class QueryData {\n constructor(\n /** The query being listened to. */\n public query: Query,\n /**\n * The target ID to which the query corresponds; Assigned by the\n * LocalStore for user listens and by the SyncEngine for limbo watches.\n */\n public targetId: TargetId,\n /** The purpose of the query. */\n public purpose: QueryPurpose,\n /** The latest snapshot version seen for this target. */\n public snapshotVersion: SnapshotVersion = SnapshotVersion.MIN,\n /**\n * An opaque, server-assigned token that allows watching a query to be\n * resumed after disconnecting without retransmitting all the data that\n * matches the query. The resume token essentially identifies a point in\n * time from which the server should resume sending results.\n */\n public resumeToken: ProtoByteString = emptyByteString()\n ) {}\n\n /**\n * Creates a new query data instance with an updated snapshot version and\n * resume token.\n */\n update(updated: {\n resumeToken: ProtoByteString;\n snapshotVersion: SnapshotVersion;\n }): QueryData {\n return new QueryData(\n this.query,\n this.targetId,\n this.purpose,\n updated.snapshotVersion,\n updated.resumeToken\n );\n }\n\n equals(other: QueryData): boolean {\n return (\n this.targetId === other.targetId &&\n this.purpose === other.purpose &&\n this.snapshotVersion.equals(other.snapshotVersion) &&\n this.resumeToken === other.resumeToken &&\n this.query.equals(other.query)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/query_data.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from '../util/assert';\nimport { primitiveComparator } from '../util/misc';\n\n// A RegExp matching ISO 8601 UTC timestamps with optional fraction.\nconst isoRegExp = new RegExp(/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.(\\d+))?Z$/);\n\nexport class Timestamp {\n static now(): Timestamp {\n return Timestamp.fromEpochMilliseconds(Date.now());\n }\n\n static fromDate(date: Date): Timestamp {\n return Timestamp.fromEpochMilliseconds(date.getTime());\n }\n\n static fromEpochMilliseconds(milliseconds: number): Timestamp {\n const seconds = Math.floor(milliseconds / 1000);\n const nanos = (milliseconds - seconds * 1000) * 1e6;\n return new Timestamp(seconds, nanos);\n }\n\n static fromISOString(utc: string): Timestamp {\n // The date string can have higher precision (nanos) than the Date class\n // (millis), so we do some custom parsing here.\n\n // Parse the nanos right out of the string.\n let nanos = 0;\n const fraction = isoRegExp.exec(utc);\n assert(!!fraction, 'invalid timestamp: ' + utc);\n if (fraction![1]) {\n // Pad the fraction out to 9 digits (nanos).\n let nanoStr = fraction![1];\n nanoStr = (nanoStr + '000000000').substr(0, 9);\n nanos = parseInt(nanoStr, 10);\n }\n\n // Parse the date to get the seconds.\n const date = new Date(utc);\n const seconds = Math.floor(date.getTime() / 1000);\n\n return new Timestamp(seconds, nanos);\n }\n\n constructor(readonly seconds: number, readonly nanos: number) {\n assert(nanos >= 0, 'timestamp nanoseconds out of range: ' + nanos);\n assert(nanos < 1e9, 'timestamp nanoseconds out of range' + nanos);\n // Midnight at the beginning of 1/1/1 is the earliest Firestore supports.\n assert(\n seconds >= -62135596800,\n 'timestamp seconds out of range: ' + seconds\n );\n // This will break in the year 10,000.\n assert(seconds < 253402300800, 'timestamp seconds out of range' + seconds);\n }\n\n toDate(): Date {\n return new Date(this.toEpochMilliseconds());\n }\n\n toEpochMilliseconds(): number {\n return this.seconds * 1000 + this.nanos / 1e6;\n }\n\n compareTo(other: Timestamp): number {\n if (this.seconds === other.seconds) {\n return primitiveComparator(this.nanos, other.nanos);\n }\n return primitiveComparator(this.seconds, other.seconds);\n }\n\n equals(other: Timestamp): boolean {\n return other.seconds === this.seconds && other.nanos === this.nanos;\n }\n\n toString(): string {\n return 'Timestamp(seconds=' + this.seconds + ', nanos=' + this.nanos + ')';\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/timestamp.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Timestamp } from './timestamp';\n\n/**\n * A version of a document in Firestore. This corresponds to the version\n * timestamp, such as update_time or read_time.\n */\nexport class SnapshotVersion {\n static readonly MIN = new SnapshotVersion(new Timestamp(0, 0));\n\n // TODO(b/34176344): Once we no longer need to use the old alpha protos,\n // delete this constructor and use a timestamp-backed version everywhere.\n static fromMicroseconds(value: number): SnapshotVersion {\n const seconds = Math.floor(value / 1e6);\n const nanos = (value % 1e6) * 1e3;\n return new SnapshotVersion(new Timestamp(seconds, nanos));\n }\n\n static fromTimestamp(value: Timestamp): SnapshotVersion {\n return new SnapshotVersion(value);\n }\n\n static forDeletedDoc(): SnapshotVersion {\n return SnapshotVersion.MIN;\n }\n\n private constructor(private timestamp: Timestamp) {}\n\n compareTo(other: SnapshotVersion): number {\n return this.timestamp.compareTo(other.timestamp);\n }\n\n equals(other: SnapshotVersion): boolean {\n return this.timestamp.equals(other.timestamp);\n }\n\n /** Returns a number representation of the version for use in spec tests. */\n toMicroseconds(): number {\n // Convert to microseconds.\n return this.timestamp.seconds * 1e6 + this.timestamp.nanos / 1000;\n }\n\n toString(): string {\n return 'SnapshotVersion(' + this.timestamp.toString() + ')';\n }\n\n toTimestamp(): Timestamp {\n return this.timestamp;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/snapshot_version.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { Timestamp } from '../core/timestamp';\nimport { assert, fail } from '../util/assert';\nimport * as misc from '../util/misc';\n\nimport { Document, MaybeDocument, NoDocument } from './document';\nimport { DocumentKey } from './document_key';\nimport { FieldValue, ObjectValue, ServerTimestampValue } from './field_value';\nimport { FieldPath } from './path';\n\n/**\n * Provides a set of fields that can be used to partially patch a document.\n * FieldMask is used in conjunction with ObjectValue.\n * Examples:\n * foo - Overwrites foo entirely with the provided value. If foo is not\n * present in the companion ObjectValue, the field is deleted.\n * foo.bar - Overwrites only the field bar of the object foo.\n * If foo is not an object, foo is replaced with an object\n * containing foo\n */\nexport class FieldMask {\n constructor(readonly fields: FieldPath[]) {\n // TODO(dimond): validation of FieldMask\n }\n\n equals(other: FieldMask): boolean {\n return misc.arrayEquals(this.fields, other.fields);\n }\n}\n\n/** Represents a transform within a TransformMutation. */\nexport interface TransformOperation {\n equals(other: TransformOperation): boolean;\n}\n\n/** Transforms a value into a server-generated timestamp. */\nexport class ServerTimestampTransform implements TransformOperation {\n private constructor() {}\n static instance = new ServerTimestampTransform();\n\n equals(other: TransformOperation): boolean {\n return other instanceof ServerTimestampTransform;\n }\n}\n\n/** A field path and the TransformOperation to perform upon it. */\nexport class FieldTransform {\n constructor(\n readonly field: FieldPath,\n readonly transform: TransformOperation\n ) {}\n\n equals(other: FieldTransform): boolean {\n return (\n this.field.equals(other.field) && this.transform.equals(other.transform)\n );\n }\n}\n\n/** The result of successfully applying a mutation to the backend. */\nexport class MutationResult {\n constructor(\n /**\n * The version at which the mutation was committed or null for a delete.\n */\n readonly version: SnapshotVersion | null,\n /**\n * The resulting fields returned from the backend after a\n * TransformMutation has been committed. Contains one FieldValue for each\n * FieldTransform that was in the mutation.\n *\n * Will be null if the mutation was not a TransformMutation.\n */\n readonly transformResults: FieldValue[] | null\n ) {}\n}\n\nexport enum MutationType {\n Set,\n Patch,\n Transform,\n Delete\n}\n\n/**\n * Encodes a precondition for a mutation. This follows the model that the\n * backend accepts with the special case of an explicit \"empty\" precondition\n * (meaning no precondition).\n */\nexport class Precondition {\n static readonly NONE = new Precondition();\n\n private constructor(\n public readonly updateTime?: SnapshotVersion,\n public readonly exists?: boolean\n ) {\n assert(\n updateTime === undefined || exists === undefined,\n 'Precondition can specify \"exists\" or \"updateTime\" but not both'\n );\n }\n\n /** Creates a new Precondition with an exists flag. */\n static exists(exists: boolean) {\n return new Precondition(undefined, exists);\n }\n\n /** Creates a new Precondition based on a version a document exists at. */\n static updateTime(version: SnapshotVersion) {\n return new Precondition(version);\n }\n\n /** Returns whether this Precondition is empty. */\n get isNone(): boolean {\n return this.updateTime === undefined && this.exists === undefined;\n }\n\n /**\n * Returns true if the preconditions is valid for the given document\n * (or null if no document is available).\n */\n isValidFor(maybeDoc: MaybeDocument | null) {\n if (this.updateTime !== undefined) {\n return (\n maybeDoc instanceof Document && maybeDoc.version.equals(this.updateTime)\n );\n } else if (this.exists !== undefined) {\n if (this.exists) {\n return maybeDoc instanceof Document;\n } else {\n return maybeDoc === null || maybeDoc instanceof NoDocument;\n }\n } else {\n assert(this.isNone, 'Precondition should be empty');\n return true;\n }\n }\n\n equals(other: Precondition) {\n return (\n misc.equals(this.updateTime, other.updateTime) &&\n this.exists === other.exists\n );\n }\n}\n\n/**\n * A mutation describes a self-contained change to a document. Mutations can\n * create, replace, delete, and update subsets of documents.\n *\n * Mutations not only act on the value of the document but also it version.\n * In the case of Set, Patch, and Transform mutations we preserve the existing\n * version. In the case of Delete mutations, we reset the version to 0.\n *\n * Here's the expected transition table.\n *\n * MUTATION APPLIED TO RESULTS IN\n *\n * SetMutation Document(v3) Document(v3)\n * SetMutation NoDocument(v3) Document(v0)\n * SetMutation null Document(v0)\n * PatchMutation Document(v3) Document(v3)\n * PatchMutation NoDocument(v3) NoDocument(v3)\n * PatchMutation null null\n * TransformMutation Document(v3) Document(v3)\n * TransformMutation NoDocument(v3) NoDocument(v3)\n * TransformMutation null null\n * DeleteMutation Document(v3) NoDocument(v0)\n * DeleteMutation NoDocument(v3) NoDocument(v0)\n * DeleteMutation null NoDocument(v0)\n *\n * Note that TransformMutations don't create Documents (in the case of being\n * applied to a NoDocument), even though they would on the backend. This is\n * because the client always combines the TransformMutation with a SetMutation\n * or PatchMutation and we only want to apply the transform if the prior\n * mutation resulted in a Document (always true for a SetMutation, but not\n * necessarily for a PatchMutation).\n *\n * ## Subclassing Notes\n *\n * Subclasses of Mutation need to implement applyToRemoteDocument() and\n * applyToLocalView() to implement the actual behavior of applying the mutation\n * to some source document.\n */\nexport abstract class Mutation {\n readonly type: MutationType;\n readonly key: DocumentKey;\n readonly precondition: Precondition;\n\n /**\n * Applies this mutation to the given MaybeDocument or null for the purposes\n * of computing a new remote document. Both the input and returned documents\n * can be null.\n *\n * @param maybeDoc The document to mutate. The input document can be null if\n * the client has no knowledge of the pre-mutation state of the document.\n * @param mutationResult The result of applying the mutation from the backend.\n * @return The mutated document. The returned document may be null, but only\n * if maybeDoc was null and the mutation would not create a new document.\n */\n abstract applyToRemoteDocument(\n maybeDoc: MaybeDocument | null,\n mutationResult: MutationResult\n ): MaybeDocument | null;\n\n /**\n * Applies this mutation to the given MaybeDocument or null for the purposes\n * of computing the new local view of a document. Both the input and returned\n * documents can be null.\n *\n * @param maybeDoc The document to mutate. The input document can be null if\n * the client has no knowledge of the pre-mutation state of the document.\n * @param localWriteTime A timestamp indicating the local write time of the\n * batch this mutation is a part of.\n * @return The mutated document. The returned document may be null, but only\n * if maybeDoc was null and the mutation would not create a new document.\n */\n abstract applyToLocalView(\n maybeDoc: MaybeDocument | null,\n localWriteTime: Timestamp\n ): MaybeDocument | null;\n\n abstract equals(other: Mutation): boolean;\n\n protected verifyKeyMatches(maybeDoc: MaybeDocument | null): void {\n if (maybeDoc != null) {\n assert(\n maybeDoc.key.equals(this.key),\n 'Can only apply a mutation to a document with the same key'\n );\n }\n }\n\n /**\n * Returns the version from the given document for use as the result of a\n * mutation. Mutations are defined to return the version of the base document\n * only if it is an existing document. Deleted and unknown documents have a\n * post-mutation version of SnapshotVersion.MIN.\n */\n protected static getPostMutationVersion(\n maybeDoc: MaybeDocument | null\n ): SnapshotVersion {\n if (maybeDoc instanceof Document) {\n return maybeDoc.version;\n } else {\n return SnapshotVersion.MIN;\n }\n }\n}\n\n/**\n * A mutation that creates or replaces the document at the given key with the\n * object value contents.\n */\nexport class SetMutation extends Mutation {\n constructor(\n readonly key: DocumentKey,\n readonly value: ObjectValue,\n readonly precondition: Precondition\n ) {\n super();\n }\n\n readonly type: MutationType = MutationType.Set;\n\n applyToRemoteDocument(\n maybeDoc: MaybeDocument | null,\n mutationResult: MutationResult\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n assert(\n mutationResult.transformResults == null,\n 'Transform results received by SetMutation.'\n );\n\n // Unlike applyToLocalView, if we're applying a mutation to a remote\n // document the server has accepted the mutation so the precondition must\n // have held.\n\n const version = Mutation.getPostMutationVersion(maybeDoc);\n return new Document(this.key, version, this.value, {\n hasLocalMutations: false\n });\n }\n\n applyToLocalView(\n maybeDoc: MaybeDocument | null,\n localWriteTime: Timestamp\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n\n const version = Mutation.getPostMutationVersion(maybeDoc);\n return new Document(this.key, version, this.value, {\n hasLocalMutations: true\n });\n }\n\n equals(other: Mutation): boolean {\n return (\n other instanceof SetMutation &&\n this.key.equals(other.key) &&\n this.value.equals(other.value) &&\n this.precondition.equals(other.precondition)\n );\n }\n}\n\n/**\n * A mutation that modifies fields of the document at the given key with the\n * given values. The values are applied through a field mask:\n *\n * * When a field is in both the mask and the values, the corresponding field\n * is updated.\n * * When a field is in neither the mask nor the values, the corresponding\n * field is unmodified.\n * * When a field is in the mask but not in the values, the corresponding field\n * is deleted.\n * * When a field is not in the mask but is in the values, the values map is\n * ignored.\n */\nexport class PatchMutation extends Mutation {\n constructor(\n readonly key: DocumentKey,\n readonly data: ObjectValue,\n readonly fieldMask: FieldMask,\n readonly precondition: Precondition\n ) {\n super();\n }\n\n readonly type: MutationType = MutationType.Patch;\n\n applyToRemoteDocument(\n maybeDoc: MaybeDocument | null,\n mutationResult: MutationResult\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n assert(\n mutationResult.transformResults == null,\n 'Transform results received by PatchMutation.'\n );\n\n // TODO(mcg): Relax enforcement of this precondition\n //\n // We shouldn't actually enforce the precondition since it already passed on\n // the backend, but we may not have a local version of the document to\n // patch, so we use the precondition to prevent incorrectly putting a\n // partial document into our cache.\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n\n const version = Mutation.getPostMutationVersion(maybeDoc);\n const newData = this.patchDocument(maybeDoc);\n return new Document(this.key, version, newData, {\n hasLocalMutations: false\n });\n }\n\n applyToLocalView(\n maybeDoc: MaybeDocument | null,\n localWriteTime: Timestamp\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n\n const version = Mutation.getPostMutationVersion(maybeDoc);\n const newData = this.patchDocument(maybeDoc);\n return new Document(this.key, version, newData, {\n hasLocalMutations: true\n });\n }\n\n equals(other: Mutation): boolean {\n return (\n other instanceof PatchMutation &&\n this.key.equals(other.key) &&\n this.fieldMask.equals(other.fieldMask) &&\n this.precondition.equals(other.precondition)\n );\n }\n\n /**\n * Patches the data of document if available or creates a new document. Note\n * that this does not check whether or not the precondition of this patch\n * holds.\n */\n private patchDocument(maybeDoc: MaybeDocument | null): ObjectValue {\n let data: ObjectValue;\n if (maybeDoc instanceof Document) {\n data = maybeDoc.data;\n } else {\n data = ObjectValue.EMPTY;\n }\n return this.patchObject(data);\n }\n\n private patchObject(data: ObjectValue): ObjectValue {\n for (const fieldPath of this.fieldMask.fields) {\n const newValue = this.data.field(fieldPath);\n if (newValue !== undefined) {\n data = data.set(fieldPath, newValue);\n } else {\n data = data.delete(fieldPath);\n }\n }\n return data;\n }\n}\n\n/**\n * A mutation that modifies specific fields of the document with transform\n * operations. Currently the only supported transform is a server timestamp, but\n * IP Address, increment(n), etc. could be supported in the future.\n *\n * It is somewhat similar to a PatchMutation in that it patches specific fields\n * and has no effect when applied to a null or NoDocument (see comment on\n * Mutation for rationale).\n */\nexport class TransformMutation extends Mutation {\n readonly type: MutationType = MutationType.Transform;\n\n // NOTE: We set a precondition of exists: true as a safety-check, since we\n // always combine TransformMutations with a SetMutation or PatchMutation which\n // (if successful) should end up with an existing document.\n readonly precondition = Precondition.exists(true);\n\n constructor(\n readonly key: DocumentKey,\n readonly fieldTransforms: FieldTransform[]\n ) {\n super();\n }\n\n applyToRemoteDocument(\n maybeDoc: MaybeDocument | null,\n mutationResult: MutationResult\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n assert(\n mutationResult.transformResults != null,\n 'Transform results missing for TransformMutation.'\n );\n const transformResults = mutationResult.transformResults!;\n\n // TODO(mcg): Relax enforcement of this precondition\n //\n // We shouldn't actually enforce the precondition since it already passed on\n // the backend, but we may not have a local version of the document to\n // patch, so we use the precondition to prevent incorrectly putting a\n // partial document into our cache.\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n\n const doc = this.requireDocument(maybeDoc);\n const newData = this.transformObject(doc.data, transformResults);\n return new Document(this.key, doc.version, newData, {\n hasLocalMutations: false\n });\n }\n\n applyToLocalView(\n maybeDoc: MaybeDocument | null,\n localWriteTime: Timestamp\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n\n const doc = this.requireDocument(maybeDoc);\n const transformResults = this.localTransformResults(localWriteTime);\n const newData = this.transformObject(doc.data, transformResults);\n return new Document(this.key, doc.version, newData, {\n hasLocalMutations: true\n });\n }\n\n equals(other: Mutation): boolean {\n return (\n other instanceof TransformMutation &&\n this.key.equals(other.key) &&\n misc.arrayEquals(this.fieldTransforms, other.fieldTransforms) &&\n this.precondition.equals(other.precondition)\n );\n }\n\n /**\n * Asserts that the given MaybeDocument is actually a Document and verifies\n * that it matches the key for this mutation. Since we only support\n * transformations with precondition exists this method is guaranteed to be\n * safe.\n */\n private requireDocument(maybeDoc: MaybeDocument | null): Document {\n assert(\n maybeDoc instanceof Document,\n 'Unknown MaybeDocument type ' + maybeDoc\n );\n const doc = maybeDoc! as Document;\n assert(\n doc.key.equals(this.key),\n 'Can only transform a document with the same key'\n );\n return doc;\n }\n\n /**\n * Creates a list of \"transform results\" (a transform result is a field value\n * representing the result of applying a transform) for use when applying a\n * TransformMutation locally.\n *\n * @param localWriteTime The local time of the transform mutation (used to\n * generate ServerTimestampValues).\n * @return The transform results list.\n */\n private localTransformResults(localWriteTime: Timestamp): FieldValue[] {\n const transformResults = [] as FieldValue[];\n for (const fieldTransform of this.fieldTransforms) {\n const transform = fieldTransform.transform;\n if (transform instanceof ServerTimestampTransform) {\n transformResults.push(new ServerTimestampValue(localWriteTime));\n } else {\n return fail('Encountered unknown transform: ' + transform);\n }\n }\n return transformResults;\n }\n\n private transformObject(\n data: ObjectValue,\n transformResults: FieldValue[]\n ): ObjectValue {\n assert(\n transformResults.length === this.fieldTransforms.length,\n 'TransformResults length mismatch.'\n );\n\n for (let i = 0; i < this.fieldTransforms.length; i++) {\n const fieldTransform = this.fieldTransforms[i];\n const transform = fieldTransform.transform;\n const fieldPath = fieldTransform.field;\n if (transform instanceof ServerTimestampTransform) {\n data = data.set(fieldPath, transformResults[i]);\n } else {\n return fail('Encountered unknown transform: ' + transform);\n }\n }\n return data;\n }\n}\n\n/** A mutation that deletes the document at the given key. */\nexport class DeleteMutation extends Mutation {\n constructor(readonly key: DocumentKey, readonly precondition: Precondition) {\n super();\n }\n\n readonly type: MutationType = MutationType.Delete;\n\n applyToRemoteDocument(\n maybeDoc: MaybeDocument | null,\n mutationResult: MutationResult\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n assert(\n mutationResult.transformResults == null,\n 'Transform results received by DeleteMutation.'\n );\n\n // Unlike applyToLocalView, if we're applying a mutation to a remote\n // document the server has accepted the mutation so the precondition must\n // have held.\n\n return new NoDocument(this.key, SnapshotVersion.MIN);\n }\n\n applyToLocalView(\n maybeDoc: MaybeDocument | null,\n localWriteTime: Timestamp\n ): MaybeDocument | null {\n this.verifyKeyMatches(maybeDoc);\n\n if (!this.precondition.isValidFor(maybeDoc)) {\n return maybeDoc;\n }\n\n if (maybeDoc) {\n assert(\n maybeDoc.key.equals(this.key),\n 'Can only apply mutation to document with same key'\n );\n }\n return new NoDocument(this.key, SnapshotVersion.forDeletedDoc());\n }\n\n equals(other: Mutation): boolean {\n return (\n other instanceof DeleteMutation &&\n this.key.equals(other.key) &&\n this.precondition.equals(other.precondition)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/mutation.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport class ExistenceFilter {\n // TODO(b/33078163): just use simplest form of existence filter for now\n constructor(public count: number) {}\n\n public equals(other: ExistenceFilter) {\n return other && other.count === this.count;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/existence_filter.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entry, SortedMap, SortedMapIterator } from './sorted_map';\n\n/**\n * SortedSet is an immutable (copy-on-write) collection that holds elements\n * in order specified by the provided comparator.\n *\n * NOTE: if provided comparator returns 0 for two elements, we consider them to\n * be equal!\n */\nexport class SortedSet {\n private data: SortedMap;\n\n constructor(private comparator: (left: T, right: T) => number) {\n this.data = new SortedMap(this.comparator);\n }\n\n /**\n * Creates a SortedSet from the keys of the map.\n * This is currently implemented as an O(n) copy.\n */\n static fromMapKeys(map: SortedMap): SortedSet {\n let keys = new SortedSet(map.comparator);\n map.forEach(key => {\n keys = keys.add(key);\n });\n return keys;\n }\n\n has(elem: T): boolean {\n return this.data.get(elem) !== null;\n }\n\n first(): T | null {\n return this.data.minKey();\n }\n\n last(): T | null {\n return this.data.maxKey();\n }\n\n get size(): number {\n return this.data.size;\n }\n\n indexOf(elem: T): number {\n return this.data.indexOf(elem);\n }\n\n /** Iterates elements in order defined by \"comparator\" */\n forEach(cb: (elem: T) => void): void {\n this.data.inorderTraversal((k: T, v: boolean) => {\n cb(k);\n return false;\n });\n }\n\n /** Iterates over `elem`s such that: range[0] <= elem < range[1]. */\n forEachInRange(range: [T, T], cb: (elem: T) => void): void {\n const iter = this.data.getIteratorFrom(range[0]);\n while (iter.hasNext()) {\n const elem = iter.getNext();\n if (this.comparator(elem.key, range[1]) >= 0) return;\n cb(elem.key);\n }\n }\n\n /**\n * Iterates over `elem`s such that: start <= elem until false is returned.\n */\n forEachWhile(cb: (elem: T) => boolean, start?: T): void {\n let iter: SortedMapIterator>;\n if (start !== undefined) {\n iter = this.data.getIteratorFrom(start);\n } else {\n iter = this.data.getIterator();\n }\n while (iter.hasNext()) {\n const elem = iter.getNext();\n const result = cb(elem.key);\n if (!result) return;\n }\n }\n\n /** Finds the least element greater than or equal to `elem`. */\n firstAfterOrEqual(elem: T): T | null {\n const iter = this.data.getIteratorFrom(elem);\n return iter.hasNext() ? iter.getNext().key : null;\n }\n\n /** Inserts or updates an element */\n add(elem: T): SortedSet {\n return this.copy(this.data.remove(elem).insert(elem, true));\n }\n\n /** Deletes an element */\n delete(elem: T): SortedSet {\n if (!this.has(elem)) return this;\n return this.copy(this.data.remove(elem));\n }\n\n isEmpty(): boolean {\n return this.data.isEmpty();\n }\n\n unionWith(other: SortedSet): SortedSet {\n let result: SortedSet = this;\n other.forEach(elem => {\n result = result.add(elem);\n });\n return result;\n }\n\n equals(other: SortedSet): boolean {\n if (!(other instanceof SortedSet)) return false;\n if (this.size !== other.size) return false;\n\n const thisIt = this.data.getIterator();\n const otherIt = other.data.getIterator();\n while (thisIt.hasNext()) {\n const thisElem = thisIt.getNext().key;\n const otherElem = otherIt.getNext().key;\n if (this.comparator(thisElem, otherElem) !== 0) return false;\n }\n return true;\n }\n\n toString(): string {\n const result: T[] = [];\n this.forEach(elem => result.push(elem));\n return 'SortedSet(' + result.toString() + ')';\n }\n\n private copy(data: SortedMap): SortedSet {\n const result = new SortedSet(this.comparator);\n result.data = data;\n return result;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/sorted_set.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { ProtoByteString, TargetId } from '../core/types';\nimport {\n documentKeySet,\n DocumentKeySet,\n MaybeDocumentMap\n} from '../model/collections';\nimport { MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { emptyByteString } from '../platform/platform';\n\n/**\n * An event from the RemoteStore. It is split into targetChanges (changes to the\n * state or the set of documents in our watched targets) and documentUpdates\n * (changes to the actual documents).\n */\nexport class RemoteEvent {\n constructor(\n /**\n * The snapshot version this event brings us up to, or MIN if not set.\n */\n public readonly snapshotVersion: SnapshotVersion,\n /**\n * A map from target to changes to the target. See TargetChange.\n */\n public readonly targetChanges: { [targetId: number]: TargetChange },\n /**\n * A set of which documents have changed or been deleted, along with the\n * doc's new values (if not deleted).\n */\n public documentUpdates: MaybeDocumentMap\n ) {}\n\n addDocumentUpdate(doc: MaybeDocument) {\n this.documentUpdates = this.documentUpdates.insert(doc.key, doc);\n }\n\n handleExistenceFilterMismatch(targetId: TargetId) {\n /*\n * An existence filter mismatch will reset the query and we need to reset\n * the mapping to contain no documents and an empty resume token.\n *\n * Note:\n * * The reset mapping is empty, specifically forcing the consumer of the\n * change to forget all keys for this targetID;\n * * The resume snapshot for this target must be reset\n * * The target must be unacked because unwatching and rewatching\n * introduces a race for changes.\n */\n this.targetChanges[targetId] = {\n mapping: new ResetMapping(),\n snapshotVersion: SnapshotVersion.MIN,\n currentStatusUpdate: CurrentStatusUpdate.MarkNotCurrent,\n resumeToken: emptyByteString()\n };\n }\n}\n\n/**\n * Represents an update to the current status of a target, either explicitly\n * having no new state, or the new value to set. Note \"current\" has special\n * meaning for in the RPC protocol that implies that a target is both up-to-date\n * and consistent with the rest of the watch stream.\n */\nexport enum CurrentStatusUpdate {\n /** The current status is not affected and should not be modified. */\n None,\n /** The target must be marked as no longer \"current\". */\n MarkNotCurrent,\n /** The target must be marked as \"current\". */\n MarkCurrent\n}\n\n/**\n * A part of a RemoteEvent specifying set of changes to a specific target. These\n * changes track what documents are currently included in the target as well as\n * the current snapshot version and resume token but the actual changes *to*\n * documents are not part of the TargetChange since documents may be part of\n * multiple targets.\n */\nexport interface TargetChange {\n /**\n * The new \"current\" (synced) status of this target. Set to\n * CurrentStatusUpdateNone if the status should not be updated. Note \"current\"\n * has special meaning in the RPC protocol that implies that a target is\n * both up-to-date and consistent with the rest of the watch stream.\n */\n currentStatusUpdate: CurrentStatusUpdate;\n\n /**\n * A set of changes to documents in this target.\n */\n mapping: TargetMapping;\n\n /** The snapshot version that this target change brings us up to. */\n snapshotVersion: SnapshotVersion;\n\n /**\n * An opaque, server-assigned token that allows watching a query to be resumed\n * after disconnecting without retransmitting all the data that matches the\n * query. The resume token essentially identifies a point in time from which\n * the server should resume sending results.\n */\n resumeToken: ProtoByteString;\n}\n\nexport type TargetMapping = ResetMapping | UpdateMapping;\n\nconst EMPTY_KEY_SET = documentKeySet();\n\nexport class ResetMapping {\n private docs: DocumentKeySet = EMPTY_KEY_SET;\n\n get documents(): DocumentKeySet {\n return this.docs;\n }\n\n add(key: DocumentKey) {\n this.docs = this.docs.add(key);\n }\n\n delete(key: DocumentKey) {\n this.docs = this.docs.delete(key);\n }\n\n equals(other: ResetMapping): boolean {\n return other !== null && this.docs.equals(other.docs);\n }\n}\n\nexport class UpdateMapping {\n addedDocuments: DocumentKeySet = EMPTY_KEY_SET;\n removedDocuments: DocumentKeySet = EMPTY_KEY_SET;\n\n applyToKeySet(keys: DocumentKeySet): DocumentKeySet {\n let result = keys;\n this.addedDocuments.forEach(key => (result = result.add(key)));\n this.removedDocuments.forEach(key => (result = result.delete(key)));\n return result;\n }\n\n add(key: DocumentKey) {\n this.addedDocuments = this.addedDocuments.add(key);\n this.removedDocuments = this.removedDocuments.delete(key);\n }\n\n delete(key: DocumentKey) {\n this.addedDocuments = this.addedDocuments.delete(key);\n this.removedDocuments = this.removedDocuments.add(key);\n }\n\n equals(other: UpdateMapping): boolean {\n return (\n other !== null &&\n this.addedDocuments.equals(other.addedDocuments) &&\n this.removedDocuments.equals(other.removedDocuments)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/remote_event.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from '../util/assert';\nimport { FirestoreError } from '../util/error';\nimport { AnyJs } from '../util/misc';\n\nimport { Stream } from './connection';\n\n/**\n * Provides a simple helper class that implements the Stream interface to\n * bridge to other implementations that are streams but do not implement the\n * interface. The stream callbacks are invoked with the callOn... methods.\n */\nexport class StreamBridge implements Stream {\n private wrappedOnOpen: () => void = null as any;\n private wrappedOnClose: (err?: FirestoreError) => void = null as any;\n private wrappedOnMessage: (msg: O) => void = null as any;\n\n private sendFn: (msg: I) => void;\n private closeFn: () => void;\n\n constructor(args: { sendFn: (msg: I) => void; closeFn: () => void }) {\n this.sendFn = args.sendFn;\n this.closeFn = args.closeFn;\n }\n\n onOpen(callback: () => void): void {\n assert(!this.wrappedOnOpen, 'Called onOpen on stream twice!');\n this.wrappedOnOpen = callback;\n }\n\n onClose(callback: (err?: FirestoreError) => void): void {\n assert(!this.wrappedOnClose, 'Called onClose on stream twice!');\n this.wrappedOnClose = callback;\n }\n\n onMessage(callback: (msg: O) => void): void {\n assert(!this.wrappedOnMessage, 'Called onMessage on stream twice!');\n this.wrappedOnMessage = callback;\n }\n\n close(): void {\n this.closeFn();\n }\n\n send(msg: I): void {\n this.sendFn(msg);\n }\n\n callOnOpen(): void {\n assert(\n this.wrappedOnOpen !== null,\n 'Cannot call onOpen because no callback ' + 'was set'\n );\n this.wrappedOnOpen();\n }\n\n callOnClose(err?: FirestoreError): void {\n assert(\n this.wrappedOnClose !== null,\n 'Cannot call onClose because no ' + 'callback was set'\n );\n this.wrappedOnClose(err);\n }\n\n callOnMessage(msg: O): void {\n assert(\n this.wrappedOnMessage !== null,\n 'Cannot call onMessage because no ' + 'callback was set'\n );\n this.wrappedOnMessage(msg);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/stream_bridge.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ErrorCode,\n EventType,\n WebChannel,\n XhrIoPool,\n createWebChannelTransport\n} from '@firebase/webchannel-wrapper';\n\nimport { Token } from '../api/credentials';\nimport { DatabaseId, DatabaseInfo } from '../core/database_info';\nimport { SDK_VERSION } from '../core/version';\nimport { Connection, Stream } from '../remote/connection';\nimport {\n mapCodeFromHttpStatus,\n mapCodeFromRpcStatus\n} from '../remote/rpc_error';\nimport { StreamBridge } from '../remote/stream_bridge';\nimport { assert, fail } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport * as log from '../util/log';\nimport { Rejecter, Resolver } from '../util/promise';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nconst LOG_TAG = 'Connection';\n\nconst RPC_URL_VERSION = 'v1beta1';\n\n// TODO(b/38203344): The SDK_VERSION is set independently from Firebase because\n// we are doing out-of-band releases. Once we release as part of Firebase, we\n// should use the Firebase version instead.\nconst X_GOOG_API_CLIENT_VALUE = 'gl-js/ fire/' + SDK_VERSION;\n\nconst XHR_TIMEOUT_SECS = 15;\n\nexport class WebChannelConnection implements Connection {\n private readonly databaseId: DatabaseId;\n private readonly baseUrl: string;\n private readonly pool: XhrIoPool;\n\n /**\n * Mapping from RPC name to service providing the RPC.\n * For streaming RPCs only.\n */\n private static RPC_STREAM_SERVICE_MAPPING: { [rpc: string]: string } = {\n Write: 'google.firestore.v1beta1.Firestore',\n Listen: 'google.firestore.v1beta1.Firestore'\n };\n\n /**\n * Mapping from RPC name to actual RPC name in URLs.\n * For streaming RPCs only.\n */\n private static RPC_STREAM_NAME_MAPPING: { [rpc: string]: string } = {\n Write: 'Write',\n Listen: 'Listen'\n };\n\n constructor(info: DatabaseInfo) {\n this.databaseId = info.databaseId;\n this.pool = new XhrIoPool();\n const proto = info.ssl ? 'https' : 'http';\n this.baseUrl = proto + '://' + info.host;\n }\n\n /**\n * Modifies the headers for a request, adding any authorization token if\n * present and any additional headers for the request.\n */\n private modifyHeadersForRequest(\n headers: { [key: string]: string },\n token: Token | null\n ) {\n if (token) {\n for (const header in token.authHeaders) {\n if (token.authHeaders.hasOwnProperty(header)) {\n headers[header] = token.authHeaders[header];\n }\n }\n }\n headers['X-Goog-Api-Client'] = X_GOOG_API_CLIENT_VALUE;\n // This header is used to improve routing and project isolation by the\n // backend.\n headers['google-cloud-resource-prefix'] =\n `projects/${this.databaseId.projectId}/` +\n `databases/${this.databaseId.database}`;\n }\n\n invoke(rpcName: string, request: any, token: Token | null): Promise {\n const url = this.makeUrl(rpcName);\n\n return new Promise((resolve: Resolver, reject: Rejecter) => {\n this.pool.getObject((xhr: any) => {\n xhr.listenOnce(EventType.COMPLETE, () => {\n try {\n switch (xhr.getLastErrorCode()) {\n case ErrorCode.NO_ERROR:\n const json = xhr.getResponseJson();\n log.debug(LOG_TAG, 'XHR received:', JSON.stringify(json));\n resolve(json);\n break;\n case ErrorCode.TIMEOUT:\n log.error('RPC \"' + rpcName + '\" timed out, retrying.');\n reject(\n new FirestoreError(Code.DEADLINE_EXCEEDED, 'Request time out')\n );\n break;\n case ErrorCode.HTTP_ERROR:\n const status = xhr.getStatus();\n log.error(\n 'RPC \"' + rpcName + '\" failed with status:',\n status,\n 'response text:',\n xhr.getResponseText()\n );\n if (status > 0) {\n reject(\n new FirestoreError(\n mapCodeFromHttpStatus(status),\n 'Server responded with status ' + xhr.getStatusText()\n )\n );\n } else {\n // If we received an HTTP_ERROR but there's no status code,\n // it's most probably a connection issue, let's retry.\n log.error(LOG_TAG, 'RPC \"' + rpcName + '\" failed, retrying.');\n reject(\n new FirestoreError(Code.UNAVAILABLE, 'Connection failed.')\n );\n }\n break;\n default:\n fail(\n 'RPC \"' +\n rpcName +\n '\" failed with unanticipated ' +\n 'webchannel error ' +\n xhr.getLastErrorCode() +\n ': ' +\n xhr.getLastError() +\n ', giving up.'\n );\n }\n } finally {\n log.debug(LOG_TAG, 'RPC \"' + rpcName + '\" completed.');\n this.pool.releaseObject(xhr);\n }\n });\n\n const requestString = JSON.stringify(request);\n log.debug(LOG_TAG, 'XHR sending: ', url + ' ' + requestString);\n // Content-Type: text/plain will avoid preflight requests which might\n // mess with CORS and redirects by proxies. If we add custom headers\n // we will need to change this code to potentially use the\n // $httpOverwrite parameter supported by ESF to avoid\n // triggering preflight requests.\n const headers: any = { 'Content-Type': 'text/plain' };\n\n this.modifyHeadersForRequest(headers, token);\n\n xhr.send(url, 'POST', requestString, headers, XHR_TIMEOUT_SECS);\n });\n });\n }\n\n openStream(rpcName: string, token: Token | null): Stream {\n const rpcService = WebChannelConnection.RPC_STREAM_SERVICE_MAPPING[rpcName];\n const rpcUrlName = WebChannelConnection.RPC_STREAM_NAME_MAPPING[rpcName];\n if (!rpcService || !rpcUrlName) {\n fail('Unknown RPC name: ' + rpcName);\n }\n const urlParts = [\n this.baseUrl,\n '/',\n rpcService,\n '/',\n rpcUrlName,\n '/channel'\n ];\n const webchannelTransport = createWebChannelTransport();\n const request = {\n // Background channel test avoids the initial two test calls and decreases\n // initial cold start time.\n // TODO(dimond): wenboz@ mentioned this might affect use with proxies and\n // we should monitor closely for any reports.\n backgroundChannelTest: true,\n // Required for backend stickiness, routing behavior is based on this\n // parameter.\n httpSessionIdParam: 'gsessionid',\n initMessageHeaders: {},\n sendRawJson: true,\n supportsCrossDomainXhr: true\n };\n this.modifyHeadersForRequest(request.initMessageHeaders, token);\n const url = urlParts.join('');\n log.debug(LOG_TAG, 'Creating WebChannel: ' + url + ' ' + request);\n // tslint:disable-next-line:no-any Because listen isn't defined on it.\n const channel = webchannelTransport.createWebChannel(url, request) as any;\n\n // WebChannel supports sending the first message with the handshake - saving\n // a network round trip. However, it will have to call send in the same\n // JS event loop as open. In order to enforce this, we delay actually\n // opening the WebChannel until send is called. Whether we have called\n // open is tracked with this variable.\n let opened = false;\n\n // A flag to determine whether the stream was closed (by us or through an\n // error/close event) to avoid delivering multiple close events or sending\n // on a closed stream\n let closed = false;\n\n // tslint:disable-next-line:no-any\n const streamBridge = new StreamBridge({\n sendFn: (msg: any) => {\n if (!closed) {\n if (!opened) {\n log.debug(LOG_TAG, 'Opening WebChannel transport.');\n channel.open();\n opened = true;\n }\n log.debug(LOG_TAG, 'WebChannel sending:', msg);\n channel.send(msg);\n } else {\n log.debug(LOG_TAG, 'Not sending because WebChannel is closed:', msg);\n }\n },\n closeFn: () => channel.close()\n });\n\n // Closure events are guarded and exceptions are swallowed, so catch any\n // exception and rethrow using a setTimeout so they become visible again.\n // Note that eventually this function could go away if we are confident\n // enough the code is exception free.\n const unguardedEventListen = (\n type: WebChannel.EventType,\n fn: (param: any) => void\n ) => {\n // TODO(dimond): closure typing seems broken because WebChannel does\n // not implement goog.events.Listenable\n channel.listen(type, (param: any) => {\n try {\n fn(param);\n } catch (e) {\n setTimeout(() => {\n throw e;\n }, 0);\n }\n });\n };\n\n unguardedEventListen(WebChannel.EventType.OPEN, () => {\n if (!closed) {\n log.debug(LOG_TAG, 'WebChannel transport opened.');\n }\n });\n\n unguardedEventListen(WebChannel.EventType.CLOSE, () => {\n if (!closed) {\n closed = true;\n log.debug(LOG_TAG, 'WebChannel transport closed');\n streamBridge.callOnClose();\n }\n });\n\n unguardedEventListen(WebChannel.EventType.ERROR, (err: any) => {\n if (!closed) {\n closed = true;\n log.debug(LOG_TAG, 'WebChannel transport errored:', err);\n streamBridge.callOnClose(\n new FirestoreError(\n Code.UNAVAILABLE,\n 'The operation could not be completed'\n )\n );\n }\n });\n\n unguardedEventListen(WebChannel.EventType.MESSAGE, (msg: any) => {\n if (!closed) {\n // WebChannel delivers message events as array. If batching\n // is not enabled (it's off by default) each message will be\n // delivered alone, resulting in a single element array.\n const msgData = msg.data[0];\n assert(!!msgData, 'Got a webchannel message without data.');\n // TODO(b/35143891): There is a bug in One Platform that caused errors\n // (and only errors) to be wrapped in an extra array. To be forward\n // compatible with the bug we need to check either condition. The latter\n // can be removed once the fix has been rolled out.\n const error = msgData.error || (msgData[0] && msgData[0].error);\n if (error) {\n log.debug(LOG_TAG, 'WebChannel received error:', error);\n // error.status will be a string like 'OK' or 'NOT_FOUND'.\n const status: string = error.status;\n let code = mapCodeFromRpcStatus(status);\n let message = error.message;\n if (code === undefined) {\n code = Code.INTERNAL;\n message =\n 'Unknown error status: ' +\n status +\n ' with message ' +\n error.message;\n }\n // Mark closed so no further events are propagated\n closed = true;\n streamBridge.callOnClose(new FirestoreError(code, message));\n channel.close();\n } else {\n log.debug(LOG_TAG, 'WebChannel received:', msgData);\n streamBridge.callOnMessage(msgData);\n }\n }\n });\n\n setTimeout(() => {\n // Technically we could/should wait for the WebChannel opened event,\n // but because we want to send the first message with the WebChannel\n // handshake we pretend the channel opened here (asynchronously), and\n // then delay the actual open until the first message is sent.\n streamBridge.callOnOpen();\n }, 0);\n return streamBridge;\n }\n\n // visible for testing\n makeUrl(rpcName: string): string {\n const url = [this.baseUrl, '/', RPC_URL_VERSION];\n url.push('/projects/');\n url.push(this.databaseId.projectId);\n\n url.push('/databases/');\n url.push(this.databaseId.database);\n url.push('/documents');\n\n url.push(':');\n url.push(rpcName);\n return url.join('');\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/platform_browser/webchannel_connection.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DatabaseId, DatabaseInfo } from '../core/database_info';\nimport { Platform } from '../platform/platform';\nimport { Connection } from '../remote/connection';\nimport { JsonProtoSerializer } from '../remote/serializer';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { WebChannelConnection } from './webchannel_connection';\n\nexport class BrowserPlatform implements Platform {\n readonly base64Available: boolean;\n\n readonly emptyByteString = '';\n\n constructor() {\n this.base64Available = typeof atob !== 'undefined';\n }\n\n loadConnection(databaseInfo: DatabaseInfo): Promise {\n return Promise.resolve(new WebChannelConnection(databaseInfo));\n }\n\n newSerializer(databaseId: DatabaseId): JsonProtoSerializer {\n return new JsonProtoSerializer(databaseId, { useProto3Json: true });\n }\n\n atob(encoded: string): string {\n return atob(encoded);\n }\n\n btoa(raw: string): string {\n return btoa(raw);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/platform_browser/browser_platform.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PlatformSupport } from '../platform/platform';\nimport { BrowserPlatform } from './browser_platform';\n\n/**\n * This code needs to run before Firestore is used. This can be achieved in\n * several ways:\n * 1) Through the JSCompiler compiling this code and then (automatically)\n * executing it before exporting the Firestore symbols.\n * 2) Through importing this module first in a Firestore main module\n */\nPlatformSupport.setPlatform(new BrowserPlatform());\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/platform_browser/browser_init.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * BatchID is a locally assigned ID for a batch of mutations that have been\n * applied.\n */\nexport type BatchId = number;\n\n/**\n * A locally-assigned ID used to refer to a target being watched via the\n * Watch service.\n */\nexport type TargetId = number;\n\n// TODO(b/35918695): In GRPC / node, tokens are Uint8Array. In WebChannel,\n// they're strings. We should probably (de-)serialize to a common internal type.\nexport type ProtoByteString = Uint8Array | string;\n\n/** Describes the online state of the Firestore client */\nexport enum OnlineState {\n /**\n * The Firestore client is in an unknown online state. This means the client\n * is either not actively trying to establish a connection or it was\n * previously in an unknown state and is trying to establish a connection.\n */\n Unknown,\n\n /**\n * The client is connected and the connections are healthy. This state is\n * reached after a successful connection and there has been at least one\n * succesful message received from the backends.\n */\n Healthy,\n\n /**\n * The client has tried to establish a connection but has failed.\n * This state is reached after either a connection attempt failed or a\n * healthy stream was closed for unexpected reasons.\n */\n Failed\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/types.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Document } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { DocumentSet } from '../model/document_set';\nimport { fail } from '../util/assert';\nimport { SortedMap } from '../util/sorted_map';\n\nimport { Query } from './query';\n\nexport enum ChangeType {\n Added,\n Removed,\n Modified,\n Metadata\n}\n\nexport interface DocumentViewChange {\n type: ChangeType;\n doc: Document;\n}\n\nexport enum SyncState {\n Local,\n Synced\n}\n\n/**\n * DocumentChangeSet keeps track of a set of changes to docs in a query, merging\n * duplicate events for the same doc.\n */\nexport class DocumentChangeSet {\n private changeMap = new SortedMap(\n DocumentKey.comparator\n );\n\n constructor() {}\n\n track(change: DocumentViewChange) {\n const key = change.doc.key;\n const oldChange = this.changeMap.get(key);\n if (!oldChange) {\n this.changeMap = this.changeMap.insert(key, change);\n return;\n }\n\n // Merge the new change with the existing change.\n if (\n change.type !== ChangeType.Added &&\n oldChange.type === ChangeType.Metadata\n ) {\n this.changeMap = this.changeMap.insert(key, change);\n } else if (\n change.type === ChangeType.Metadata &&\n oldChange.type !== ChangeType.Removed\n ) {\n this.changeMap = this.changeMap.insert(key, {\n type: oldChange.type,\n doc: change.doc\n });\n } else if (\n change.type === ChangeType.Modified &&\n oldChange.type === ChangeType.Modified\n ) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Modified,\n doc: change.doc\n });\n } else if (\n change.type === ChangeType.Modified &&\n oldChange.type === ChangeType.Added\n ) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Added,\n doc: change.doc\n });\n } else if (\n change.type === ChangeType.Removed &&\n oldChange.type === ChangeType.Added\n ) {\n this.changeMap = this.changeMap.remove(key);\n } else if (\n change.type === ChangeType.Removed &&\n oldChange.type === ChangeType.Modified\n ) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Removed,\n doc: oldChange.doc\n });\n } else if (\n change.type === ChangeType.Added &&\n oldChange.type === ChangeType.Removed\n ) {\n this.changeMap = this.changeMap.insert(key, {\n type: ChangeType.Modified,\n doc: change.doc\n });\n } else {\n // This includes these cases, which don't make sense:\n // Added->Added\n // Removed->Removed\n // Modified->Added\n // Removed->Modified\n // Metadata->Added\n // Removed->Metadata\n fail(\n 'unsupported combination of changes: ' +\n JSON.stringify(change) +\n ' after ' +\n JSON.stringify(oldChange)\n );\n }\n }\n\n getChanges(): DocumentViewChange[] {\n const changes: DocumentViewChange[] = [];\n this.changeMap.inorderTraversal(\n (key: DocumentKey, change: DocumentViewChange) => {\n changes.push(change);\n }\n );\n return changes;\n }\n}\n\nexport interface ViewSnapshot {\n readonly query: Query;\n readonly docs: DocumentSet;\n readonly oldDocs: DocumentSet;\n readonly docChanges: DocumentViewChange[];\n readonly fromCache: boolean;\n readonly hasPendingWrites: boolean;\n readonly syncStateChanged: boolean;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/view_snapshot.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TargetId } from './types';\n\nconst RESERVED_BITS = 1;\n\nenum GeneratorIds {\n LocalStore = 0,\n SyncEngine = 1\n}\n\n/**\n * TargetIdGenerator generates monotonically increasing integer IDs. There are\n * separate generators for different scopes. While these generators will operate\n * independently of each other, they are scoped, such that no two generators\n * will ever produce the same ID. This is useful, because sometimes the backend\n * may group IDs from separate parts of the client into the same ID space.\n */\nexport class TargetIdGenerator {\n private previousId: TargetId;\n\n constructor(private generatorId: number, initAfter: TargetId = 0) {\n // Replace the generator part of initAfter with this generator's ID.\n const afterWithoutGenerator = (initAfter >> RESERVED_BITS) << RESERVED_BITS;\n const afterGenerator = initAfter - afterWithoutGenerator;\n if (afterGenerator >= generatorId) {\n // For example, if:\n // this.generatorId = 0b0000\n // after = 0b1011\n // afterGenerator = 0b0001\n // Then:\n // previous = 0b1010\n // next = 0b1100\n this.previousId = afterWithoutGenerator | this.generatorId;\n } else {\n // For example, if:\n // this.generatorId = 0b0001\n // after = 0b1010\n // afterGenerator = 0b0000\n // Then:\n // previous = 0b1001\n // next = 0b1011\n this.previousId =\n (afterWithoutGenerator | this.generatorId) - (1 << RESERVED_BITS);\n }\n }\n\n next(): TargetId {\n this.previousId += 1 << RESERVED_BITS;\n return this.previousId;\n }\n\n static forLocalStore(initAfter: TargetId = 0): TargetIdGenerator {\n return new TargetIdGenerator(GeneratorIds.LocalStore, initAfter);\n }\n\n static forSyncEngine(): TargetIdGenerator {\n return new TargetIdGenerator(GeneratorIds.SyncEngine);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/target_id_generator.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { assert } from '../util/assert';\nimport { SortedMap } from '../util/sorted_map';\n\nimport { documentMap } from './collections';\nimport { Document } from './document';\nimport { DocumentComparator } from './document_comparator';\nimport { DocumentKey } from './document_key';\n\n/**\n * DocumentSet is an immutable (copy-on-write) collection that holds documents\n * in order specified by the provided comparator. We always add a document key\n * comparator on top of what is provided to guarantee document equality based on\n * the key.\n */\n\nexport class DocumentSet {\n /**\n * Returns an empty copy of the existing DocumentSet, using the same\n * comparator.\n */\n static emptySet(oldSet: DocumentSet): DocumentSet {\n return new DocumentSet(oldSet.comparator);\n }\n\n private comparator: DocumentComparator;\n private keyedMap: SortedMap;\n private sortedSet: SortedMap;\n\n /** The default ordering is by key if the comparator is omitted */\n constructor(comp?: DocumentComparator) {\n // We are adding document key comparator to the end as it's the only\n // guaranteed unique property of a document.\n if (comp) {\n this.comparator = (d1: Document, d2: Document) =>\n comp(d1, d2) || DocumentKey.comparator(d1.key, d2.key);\n } else {\n this.comparator = (d1: Document, d2: Document) =>\n DocumentKey.comparator(d1.key, d2.key);\n }\n\n this.keyedMap = documentMap();\n this.sortedSet = new SortedMap(this.comparator);\n }\n\n has(key: DocumentKey): boolean {\n return this.keyedMap.get(key) != null;\n }\n\n get(key: DocumentKey): Document | null {\n return this.keyedMap.get(key);\n }\n\n first(): Document | null {\n return this.sortedSet.minKey();\n }\n\n last(): Document | null {\n return this.sortedSet.maxKey();\n }\n\n isEmpty(): boolean {\n return this.sortedSet.isEmpty();\n }\n\n /**\n * Returns previous document or null if it's a first doc.\n *\n * @param key A key that MUST be present in the DocumentSet.\n */\n prevDoc(key: DocumentKey): Document | null {\n assert(\n this.has(key),\n 'Trying to get a previous document to non-existing key: ' + key\n );\n const doc = this.keyedMap.get(key);\n return this.sortedSet.getPredecessorKey(doc!);\n }\n\n /**\n * Returns the index of the provided key in the document set, or -1 if the\n * document key is not present in the set;\n */\n indexOf(key: DocumentKey): number {\n const doc = this.keyedMap.get(key);\n return doc ? this.sortedSet.indexOf(doc) : -1;\n }\n\n get size(): number {\n return this.sortedSet.size;\n }\n\n /** Iterates documents in order defined by \"comparator\" */\n forEach(cb: (doc: Document) => void): void {\n this.sortedSet.inorderTraversal((k, v) => {\n cb(k);\n return false;\n });\n }\n\n /** Inserts or updates a document with the same key */\n add(doc: Document): DocumentSet {\n // First remove the element if we have it.\n const set = this.delete(doc.key);\n return set.copy(\n set.keyedMap.insert(doc.key, doc),\n set.sortedSet.insert(doc, null)\n );\n }\n\n /** Deletes a document with a given key */\n delete(key: DocumentKey): DocumentSet {\n const doc = this.get(key);\n if (!doc) {\n return this;\n }\n\n return this.copy(this.keyedMap.remove(key), this.sortedSet.remove(doc));\n }\n\n equals(other: DocumentSet | null | undefined): boolean {\n if (!(other instanceof DocumentSet)) return false;\n if (this.size !== other.size) return false;\n\n const thisIt = this.sortedSet.getIterator();\n const otherIt = other.sortedSet.getIterator();\n while (thisIt.hasNext()) {\n const thisDoc = thisIt.getNext().key;\n const otherDoc = otherIt.getNext().key;\n if (!thisDoc.equals(otherDoc)) return false;\n }\n return true;\n }\n\n toString(): string {\n const docStrings: string[] = [];\n this.forEach(doc => {\n docStrings.push(doc.toString());\n });\n if (docStrings.length === 0) {\n return 'DocumentSet ()';\n } else {\n return 'DocumentSet (\\n ' + docStrings.join(' \\n') + '\\n)';\n }\n }\n\n private copy(\n keyedMap: SortedMap,\n sortedSet: SortedMap\n ): DocumentSet {\n const newSet = new DocumentSet();\n newSet.comparator = this.comparator;\n newSet.keyedMap = keyedMap;\n newSet.sortedSet = sortedSet;\n return newSet;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/document_set.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Equatable } from './misc';\nimport * as objUtil from './obj';\n\ntype Entry = [K, V];\n\n/**\n * A map implementation that uses objects as keys. Objects must implement the\n * Equatable interface and must be immutable. Entries in the map are stored\n * together with the key being produced from the mapKeyFn. This map\n * automatically handles collisions of keys.\n */\nexport class ObjectMap, ValueType> {\n /**\n * The inner map for a key -> value pair. Due to the possibility of\n * collisions we keep a list of entries that we do a linear search through\n * to find an actual match. Note that collisions should be rare, so we still\n * expect near constant time lookups in practice.\n */\n private inner: {\n [canonicalId: string]: Array>;\n } = {};\n\n constructor(private mapKeyFn: (key: KeyType) => string) {}\n\n /** Get a value for this key, or undefined if it does not exist. */\n get(key: KeyType): ValueType | undefined {\n const id = this.mapKeyFn(key);\n const matches = this.inner[id];\n if (matches === undefined) {\n return undefined;\n }\n for (const [otherKey, value] of matches) {\n if (otherKey.equals(key)) {\n return value;\n }\n }\n return undefined;\n }\n\n has(key: KeyType): boolean {\n return this.get(key) !== undefined;\n }\n\n /** Put this key and value in the map. */\n set(key: KeyType, value: ValueType): void {\n const id = this.mapKeyFn(key);\n const matches = this.inner[id];\n if (matches === undefined) {\n this.inner[id] = [[key, value]];\n return;\n }\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][0].equals(key)) {\n matches[i] = [key, value];\n return;\n }\n }\n matches.push([key, value]);\n }\n\n /**\n * Remove this key from the map. Returns a boolean if anything was deleted.\n */\n delete(key: KeyType): boolean {\n const id = this.mapKeyFn(key);\n const matches = this.inner[id];\n if (matches === undefined) {\n return false;\n }\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][0].equals(key)) {\n if (matches.length === 1) {\n delete this.inner[id];\n } else {\n matches.splice(i, 1);\n }\n return true;\n }\n }\n return false;\n }\n\n forEach(fn: (key: KeyType, val: ValueType) => void): void {\n objUtil.forEach(this.inner, (_, entries) => {\n for (const [k, v] of entries) {\n fn(k, v);\n }\n });\n }\n\n isEmpty(): boolean {\n return objUtil.isEmpty(this.inner);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/obj_map.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from './query';\nimport { SyncEngine } from './sync_engine';\nimport { OnlineState, TargetId } from './types';\nimport { DocumentViewChange } from './view_snapshot';\nimport { ChangeType, ViewSnapshot } from './view_snapshot';\nimport { DocumentSet } from '../model/document_set';\nimport { assert } from '../util/assert';\nimport { EventHandler } from '../util/misc';\nimport * as obj from '../util/obj';\nimport { ObjectMap } from '../util/obj_map';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\n/**\n * Holds the listeners and the last received ViewSnapshot for a query being\n * tracked by EventManager.\n */\nclass QueryListenersInfo {\n public viewSnap: ViewSnapshot | null;\n public targetId: TargetId;\n public listeners: QueryListener[] = [];\n}\n\n/**\n * Interface for handling events from the EventManager.\n */\nexport interface Observer {\n next: EventHandler;\n error: EventHandler;\n}\n\n/**\n * EventManager is responsible for mapping queries to query event emitters.\n * It handles \"fan-out\". -- Identical queries will re-use the same watch on the\n * backend.\n */\nexport class EventManager {\n private queries = new ObjectMap(q =>\n q.canonicalId()\n );\n\n private onlineState: OnlineState = OnlineState.Unknown;\n\n constructor(private syncEngine: SyncEngine) {\n this.syncEngine.subscribe(\n this.onChange.bind(this),\n this.onError.bind(this)\n );\n }\n\n listen(listener: QueryListener): Promise {\n const query = listener.query;\n let firstListen = false;\n\n let queryInfo = this.queries.get(query);\n if (!queryInfo) {\n firstListen = true;\n queryInfo = new QueryListenersInfo();\n this.queries.set(query, queryInfo);\n }\n queryInfo.listeners.push(listener);\n\n listener.onOnlineStateChanged(this.onlineState);\n\n if (queryInfo.viewSnap) listener.onViewSnapshot(queryInfo.viewSnap);\n\n if (firstListen) {\n return this.syncEngine.listen(query).then(targetId => {\n queryInfo!.targetId = targetId;\n return targetId;\n });\n } else {\n return Promise.resolve(queryInfo.targetId);\n }\n }\n\n unlisten(listener: QueryListener): Promise {\n const query = listener.query;\n let lastListen = false;\n\n const queryInfo = this.queries.get(query);\n if (queryInfo) {\n const i = queryInfo.listeners.indexOf(listener);\n if (i >= 0) {\n queryInfo.listeners.splice(i, 1);\n lastListen = queryInfo.listeners.length === 0;\n }\n }\n\n if (lastListen) {\n this.queries.delete(query);\n return this.syncEngine.unlisten(query);\n } else {\n return Promise.resolve();\n }\n }\n\n onChange(viewSnaps: ViewSnapshot[]): void {\n for (const viewSnap of viewSnaps) {\n const query = viewSnap.query;\n const queryInfo = this.queries.get(query);\n if (queryInfo) {\n for (const listener of queryInfo.listeners) {\n listener.onViewSnapshot(viewSnap);\n }\n queryInfo.viewSnap = viewSnap;\n }\n }\n }\n\n onError(query: Query, error: Error): void {\n const queryInfo = this.queries.get(query);\n if (queryInfo) {\n for (const listener of queryInfo.listeners) {\n listener.onError(error);\n }\n }\n\n // Remove all listeners. NOTE: We don't need to call syncEngine.unlisten()\n // after an error.\n this.queries.delete(query);\n }\n\n onOnlineStateChanged(onlineState: OnlineState): void {\n this.onlineState = onlineState;\n this.queries.forEach((_, queryInfo) => {\n for (const listener of queryInfo.listeners) {\n listener.onOnlineStateChanged(onlineState);\n }\n });\n }\n}\n\nexport interface ListenOptions {\n /** Raise events when only metadata of documents changes */\n readonly includeDocumentMetadataChanges?: boolean;\n\n /** Raise events when only metadata of the query changes */\n readonly includeQueryMetadataChanges?: boolean;\n\n /**\n * Wait for a sync with the server when online, but still raise events while\n * offline.\n */\n readonly waitForSyncWhenOnline?: boolean;\n}\n\n/**\n * QueryListener takes a series of internal view snapshots and determines\n * when to raise the event.\n *\n * It uses an Observer to dispatch events.\n */\nexport class QueryListener {\n /**\n * Initial snapshots (e.g. from cache) may not be propagated to the wrapped\n * observer. This flag is set to true once we've actually raised an event.\n */\n private raisedInitialEvent = false;\n\n private options: ListenOptions;\n\n private snap: ViewSnapshot;\n\n private onlineState: OnlineState = OnlineState.Unknown;\n\n constructor(\n readonly query: Query,\n private queryObserver: Observer,\n options?: ListenOptions\n ) {\n this.options = options || {};\n }\n\n onViewSnapshot(snap: ViewSnapshot): void {\n assert(\n snap.docChanges.length > 0 || snap.syncStateChanged,\n 'We got a new snapshot with no changes?'\n );\n\n if (!this.options.includeDocumentMetadataChanges) {\n // Remove the metadata only changes.\n const docChanges: DocumentViewChange[] = [];\n for (const docChange of snap.docChanges) {\n if (docChange.type !== ChangeType.Metadata) {\n docChanges.push(docChange);\n }\n }\n snap = {\n query: snap.query,\n docs: snap.docs,\n oldDocs: snap.oldDocs,\n docChanges,\n fromCache: snap.fromCache,\n hasPendingWrites: snap.hasPendingWrites,\n syncStateChanged: snap.syncStateChanged\n };\n }\n\n if (!this.raisedInitialEvent) {\n if (this.shouldRaiseInitialEvent(snap, this.onlineState)) {\n this.raiseInitialEvent(snap);\n }\n } else if (this.shouldRaiseEvent(snap)) {\n this.queryObserver.next(snap);\n }\n\n this.snap = snap;\n }\n\n onError(error: Error): void {\n this.queryObserver.error(error);\n }\n\n onOnlineStateChanged(onlineState: OnlineState): void {\n this.onlineState = onlineState;\n if (\n this.snap &&\n !this.raisedInitialEvent &&\n this.shouldRaiseInitialEvent(this.snap, onlineState)\n ) {\n this.raiseInitialEvent(this.snap);\n }\n }\n\n private shouldRaiseInitialEvent(\n snap: ViewSnapshot,\n onlineState: OnlineState\n ): boolean {\n assert(\n !this.raisedInitialEvent,\n 'Determining whether to raise first event but already had first event'\n );\n\n // Always raise the first event when we're synced\n if (!snap.fromCache) {\n return true;\n }\n\n // NOTE: We consider OnlineState.Unknown as online (it should become Failed\n // or Online if we wait long enough).\n const maybeOnline = onlineState !== OnlineState.Failed;\n // Don't raise the event if we're online, aren't synced yet (checked\n // above) and are waiting for a sync.\n if (this.options.waitForSyncWhenOnline && maybeOnline) {\n assert(\n snap.fromCache,\n 'Waiting for sync, but snapshot is not from cache'\n );\n return false;\n }\n\n // Raise data from cache if we have any documents or we are offline\n return !snap.docs.isEmpty() || onlineState === OnlineState.Failed;\n }\n\n private shouldRaiseEvent(snap: ViewSnapshot): boolean {\n // We don't need to handle includeDocumentMetadataChanges here because\n // the Metadata only changes have already been stripped out if needed.\n // At this point the only changes we will see are the ones we should\n // propagate.\n if (snap.docChanges.length > 0) {\n return true;\n }\n\n const hasPendingWritesChanged =\n this.snap && this.snap.hasPendingWrites !== snap.hasPendingWrites;\n if (snap.syncStateChanged || hasPendingWritesChanged) {\n return this.options.includeQueryMetadataChanges === true;\n }\n\n // Generally we should have hit one of the cases above, but it's possible\n // to get here if there were only metadata docChanges and they got\n // stripped out.\n return false;\n }\n\n private raiseInitialEvent(snap: ViewSnapshot): void {\n assert(\n !this.raisedInitialEvent,\n 'Trying to raise initial events for second time'\n );\n snap = {\n query: snap.query,\n docs: snap.docs,\n oldDocs: DocumentSet.emptySet(snap.docs),\n docChanges: QueryListener.getInitialViewChanges(snap),\n fromCache: snap.fromCache,\n hasPendingWrites: snap.hasPendingWrites,\n syncStateChanged: true\n };\n this.raisedInitialEvent = true;\n this.queryObserver.next(snap);\n }\n\n /** Returns changes as if all documents in the snap were added. */\n private static getInitialViewChanges(\n snap: ViewSnapshot\n ): DocumentViewChange[] {\n const result: DocumentViewChange[] = [];\n snap.docs.forEach(doc => {\n result.push({ type: ChangeType.Added, doc });\n });\n return result;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/event_manager.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { fail } from '../util/assert';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nexport type FulfilledHandler =\n | ((result: T) => R | PersistencePromise)\n | null;\nexport type RejectedHandler =\n | ((reason: any) => R | PersistencePromise)\n | null;\nexport type Resolver = (value?: T) => void;\nexport type Rejector = (error: any) => void;\n\n/**\n * PersistencePromise<> is essentially a re-implementation of Promise<> except\n * it has a .next() method instead of .then() and .next() and .catch() callbacks\n * are executed synchronously when a PersistencePromise resolves rather than\n * asynchronously (Promise<> implementations use setImmediate() or similar).\n *\n * This is necessary to interoperate with IndexedDB which will automatically\n * commit transactions if control is returned to the event loop without\n * synchronously initiating another operation on the transaction.\n *\n * NOTE: .then() and .catch() only allow a single consumer, unlike normal\n * Promises.\n */\nexport class PersistencePromise {\n // NOTE: next/catchCallback will always point to our own wrapper functions,\n // not the user's raw next() or catch() callbacks.\n private nextCallback: FulfilledHandler = null;\n private catchCallback: RejectedHandler = null;\n\n // When the operation resolves, we'll set result or error and mark isDone.\n private result: T | undefined = undefined;\n private error: any = null;\n private isDone = false;\n\n // Set to true when .then() or .catch() are called and prevents additional\n // chaining.\n private callbackAttached = false;\n\n constructor(callback: (resolve: Resolver, reject: Rejector) => void) {\n callback(\n value => {\n this.isDone = true;\n this.result = value;\n if (this.nextCallback) {\n // value should be defined unless T is Void, but we can't express\n // that in the type system.\n this.nextCallback(value!);\n }\n },\n error => {\n this.isDone = true;\n this.error = error;\n if (this.catchCallback) {\n this.catchCallback(error);\n }\n }\n );\n }\n\n catch(\n fn: (error: any) => R | PersistencePromise\n ): PersistencePromise {\n return this.next(undefined, fn);\n }\n\n next(\n nextFn?: FulfilledHandler,\n catchFn?: RejectedHandler\n ): PersistencePromise {\n if (this.callbackAttached) {\n fail('Called next() or catch() twice for PersistencePromise');\n }\n this.callbackAttached = true;\n if (this.isDone) {\n if (!this.error) {\n return this.wrapSuccess(nextFn, this.result!);\n } else {\n return this.wrapFailure(catchFn, this.error);\n }\n } else {\n return new PersistencePromise((resolve, reject) => {\n this.nextCallback = (value: T) => {\n this.wrapSuccess(nextFn, value).next(resolve, reject);\n };\n this.catchCallback = (error: any) => {\n this.wrapFailure(catchFn, error).next(resolve, reject);\n };\n });\n }\n }\n\n toPromise(): Promise {\n return new Promise((resolve, reject) => {\n this.next(resolve, reject);\n });\n }\n\n private wrapUserFunction(\n fn: () => R | PersistencePromise\n ): PersistencePromise {\n try {\n const result = fn();\n if (result instanceof PersistencePromise) {\n return result;\n } else {\n return PersistencePromise.resolve(result);\n }\n } catch (e) {\n return PersistencePromise.reject(e);\n }\n }\n\n private wrapSuccess(\n nextFn: FulfilledHandler | undefined,\n value: T\n ): PersistencePromise {\n if (nextFn) {\n return this.wrapUserFunction(() => nextFn(value));\n } else {\n // If there's no nextFn, then R must be the same as T but we\n // can't express that in the type system.\n return PersistencePromise.resolve(value as any);\n }\n }\n\n private wrapFailure(\n catchFn: RejectedHandler | undefined,\n error: any\n ): PersistencePromise {\n if (catchFn) {\n return this.wrapUserFunction(() => catchFn(error));\n } else {\n return PersistencePromise.reject(error);\n }\n }\n\n static resolve(): PersistencePromise;\n static resolve(result: R): PersistencePromise;\n static resolve(result?: R): PersistencePromise {\n return new PersistencePromise((resolve, reject) => {\n resolve(result);\n });\n }\n\n static reject(error: any): PersistencePromise {\n return new PersistencePromise((resolve, reject) => {\n reject(error);\n });\n }\n\n static waitFor(\n all: Array>\n ): PersistencePromise {\n return all.reduce((promise, nextPromise, idx) => {\n return promise.next(() => {\n return nextPromise;\n });\n }, PersistencePromise.resolve());\n }\n\n static map(all: Array>): PersistencePromise {\n const results: R[] = [];\n let first = true;\n // initial is ignored, so we can cheat on the type.\n const initial = PersistencePromise.resolve(null as any);\n return all\n .reduce((promise, nextPromise) => {\n return promise.next(result => {\n if (!first) {\n results.push(result);\n }\n first = false;\n return nextPromise;\n });\n }, initial)\n .next(result => {\n results.push(result);\n return results;\n });\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/persistence_promise.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DocumentKeySet, documentKeySet } from '../model/collections';\nimport { DocumentKey } from '../model/document_key';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { GarbageCollector } from './garbage_collector';\nimport { GarbageSource } from './garbage_source';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\n\n/**\n * A garbage collector implementation that eagerly collects documents as soon as\n * they're no longer referenced in any of its registered GarbageSources.\n *\n * This implementation keeps track of a set of keys that are potentially garbage\n * without keeping an exact reference count. During collectGarbage, the\n * collector verifies that all potential garbage keys actually have no\n * references by consulting its list of garbage sources.\n */\nexport class EagerGarbageCollector implements GarbageCollector {\n readonly isEager = true;\n\n /**\n * The garbage collectible sources to double-check during garbage collection.\n */\n private sources: GarbageSource[] = [];\n\n /**\n * A set of potentially garbage keys.\n * PORTING NOTE: This would be a mutable set if Javascript had one.\n */\n private potentialGarbage: DocumentKeySet = documentKeySet();\n\n addGarbageSource(garbageSource: GarbageSource): void {\n this.sources.push(garbageSource);\n garbageSource.setGarbageCollector(this);\n }\n\n removeGarbageSource(garbageSource: GarbageSource): void {\n this.sources.splice(this.sources.indexOf(garbageSource), 1);\n garbageSource.setGarbageCollector(null);\n }\n\n addPotentialGarbageKey(key: DocumentKey): void {\n this.potentialGarbage = this.potentialGarbage.add(key);\n }\n\n collectGarbage(\n txn: PersistenceTransaction | null\n ): PersistencePromise {\n const promises: Array> = [];\n let garbageKeys = documentKeySet();\n\n this.potentialGarbage.forEach(key => {\n const hasRefsPromise = this.documentHasAnyReferences(txn, key);\n promises.push(\n hasRefsPromise.next(hasRefs => {\n // If there are no references, get the key.\n if (!hasRefs) {\n garbageKeys = garbageKeys.add(key);\n }\n return PersistencePromise.resolve();\n })\n );\n });\n\n // Clear locally retained potential keys and returned confirmed garbage.\n this.potentialGarbage = documentKeySet();\n return PersistencePromise.waitFor(promises).next(() => garbageKeys);\n }\n\n documentHasAnyReferences(\n txn: PersistenceTransaction | null,\n key: DocumentKey\n ): PersistencePromise {\n const initial = PersistencePromise.resolve(false);\n return this.sources\n .map(source => () => source.containsKey(txn, key))\n .reduce>((promise, nextPromise) => {\n return promise.next(result => {\n if (result) {\n return PersistencePromise.resolve(true);\n } else {\n return nextPromise();\n }\n });\n }, initial);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/eager_garbage_collector.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport { ChangeType, ViewSnapshot } from '../core/view_snapshot';\nimport { documentKeySet, DocumentKeySet } from '../model/collections';\n\n/**\n * A set of changes to what documents are currently in view and out of view for\n * a given query. These changes are sent to the LocalStore by the View (via\n * the SyncEngine) and are used to pin / unpin documents as appropriate.\n */\nexport class LocalViewChanges {\n constructor(\n readonly query: Query,\n readonly addedKeys: DocumentKeySet,\n readonly removedKeys: DocumentKeySet\n ) {}\n\n static fromSnapshot(viewSnapshot: ViewSnapshot): LocalViewChanges {\n let addedKeys = documentKeySet();\n let removedKeys = documentKeySet();\n\n for (const docChange of viewSnapshot.docChanges) {\n switch (docChange.type) {\n case ChangeType.Added:\n addedKeys = addedKeys.add(docChange.doc.key);\n break;\n case ChangeType.Removed:\n removedKeys = removedKeys.add(docChange.doc.key);\n break;\n default:\n // do nothing\n }\n }\n\n return new LocalViewChanges(viewSnapshot.query, addedKeys, removedKeys);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/local_view_changes.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BatchId, TargetId } from '../core/types';\nimport { documentKeySet, DocumentKeySet } from '../model/collections';\nimport { DocumentKey } from '../model/document_key';\nimport { assert } from '../util/assert';\nimport { primitiveComparator } from '../util/misc';\nimport { SortedSet } from '../util/sorted_set';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { GarbageCollector } from './garbage_collector';\nimport { GarbageSource } from './garbage_source';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\n\n/**\n * A collection of references to a document from some kind of numbered entity\n * (either a target ID or batch ID). As references are added to or removed from\n * the set corresponding events are emitted to a registered garbage collector.\n *\n * Each reference is represented by a DocumentReference object. Each of them\n * contains enough information to uniquely identify the reference. They are all\n * stored primarily in a set sorted by key. A document is considered garbage if\n * there's no references in that set (this can be efficiently checked thanks to\n * sorting by key).\n *\n * ReferenceSet also keeps a secondary set that contains references sorted by\n * IDs. This one is used to efficiently implement removal of all references by\n * some target ID.\n */\nexport class ReferenceSet implements GarbageSource {\n // A set of outstanding references to a document sorted by key.\n private refsByKey = new SortedSet(DocReference.compareByKey);\n\n // A set of outstanding references to a document sorted by target id.\n private refsByTarget = new SortedSet(DocReference.compareByTargetId);\n\n /** Keeps track of keys that have references */\n private garbageCollector: GarbageCollector | null = null;\n\n /** Returns true if the reference set contains no references. */\n isEmpty(): boolean {\n return this.refsByKey.isEmpty();\n }\n\n /** Adds a reference to the given document key for the given ID. */\n addReference(key: DocumentKey, id: TargetId | BatchId): void {\n const ref = new DocReference(key, id);\n this.refsByKey = this.refsByKey.add(ref);\n this.refsByTarget = this.refsByTarget.add(ref);\n }\n\n /** Add references to the given document keys for the given ID. */\n addReferences(keys: DocumentKeySet, id: TargetId | BatchId): void {\n keys.forEach(key => this.addReference(key, id));\n }\n\n /**\n * Removes a reference to the given document key for the given\n * ID.\n */\n removeReference(key: DocumentKey, id: TargetId | BatchId): void {\n this.removeRef(new DocReference(key, id));\n }\n\n removeReferences(keys: DocumentKeySet, id: TargetId | BatchId): void {\n keys.forEach(key => this.removeReference(key, id));\n }\n\n /**\n * Clears all references with a given ID. Calls removeRef() for each key\n * removed.\n */\n removeReferencesForId(id: TargetId | BatchId): void {\n const emptyKey = DocumentKey.EMPTY;\n const startRef = new DocReference(emptyKey, id);\n const endRef = new DocReference(emptyKey, id + 1);\n this.refsByTarget.forEachInRange([startRef, endRef], ref => {\n this.removeRef(ref);\n });\n }\n\n removeAllReferences(): void {\n this.refsByKey.forEach(ref => this.removeRef(ref));\n }\n\n private removeRef(ref: DocReference): void {\n this.refsByKey = this.refsByKey.delete(ref);\n this.refsByTarget = this.refsByTarget.delete(ref);\n if (this.garbageCollector !== null) {\n this.garbageCollector.addPotentialGarbageKey(ref.key);\n }\n }\n\n referencesForId(id: TargetId | BatchId): DocumentKeySet {\n const emptyKey = DocumentKey.EMPTY;\n const startRef = new DocReference(emptyKey, id);\n const endRef = new DocReference(emptyKey, id + 1);\n let keys = documentKeySet();\n this.refsByTarget.forEachInRange([startRef, endRef], ref => {\n keys = keys.add(ref.key);\n });\n return keys;\n }\n\n setGarbageCollector(garbageCollector: GarbageCollector | null): void {\n this.garbageCollector = garbageCollector;\n }\n\n containsKey(\n txn: PersistenceTransaction | null,\n key: DocumentKey\n ): PersistencePromise {\n const ref = new DocReference(key, 0);\n const firstRef = this.refsByKey.firstAfterOrEqual(ref);\n return PersistencePromise.resolve(\n firstRef !== null && key.equals(firstRef.key)\n );\n }\n}\n\nexport class DocReference {\n constructor(\n public key: DocumentKey,\n public targetOrBatchId: TargetId | BatchId\n ) {}\n\n /** Compare by key then by ID */\n static compareByKey(left: DocReference, right: DocReference): number {\n return (\n DocumentKey.comparator(left.key, right.key) ||\n primitiveComparator(left.targetOrBatchId, right.targetOrBatchId)\n );\n }\n\n /** Compare by ID then by key */\n static compareByTargetId(left: DocReference, right: DocReference): number {\n return (\n primitiveComparator(left.targetOrBatchId, right.targetOrBatchId) ||\n DocumentKey.comparator(left.key, right.key)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/reference_set.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '../protos/firestore_proto_api';\nimport { CredentialsProvider, Token } from '../api/credentials';\nimport { DatabaseInfo } from '../core/database_info';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { ProtoByteString, TargetId } from '../core/types';\nimport { QueryData } from '../local/query_data';\nimport { Mutation, MutationResult } from '../model/mutation';\nimport { assert } from '../util/assert';\nimport { AsyncQueue } from '../util/async_queue';\nimport { Code, FirestoreError } from '../util/error';\nimport * as log from '../util/log';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { ExponentialBackoff } from './backoff';\nimport { Connection, Stream } from './connection';\nimport { JsonProtoSerializer } from './serializer';\nimport { WatchChange } from './watch_change';\n\nconst LOG_TAG = 'PersistentStream';\n\n// The generated proto interfaces for these class are missing the database\n// field. So we add it here.\n// TODO(b/36015800): Remove this once the api generator is fixed.\ninterface ListenRequest extends api.ListenRequest {\n database?: string;\n}\nexport interface WriteRequest extends api.WriteRequest {\n database?: string;\n}\n\nenum PersistentStreamState {\n /**\n * The streaming RPC is not running and there's no error condition.\n * Calling `start` will start the stream immediately without backoff.\n * While in this state isStarted will return false.\n */\n Initial,\n\n /**\n * The stream is starting, and is waiting for an auth token to attach to\n * the initial request. While in this state, isStarted will return\n * true but isOpen will return false.\n */\n Auth,\n\n /**\n * The streaming RPC is up and running. Requests and responses can flow\n * freely. Both isStarted and isOpen will return true.\n */\n Open,\n\n /**\n * The stream encountered an error. The next start attempt will back off.\n * While in this state isStarted() will return false.\n *\n */\n Error,\n\n /**\n * An in-between state after an error where the stream is waiting before\n * re-starting. After\n * waiting is complete, the stream will try to open. While in this\n * state isStarted() will return YES but isOpen will return false.\n */\n Backoff,\n\n /**\n * The stream has been explicitly stopped; no further events will be emitted.\n */\n Stopped\n}\n\n/**\n * Provides a common interface that is shared by the listeners for stream\n * events by the concrete implementation classes.\n */\nexport interface PersistentStreamListener {\n /**\n * Called after the stream was established and can accept outgoing\n * messages\n */\n onOpen: () => Promise;\n /**\n * Called after the stream has closed. If there was an error, the\n * FirestoreError will be set.\n */\n onClose: (err?: FirestoreError) => Promise;\n}\n\n/**\n * Initial backoff time in milliseconds after an error.\n * Set to 1s according to https://cloud.google.com/apis/design/errors.\n */\nconst BACKOFF_INITIAL_DELAY_MS = 1000;\n\n/** Maximum backoff time in milliseconds */\nconst BACKOFF_MAX_DELAY_MS = 60 * 1000;\n\nconst BACKOFF_FACTOR = 1.5;\n\n/**\n * A PersistentStream is an abstract base class that represents a streaming RPC\n * to the Firestore backend. It's built on top of the connections own support\n * for streaming RPCs, and adds several critical features for our clients:\n *\n * - Exponential backoff on failure\n * - Authentication via CredentialsProvider\n * - Dispatching all callbacks into the shared worker queue\n *\n * Subclasses of PersistentStream implement serialization of models to and\n * from the JSON representation of the protocol buffers for a specific\n * streaming RPC.\n *\n * ## Starting and Stopping\n *\n * Streaming RPCs are stateful and need to be `start`ed before messages can\n * be sent and received. The PersistentStream will call the onOpen function\n * of the listener once the stream is ready to accept requests.\n *\n * Should a `start` fail, PersistentStream will call the registered\n * onClose with a FirestoreError indicating what went wrong.\n *\n * A PersistentStream can be started and stopped repeatedly.\n *\n * Generic types:\n * SendType: The type of the outgoing message of the underlying\n * connection stream\n * ReceiveType: The type of the incoming message of the underlying\n * connection stream\n * ListenerType: The type of the listener that will be used for callbacks\n */\nexport abstract class PersistentStream<\n SendType,\n ReceiveType,\n ListenerType extends PersistentStreamListener\n> {\n private state: PersistentStreamState;\n\n protected stream: Stream | null = null;\n\n protected backoff: ExponentialBackoff;\n\n protected listener: ListenerType | null = null;\n\n constructor(\n private queue: AsyncQueue,\n protected connection: Connection,\n private credentialsProvider: CredentialsProvider,\n listener: ListenerType,\n // Used for faster retries in testing\n initialBackoffDelay?: number\n ) {\n this.backoff = new ExponentialBackoff(\n initialBackoffDelay ? initialBackoffDelay : BACKOFF_INITIAL_DELAY_MS,\n BACKOFF_FACTOR,\n BACKOFF_MAX_DELAY_MS\n );\n this.state = PersistentStreamState.Initial;\n this.listener = listener;\n }\n\n /**\n * Returns true if `start` has been called and no error has occurred. True\n * indicates the stream is open or in the process of opening (which\n * encompasses respecting backoff, getting auth tokens, and starting the\n * actual RPC). Use `isOpen` to determine if the stream is open and ready for\n * outbound requests.\n */\n isStarted(): boolean {\n return (\n this.state === PersistentStreamState.Backoff ||\n this.state === PersistentStreamState.Auth ||\n this.state === PersistentStreamState.Open\n );\n }\n\n /**\n * Returns true if the underlying RPC is open (the openHandler has been\n * called) and the stream is ready for outbound requests.\n */\n isOpen(): boolean {\n return this.state === PersistentStreamState.Open;\n }\n\n /**\n * Starts the RPC. Only allowed if isStarted returns false. The stream is\n * not immediately ready for use: onOpen will be invoked when the RPC is ready\n * for outbound requests, at which point isOpen will return true.\n *\n * When start returns, isStarted will return true.\n */\n start(): void {\n if (this.state === PersistentStreamState.Error) {\n this.performBackoff();\n return;\n }\n\n assert(this.state === PersistentStreamState.Initial, 'Already started');\n\n this.auth();\n }\n\n /**\n * Stops the RPC. This call is idempotent and allowed regardless of the\n * current isStarted state.\n *\n * When stop returns, isStarted and isOpen will both return false.\n */\n stop(): void {\n // Prevent any possible future restart of this stream\n this.state = PersistentStreamState.Stopped;\n\n // Clear the listener to avoid bleeding of events from the underlying\n // streams\n this.listener = null;\n\n // Clean up the underlying stream because we are no longer interested in\n // events\n if (this.stream !== null) {\n this.stream.close();\n this.stream = null;\n }\n }\n\n /**\n * After an error the stream will usually back off on the next attempt to\n * start it. If the error warrants an immediate restart of the stream, the\n * sender can use this to indicate that the receiver should not back off.\n *\n * Each error will call the onClose function. That function can decide to\n * inhibit backoff if required.\n */\n inhibitBackoff(): void {\n assert(!this.isStarted(), 'Can only inhibit backoff in a stopped state');\n\n this.state = PersistentStreamState.Initial;\n this.backoff.reset();\n }\n\n /**\n * Used by subclasses to start the concrete RPC and return the underlying\n * connection stream.\n */\n protected abstract startRpc(\n token: Token | null\n ): Stream;\n\n /**\n * Called after the stream has received a message. The function will be\n * called on the right queue and must return a Promise.\n * @param message The message received from the stream.\n */\n protected abstract onMessage(message: ReceiveType): Promise;\n\n private auth(): void {\n assert(\n this.state === PersistentStreamState.Initial,\n 'Must be in initial state to auth'\n );\n\n this.state = PersistentStreamState.Auth;\n\n this.credentialsProvider.getToken(/*forceRefresh=*/ false).then(\n token => {\n // Normally we'd have to schedule the callback on the AsyncQueue.\n // However, the following calls are safe to be called outside the\n // AsyncQueue since they don't chain asynchronous calls\n this.startStream(token);\n },\n (error: Error) => {\n this.queue.schedule(() => {\n if (this.state !== PersistentStreamState.Stopped) {\n // Stream can be stopped while waiting for authorization.\n const rpcError = new FirestoreError(\n Code.UNKNOWN,\n 'Fetching auth token failed: ' + error.message\n );\n return this.handleStreamClose(rpcError);\n } else {\n return Promise.resolve();\n }\n });\n }\n );\n }\n\n private startStream(token: Token | null): void {\n if (this.state === PersistentStreamState.Stopped) {\n // Stream can be stopped while waiting for authorization.\n return;\n }\n\n assert(\n this.state === PersistentStreamState.Auth,\n 'Trying to start stream in a non-auth state'\n );\n // Helper function to dispatch to AsyncQueue and make sure that any\n // close will seem instantaneous and events are prevented from being\n // raised after the close call\n const dispatchIfNotStopped = (fn: () => Promise) => {\n this.queue.schedule(() => {\n // Only raise events if the listener has not changed\n if (this.state !== PersistentStreamState.Stopped) {\n return fn();\n } else {\n return Promise.resolve();\n }\n });\n };\n\n // Only start stream if listener has not changed\n if (this.listener !== null) {\n this.stream = this.startRpc(token);\n this.stream.onOpen(() => {\n dispatchIfNotStopped(() => {\n assert(\n this.state === PersistentStreamState.Auth,\n 'Expected stream to be in state auth, but was ' + this.state\n );\n this.state = PersistentStreamState.Open;\n return this.listener!.onOpen();\n });\n });\n this.stream.onClose((error: FirestoreError) => {\n dispatchIfNotStopped(() => {\n return this.handleStreamClose(error);\n });\n });\n this.stream.onMessage((msg: ReceiveType) => {\n dispatchIfNotStopped(() => {\n return this.onMessage(msg);\n });\n });\n }\n }\n\n private performBackoff(): void {\n assert(\n this.state === PersistentStreamState.Error,\n 'Should only perform backoff in an error case'\n );\n this.state = PersistentStreamState.Backoff;\n\n this.backoff.backoffAndWait().then(() => {\n // Backoff does not run on the AsyncQueue, so we need to reschedule to\n // make sure the queue blocks\n this.queue.schedule(() => {\n if (this.state === PersistentStreamState.Stopped) {\n // Stream can be stopped while waiting for backoff to complete.\n return Promise.resolve();\n }\n\n this.state = PersistentStreamState.Initial;\n this.start();\n assert(this.isStarted(), 'PersistentStream should have started');\n return Promise.resolve();\n });\n });\n }\n\n private handleStreamClose(error?: FirestoreError): Promise {\n assert(this.isStarted(), \"Can't handle server close on non-started stream\");\n log.debug(LOG_TAG, `close with error: ${error}`);\n\n this.stream = null;\n\n // In theory the stream could close cleanly, however, in our current model\n // we never expect this to happen because if we stop a stream ourselves,\n // this callback will never be called. To prevent cases where we retry\n // without a backoff accidentally, we set the stream to error in all cases.\n this.state = PersistentStreamState.Error;\n\n if (error && error.code === Code.RESOURCE_EXHAUSTED) {\n log.debug(\n LOG_TAG,\n 'Using maximum backoff delay to prevent overloading the backend.'\n );\n this.backoff.resetToMax();\n }\n\n return this.listener!.onClose(error);\n }\n}\n\n/** Listener for the PersistentWatchStream */\nexport interface WatchStreamListener extends PersistentStreamListener {\n /**\n * Called on a watchChange. The snapshot parameter will be MIN if the watch\n * change did not have a snapshot associated with it.\n */\n onWatchChange: (\n watchChange: WatchChange,\n snapshot: SnapshotVersion\n ) => Promise;\n}\n\n/**\n * A PersistentStream that implements the Listen RPC.\n *\n * Once the Listen stream has called the openHandler, any number of listen and\n * unlisten calls calls can be sent to control what changes will be sent from\n * the server for ListenResponses.\n */\nexport class PersistentListenStream extends PersistentStream<\n api.ListenRequest,\n api.ListenResponse,\n WatchStreamListener\n> {\n constructor(\n private databaseInfo: DatabaseInfo,\n queue: AsyncQueue,\n connection: Connection,\n credentials: CredentialsProvider,\n private serializer: JsonProtoSerializer,\n listener: WatchStreamListener,\n initialBackoffDelay?: number\n ) {\n super(queue, connection, credentials, listener, initialBackoffDelay);\n }\n\n protected startRpc(\n token: Token | null\n ): Stream {\n return this.connection.openStream('Listen', token);\n }\n\n protected onMessage(watchChangeProto: api.ListenResponse): Promise {\n // A successful response means the stream is healthy\n this.backoff.reset();\n\n const watchChange = this.serializer.fromWatchChange(watchChangeProto);\n const snapshot = this.serializer.versionFromListenResponse(\n watchChangeProto\n );\n return this.listener!.onWatchChange(watchChange, snapshot);\n }\n\n /**\n * Registers interest in the results of the given query. If the query\n * includes a resumeToken it will be included in the request. Results that\n * affect the query will be streamed back as WatchChange messages that\n * reference the targetId.\n */\n watch(queryData: QueryData): void {\n const request: ListenRequest = {};\n request.database = this.serializer.encodedDatabaseId;\n request.addTarget = this.serializer.toTarget(queryData);\n\n const labels = this.serializer.toListenRequestLabels(queryData);\n if (labels) {\n request.labels = labels;\n }\n\n this.stream!.send(request);\n }\n\n /**\n * Unregisters interest in the results of the query associated with the\n * given targetId.\n */\n unwatch(targetId: TargetId): void {\n const request: ListenRequest = {};\n request.database = this.serializer.encodedDatabaseId;\n request.removeTarget = targetId;\n this.stream!.send(request);\n }\n}\n\n/** Listener for the PersistentWriteStream */\nexport interface WriteStreamListener extends PersistentStreamListener {\n /**\n * Called by the PersistentWriteStream upon a successful handshake response\n * from the server, which is the receiver's cue to send any pending writes.\n */\n onHandshakeComplete: () => Promise;\n\n /**\n * Called by the PersistentWriteStream upon receiving a StreamingWriteResponse\n * from the server that contains a mutation result.\n */\n onMutationResult: (\n commitVersion: SnapshotVersion,\n results: MutationResult[]\n ) => Promise;\n}\n\n/**\n * A Stream that implements the Write RPC.\n *\n * The Write RPC requires the caller to maintain special streamToken\n * state in between calls, to help the server understand which responses the\n * client has processed by the time the next request is made. Every response\n * will contain a streamToken; this value must be passed to the next\n * request.\n *\n * After calling start() on this stream, the next request must be a handshake,\n * containing whatever streamToken is on hand. Once a response to this\n * request is received, all pending mutations may be submitted. When\n * submitting multiple batches of mutations at the same time, it's\n * okay to use the same streamToken for the calls to writeMutations.\n *\n * TODO(b/33271235): Use proto types\n */\nexport class PersistentWriteStream extends PersistentStream<\n api.WriteRequest,\n api.WriteResponse,\n WriteStreamListener\n> {\n private handshakeComplete_ = false;\n\n constructor(\n private databaseInfo: DatabaseInfo,\n queue: AsyncQueue,\n connection: Connection,\n credentials: CredentialsProvider,\n private serializer: JsonProtoSerializer,\n listener: WriteStreamListener,\n initialBackoffDelay?: number\n ) {\n super(queue, connection, credentials, listener, initialBackoffDelay);\n }\n\n /**\n * The last received stream token from the server, used to acknowledge which\n * responses the client has processed. Stream tokens are opaque checkpoint\n * markers whose only real value is their inclusion in the next request.\n *\n * PersistentWriteStream manages propagating this value from responses to the\n * next request.\n */\n public lastStreamToken: ProtoByteString;\n\n /**\n * Tracks whether or not a handshake has been successfully exchanged and\n * the stream is ready to accept mutations.\n */\n get handshakeComplete(): boolean {\n return this.handshakeComplete_;\n }\n\n // Override of PersistentStream.start\n start(): void {\n this.handshakeComplete_ = false;\n super.start();\n }\n\n protected startRpc(\n token: Token | null\n ): Stream {\n return this.connection.openStream('Write', token);\n }\n\n protected onMessage(responseProto: api.WriteResponse): Promise {\n // Always capture the last stream token.\n assert(\n !!responseProto.streamToken,\n 'Got a write response without a stream token'\n );\n this.lastStreamToken = responseProto.streamToken!;\n\n if (!this.handshakeComplete_) {\n // The first response is always the handshake response\n assert(\n !responseProto.writeResults || responseProto.writeResults.length === 0,\n 'Got mutation results for handshake'\n );\n this.handshakeComplete_ = true;\n return this.listener!.onHandshakeComplete();\n } else {\n // A successful first write response means the stream is healthy,\n // Note, that we could consider a successful handshake healthy, however,\n // the write itself might be causing an error we want to back off from.\n this.backoff.reset();\n\n const results = this.serializer.fromWriteResults(\n responseProto.writeResults\n );\n const commitVersion = this.serializer.fromVersion(\n responseProto.commitTime!\n );\n return this.listener!.onMutationResult(commitVersion, results);\n }\n }\n\n /**\n * Sends an initial streamToken to the server, performing the handshake\n * required to make the StreamingWrite RPC work. Subsequent\n * calls should wait until onHandshakeComplete was called.\n */\n writeHandshake(): void {\n assert(this.isOpen(), 'Writing handshake requires an opened stream');\n assert(!this.handshakeComplete_, 'Handshake already completed');\n // TODO(dimond): Support stream resumption. We intentionally do not set the\n // stream token on the handshake, ignoring any stream token we might have.\n const request: WriteRequest = {};\n request.database = this.serializer.encodedDatabaseId;\n this.stream!.send(request);\n }\n\n /** Sends a group of mutations to the Firestore backend to apply. */\n writeMutations(mutations: Mutation[]): void {\n assert(this.isOpen(), 'Writing mutations requires an opened stream');\n assert(\n this.handshakeComplete_,\n 'Handshake must be complete before writing mutations'\n );\n assert(\n this.lastStreamToken.length > 0,\n 'Trying to write mutation without a token'\n );\n\n const request: WriteRequest = {\n // Protos are typed with string, but we support UInt8Array on Node\n // tslint:disable-next-line:no-any\n streamToken: this.lastStreamToken as any,\n writes: mutations.map(mutation => this.serializer.toMutation(mutation))\n };\n\n this.stream!.send(request);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/persistent_stream.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { EagerGarbageCollector } from '../local/eager_garbage_collector';\nimport { LocalStore } from '../local/local_store';\nimport { LocalViewChanges } from '../local/local_view_changes';\nimport { QueryData, QueryPurpose } from '../local/query_data';\nimport { ReferenceSet } from '../local/reference_set';\nimport { MaybeDocumentMap } from '../model/collections';\nimport { MaybeDocument, NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { Mutation } from '../model/mutation';\nimport { MutationBatchResult } from '../model/mutation_batch';\nimport { CurrentStatusUpdate, RemoteEvent } from '../remote/remote_event';\nimport { RemoteStore } from '../remote/remote_store';\nimport { RemoteSyncer } from '../remote/remote_syncer';\nimport { assert, fail } from '../util/assert';\nimport { FirestoreError } from '../util/error';\nimport * as log from '../util/log';\nimport { AnyJs, primitiveComparator } from '../util/misc';\nimport * as objUtils from '../util/obj';\nimport { ObjectMap } from '../util/obj_map';\nimport { Deferred } from '../util/promise';\nimport { SortedMap } from '../util/sorted_map';\nimport { isNullOrUndefined } from '../util/types';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { Query } from './query';\nimport { SnapshotVersion } from './snapshot_version';\nimport { TargetIdGenerator } from './target_id_generator';\nimport { Transaction } from './transaction';\nimport { BatchId, ProtoByteString, TargetId } from './types';\nimport {\n AddedLimboDocument,\n LimboDocumentChange,\n RemovedLimboDocument,\n View,\n ViewDocumentChanges\n} from './view';\nimport { ViewSnapshot } from './view_snapshot';\n\nconst LOG_TAG = 'SyncEngine';\n\nexport type ViewHandler = (viewSnaps: ViewSnapshot[]) => void;\nexport type ErrorHandler = (query: Query, error: Error) => void;\n\n/**\n * QueryView contains all of the data that SyncEngine needs to keep track of for\n * a particular query.\n */\nclass QueryView {\n constructor(\n /**\n * The query itself.\n */\n public query: Query,\n /**\n * The target number created by the client that is used in the watch\n * stream to identify this query.\n */\n public targetId: TargetId,\n /**\n * An identifier from the datastore backend that indicates the last state\n * of the results that was received. This can be used to indicate where\n * to continue receiving new doc changes for the query.\n */\n public resumeToken: ProtoByteString,\n /**\n * The view is responsible for computing the final merged truth of what\n * docs are in the query. It gets notified of local and remote changes,\n * and applies the query filters and limits to determine the most correct\n * possible results.\n */\n public view: View\n ) {}\n}\n\n/**\n * SyncEngine is the central controller in the client SDK architecture. It is\n * the glue code between the EventManager, LocalStore, and RemoteStore. Some of\n * SyncEngine's responsibilities include:\n * 1. Coordinating client requests and remote events between the EventManager\n * and the local and remote data stores.\n * 2. Managing a View object for each query, providing the unified view between\n * the local and remote data stores.\n * 3. Notifying the RemoteStore when the LocalStore has new mutations in its\n * queue that need sending to the backend.\n *\n * The SyncEngine’s methods should only ever be called by methods running in the\n * global async queue.\n */\nexport class SyncEngine implements RemoteSyncer {\n private viewHandler: ViewHandler | null = null;\n private errorHandler: ErrorHandler | null = null;\n\n private queryViewsByQuery = new ObjectMap(q =>\n q.canonicalId()\n );\n private queryViewsByTarget: { [targetId: number]: QueryView } = {};\n private limboTargetsByKey = new SortedMap(\n DocumentKey.comparator\n );\n private limboKeysByTarget: { [targetId: number]: DocumentKey } = {};\n private limboDocumentRefs = new ReferenceSet();\n private limboCollector = new EagerGarbageCollector();\n /** Stores user completion handlers, indexed by User and BatchId. */\n private mutationUserCallbacks = {} as {\n [uidKey: string]: SortedMap>;\n };\n private targetIdGenerator = TargetIdGenerator.forSyncEngine();\n\n constructor(\n private localStore: LocalStore,\n private remoteStore: RemoteStore,\n private currentUser: User\n ) {}\n\n /** Subscribes view and error handler. Can be called only once. */\n subscribe(viewHandler: ViewHandler, errorHandler: ErrorHandler): void {\n assert(\n viewHandler !== null && errorHandler !== null,\n 'View and error handlers cannot be null'\n );\n assert(\n this.viewHandler === null && this.errorHandler === null,\n 'SyncEngine already has a subscriber.'\n );\n this.viewHandler = viewHandler;\n this.errorHandler = errorHandler;\n this.limboCollector.addGarbageSource(this.limboDocumentRefs);\n }\n\n /**\n * Initiates the new listen, resolves promise when listen enqueued to the\n * server. All the subsequent view snapshots or errors are sent to the\n * subscribed handlers. Returns the targetId of the query.\n */\n listen(query: Query): Promise {\n this.assertSubscribed('listen()');\n assert(\n !this.queryViewsByQuery.has(query),\n 'We already listen to the query: ' + query\n );\n\n return this.localStore.allocateQuery(query).then(queryData => {\n return this.localStore\n .executeQuery(query)\n .then(docs => {\n return this.localStore\n .remoteDocumentKeys(queryData.targetId)\n .then(remoteKeys => {\n const view = new View(query, remoteKeys);\n const viewDocChanges = view.computeDocChanges(docs);\n const viewChange = view.applyChanges(viewDocChanges);\n assert(\n viewChange.limboChanges.length === 0,\n 'View returned limbo docs before target ack from the server.'\n );\n assert(\n !!viewChange.snapshot,\n 'applyChanges for new view should always return a snapshot'\n );\n\n const data = new QueryView(\n query,\n queryData.targetId,\n queryData.resumeToken,\n view\n );\n this.queryViewsByQuery.set(query, data);\n this.queryViewsByTarget[queryData.targetId] = data;\n this.viewHandler!([viewChange.snapshot!]);\n this.remoteStore.listen(queryData);\n });\n })\n .then(() => {\n return queryData.targetId;\n });\n });\n }\n\n /** Stops listening to the query. */\n unlisten(query: Query): Promise {\n this.assertSubscribed('unlisten()');\n\n const queryView = this.queryViewsByQuery.get(query)!;\n assert(!!queryView, 'Trying to unlisten on query not found:' + query);\n\n return this.localStore.releaseQuery(query).then(() => {\n this.remoteStore.unlisten(queryView.targetId);\n return this.removeAndCleanupQuery(queryView).then(() => {\n return this.localStore.collectGarbage();\n });\n });\n }\n\n /**\n * Initiates the write of local mutation batch which involves adding the\n * writes to the mutation queue, notifying the remote store about new\n * mutations and raising events for any changes this write caused.\n *\n * The promise returned by this call is resolved when the above steps\n * have completed, *not* when the write was acked by the backend. The\n * userCallback is resolved once the write was acked/rejected by the\n * backend (or failed locally for any other reason).\n */\n write(batch: Mutation[], userCallback: Deferred): Promise {\n this.assertSubscribed('write()');\n return this.localStore\n .localWrite(batch)\n .then(result => {\n this.addMutationCallback(result.batchId, userCallback);\n return this.emitNewSnapsAndNotifyLocalStore(result.changes);\n })\n .then(() => {\n return this.remoteStore.fillWritePipeline();\n });\n }\n\n // TODO(klimt): Wrap the given error in a standard Firestore error object.\n private wrapUpdateFunctionError(error: AnyJs): AnyJs {\n return error;\n }\n\n /**\n * Takes an updateFunction in which a set of reads and writes can be performed\n * atomically. In the updateFunction, the client can read and write values\n * using the supplied transaction object. After the updateFunction, all\n * changes will be committed. If some other client has changed any of the data\n * referenced, then the updateFunction will be called again. If the\n * updateFunction still fails after the given number of retries, then the\n * transaction will be rejection.\n *\n * The transaction object passed to the updateFunction contains methods for\n * accessing documents and collections. Unlike other datastore access, data\n * accessed with the transaction will not reflect local changes that have not\n * been committed. For this reason, it is required that all reads are\n * performed before any writes. Transactions must be performed while online.\n *\n * The promise returned is resolved when the transaction is fully committed.\n */\n runTransaction(\n updateFunction: (transaction: Transaction) => Promise,\n retries = 5\n ): Promise {\n assert(retries >= 0, 'Got negative number of retries for transaction.');\n const transaction = this.remoteStore.createTransaction();\n const wrappedUpdateFunction = () => {\n try {\n const userPromise = updateFunction(transaction);\n if (\n isNullOrUndefined(userPromise) ||\n !userPromise.catch ||\n !userPromise.then\n ) {\n return Promise.reject(\n Error('Transaction callback must return a Promise')\n );\n }\n return userPromise.catch(e => {\n return Promise.reject(this.wrapUpdateFunctionError(e));\n });\n } catch (e) {\n return Promise.reject(this.wrapUpdateFunctionError(e));\n }\n };\n return wrappedUpdateFunction().then(result => {\n return transaction\n .commit()\n .then(() => {\n return result;\n })\n .catch(error => {\n if (retries === 0) {\n return Promise.reject(error);\n }\n // TODO(klimt): Put in a retry delay?\n return this.runTransaction(updateFunction, retries - 1);\n });\n });\n }\n\n applyRemoteEvent(remoteEvent: RemoteEvent): Promise {\n this.assertSubscribed('applyRemoteEvent()');\n\n // Make sure limbo documents are deleted if there were no results\n objUtils.forEachNumber(\n remoteEvent.targetChanges,\n (targetId, targetChange) => {\n const limboKey = this.limboKeysByTarget[targetId];\n if (\n limboKey &&\n targetChange.currentStatusUpdate ===\n CurrentStatusUpdate.MarkCurrent &&\n !remoteEvent.documentUpdates.get(limboKey)\n ) {\n // When listening to a query the server responds with a snapshot\n // containing documents matching the query and a current marker\n // telling us we're now in sync. It's possible for these to arrive\n // as separate remote events or as a single remote event.\n // For a document query, there will be no documents sent in the\n // response if the document doesn't exist.\n //\n // If the snapshot arrives separately from the current marker,\n // we handle it normally and updateTrackedLimbos will resolve the\n // limbo status of the document, removing it from limboDocumentRefs.\n // This works because clients only initiate limbo resolution when\n // a target is current and because all current targets are\n // always at a consistent snapshot.\n //\n // However, if the document doesn't exist and the current marker\n // arrives, the document is not present in the snapshot and our\n // normal view handling would consider the document to remain in\n // limbo indefinitely because there are no updates to the document.\n // To avoid this, we specially handle this just this case here:\n // synthesizing a delete.\n //\n // TODO(dimond): Ideally we would have an explicit lookup query\n // instead resulting in an explicit delete message and we could\n // remove this special logic.\n remoteEvent.addDocumentUpdate(\n new NoDocument(limboKey, remoteEvent.snapshotVersion)\n );\n }\n }\n );\n\n return this.localStore.applyRemoteEvent(remoteEvent).then(changes => {\n return this.emitNewSnapsAndNotifyLocalStore(changes, remoteEvent);\n });\n }\n\n rejectListen(targetId: TargetId, err: FirestoreError): Promise {\n this.assertSubscribed('rejectListens()');\n const limboKey = this.limboKeysByTarget[targetId];\n if (limboKey) {\n // Since this query failed, we won't want to manually unlisten to it.\n // So go ahead and remove it from bookkeeping.\n this.limboTargetsByKey = this.limboTargetsByKey.remove(limboKey);\n delete this.limboKeysByTarget[targetId];\n\n // TODO(klimt): We really only should do the following on permission\n // denied errors, but we don't have the cause code here.\n\n // It's a limbo doc. Create a synthetic event saying it was deleted.\n // This is kind of a hack. Ideally, we would have a method in the local\n // store to purge a document. However, it would be tricky to keep all of\n // the local store's invariants with another method.\n let docMap = new SortedMap(\n DocumentKey.comparator\n );\n docMap = docMap.insert(\n limboKey,\n new NoDocument(limboKey, SnapshotVersion.forDeletedDoc())\n );\n const event = new RemoteEvent(SnapshotVersion.MIN, {}, docMap);\n return this.applyRemoteEvent(event);\n } else {\n const queryView = this.queryViewsByTarget[targetId];\n assert(!!queryView, 'Unknown targetId: ' + targetId);\n return this.localStore.releaseQuery(queryView.query).then(() => {\n return this.removeAndCleanupQuery(queryView).then(() => {\n this.errorHandler!(queryView.query, err);\n });\n });\n }\n }\n\n applySuccessfulWrite(\n mutationBatchResult: MutationBatchResult\n ): Promise {\n this.assertSubscribed('applySuccessfulWrite()');\n\n // The local store may or may not be able to apply the write result and\n // raise events immediately (depending on whether the watcher is caught\n // up), so we raise user callbacks first so that they consistently happen\n // before listen events.\n this.processUserCallback(\n mutationBatchResult.batch.batchId,\n /*error=*/ null\n );\n\n return this.localStore\n .acknowledgeBatch(mutationBatchResult)\n .then(changes => {\n return this.emitNewSnapsAndNotifyLocalStore(changes);\n });\n }\n\n rejectFailedWrite(batchId: BatchId, error: FirestoreError): Promise {\n this.assertSubscribed('rejectFailedWrite()');\n\n // The local store may or may not be able to apply the write result and\n // raise events immediately (depending on whether the watcher is caught up),\n // so we raise user callbacks first so that they consistently happen before\n // listen events.\n this.processUserCallback(batchId, error);\n\n return this.localStore.rejectBatch(batchId).then(changes => {\n return this.emitNewSnapsAndNotifyLocalStore(changes);\n });\n }\n\n private addMutationCallback(\n batchId: BatchId,\n callback: Deferred\n ): void {\n let newCallbacks = this.mutationUserCallbacks[this.currentUser.toKey()];\n if (!newCallbacks) {\n newCallbacks = new SortedMap>(\n primitiveComparator\n );\n }\n newCallbacks = newCallbacks.insert(batchId, callback);\n this.mutationUserCallbacks[this.currentUser.toKey()] = newCallbacks;\n }\n\n /**\n * Resolves or rejects the user callback for the given batch and then discards\n * it.\n */\n private processUserCallback(batchId: BatchId, error: Error | null): void {\n let newCallbacks = this.mutationUserCallbacks[this.currentUser.toKey()];\n\n // NOTE: Mutations restored from persistence won't have callbacks, so it's\n // okay for there to be no callback for this ID.\n if (newCallbacks) {\n const callback = newCallbacks.get(batchId);\n if (callback) {\n assert(\n batchId === newCallbacks.minKey(),\n 'Mutation callbacks processed out-of-order?'\n );\n if (error) {\n callback.reject(error);\n } else {\n callback.resolve();\n }\n newCallbacks = newCallbacks.remove(batchId);\n }\n this.mutationUserCallbacks[this.currentUser.toKey()] = newCallbacks;\n }\n }\n\n private removeAndCleanupQuery(queryView: QueryView): Promise {\n this.queryViewsByQuery.delete(queryView.query);\n delete this.queryViewsByTarget[queryView.targetId];\n\n this.limboDocumentRefs.removeReferencesForId(queryView.targetId);\n return this.gcLimboDocuments();\n }\n\n private updateTrackedLimbos(\n targetId: TargetId,\n limboChanges: LimboDocumentChange[]\n ): Promise {\n for (const limboChange of limboChanges) {\n if (limboChange instanceof AddedLimboDocument) {\n this.limboDocumentRefs.addReference(limboChange.key, targetId);\n this.trackLimboChange(limboChange);\n } else if (limboChange instanceof RemovedLimboDocument) {\n log.debug(LOG_TAG, 'Document no longer in limbo: ' + limboChange.key);\n this.limboDocumentRefs.removeReference(limboChange.key, targetId);\n } else {\n fail('Unknown limbo change: ' + JSON.stringify(limboChange));\n }\n }\n return this.gcLimboDocuments();\n }\n\n private trackLimboChange(limboChange: AddedLimboDocument): void {\n const key = limboChange.key;\n if (!this.limboTargetsByKey.get(key)) {\n log.debug(LOG_TAG, 'New document in limbo: ' + key);\n const limboTargetId = this.targetIdGenerator.next();\n const query = Query.atPath(key.path);\n this.limboKeysByTarget[limboTargetId] = key;\n this.remoteStore.listen(\n new QueryData(query, limboTargetId, QueryPurpose.Listen)\n );\n this.limboTargetsByKey = this.limboTargetsByKey.insert(\n key,\n limboTargetId\n );\n }\n }\n\n private gcLimboDocuments(): Promise {\n // HACK: We can use a null transaction here, because we know that the\n // reference set is entirely within memory and doesn't need a store engine.\n return this.limboCollector\n .collectGarbage(null)\n .next(keys => {\n keys.forEach(key => {\n const limboTargetId = this.limboTargetsByKey.get(key);\n if (limboTargetId === null) {\n // This target already got removed, because the query failed.\n return;\n }\n this.remoteStore.unlisten(limboTargetId);\n this.limboTargetsByKey = this.limboTargetsByKey.remove(key);\n delete this.limboKeysByTarget[limboTargetId];\n });\n })\n .toPromise();\n }\n\n // Visible for testing\n currentLimboDocs(): SortedMap {\n return this.limboTargetsByKey;\n }\n\n private emitNewSnapsAndNotifyLocalStore(\n changes: MaybeDocumentMap,\n remoteEvent?: RemoteEvent\n ): Promise {\n const newSnaps: ViewSnapshot[] = [];\n const docChangesInAllViews: LocalViewChanges[] = [];\n const queriesProcessed: Array> = [];\n\n this.queryViewsByQuery.forEach((_, queryView) => {\n queriesProcessed.push(\n Promise.resolve()\n .then(() => {\n const viewDocChanges = queryView.view.computeDocChanges(changes);\n if (!viewDocChanges.needsRefill) {\n return viewDocChanges;\n }\n // The query has a limit and some docs were removed, so we need\n // to re-run the query against the local store to make sure we\n // didn't lose any good docs that had been past the limit.\n return this.localStore.executeQuery(queryView.query).then(docs => {\n return queryView.view.computeDocChanges(docs, viewDocChanges);\n });\n })\n .then((viewDocChanges: ViewDocumentChanges) => {\n const targetChange =\n remoteEvent && remoteEvent.targetChanges[queryView.targetId];\n const viewChange = queryView.view.applyChanges(\n viewDocChanges,\n targetChange\n );\n return this.updateTrackedLimbos(\n queryView.targetId,\n viewChange.limboChanges\n ).then(() => {\n if (viewChange.snapshot) {\n newSnaps.push(viewChange.snapshot);\n const docChanges = LocalViewChanges.fromSnapshot(\n viewChange.snapshot\n );\n docChangesInAllViews.push(docChanges);\n }\n });\n })\n );\n });\n\n return Promise.all(queriesProcessed)\n .then(() => {\n this.viewHandler!(newSnaps);\n return this.localStore.notifyLocalViewChanges(docChangesInAllViews);\n })\n .then(() => {\n return this.localStore.collectGarbage();\n });\n }\n\n private assertSubscribed(fnName: string): void {\n assert(\n this.viewHandler !== null && this.errorHandler !== null,\n 'Trying to call ' + fnName + ' before calling subscribe().'\n );\n }\n\n handleUserChange(user: User): Promise {\n this.currentUser = user;\n return this.localStore\n .handleUserChange(user)\n .then(changes => {\n return this.emitNewSnapsAndNotifyLocalStore(changes);\n })\n .then(() => {\n return this.remoteStore.handleUserChange(user);\n });\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/sync_engine.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { Timestamp } from '../core/timestamp';\nimport { BatchId, ProtoByteString } from '../core/types';\nimport {\n documentKeySet,\n DocumentKeySet,\n DocumentVersionMap,\n documentVersionMap\n} from './collections';\nimport { MaybeDocument } from './document';\nimport { DocumentKey } from './document_key';\nimport { Mutation, MutationResult } from './mutation';\nimport { assert } from '../util/assert';\nimport * as misc from '../util/misc';\n\nexport const BATCHID_UNKNOWN = -1;\n\n/**\n * A batch of mutations that will be sent as one unit to the backend.\n */\nexport class MutationBatch {\n constructor(\n public batchId: BatchId,\n public localWriteTime: Timestamp,\n public mutations: Mutation[]\n ) {}\n\n /**\n * Applies all the mutations in this MutationBatch to the specified document\n * to create a new remote document\n *\n * @param docKey The key of the document to apply mutations to.\n * @param maybeDoc The document to apply mutations to.\n * @param batchResult The result of applying the MutationBatch to the\n * backend.\n */\n applyToRemoteDocument(\n docKey: DocumentKey,\n maybeDoc: MaybeDocument | null,\n batchResult: MutationBatchResult\n ): MaybeDocument | null {\n if (maybeDoc) {\n assert(\n maybeDoc.key.equals(docKey),\n `applyToRemoteDocument: key ${docKey} should match maybeDoc key\n ${maybeDoc.key}`\n );\n }\n\n const mutationResults = batchResult.mutationResults;\n assert(\n mutationResults.length === this.mutations.length,\n `Mismatch between mutations length\n (${this.mutations.length}) and mutation results length\n (${mutationResults.length}).`\n );\n\n for (let i = 0; i < this.mutations.length; i++) {\n const mutation = this.mutations[i];\n if (mutation.key.equals(docKey)) {\n const mutationResult = mutationResults[i];\n maybeDoc = mutation.applyToRemoteDocument(maybeDoc, mutationResult);\n }\n }\n return maybeDoc;\n }\n\n /**\n * Computes the local view of a document given all the mutations in this\n * batch.\n *\n * @param docKey The key of the document to apply mutations to.\n * @param maybeDoc The document to apply mutations to.\n */\n applyToLocalView(\n docKey: DocumentKey,\n maybeDoc: MaybeDocument | null\n ): MaybeDocument | null {\n if (maybeDoc) {\n assert(\n maybeDoc.key.equals(docKey),\n `applyToLocalDocument: key ${docKey} should match maybeDoc key\n ${maybeDoc.key}`\n );\n }\n\n for (let i = 0; i < this.mutations.length; i++) {\n const mutation = this.mutations[i];\n if (mutation.key.equals(docKey)) {\n maybeDoc = mutation.applyToLocalView(maybeDoc, this.localWriteTime);\n }\n }\n return maybeDoc;\n }\n\n keys(): DocumentKeySet {\n let keySet = documentKeySet();\n\n for (const mutation of this.mutations) {\n keySet = keySet.add(mutation.key);\n }\n return keySet;\n }\n\n equals(other: MutationBatch): boolean {\n return (\n this.batchId === other.batchId &&\n misc.arrayEquals(this.mutations, other.mutations)\n );\n }\n\n /**\n * Returns true if this mutation batch has already been removed from the\n * mutation queue.\n *\n * Note that not all implementations of the MutationQueue necessarily use\n * tombstones as part of their implementation and generally speaking no code\n * outside the mutation queues should really care about this.\n */\n isTombstone(): boolean {\n return this.mutations.length === 0;\n }\n\n /** Converts this batch into a tombstone */\n toTombstone(): MutationBatch {\n return new MutationBatch(this.batchId, this.localWriteTime, []);\n }\n}\n\n/** The result of applying a mutation batch to the backend. */\nexport class MutationBatchResult {\n private constructor(\n readonly batch: MutationBatch,\n readonly commitVersion: SnapshotVersion,\n readonly mutationResults: MutationResult[],\n readonly streamToken: ProtoByteString,\n /**\n * A pre-computed mapping from each mutated document to the resulting\n * version.\n */\n readonly docVersions: DocumentVersionMap\n ) {}\n\n /**\n * Creates a new MutationBatchResult for the given batch and results. There\n * must be one result for each mutation in the batch. This static factory\n * caches a document=>version mapping (docVersions).\n */\n static from(\n batch: MutationBatch,\n commitVersion: SnapshotVersion,\n results: MutationResult[],\n streamToken: ProtoByteString\n ) {\n assert(\n batch.mutations.length === results.length,\n 'Mutations sent ' +\n batch.mutations.length +\n ' must equal results received ' +\n results.length\n );\n\n let versionMap = documentVersionMap();\n const mutations = batch.mutations;\n for (let i = 0; i < mutations.length; i++) {\n let version = results[i].version;\n if (version === null) {\n // deletes don't have a version, so we substitute the commitVersion\n // of the entire batch.\n version = commitVersion;\n }\n\n versionMap = versionMap.insert(mutations[i].key, version);\n }\n\n return new MutationBatchResult(\n batch,\n commitVersion,\n results,\n streamToken,\n versionMap\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/model/mutation_batch.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { DatabaseInfo } from '../core/database_info';\nimport { JsonProtoSerializer } from '../remote/serializer';\nimport { assert } from '../util/assert';\nimport { Code, FirestoreError } from '../util/error';\nimport * as log from '../util/log';\nimport { AutoId } from '../util/misc';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { IndexedDbMutationQueue } from './indexeddb_mutation_queue';\nimport { IndexedDbQueryCache } from './indexeddb_query_cache';\nimport { IndexedDbRemoteDocumentCache } from './indexeddb_remote_document_cache';\nimport { ALL_STORES, DbOwner, DbOwnerKey } from './indexeddb_schema';\nimport { createOrUpgradeDb, SCHEMA_VERSION } from './indexeddb_schema';\nimport { LocalSerializer } from './local_serializer';\nimport { MutationQueue } from './mutation_queue';\nimport { Persistence } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { QueryCache } from './query_cache';\nimport { RemoteDocumentCache } from './remote_document_cache';\nimport { SimpleDb, SimpleDbTransaction } from './simple_db';\n\nconst LOG_TAG = 'IndexedDbPersistence';\n\n/** If the owner lease is older than 5 seconds, try to take ownership. */\nconst OWNER_LEASE_MAX_AGE_MS = 5000;\n/** Refresh the owner lease every 4 seconds while owner. */\nconst OWNER_LEASE_REFRESH_INTERVAL_MS = 4000;\n\n/** LocalStorage location to indicate a zombied ownerId (see class comment). */\nconst ZOMBIE_OWNER_LOCALSTORAGE_SUFFIX = 'zombiedOwnerId';\n/** Error when the owner lease cannot be acquired or is lost. */\nconst EXISTING_OWNER_ERROR_MSG =\n 'There is another tab open with offline' +\n ' persistence enabled. Only one such tab is allowed at a time. The' +\n ' other tab must be closed or persistence must be disabled.';\nconst UNSUPPORTED_PLATFORM_ERROR_MSG =\n 'This platform is either missing' +\n ' IndexedDB or is known to have an incomplete implementation. Offline' +\n ' persistence has been disabled.';\n\n/**\n * An IndexedDB-backed instance of Persistence. Data is stored persistently\n * across sessions.\n *\n * Currently the Firestore SDK only supports a single consumer of the database,\n * but browsers obviously support multiple tabs. IndexedDbPersistence ensures a\n * single consumer of the database via an \"owner lease\" stored in the database.\n *\n * On startup, IndexedDbPersistence assigns itself a random \"ownerId\" and writes\n * it to a special \"owner\" object in the database (if no entry exists already or\n * the current entry is expired). This owner lease is then verified inside every\n * transaction to ensure the lease has not been lost.\n *\n * If a tab opts not to acquire the owner lease (because there's an existing\n * non-expired owner) or loses the owner lease, IndexedDbPersistence enters a\n * failed state and all subsequent operations will automatically fail.\n *\n * The current owner regularly refreshes the owner lease with new timestamps to\n * prevent newly-opened tabs from taking over ownership.\n *\n * Additionally there is an optimization so that when a tab is closed, the owner\n * lease is released immediately (this is especially important to make sure that\n * a refreshed tab is able to immediately re-acquire the owner lease).\n * Unfortunately, IndexedDB cannot be reliably used in window.unload since it is\n * an asynchronous API. So in addition to attempting to give up the lease,\n * the owner writes its ownerId to a \"zombiedOwnerId\" entry in LocalStorage\n * which acts as an indicator that another tab should go ahead and take the\n * owner lease immediately regardless of the current lease timestamp.\n */\nexport class IndexedDbPersistence implements Persistence {\n /**\n * The name of the main (and currently only) IndexedDB database. this name is\n * appended to the prefix provided to the IndexedDbPersistence constructor.\n */\n static MAIN_DATABASE = 'main';\n\n private simpleDb: SimpleDb;\n private started: boolean;\n private dbName: string;\n private localStoragePrefix: string;\n private ownerId: string = this.generateOwnerId();\n\n /**\n * Set to an Error object if we encounter an unrecoverable error. All further\n * transactions will be failed with this error.\n */\n private persistenceError: Error | null;\n /** The setInterval() handle tied to refreshing the owner lease. */\n // tslint:disable-next-line:no-any setTimeout() type differs on browser / node\n private ownerLeaseRefreshHandle: any;\n /** Our window.unload handler, if registered. */\n private windowUnloadHandler: (() => void) | null;\n\n private serializer: LocalSerializer;\n\n constructor(prefix: string, serializer: JsonProtoSerializer) {\n this.dbName = prefix + IndexedDbPersistence.MAIN_DATABASE;\n this.serializer = new LocalSerializer(serializer);\n this.localStoragePrefix = prefix;\n }\n\n start(): Promise {\n if (!IndexedDbPersistence.isAvailable()) {\n this.persistenceError = new FirestoreError(\n Code.UNIMPLEMENTED,\n UNSUPPORTED_PLATFORM_ERROR_MSG\n );\n return Promise.reject(this.persistenceError);\n }\n\n assert(!this.started, 'IndexedDbPersistence double-started!');\n this.started = true;\n\n return SimpleDb.openOrCreate(this.dbName, SCHEMA_VERSION, createOrUpgradeDb)\n .then(db => {\n this.simpleDb = db;\n })\n .then(() => this.tryAcquireOwnerLease())\n .then(() => {\n this.scheduleOwnerLeaseRefreshes();\n this.attachWindowUnloadHook();\n });\n }\n\n shutdown(): Promise {\n assert(this.started, 'IndexedDbPersistence shutdown without start!');\n this.started = false;\n this.detachWindowUnloadHook();\n this.stopOwnerLeaseRefreshes();\n return this.releaseOwnerLease().then(() => {\n this.simpleDb.close();\n });\n }\n\n getMutationQueue(user: User): MutationQueue {\n return IndexedDbMutationQueue.forUser(user, this.serializer);\n }\n\n getQueryCache(): QueryCache {\n return new IndexedDbQueryCache(this.serializer);\n }\n\n getRemoteDocumentCache(): RemoteDocumentCache {\n return new IndexedDbRemoteDocumentCache(this.serializer);\n }\n\n runTransaction(\n action: string,\n operation: (transaction: SimpleDbTransaction) => PersistencePromise\n ): Promise {\n if (this.persistenceError) {\n return Promise.reject(this.persistenceError);\n }\n\n log.debug(LOG_TAG, 'Starting transaction:', action);\n\n // Do all transactions as readwrite against all object stores, since we\n // are the only reader/writer.\n return this.simpleDb.runTransaction('readwrite', ALL_STORES, txn => {\n // Verify that we still have the owner lease as part of every transaction.\n return this.ensureOwnerLease(txn).next(() => operation(txn));\n });\n }\n\n static isAvailable(): boolean {\n return SimpleDb.isAvailable();\n }\n\n /**\n * Generates a string used as a prefix when storing data in IndexedDB and\n * LocalStorage.\n */\n static buildStoragePrefix(databaseInfo: DatabaseInfo): string {\n // Use two different prefix formats:\n //\n // * firestore / persistenceKey / projectID . databaseID / ...\n // * firestore / persistenceKey / projectID / ...\n //\n // projectIDs are DNS-compatible names and cannot contain dots\n // so there's no danger of collisions.\n let database = databaseInfo.databaseId.projectId;\n if (!databaseInfo.databaseId.isDefaultDatabase) {\n database += '.' + databaseInfo.databaseId.database;\n }\n\n return 'firestore/' + databaseInfo.persistenceKey + '/' + database + '/';\n }\n\n /**\n * Acquires the owner lease if there's no valid owner. Else returns a rejected\n * promise.\n */\n private tryAcquireOwnerLease(): Promise {\n // NOTE: Don't use this.runTransaction, since it requires us to already\n // have the lease.\n return this.simpleDb.runTransaction('readwrite', [DbOwner.store], txn => {\n const store = txn.store(DbOwner.store);\n return store.get('owner').next(dbOwner => {\n if (!this.validOwner(dbOwner)) {\n const newDbOwner = new DbOwner(this.ownerId, Date.now());\n log.debug(\n LOG_TAG,\n 'No valid owner. Acquiring owner lease. Current owner:',\n dbOwner,\n 'New owner:',\n newDbOwner\n );\n return store.put('owner', newDbOwner);\n } else {\n log.debug(\n LOG_TAG,\n 'Valid owner already. Failing. Current owner:',\n dbOwner\n );\n this.persistenceError = new FirestoreError(\n Code.FAILED_PRECONDITION,\n EXISTING_OWNER_ERROR_MSG\n );\n return PersistencePromise.reject(this.persistenceError);\n }\n });\n });\n }\n\n /** Checks the owner lease and deletes it if we are the current owner. */\n private releaseOwnerLease(): Promise {\n // NOTE: Don't use this.runTransaction, since it requires us to already\n // have the lease.\n return this.simpleDb.runTransaction('readwrite', [DbOwner.store], txn => {\n const store = txn.store(DbOwner.store);\n return store.get('owner').next(dbOwner => {\n if (dbOwner !== null && dbOwner.ownerId === this.ownerId) {\n log.debug(LOG_TAG, 'Releasing owner lease.');\n return store.delete('owner');\n } else {\n return PersistencePromise.resolve();\n }\n });\n });\n }\n\n /**\n * Checks the owner lease and returns a rejected promise if we are not the\n * current owner. This should be included in every transaction to guard\n * against losing the owner lease.\n */\n private ensureOwnerLease(txn: SimpleDbTransaction): PersistencePromise {\n const store = txn.store(DbOwner.store);\n return store.get('owner').next(dbOwner => {\n if (dbOwner === null || dbOwner.ownerId !== this.ownerId) {\n this.persistenceError = new FirestoreError(\n Code.FAILED_PRECONDITION,\n EXISTING_OWNER_ERROR_MSG\n );\n return PersistencePromise.reject(this.persistenceError);\n } else {\n return PersistencePromise.resolve();\n }\n });\n }\n\n /**\n * Returns true if the provided owner exists, has a recent timestamp, and\n * isn't zombied.\n *\n * NOTE: To determine if the owner is zombied, this method reads from\n * LocalStorage which could be mildly expensive.\n */\n private validOwner(dbOwner: DbOwner | null): boolean {\n const now = Date.now();\n const minAcceptable = now - OWNER_LEASE_MAX_AGE_MS;\n const maxAcceptable = now;\n if (dbOwner === null) {\n return false; // no owner.\n } else if (dbOwner.leaseTimestampMs < minAcceptable) {\n return false; // owner lease has expired.\n } else if (dbOwner.leaseTimestampMs > maxAcceptable) {\n log.error(\n 'Persistence owner-lease is in the future. Discarding.',\n dbOwner\n );\n return false;\n } else if (dbOwner.ownerId === this.getZombiedOwnerId()) {\n return false; // owner's tab closed.\n } else {\n return true;\n }\n }\n\n /**\n * Schedules a recurring timer to update the owner lease timestamp to prevent\n * other tabs from taking the lease.\n */\n private scheduleOwnerLeaseRefreshes(): void {\n // NOTE: This doesn't need to be scheduled on the async queue and doing so\n // would increase the chances of us not refreshing on time if the queue is\n // backed up for some reason.\n this.ownerLeaseRefreshHandle = setInterval(() => {\n const txResult = this.runTransaction('Refresh owner timestamp', txn => {\n // NOTE: We don't need to validate the current owner contents, since\n // runTransaction does that automatically.\n const store = txn.store(DbOwner.store);\n return store.put('owner', new DbOwner(this.ownerId, Date.now()));\n });\n\n txResult.catch(reason => {\n // Probably means we lost the lease. Report the error and stop trying to\n // refresh the lease.\n log.error(reason);\n this.stopOwnerLeaseRefreshes();\n });\n }, OWNER_LEASE_REFRESH_INTERVAL_MS);\n }\n\n private stopOwnerLeaseRefreshes(): void {\n if (this.ownerLeaseRefreshHandle) {\n clearInterval(this.ownerLeaseRefreshHandle);\n this.ownerLeaseRefreshHandle = null;\n }\n }\n\n /**\n * Attaches a window.unload handler that will synchronously write our\n * ownerId to a \"zombie owner id\" location in localstorage. This can be used\n * by tabs trying to acquire the lease to determine that the lease should be\n * acquired immediately even if the timestamp is recent. This is particularly\n * important for the refresh case (so the tab correctly re-acquires the owner\n * lease). LocalStorage is used for this rather than IndexedDb because it is\n * a synchronous API and so can be used reliably from an unload handler.\n */\n private attachWindowUnloadHook(): void {\n this.windowUnloadHandler = () => {\n // Record that we're zombied.\n this.setZombiedOwnerId(this.ownerId);\n\n // Attempt graceful shutdown (including releasing our owner lease), but\n // there's no guarantee it will complete.\n this.shutdown();\n };\n window.addEventListener('unload', this.windowUnloadHandler);\n }\n\n private detachWindowUnloadHook(): void {\n if (this.windowUnloadHandler) {\n window.removeEventListener('unload', this.windowUnloadHandler);\n this.windowUnloadHandler = null;\n }\n }\n\n /**\n * Returns any recorded \"zombied owner\" (i.e. a previous owner that became\n * zombied due to their tab closing) from LocalStorage, or null if no such\n * record exists.\n */\n private getZombiedOwnerId(): string | null {\n try {\n const zombiedOwnerId = window.localStorage.getItem(\n this.zombiedOwnerLocalStorageKey()\n );\n log.debug(LOG_TAG, 'Zombied ownerID from LocalStorage:', zombiedOwnerId);\n return zombiedOwnerId;\n } catch (e) {\n // Gracefully handle if LocalStorage isn't available / working.\n log.error(LOG_TAG, 'Failed to get zombie owner id.', e);\n return null;\n }\n }\n\n /**\n * Records a zombied owner (an owner that had its tab closed) in LocalStorage\n * or, if passed null, deletes any recorded zombied owner.\n */\n private setZombiedOwnerId(zombieOwnerId: string | null) {\n try {\n if (zombieOwnerId === null) {\n window.localStorage.removeItem(this.zombiedOwnerLocalStorageKey());\n } else {\n window.localStorage.setItem(\n this.zombiedOwnerLocalStorageKey(),\n zombieOwnerId\n );\n }\n } catch (e) {\n // Gracefully handle if LocalStorage isn't available / working.\n log.error(LOG_TAG, 'Failed to set zombie owner id.', e);\n }\n }\n\n private zombiedOwnerLocalStorageKey(): string {\n return this.localStoragePrefix + ZOMBIE_OWNER_LOCALSTORAGE_SUFFIX;\n }\n\n private generateOwnerId(): string {\n // For convenience, just use an AutoId.\n return AutoId.newId();\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/indexeddb_persistence.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport {\n documentKeySet,\n DocumentKeySet,\n DocumentMap,\n documentMap,\n MaybeDocumentMap,\n maybeDocumentMap\n} from '../model/collections';\nimport { Document, MaybeDocument, NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { ResourcePath } from '../model/path';\nimport { fail } from '../util/assert';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { MutationQueue } from './mutation_queue';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { RemoteDocumentCache } from './remote_document_cache';\n\n/**\n * A readonly view of the local state of all documents we're tracking (i.e. we\n * have a cached version in remoteDocumentCache or local mutations for the\n * document). The view is computed by applying the mutations in the\n * MutationQueue to the RemoteDocumentCache.\n */\nexport class LocalDocumentsView {\n constructor(\n private remoteDocumentCache: RemoteDocumentCache,\n private mutationQueue: MutationQueue\n ) {}\n\n /**\n * Get the local view of the document identified by `key`.\n *\n * @return Local view of the document or null if we don't have any cached\n * state for it.\n */\n getDocument(\n transaction: PersistenceTransaction,\n key: DocumentKey\n ): PersistencePromise {\n return this.remoteDocumentCache\n .getEntry(transaction, key)\n .next(remoteDoc => {\n return this.computeLocalDocument(transaction, key, remoteDoc);\n });\n }\n\n /**\n * Gets the local view of the documents identified by `keys`.\n *\n * If we don't have cached state for a document in `keys`, a NoDocument will\n * be stored for that key in the resulting set.\n */\n getDocuments(\n transaction: PersistenceTransaction,\n keys: DocumentKeySet\n ): PersistencePromise {\n const promises = [] as Array>;\n let results = maybeDocumentMap();\n keys.forEach(key => {\n promises.push(\n this.getDocument(transaction, key).next(maybeDoc => {\n // TODO(http://b/32275378): Don't conflate missing / deleted.\n if (!maybeDoc) {\n maybeDoc = new NoDocument(key, SnapshotVersion.forDeletedDoc());\n }\n results = results.insert(key, maybeDoc);\n })\n );\n });\n return PersistencePromise.waitFor(promises).next(() => results);\n }\n\n /** Performs a query against the local view of all documents. */\n getDocumentsMatchingQuery(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n if (DocumentKey.isDocumentKey(query.path)) {\n return this.getDocumentsMatchingDocumentQuery(transaction, query.path);\n } else {\n return this.getDocumentsMatchingCollectionQuery(transaction, query);\n }\n }\n\n private getDocumentsMatchingDocumentQuery(\n transaction: PersistenceTransaction,\n docPath: ResourcePath\n ): PersistencePromise {\n // Just do a simple document lookup.\n return this.getDocument(\n transaction,\n new DocumentKey(docPath)\n ).next(maybeDoc => {\n let result = documentMap();\n if (maybeDoc instanceof Document) {\n result = result.insert(maybeDoc.key, maybeDoc);\n }\n return result;\n });\n }\n\n private getDocumentsMatchingCollectionQuery(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n // Query the remote documents and overlay mutations.\n // TODO(mikelehen): There may be significant overlap between the mutations\n // affecting these remote documents and the\n // getAllMutationBatchesAffectingQuery() mutations. Consider optimizing.\n let results: DocumentMap;\n return this.remoteDocumentCache\n .getDocumentsMatchingQuery(transaction, query)\n .next(queryResults => {\n return this.computeLocalDocuments(transaction, queryResults);\n })\n .next(promisedResults => {\n results = promisedResults;\n // Now use the mutation queue to discover any other documents that may\n // match the query after applying mutations.\n return this.mutationQueue.getAllMutationBatchesAffectingQuery(\n transaction,\n query\n );\n })\n .next(matchingMutationBatches => {\n let matchingKeys = documentKeySet();\n for (const batch of matchingMutationBatches) {\n for (const mutation of batch.mutations) {\n // TODO(mikelehen): PERF: Check if this mutation actually\n // affects the query to reduce work.\n if (!results.get(mutation.key)) {\n matchingKeys = matchingKeys.add(mutation.key);\n }\n }\n }\n\n // Now add in the results for the matchingKeys.\n const promises = [] as Array>;\n matchingKeys.forEach(key => {\n promises.push(\n this.getDocument(transaction, key).next(doc => {\n if (doc instanceof Document) {\n results = results.insert(doc.key, doc);\n }\n })\n );\n });\n return PersistencePromise.waitFor(promises);\n })\n .next(() => {\n // Finally, filter out any documents that don't actually match\n // the query.\n results.forEach((key, doc) => {\n if (!query.matches(doc)) {\n results = results.remove(key);\n }\n });\n\n return results;\n });\n }\n\n /**\n * Takes a remote document and applies local mutations to generate the local\n * view of the document.\n * @param transaction The transaction in which to perform any persistence\n * operations.\n * @param documentKey The key of the document (necessary when remoteDocument\n * is null).\n * @param document The base remote document to apply mutations to or null.\n */\n private computeLocalDocument(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey,\n document: MaybeDocument | null\n ): PersistencePromise {\n return this.mutationQueue\n .getAllMutationBatchesAffectingDocumentKey(transaction, documentKey)\n .next(batches => {\n for (const batch of batches) {\n document = batch.applyToLocalView(documentKey, document);\n }\n return document;\n });\n }\n\n /**\n * Takes a set of remote documents and applies local mutations to generate the\n * local view of the documents.\n * @param transaction The transaction in which to perform any persistence\n * operations.\n * @param documents The base remote documents to apply mutations to.\n * @return The local view of the documents.\n */\n private computeLocalDocuments(\n transaction: PersistenceTransaction,\n documents: DocumentMap\n ): PersistencePromise {\n const promises = [] as Array>;\n documents.forEach((key, doc) => {\n promises.push(\n this.computeLocalDocument(transaction, key, doc).next(mutatedDoc => {\n if (mutatedDoc instanceof Document) {\n documents = documents.insert(mutatedDoc.key, mutatedDoc);\n } else if (mutatedDoc instanceof NoDocument) {\n documents = documents.remove(mutatedDoc.key);\n } else {\n fail('Unknown MaybeDocument: ' + mutatedDoc);\n }\n })\n );\n });\n return PersistencePromise.waitFor(promises).next(() => documents);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/local_documents_view.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { MaybeDocumentMap, maybeDocumentMap } from '../model/collections';\nimport { MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { assert } from '../util/assert';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { RemoteDocumentCache } from './remote_document_cache';\n\n/**\n * An in-memory buffer of entries to be written to a RemoteDocumentCache.\n * It can be used to batch up a set of changes to be written to the cache, but\n * additionally supports reading entries back with the `getEntry()` method,\n * falling back to the underlying RemoteDocumentCache if no entry is\n * buffered.\n *\n * NOTE: This class was introduced in iOS to work around a limitation in\n * LevelDB. Given IndexedDb has full transaction support with\n * read-your-own-writes capability, this class is not technically needed, but\n * has been preserved as a convenience and to aid portability.\n */\nexport class RemoteDocumentChangeBuffer {\n private changes: MaybeDocumentMap | null = maybeDocumentMap();\n\n constructor(private remoteDocumentCache: RemoteDocumentCache) {}\n\n /** Buffers a `RemoteDocumentCache.addEntry()` call. */\n addEntry(maybeDocument: MaybeDocument): void {\n const changes = this.assertChanges();\n this.changes = changes.insert(maybeDocument.key, maybeDocument);\n }\n\n // NOTE: removeEntry() is not presently necessary and so is omitted.\n\n /**\n * Looks up an entry in the cache. The buffered changes will first be checked,\n * and if no buffered change applies, this will forward to\n * `RemoteDocumentCache.getEntry()`.\n *\n * @param transaction The transaction in which to perform any persistence\n * operations.\n * @param documentKey The key of the entry to look up.\n * @return The cached Document or NoDocument entry, or null if we have nothing\n * cached.\n */\n getEntry(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n const changes = this.assertChanges();\n\n const bufferedEntry = changes.get(documentKey);\n if (bufferedEntry) {\n return PersistencePromise.resolve(bufferedEntry);\n } else {\n return this.remoteDocumentCache.getEntry(transaction, documentKey);\n }\n }\n\n /**\n * Applies buffered changes to the underlying RemoteDocumentCache, using\n * the provided transaction.\n */\n apply(transaction: PersistenceTransaction): PersistencePromise {\n const changes = this.assertChanges();\n\n const promises: Array> = [];\n changes.forEach((key, maybeDoc) => {\n promises.push(this.remoteDocumentCache.addEntry(transaction, maybeDoc));\n });\n\n // We should not be used to buffer any more changes.\n this.changes = null;\n\n return PersistencePromise.waitFor(promises);\n }\n\n /** Helper to assert this.changes is not null and return it. */\n private assertChanges(): MaybeDocumentMap {\n assert(this.changes !== null, 'Changes have already been applied.');\n return this.changes!;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/remote_document_change_buffer.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { Query } from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { TargetIdGenerator } from '../core/target_id_generator';\nimport { Timestamp } from '../core/timestamp';\nimport { BatchId, ProtoByteString, TargetId } from '../core/types';\nimport {\n DocumentKeySet,\n documentKeySet,\n DocumentMap,\n MaybeDocumentMap\n} from '../model/collections';\nimport { MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { Mutation } from '../model/mutation';\nimport {\n BATCHID_UNKNOWN,\n MutationBatch,\n MutationBatchResult\n} from '../model/mutation_batch';\nimport {\n RemoteEvent,\n ResetMapping,\n TargetChange,\n UpdateMapping\n} from '../remote/remote_event';\nimport { assert, fail } from '../util/assert';\nimport * as log from '../util/log';\nimport * as objUtils from '../util/obj';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { GarbageCollector } from './garbage_collector';\nimport { LocalDocumentsView } from './local_documents_view';\nimport { LocalViewChanges } from './local_view_changes';\nimport { MutationQueue } from './mutation_queue';\nimport { Persistence, PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { QueryCache } from './query_cache';\nimport { QueryData, QueryPurpose } from './query_data';\nimport { ReferenceSet } from './reference_set';\nimport { RemoteDocumentCache } from './remote_document_cache';\nimport { RemoteDocumentChangeBuffer } from './remote_document_change_buffer';\n\nconst LOG_TAG = 'LocalStore';\n\n/** The result of a write to the local store. */\nexport interface LocalWriteResult {\n batchId: BatchId;\n changes: MaybeDocumentMap;\n}\n\n/**\n * Local storage in the Firestore client. Coordinates persistence components\n * like the mutation queue and remote document cache to present a\n * latency-compensated view of stored data.\n *\n * The LocalStore is responsible for accepting mutations from the Sync Engine.\n * Writes from the client are put into a queue as provisional Mutations until\n * they are processed by the RemoteStore and confirmed as having been written\n * to the server.\n *\n * The local store provides the local version of documents that have been\n * modified locally. It maintains the constraint:\n *\n * LocalDocument = RemoteDocument + Active(LocalMutations)\n *\n * (Active mutations are those that are enqueued and have not been previously\n * acknowledged or rejected).\n *\n * The RemoteDocument (\"ground truth\") state is provided via the\n * applyChangeBatch method. It will be some version of a server-provided\n * document OR will be a server-provided document PLUS acknowledged mutations:\n *\n * RemoteDocument' = RemoteDocument + Acknowledged(LocalMutations)\n *\n * Note that this \"dirty\" version of a RemoteDocument will not be identical to a\n * server base version, since it has LocalMutations added to it pending getting\n * an authoritative copy from the server.\n *\n * Since LocalMutations can be rejected by the server, we have to be able to\n * revert a LocalMutation that has already been applied to the LocalDocument\n * (typically done by replaying all remaining LocalMutations to the\n * RemoteDocument to re-apply).\n *\n * The LocalStore is responsible for the garbage collection of the documents it\n * contains. For now, it every doc referenced by a view, the mutation queue, or\n * the RemoteStore.\n *\n * It also maintains the persistence of mapping queries to resume tokens and\n * target ids. It needs to know this data about queries to properly know what\n * docs it would be allowed to garbage collect.\n *\n * The LocalStore must be able to efficiently execute queries against its local\n * cache of the documents, to provide the initial set of results before any\n * remote changes have been received.\n *\n * Note: In TypeScript, most methods return Promises since the implementation\n * may rely on fetching data from IndexedDB which is async.\n * These Promises will only be rejected on an I/O error or other internal\n * (unexpected) failure (e.g. failed assert) and always represent an\n * unrecoverable error (should be caught / reported by the async_queue).\n */\nexport class LocalStore {\n /**\n * The set of all mutations that have been sent but not yet been applied to\n * the backend.\n */\n private mutationQueue: MutationQueue;\n\n /** The set of all cached remote documents. */\n private remoteDocuments: RemoteDocumentCache;\n\n /**\n * The \"local\" view of all documents (layering mutationQueue on top of\n * remoteDocumentCache).\n */\n private localDocuments: LocalDocumentsView;\n\n /**\n * The set of document references maintained by any local views.\n */\n private localViewReferences = new ReferenceSet();\n\n /** Maps a query to the data about that query. */\n private queryCache: QueryCache;\n\n /** Maps a targetID to data about its query. */\n private targetIds = {} as { [targetId: number]: QueryData };\n\n /** Used to generate targetIDs for queries tracked locally. */\n private targetIdGenerator = TargetIdGenerator.forLocalStore();\n\n /**\n * A heldBatchResult is a mutation batch result (from a write acknowledgement)\n * that arrived before the watch stream got notified of a snapshot that\n * includes the write. So we \"hold\" it until the watch stream catches up. It\n * ensures that the local write remains visible (latency compensation) and\n * doesn't temporarily appear reverted because the watch stream is slower than\n * the write stream and so wasn't reflecting it.\n *\n * NOTE: Eventually we want to move this functionality into the remote store.\n */\n private heldBatchResults: MutationBatchResult[] = [];\n\n constructor(\n /** Manages our in-memory or durable persistence. */\n private persistence: Persistence,\n initialUser: User,\n /**\n * The garbage collector collects documents that should no longer be\n * cached (e.g. if they are no longer retained by the above reference sets\n * and the garbage collector is performing eager collection).\n */\n private garbageCollector: GarbageCollector\n ) {\n this.mutationQueue = persistence.getMutationQueue(initialUser);\n this.remoteDocuments = persistence.getRemoteDocumentCache();\n this.queryCache = persistence.getQueryCache();\n this.localDocuments = new LocalDocumentsView(\n this.remoteDocuments,\n this.mutationQueue\n );\n this.garbageCollector.addGarbageSource(this.localViewReferences);\n this.garbageCollector.addGarbageSource(this.queryCache);\n this.garbageCollector.addGarbageSource(this.mutationQueue);\n }\n\n /** Performs any initial startup actions required by the local store. */\n start(): Promise {\n return this.persistence.runTransaction('Start LocalStore', txn => {\n return this.startMutationQueue(txn).next(() => this.startQueryCache(txn));\n });\n }\n\n /**\n * Tells the LocalStore that the currently authenticated user has changed.\n *\n * In response the local store switches the mutation queue to the new user and\n * returns any resulting document changes.\n */\n handleUserChange(user: User): Promise {\n return this.persistence.runTransaction('Handle user change', txn => {\n // Swap out the mutation queue, grabbing the pending mutation batches\n // before and after.\n let oldBatches: MutationBatch[];\n return this.mutationQueue\n .getAllMutationBatches(txn)\n .next(promisedOldBatches => {\n oldBatches = promisedOldBatches;\n\n this.garbageCollector.removeGarbageSource(this.mutationQueue);\n this.mutationQueue = this.persistence.getMutationQueue(user);\n this.garbageCollector.addGarbageSource(this.mutationQueue);\n return this.startMutationQueue(txn);\n })\n .next(() => {\n // Recreate our LocalDocumentsView using the new\n // MutationQueue.\n this.localDocuments = new LocalDocumentsView(\n this.remoteDocuments,\n this.mutationQueue\n );\n return this.mutationQueue.getAllMutationBatches(txn);\n })\n .next(newBatches => {\n // Union the old/new changed keys.\n let changedKeys = documentKeySet();\n for (const batches of [oldBatches, newBatches]) {\n for (const batch of batches) {\n for (const mutation of batch.mutations) {\n changedKeys = changedKeys.add(mutation.key);\n }\n }\n }\n\n // Return the set of all (potentially) changed documents as the\n // result of the user change.\n return this.localDocuments.getDocuments(txn, changedKeys);\n });\n });\n }\n\n private startQueryCache(\n txn: PersistenceTransaction\n ): PersistencePromise {\n return this.queryCache.start(txn).next(() => {\n const targetId = this.queryCache.getHighestTargetId();\n this.targetIdGenerator = TargetIdGenerator.forLocalStore(targetId);\n });\n }\n\n private startMutationQueue(\n txn: PersistenceTransaction\n ): PersistencePromise {\n return this.mutationQueue\n .start(txn)\n .next(() => {\n // If we have any leftover mutation batch results from a prior run,\n // just drop them.\n // TODO(http://b/33446471): We probably need to repopulate\n // heldBatchResults or similar instead, but that is not\n // straightforward since we're not persisting the write ack versions.\n this.heldBatchResults = [];\n return this.mutationQueue.getHighestAcknowledgedBatchId(txn);\n })\n .next(highestAck => {\n // TODO(mikelehen): This is the only usage of\n // getAllMutationBatchesThroughBatchId(). Consider removing it in\n // favor of a getAcknowledgedBatches() method.\n if (highestAck !== BATCHID_UNKNOWN) {\n return this.mutationQueue.getAllMutationBatchesThroughBatchId(\n txn,\n highestAck\n );\n } else {\n return PersistencePromise.resolve([]);\n }\n })\n .next(ackedBatches => {\n if (ackedBatches.length > 0) {\n return this.mutationQueue.removeMutationBatches(txn, ackedBatches);\n } else {\n return PersistencePromise.resolve();\n }\n });\n }\n\n /* Accept locally generated Mutations and commit them to storage. */\n localWrite(mutations: Mutation[]): Promise {\n return this.persistence.runTransaction('Locally write mutations', txn => {\n let batch: MutationBatch;\n const localWriteTime = Timestamp.now();\n return this.mutationQueue\n .addMutationBatch(txn, localWriteTime, mutations)\n .next(promisedBatch => {\n batch = promisedBatch;\n // TODO(koss): This is doing an N^2 update by replaying ALL the\n // mutations on each document (instead of just the ones added) in\n // this batch.\n const keys = batch.keys();\n return this.localDocuments.getDocuments(txn, keys);\n })\n .next((changedDocuments: MaybeDocumentMap) => {\n return { batchId: batch.batchId, changes: changedDocuments };\n });\n });\n }\n\n /**\n * Acknowledge the given batch.\n *\n * On the happy path when a batch is acknowledged, the local store will\n *\n * + remove the batch from the mutation queue;\n * + apply the changes to the remote document cache;\n * + recalculate the latency compensated view implied by those changes (there\n * may be mutations in the queue that affect the documents but haven't been\n * acknowledged yet); and\n * + give the changed documents back the sync engine\n *\n * @returns The resulting (modified) documents.\n */\n acknowledgeBatch(\n batchResult: MutationBatchResult\n ): Promise {\n return this.persistence.runTransaction('Acknowledge batch', txn => {\n let affected: DocumentKeySet;\n return this.mutationQueue\n .acknowledgeBatch(txn, batchResult.batch, batchResult.streamToken)\n .next(() => {\n if (this.shouldHoldBatchResult(batchResult.commitVersion)) {\n this.heldBatchResults.push(batchResult);\n affected = documentKeySet();\n return PersistencePromise.resolve();\n } else {\n const documentBuffer = new RemoteDocumentChangeBuffer(\n this.remoteDocuments\n );\n return this.releaseBatchResults(\n txn,\n [batchResult],\n documentBuffer\n ).next(promisedAffectedKeys => {\n affected = promisedAffectedKeys;\n return documentBuffer.apply(txn);\n });\n }\n })\n .next(() => {\n return this.mutationQueue.performConsistencyCheck(txn);\n })\n .next(() => {\n return this.localDocuments.getDocuments(txn, affected);\n });\n });\n }\n\n /**\n * Remove mutations from the MutationQueue for the specified batch;\n * LocalDocuments will be recalculated.\n *\n * @returns The resulting modified documents.\n */\n rejectBatch(batchId: BatchId): Promise {\n return this.persistence.runTransaction('Reject batch', txn => {\n let toReject: MutationBatch;\n let affectedKeys: DocumentKeySet;\n return this.mutationQueue\n .lookupMutationBatch(txn, batchId)\n .next((promisedToReject: MutationBatch | null) => {\n assert(\n promisedToReject != null,\n 'Attempt to reject nonexistent batch!'\n );\n toReject = promisedToReject!;\n\n return this.mutationQueue\n .getHighestAcknowledgedBatchId(txn)\n .next(lastAcked => {\n assert(\n batchId > lastAcked,\n \"Acknowledged batches can't be rejected.\"\n );\n return toReject;\n });\n })\n .next(() => {\n return this.removeMutationBatch(txn, toReject);\n })\n .next(promisedAffectedKeys => {\n affectedKeys = promisedAffectedKeys;\n return this.mutationQueue.performConsistencyCheck(txn);\n })\n .next(() => {\n return this.localDocuments.getDocuments(txn, affectedKeys);\n });\n });\n }\n\n /** Returns the last recorded stream token for the current user. */\n getLastStreamToken(): Promise {\n return this.persistence.runTransaction('Get last stream token', txn => {\n return this.mutationQueue.getLastStreamToken(txn);\n });\n }\n\n /**\n * Sets the stream token for the current user without acknowledging any\n * mutation batch. This is usually only useful after a stream handshake or in\n * response to an error that requires clearing the stream token.\n */\n setLastStreamToken(streamToken: ProtoByteString): Promise {\n return this.persistence.runTransaction('Set last stream token', txn => {\n return this.mutationQueue.setLastStreamToken(txn, streamToken);\n });\n }\n\n /**\n * Returns the last consistent snapshot processed (used by the RemoteStore to\n * determine whether to buffer incoming snapshots from the backend).\n */\n getLastRemoteSnapshotVersion(): SnapshotVersion {\n return this.queryCache.getLastRemoteSnapshotVersion();\n }\n\n /**\n * Update the \"ground-state\" (remote) documents. We assume that the remote\n * event reflects any write batches that have been acknowledged or rejected\n * (i.e. we do not re-apply local mutations to updates from this event).\n *\n * LocalDocuments are re-calculated if there are remaining mutations in the\n * queue.\n */\n applyRemoteEvent(remoteEvent: RemoteEvent): Promise {\n const documentBuffer = new RemoteDocumentChangeBuffer(this.remoteDocuments);\n return this.persistence.runTransaction('Apply remote event', txn => {\n const promises = [] as Array>;\n objUtils.forEachNumber(\n remoteEvent.targetChanges,\n (targetId: TargetId, change: TargetChange) => {\n // Do not ref/unref unassigned targetIds - it may lead to leaks.\n let queryData = this.targetIds[targetId];\n if (!queryData) return;\n\n const mapping: UpdateMapping | ResetMapping = change.mapping;\n if (mapping) {\n // First make sure that all references are deleted\n if (mapping instanceof ResetMapping) {\n promises.push(\n this.queryCache\n .removeMatchingKeysForTargetId(txn, targetId)\n .next(() => {\n return this.queryCache.addMatchingKeys(\n txn,\n mapping.documents,\n targetId\n );\n })\n );\n } else if (mapping instanceof UpdateMapping) {\n promises.push(\n this.queryCache\n .removeMatchingKeys(txn, mapping.removedDocuments, targetId)\n .next(() => {\n return this.queryCache.addMatchingKeys(\n txn,\n mapping.addedDocuments,\n targetId\n );\n })\n );\n } else {\n return fail('Unknown mapping type: ' + JSON.stringify(mapping));\n }\n }\n\n // Update the resume token if the change includes one. Don't clear\n // any preexisting value.\n const resumeToken = change.resumeToken;\n if (resumeToken.length > 0) {\n queryData = queryData.update({\n resumeToken,\n snapshotVersion: change.snapshotVersion\n });\n this.targetIds[targetId] = queryData;\n promises.push(this.queryCache.addQueryData(txn, queryData));\n }\n }\n );\n\n let changedDocKeys = documentKeySet();\n remoteEvent.documentUpdates.forEach((key, doc) => {\n changedDocKeys = changedDocKeys.add(key);\n promises.push(\n documentBuffer.getEntry(txn, key).next(existingDoc => {\n // Make sure we don't apply an old document version to the remote\n // cache, though we make an exception for SnapshotVersion.MIN which\n // can happen for manufactured events (e.g. in the case of a limbo\n // document resolution failing).\n if (\n existingDoc == null ||\n doc.version.equals(SnapshotVersion.MIN) ||\n doc.version.compareTo(existingDoc.version) >= 0\n ) {\n documentBuffer.addEntry(doc);\n } else {\n log.debug(\n LOG_TAG,\n 'Ignoring outdated watch update for ',\n key,\n '. Current version:',\n existingDoc.version,\n ' Watch version:',\n doc.version\n );\n }\n\n // The document might be garbage because it was unreferenced by\n // everything. Make sure to mark it as garbage if it is...\n this.garbageCollector.addPotentialGarbageKey(key);\n })\n );\n });\n\n // HACK: The only reason we allow a null snapshot version is so that we\n // can synthesize remote events when we get permission denied errors while\n // trying to resolve the state of a locally cached document that is in\n // limbo.\n const lastRemoteVersion = this.queryCache.getLastRemoteSnapshotVersion();\n const remoteVersion = remoteEvent.snapshotVersion;\n if (!remoteVersion.equals(SnapshotVersion.MIN)) {\n assert(\n remoteVersion.compareTo(lastRemoteVersion) >= 0,\n 'Watch stream reverted to previous snapshot?? ' +\n remoteVersion +\n ' < ' +\n lastRemoteVersion\n );\n promises.push(\n this.queryCache.setLastRemoteSnapshotVersion(txn, remoteVersion)\n );\n }\n\n let releasedWriteKeys: DocumentKeySet;\n return PersistencePromise.waitFor(promises)\n .next(() => this.releaseHeldBatchResults(txn, documentBuffer))\n .next(promisedReleasedWriteKeys => {\n releasedWriteKeys = promisedReleasedWriteKeys;\n return documentBuffer.apply(txn);\n })\n .next(() => {\n return this.localDocuments.getDocuments(\n txn,\n changedDocKeys.unionWith(releasedWriteKeys)\n );\n });\n });\n }\n\n /**\n * Notify local store of the changed views to locally pin documents.\n */\n notifyLocalViewChanges(viewChanges: LocalViewChanges[]): Promise {\n return this.persistence.runTransaction('Notify local view changes', txn => {\n const promises = [] as Array>;\n for (const view of viewChanges) {\n promises.push(\n this.queryCache\n .getQueryData(txn, view.query)\n .next((queryData: QueryData | null) => {\n assert(\n queryData !== null,\n 'Local view changes contain unallocated query.'\n );\n const targetId = queryData!.targetId;\n this.localViewReferences.addReferences(view.addedKeys, targetId);\n this.localViewReferences.removeReferences(\n view.removedKeys,\n targetId\n );\n })\n );\n }\n return PersistencePromise.waitFor(promises);\n });\n }\n\n /**\n * Gets the mutation batch after the passed in batchId in the mutation queue\n * or null if empty.\n * @param afterBatchId If provided, the batch to search after.\n * @returns The next mutation or null if there wasn't one.\n */\n nextMutationBatch(afterBatchId?: BatchId): Promise {\n return this.persistence.runTransaction('Get next mutation batch', txn => {\n if (afterBatchId === undefined) {\n afterBatchId = BATCHID_UNKNOWN;\n }\n return this.mutationQueue.getNextMutationBatchAfterBatchId(\n txn,\n afterBatchId\n );\n });\n }\n\n /**\n * Read the current value of a Document with a given key or null if not\n * found - used for testing.\n */\n readDocument(key: DocumentKey): Promise {\n return this.persistence.runTransaction('read document', txn => {\n return this.localDocuments.getDocument(txn, key);\n });\n }\n\n /**\n * Assigns the given query an internal ID so that its results can be pinned so\n * they don't get GC'd. A query must be allocated in the local store before\n * the store can be used to manage its view.\n */\n allocateQuery(query: Query): Promise {\n return this.persistence.runTransaction('Allocate query', txn => {\n let queryData: QueryData;\n return this.queryCache\n .getQueryData(txn, query)\n .next((cached: QueryData | null) => {\n if (cached) {\n // This query has been listened to previously, so reuse the\n // previous targetID.\n // TODO(mcg): freshen last accessed date?\n queryData = cached;\n return PersistencePromise.resolve();\n } else {\n const targetId = this.targetIdGenerator.next();\n queryData = new QueryData(query, targetId, QueryPurpose.Listen);\n return this.queryCache.addQueryData(txn, queryData);\n }\n })\n .next(() => {\n assert(\n !this.targetIds[queryData.targetId],\n 'Tried to allocate an already allocated query: ' + query\n );\n this.targetIds[queryData.targetId] = queryData;\n return queryData;\n });\n });\n }\n\n /** Unpin all the documents associated with the given query. */\n releaseQuery(query: Query): Promise {\n return this.persistence.runTransaction('Release query', txn => {\n return this.queryCache\n .getQueryData(txn, query)\n .next((queryData: QueryData | null) => {\n assert(\n queryData != null,\n 'Tried to release nonexistent query: ' + query\n );\n this.localViewReferences.removeReferencesForId(queryData!.targetId);\n delete this.targetIds[queryData!.targetId];\n if (this.garbageCollector.isEager) {\n return this.queryCache.removeQueryData(txn, queryData!);\n } else {\n return PersistencePromise.resolve();\n }\n })\n .next(() => {\n // If this was the last watch target, then we won't get any more\n // watch snapshots, so we should release any held batch results.\n if (objUtils.isEmpty(this.targetIds)) {\n const documentBuffer = new RemoteDocumentChangeBuffer(\n this.remoteDocuments\n );\n return this.releaseHeldBatchResults(\n txn,\n documentBuffer\n ).next(() => {\n documentBuffer.apply(txn);\n });\n } else {\n return PersistencePromise.resolve();\n }\n });\n });\n }\n\n /**\n * Runs the specified query against all the documents in the local store and\n * returns the results.\n */\n executeQuery(query: Query): Promise {\n return this.persistence.runTransaction('Execute query', txn => {\n return this.localDocuments.getDocumentsMatchingQuery(txn, query);\n });\n }\n\n /**\n * Returns the keys of the documents that are associated with the given\n * target id in the remote table.\n */\n remoteDocumentKeys(targetId: TargetId): Promise {\n return this.persistence.runTransaction('Remote document keys', txn => {\n return this.queryCache.getMatchingKeysForTargetId(txn, targetId);\n });\n }\n\n /**\n * Collect garbage if necessary.\n * Should be called periodically by Sync Engine to recover resources. The\n * implementation must guarantee that GC won't happen in other places than\n * this method call.\n */\n collectGarbage(): Promise {\n // Call collectGarbage regardless of whether isGCEnabled so the referenceSet\n // doesn't continue to accumulate the garbage keys.\n return this.persistence.runTransaction('Garbage collection', txn => {\n return this.garbageCollector.collectGarbage(txn).next(garbage => {\n const promises = [] as Array>;\n garbage.forEach(key => {\n promises.push(this.remoteDocuments.removeEntry(txn, key));\n });\n return PersistencePromise.waitFor(promises);\n });\n });\n }\n\n private releaseHeldBatchResults(\n txn: PersistenceTransaction,\n documentBuffer: RemoteDocumentChangeBuffer\n ): PersistencePromise {\n const toRelease: MutationBatchResult[] = [];\n for (const batchResult of this.heldBatchResults) {\n if (!this.isRemoteUpToVersion(batchResult.commitVersion)) {\n break;\n }\n toRelease.push(batchResult);\n }\n\n if (toRelease.length === 0) {\n return PersistencePromise.resolve(documentKeySet());\n } else {\n this.heldBatchResults.splice(0, toRelease.length);\n return this.releaseBatchResults(txn, toRelease, documentBuffer);\n }\n }\n\n private isRemoteUpToVersion(version: SnapshotVersion): boolean {\n // If there are no watch targets, then we won't get remote snapshots, and\n // we are always \"up-to-date.\"\n const lastRemoteVersion = this.queryCache.getLastRemoteSnapshotVersion();\n return (\n version.compareTo(lastRemoteVersion) <= 0 ||\n objUtils.isEmpty(this.targetIds)\n );\n }\n\n private shouldHoldBatchResult(version: SnapshotVersion): boolean {\n // Check if watcher isn't up to date or prior results are already held.\n return (\n !this.isRemoteUpToVersion(version) || this.heldBatchResults.length > 0\n );\n }\n\n private releaseBatchResults(\n txn: PersistenceTransaction,\n batchResults: MutationBatchResult[],\n documentBuffer: RemoteDocumentChangeBuffer\n ): PersistencePromise {\n let promiseChain = PersistencePromise.resolve();\n for (const batchResult of batchResults) {\n promiseChain = promiseChain.next(() =>\n this.applyWriteToRemoteDocuments(txn, batchResult, documentBuffer)\n );\n }\n return promiseChain.next(() => {\n return this.removeMutationBatches(\n txn,\n batchResults.map(result => result.batch)\n );\n });\n }\n\n private removeMutationBatch(\n txn: PersistenceTransaction,\n batch: MutationBatch\n ): PersistencePromise {\n return this.removeMutationBatches(txn, [batch]);\n }\n\n /** Removes all the mutation batches named in the given array. */\n private removeMutationBatches(\n txn: PersistenceTransaction,\n batches: MutationBatch[]\n ): PersistencePromise {\n let affectedDocs = documentKeySet();\n for (const batch of batches) {\n for (const mutation of batch.mutations) {\n const key = mutation.key;\n affectedDocs = affectedDocs.add(key);\n }\n }\n\n return this.mutationQueue\n .removeMutationBatches(txn, batches)\n .next(() => affectedDocs);\n }\n\n private applyWriteToRemoteDocuments(\n txn: PersistenceTransaction,\n batchResult: MutationBatchResult,\n documentBuffer: RemoteDocumentChangeBuffer\n ): PersistencePromise {\n const batch = batchResult.batch;\n const docKeys = batch.keys();\n let promiseChain = PersistencePromise.resolve();\n docKeys.forEach(docKey => {\n promiseChain = promiseChain\n .next(() => {\n return documentBuffer.getEntry(txn, docKey);\n })\n .next((remoteDoc: MaybeDocument | null) => {\n let doc = remoteDoc;\n const ackVersion = batchResult.docVersions.get(docKey);\n assert(\n ackVersion !== null,\n 'ackVersions should contain every doc in the write.'\n );\n if (!doc || doc.version.compareTo(ackVersion!) < 0) {\n doc = batch.applyToRemoteDocument(docKey, doc, batchResult);\n if (!doc) {\n assert(\n !remoteDoc,\n 'Mutation batch ' +\n batch +\n ' applied to document ' +\n remoteDoc +\n ' resulted in null'\n );\n } else {\n documentBuffer.addEntry(doc);\n }\n }\n });\n });\n return promiseChain;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/local_store.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport { Timestamp } from '../core/timestamp';\nimport { BatchId, ProtoByteString } from '../core/types';\nimport { DocumentKey } from '../model/document_key';\nimport { Mutation } from '../model/mutation';\nimport { BATCHID_UNKNOWN, MutationBatch } from '../model/mutation_batch';\nimport { emptyByteString } from '../platform/platform';\nimport { assert } from '../util/assert';\nimport { primitiveComparator } from '../util/misc';\nimport { SortedSet } from '../util/sorted_set';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { GarbageCollector } from './garbage_collector';\nimport { MutationQueue } from './mutation_queue';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { DocReference } from './reference_set';\n\nexport class MemoryMutationQueue implements MutationQueue {\n /**\n * The set of all mutations that have been sent but not yet been applied to\n * the backend.\n */\n private mutationQueue: MutationBatch[] = [];\n\n /** Next value to use when assigning sequential IDs to each mutation batch. */\n private nextBatchId: BatchId = 1;\n\n /** The highest acknowledged mutation in the queue. */\n private highestAcknowledgedBatchId: BatchId = BATCHID_UNKNOWN;\n\n /** The last received stream token from the server, used to acknowledge which\n * responses the client has processed. Stream tokens are opaque checkpoint\n * markers whose only real value is their inclusion in the next request.\n */\n private lastStreamToken: ProtoByteString = emptyByteString();\n\n /** The garbage collector to notify about potential garbage keys. */\n private garbageCollector: GarbageCollector | null = null;\n\n /** An ordered mapping between documents and the mutations batch IDs. */\n private batchesByDocumentKey = new SortedSet(DocReference.compareByKey);\n\n start(transaction: PersistenceTransaction): PersistencePromise {\n // NOTE: The queue may be shutdown / started multiple times, since we\n // maintain the queue for the duration of the app session in case a user\n // logs out / back in. To behave like the LevelDB-backed MutationQueue (and\n // accommodate tests that expect as much), we reset nextBatchId and\n // highestAcknowledgedBatchId if the queue is empty.\n if (this.mutationQueue.length === 0) {\n this.nextBatchId = 1;\n this.highestAcknowledgedBatchId = BATCHID_UNKNOWN;\n }\n assert(\n this.highestAcknowledgedBatchId < this.nextBatchId,\n 'highestAcknowledgedBatchId must be less than the nextBatchId'\n );\n return PersistencePromise.resolve();\n }\n\n checkEmpty(transaction: PersistenceTransaction): PersistencePromise {\n return PersistencePromise.resolve(this.mutationQueue.length === 0);\n }\n\n getNextBatchId(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(this.nextBatchId);\n }\n\n getHighestAcknowledgedBatchId(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(this.highestAcknowledgedBatchId);\n }\n\n acknowledgeBatch(\n transaction: PersistenceTransaction,\n batch: MutationBatch,\n streamToken: ProtoByteString\n ): PersistencePromise {\n const batchId = batch.batchId;\n assert(\n batchId > this.highestAcknowledgedBatchId,\n 'Mutation batchIDs must be acknowledged in order'\n );\n\n const batchIndex = this.indexOfExistingBatchId(batchId, 'acknowledged');\n\n // Verify that the batch in the queue is the one to be acknowledged.\n const check = this.mutationQueue[batchIndex];\n assert(\n batchId === check.batchId,\n 'Queue ordering failure: expected batch ' +\n batchId +\n ', got batch ' +\n check.batchId\n );\n assert(\n !check.isTombstone(),\n \"Can't acknowledge a previously removed batch\"\n );\n\n this.highestAcknowledgedBatchId = batchId;\n this.lastStreamToken = streamToken;\n return PersistencePromise.resolve();\n }\n\n getLastStreamToken(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(this.lastStreamToken);\n }\n\n setLastStreamToken(\n transaction: PersistenceTransaction,\n streamToken: ProtoByteString\n ): PersistencePromise {\n this.lastStreamToken = streamToken;\n return PersistencePromise.resolve();\n }\n\n addMutationBatch(\n transaction: PersistenceTransaction,\n localWriteTime: Timestamp,\n mutations: Mutation[]\n ): PersistencePromise {\n assert(mutations.length !== 0, 'Mutation batches should not be empty');\n\n const batchId = this.nextBatchId;\n this.nextBatchId++;\n\n if (this.mutationQueue.length > 0) {\n const prior = this.mutationQueue[this.mutationQueue.length - 1];\n assert(\n prior.batchId < batchId,\n 'Mutation batchIDs must be monotonically increasing order'\n );\n }\n\n const batch = new MutationBatch(batchId, localWriteTime, mutations);\n this.mutationQueue.push(batch);\n\n // Track references by document key.\n for (const mutation of mutations) {\n this.batchesByDocumentKey = this.batchesByDocumentKey.add(\n new DocReference(mutation.key, batchId)\n );\n }\n\n return PersistencePromise.resolve(batch);\n }\n\n lookupMutationBatch(\n transaction: PersistenceTransaction,\n batchId: BatchId\n ): PersistencePromise {\n return PersistencePromise.resolve(this.findMutationBatch(batchId));\n }\n\n getNextMutationBatchAfterBatchId(\n transaction: PersistenceTransaction,\n batchId: BatchId\n ): PersistencePromise {\n const size = this.mutationQueue.length;\n\n // All batches with batchId <= this.highestAcknowledgedBatchId have been\n // acknowledged so the first unacknowledged batch after batchID will have a\n // batchID larger than both of these values.\n batchId = Math.max(batchId + 1, this.highestAcknowledgedBatchId);\n\n // The requested batchId may still be out of range so normalize it to the\n // start of the queue.\n const rawIndex = this.indexOfBatchId(batchId);\n let index = rawIndex < 0 ? 0 : rawIndex;\n\n // Finally return the first non-tombstone batch.\n for (; index < size; index++) {\n const batch = this.mutationQueue[index];\n if (!batch.isTombstone()) {\n return PersistencePromise.resolve(batch);\n }\n }\n return PersistencePromise.resolve(null);\n }\n\n getAllMutationBatches(\n transaction: PersistenceTransaction\n ): PersistencePromise {\n return PersistencePromise.resolve(\n this.getAllLiveMutationBatchesBeforeIndex(this.mutationQueue.length)\n );\n }\n\n getAllMutationBatchesThroughBatchId(\n transaction: PersistenceTransaction,\n batchId: BatchId\n ): PersistencePromise {\n const count = this.mutationQueue.length;\n\n let endIndex = this.indexOfBatchId(batchId);\n if (endIndex < 0) {\n endIndex = 0;\n } else if (endIndex >= count) {\n endIndex = count;\n } else {\n // The endIndex is in the queue so increment to pull everything in the\n // queue including it.\n endIndex++;\n }\n\n return PersistencePromise.resolve(\n this.getAllLiveMutationBatchesBeforeIndex(endIndex)\n );\n }\n\n getAllMutationBatchesAffectingDocumentKey(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n const start = new DocReference(documentKey, 0);\n const end = new DocReference(documentKey, Number.POSITIVE_INFINITY);\n const result: MutationBatch[] = [];\n this.batchesByDocumentKey.forEachInRange([start, end], ref => {\n assert(\n documentKey.equals(ref.key),\n \"Should only iterate over a single key's batches\"\n );\n const batch = this.findMutationBatch(ref.targetOrBatchId);\n assert(\n batch !== null,\n 'Batches in the index must exist in the main table'\n );\n result.push(batch!);\n });\n\n return PersistencePromise.resolve(result);\n }\n\n getAllMutationBatchesAffectingQuery(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n // Use the query path as a prefix for testing if a document matches the\n // query.\n const prefix = query.path;\n const immediateChildrenPathLength = prefix.length + 1;\n\n // Construct a document reference for actually scanning the index. Unlike\n // the prefix the document key in this reference must have an even number of\n // segments. The empty segment can be used a suffix of the query path\n // because it precedes all other segments in an ordered traversal.\n let startPath = prefix;\n if (!DocumentKey.isDocumentKey(startPath)) {\n startPath = startPath.child('');\n }\n\n const start = new DocReference(new DocumentKey(startPath), 0);\n\n // Find unique batchIDs referenced by all documents potentially matching the\n // query.\n let uniqueBatchIDs = new SortedSet(primitiveComparator);\n\n this.batchesByDocumentKey.forEachWhile(ref => {\n const rowKeyPath = ref.key.path;\n if (!prefix.isPrefixOf(rowKeyPath)) {\n return false;\n } else {\n // Rows with document keys more than one segment longer than the query\n // path can't be matches. For example, a query on 'rooms' can't match\n // the document /rooms/abc/messages/xyx.\n // TODO(mcg): we'll need a different scanner when we implement\n // ancestor queries.\n if (rowKeyPath.length === immediateChildrenPathLength) {\n uniqueBatchIDs = uniqueBatchIDs.add(ref.targetOrBatchId);\n }\n return true;\n }\n }, start);\n\n // Construct an array of matching batches, sorted by batchID to ensure that\n // multiple mutations affecting the same document key are applied in order.\n const result: MutationBatch[] = [];\n uniqueBatchIDs.forEach(batchId => {\n const batch = this.findMutationBatch(batchId);\n if (batch !== null) {\n result.push(batch);\n }\n });\n return PersistencePromise.resolve(result);\n }\n\n removeMutationBatches(\n transaction: PersistenceTransaction,\n batches: MutationBatch[]\n ): PersistencePromise {\n const batchCount = batches.length;\n assert(batchCount > 0, 'Should not remove mutations when none exist.');\n\n const firstBatchId = batches[0].batchId;\n const queueCount = this.mutationQueue.length;\n\n // Find the position of the first batch for removal. This need not be the\n // first entry in the queue.\n const startIndex = this.indexOfExistingBatchId(firstBatchId, 'removed');\n assert(\n this.mutationQueue[startIndex].batchId === firstBatchId,\n 'Removed batches must exist in the queue'\n );\n\n // Check that removed batches are contiguous (while excluding tombstones).\n let batchIndex = 1;\n let queueIndex = startIndex + 1;\n while (batchIndex < batchCount && queueIndex < queueCount) {\n const batch = this.mutationQueue[queueIndex];\n if (batch.isTombstone()) {\n queueIndex++;\n continue;\n }\n\n assert(\n batch.batchId === batches[batchIndex].batchId,\n 'Removed batches must be contiguous in the queue'\n );\n batchIndex++;\n queueIndex++;\n }\n\n // Only actually remove batches if removing at the front of the queue.\n // Previously rejected batches may have left tombstones in the queue, so\n // expand the removal range to include any tombstones.\n if (startIndex === 0) {\n for (; queueIndex < queueCount; queueIndex++) {\n const batch = this.mutationQueue[queueIndex];\n if (!batch.isTombstone()) {\n break;\n }\n }\n const length = queueIndex - startIndex;\n this.mutationQueue.splice(startIndex, length);\n } else {\n // Mark the tombstones\n for (let i = startIndex; i < queueIndex; i++) {\n this.mutationQueue[i] = this.mutationQueue[i].toTombstone();\n }\n }\n\n let references = this.batchesByDocumentKey;\n for (const batch of batches) {\n const batchId = batch.batchId;\n for (const mutation of batch.mutations) {\n const key = mutation.key;\n if (this.garbageCollector !== null) {\n this.garbageCollector.addPotentialGarbageKey(key);\n }\n\n const ref = new DocReference(key, batchId);\n references = references.delete(ref);\n }\n }\n this.batchesByDocumentKey = references;\n return PersistencePromise.resolve();\n }\n\n setGarbageCollector(garbageCollector: GarbageCollector | null): void {\n this.garbageCollector = garbageCollector;\n }\n\n containsKey(\n txn: PersistenceTransaction,\n key: DocumentKey\n ): PersistencePromise {\n const ref = new DocReference(key, 0);\n const firstRef = this.batchesByDocumentKey.firstAfterOrEqual(ref);\n return PersistencePromise.resolve(key.equals(firstRef && firstRef.key));\n }\n\n performConsistencyCheck(\n txn: PersistenceTransaction\n ): PersistencePromise {\n if (this.mutationQueue.length === 0) {\n assert(\n this.batchesByDocumentKey.isEmpty(),\n 'Document leak -- detected dangling mutation references when queue is empty.'\n );\n }\n return PersistencePromise.resolve();\n }\n\n /**\n * A private helper that collects all the mutations batches in the queue up to\n * but not including the given endIndex. All tombstones in the queue are\n * excluded.\n */\n private getAllLiveMutationBatchesBeforeIndex(\n endIndex: number\n ): MutationBatch[] {\n const result: MutationBatch[] = [];\n\n for (let i = 0; i < endIndex; i++) {\n const batch = this.mutationQueue[i];\n if (!batch.isTombstone()) {\n result.push(batch);\n }\n }\n\n return result;\n }\n\n /**\n * Finds the index of the given batchId in the mutation queue and asserts that\n * the resulting index is within the bounds of the queue.\n *\n * @param batchId The batchId to search for\n * @param action A description of what the caller is doing, phrased in passive\n * form (e.g. \"acknowledged\" in a routine that acknowledges batches).\n */\n private indexOfExistingBatchId(batchId: BatchId, action: string): number {\n const index = this.indexOfBatchId(batchId);\n assert(\n index >= 0 && index < this.mutationQueue.length,\n 'Batches must exist to be ' + action\n );\n return index;\n }\n\n /**\n * Finds the index of the given batchId in the mutation queue. This operation\n * is O(1).\n *\n * @return The computed index of the batch with the given batchId, based on\n * the state of the queue. Note this index can be negative if the requested\n * batchId has already been remvoed from the queue or past the end of the\n * queue if the batchId is larger than the last added batch.\n */\n private indexOfBatchId(batchId: BatchId): number {\n if (this.mutationQueue.length === 0) {\n // As an index this is past the end of the queue\n return 0;\n }\n\n // Examine the front of the queue to figure out the difference between the\n // batchId and indexes in the array. Note that since the queue is ordered\n // by batchId, if the first batch has a larger batchId then the requested\n // batchId doesn't exist in the queue.\n const firstBatchId = this.mutationQueue[0].batchId;\n return batchId - firstBatchId;\n }\n\n /**\n * A version of lookupMutationBatch that doesn't return a promise, this makes\n * other functions that uses this code easier to read and more efficent.\n */\n private findMutationBatch(batchId: BatchId): MutationBatch | null {\n const index = this.indexOfBatchId(batchId);\n if (index < 0 || index >= this.mutationQueue.length) {\n return null;\n }\n\n const batch = this.mutationQueue[index];\n assert(batch.batchId === batchId, 'If found batch must match');\n return batch.isTombstone() ? null : batch;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/memory_mutation_queue.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { TargetId } from '../core/types';\nimport { DocumentKeySet } from '../model/collections';\nimport { DocumentKey } from '../model/document_key';\nimport { ObjectMap } from '../util/obj_map';\nimport { SortedSet } from '../util/sorted_set';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { GarbageCollector } from './garbage_collector';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { QueryCache } from './query_cache';\nimport { QueryData } from './query_data';\nimport { ReferenceSet } from './reference_set';\n\nexport class MemoryQueryCache implements QueryCache {\n /**\n * Maps a query to the data about that query\n */\n private queries = new ObjectMap(q => q.canonicalId());\n\n /** The last received snapshot version. */\n private lastRemoteSnapshotVersion = SnapshotVersion.MIN;\n /** The highest numbered target ID encountered. */\n private highestTargetId: TargetId = 0;\n /**\n * A ordered bidirectional mapping between documents and the remote target\n * IDs.\n */\n private references = new ReferenceSet();\n\n start(transaction: PersistenceTransaction): PersistencePromise {\n // Nothing to do.\n return PersistencePromise.resolve();\n }\n\n getLastRemoteSnapshotVersion(): SnapshotVersion {\n return this.lastRemoteSnapshotVersion;\n }\n\n getHighestTargetId(): TargetId {\n return this.highestTargetId;\n }\n\n setLastRemoteSnapshotVersion(\n transaction: PersistenceTransaction,\n snapshotVersion: SnapshotVersion\n ): PersistencePromise {\n this.lastRemoteSnapshotVersion = snapshotVersion;\n return PersistencePromise.resolve();\n }\n\n addQueryData(\n transaction: PersistenceTransaction,\n queryData: QueryData\n ): PersistencePromise {\n this.queries.set(queryData.query, queryData);\n const targetId = queryData.targetId;\n if (targetId > this.highestTargetId) {\n this.highestTargetId = targetId;\n }\n return PersistencePromise.resolve();\n }\n\n removeQueryData(\n transaction: PersistenceTransaction,\n queryData: QueryData\n ): PersistencePromise {\n this.queries.delete(queryData.query);\n this.references.removeReferencesForId(queryData.targetId);\n return PersistencePromise.resolve();\n }\n\n getQueryData(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n const queryData = this.queries.get(query) || null;\n return PersistencePromise.resolve(queryData);\n }\n\n addMatchingKeys(\n txn: PersistenceTransaction,\n keys: DocumentKeySet,\n targetId: TargetId\n ): PersistencePromise {\n this.references.addReferences(keys, targetId);\n return PersistencePromise.resolve();\n }\n\n removeMatchingKeys(\n txn: PersistenceTransaction,\n keys: DocumentKeySet,\n targetId: TargetId\n ): PersistencePromise {\n this.references.removeReferences(keys, targetId);\n return PersistencePromise.resolve();\n }\n\n removeMatchingKeysForTargetId(\n txn: PersistenceTransaction,\n targetId: TargetId\n ): PersistencePromise {\n this.references.removeReferencesForId(targetId);\n return PersistencePromise.resolve();\n }\n\n getMatchingKeysForTargetId(\n txn: PersistenceTransaction,\n targetId: TargetId\n ): PersistencePromise {\n const matchingKeys = this.references.referencesForId(targetId);\n return PersistencePromise.resolve(matchingKeys);\n }\n\n setGarbageCollector(gc: GarbageCollector | null): void {\n this.references.setGarbageCollector(gc);\n }\n\n containsKey(\n txn: PersistenceTransaction | null,\n key: DocumentKey\n ): PersistencePromise {\n return this.references.containsKey(txn, key);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/memory_query_cache.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Query } from '../core/query';\nimport {\n DocumentMap,\n documentMap,\n maybeDocumentMap\n} from '../model/collections';\nimport { Document, MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { DocumentSet } from '../model/document_set';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { RemoteDocumentCache } from './remote_document_cache';\n\nexport class MemoryRemoteDocumentCache implements RemoteDocumentCache {\n private docs = maybeDocumentMap();\n\n addEntry(\n transaction: PersistenceTransaction,\n maybeDocument: MaybeDocument\n ): PersistencePromise {\n this.docs = this.docs.insert(maybeDocument.key, maybeDocument);\n return PersistencePromise.resolve();\n }\n\n removeEntry(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n this.docs = this.docs.remove(documentKey);\n return PersistencePromise.resolve();\n }\n\n getEntry(\n transaction: PersistenceTransaction,\n documentKey: DocumentKey\n ): PersistencePromise {\n return PersistencePromise.resolve(this.docs.get(documentKey));\n }\n\n getDocumentsMatchingQuery(\n transaction: PersistenceTransaction,\n query: Query\n ): PersistencePromise {\n let results = documentMap();\n\n // Documents are ordered by key, so we can use a prefix scan to narrow down\n // the documents we need to match the query against.\n const prefix = new DocumentKey(query.path.child(''));\n const iterator = this.docs.getIteratorFrom(prefix);\n while (iterator.hasNext()) {\n const { key, value: maybeDoc } = iterator.getNext();\n if (!query.path.isPrefixOf(key.path)) {\n break;\n }\n if (maybeDoc instanceof Document && query.matches(maybeDoc)) {\n results = results.insert(maybeDoc.key, maybeDoc);\n }\n }\n return PersistencePromise.resolve(results);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/memory_remote_document_cache.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { assert } from '../util/assert';\nimport { debug } from '../util/log';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { MemoryMutationQueue } from './memory_mutation_queue';\nimport { MemoryQueryCache } from './memory_query_cache';\nimport { MemoryRemoteDocumentCache } from './memory_remote_document_cache';\nimport { MutationQueue } from './mutation_queue';\nimport { Persistence, PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\nimport { QueryCache } from './query_cache';\nimport { RemoteDocumentCache } from './remote_document_cache';\n\nconst LOG_TAG = 'MemoryPersistence';\n\n/**\n * A memory-backed instance of Persistence. Data is stored only in RAM and\n * not persisted across sessions.\n */\nexport class MemoryPersistence implements Persistence {\n /**\n * Note that these are retained here to make it easier to write tests\n * affecting both the in-memory and IndexedDB-backed persistence layers. Tests\n * can create a new LocalStore wrapping this Persistence instance and this\n * will make the in-memory persistence layer behave as if it were actually\n * persisting values.\n */\n private mutationQueues: { [user: string]: MutationQueue } = {};\n private remoteDocumentCache = new MemoryRemoteDocumentCache();\n private queryCache = new MemoryQueryCache();\n\n private started = false;\n\n start(): Promise {\n assert(!this.started, 'MemoryPersistence double-started!');\n this.started = true;\n // No durable state to read on startup.\n return Promise.resolve();\n }\n\n shutdown(): Promise {\n // No durable state to ensure is closed on shutdown.\n assert(this.started, 'MemoryPersistence shutdown without start!');\n this.started = false;\n return Promise.resolve();\n }\n\n getMutationQueue(user: User): MutationQueue {\n let queue = this.mutationQueues[user.toKey()];\n if (!queue) {\n queue = new MemoryMutationQueue();\n this.mutationQueues[user.toKey()] = queue;\n }\n return queue;\n }\n\n getQueryCache(): QueryCache {\n return this.queryCache;\n }\n\n getRemoteDocumentCache(): RemoteDocumentCache {\n return this.remoteDocumentCache;\n }\n\n runTransaction(\n action: string,\n operation: (transaction: PersistenceTransaction) => PersistencePromise\n ): Promise {\n debug(LOG_TAG, 'Starting transaction:', action);\n return operation(new MemoryPersistenceTransaction()).toPromise();\n }\n}\n\n/** Dummy class since memory persistence doesn't actually use transactions. */\nclass MemoryPersistenceTransaction implements PersistenceTransaction {}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/memory_persistence.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DocumentKeySet, documentKeySet } from '../model/collections';\nimport { DocumentKey } from '../model/document_key';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { GarbageCollector } from './garbage_collector';\nimport { GarbageSource } from './garbage_source';\nimport { PersistenceTransaction } from './persistence';\nimport { PersistencePromise } from './persistence_promise';\n\n/**\n * A garbage collector implementation that does absolutely nothing. It ignores\n * all addGarbageSource and addPotentialGarbageKey messages and and never\n * produces any garbage.\n */\nexport class NoOpGarbageCollector implements GarbageCollector {\n readonly isEager = false;\n\n addGarbageSource(garbageSource: GarbageSource): void {\n // Not tracking garbage so don't track sources.\n }\n\n removeGarbageSource(garbageSource: GarbageSource): void {\n // Not tracking garbage so don't track sources.\n }\n\n addPotentialGarbageKey(key: DocumentKey): void {\n // Not tracking garbage so ignore.\n }\n\n collectGarbage(\n txn: PersistenceTransaction | null\n ): PersistencePromise {\n return PersistencePromise.resolve(documentKeySet());\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/local/no_op_garbage_collector.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { AnyDuringMigration } from './misc';\n\nexport interface Resolver {\n (value?: R | Promise): void;\n}\n\n// tslint:disable-next-line:no-any\nexport interface Rejecter {\n (value?: any): void;\n}\n\nexport class Deferred {\n promise: Promise;\n resolve: Resolver;\n reject: Rejecter;\n\n constructor() {\n this.promise = new Promise((resolve: Resolver, reject: Rejecter) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n}\n\n/**\n * Takes an array of values and sequences them using the promise (or value)\n * returned by the supplied callback. The callback for each item is called\n * after the promise is resolved for the previous item.\n * The function returns a promise which is resolved after the promise for\n * the last item is resolved.\n */\nexport function sequence(\n values: T[],\n fn: (value: T, result?: R) => R | Promise,\n initialValue?: R\n): Promise {\n let result = Promise.resolve(initialValue);\n values.forEach(value => {\n result = result.then(lastResult => fn(value, lastResult));\n });\n return result as AnyDuringMigration;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/promise.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as log from '../util/log';\nimport { Deferred } from '../util/promise';\n\nconst LOG_TAG = 'ExponentialBackoff';\n\n/**\n * A helper for running delayed tasks following an exponential backoff curve\n * between attempts.\n *\n * Each delay is made up of a \"base\" delay which follows the exponential\n * backoff curve, and a +/- 50% \"jitter\" that is calculated and added to the\n * base delay. This prevents clients from accidentally synchronizing their\n * delays causing spikes of load to the backend.\n */\nexport class ExponentialBackoff {\n private currentBaseMs: number;\n\n constructor(\n /**\n * The initial delay (used as the base delay on the first retry attempt).\n * Note that jitter will still be applied, so the actual delay could be as\n * little as 0.5*initialDelayMs.\n */\n private readonly initialDelayMs: number,\n /**\n * The multiplier to use to determine the extended base delay after each\n * attempt.\n */\n private readonly backoffFactor: number,\n /**\n * The maximum base delay after which no further backoff is performed.\n * Note that jitter will still be applied, so the actual delay could be as\n * much as 1.5*maxDelayMs.\n */\n private readonly maxDelayMs: number\n ) {\n this.reset();\n }\n\n /**\n * Resets the backoff delay.\n *\n * The very next backoffAndWait() will have no delay. If it is called again\n * (i.e. due to an error), initialDelayMs (plus jitter) will be used, and\n * subsequent ones will increase according to the backoffFactor.\n */\n reset(): void {\n this.currentBaseMs = 0;\n }\n\n /**\n * Resets the backoff delay to the maximum delay (e.g. for use after a\n * RESOURCE_EXHAUSTED error).\n */\n resetToMax(): void {\n this.currentBaseMs = this.maxDelayMs;\n }\n\n /**\n * Returns a promise that resolves after currentDelayMs, and increases the\n * delay for any subsequent attempts.\n */\n backoffAndWait(): Promise {\n const def = new Deferred();\n\n // First schedule using the current base (which may be 0 and should be\n // honored as such).\n const delayWithJitterMs = this.currentBaseMs + this.jitterDelayMs();\n if (this.currentBaseMs > 0) {\n log.debug(\n LOG_TAG,\n `Backing off for ${delayWithJitterMs} ms ` +\n `(base delay: ${this.currentBaseMs} ms)`\n );\n }\n setTimeout(() => {\n def.resolve();\n }, delayWithJitterMs);\n\n // Apply backoff factor to determine next delay and ensure it is within\n // bounds.\n this.currentBaseMs *= this.backoffFactor;\n if (this.currentBaseMs < this.initialDelayMs) {\n this.currentBaseMs = this.initialDelayMs;\n }\n if (this.currentBaseMs > this.maxDelayMs) {\n this.currentBaseMs = this.maxDelayMs;\n }\n\n return def.promise;\n }\n\n /** Returns a random value in the range [-currentBaseMs/2, currentBaseMs/2] */\n private jitterDelayMs(): number {\n return (Math.random() - 0.5) * this.currentBaseMs;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/backoff.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as api from '../protos/firestore_proto_api';\nimport { CredentialsProvider } from '../api/credentials';\nimport { DatabaseInfo } from '../core/database_info';\nimport { maybeDocumentMap } from '../model/collections';\nimport { MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { Mutation, MutationResult } from '../model/mutation';\nimport { assert } from '../util/assert';\nimport { AsyncQueue } from '../util/async_queue';\n\nimport { Connection } from './connection';\nimport {\n PersistentListenStream,\n PersistentWriteStream,\n WatchStreamListener,\n WriteStreamListener\n} from './persistent_stream';\nimport { JsonProtoSerializer } from './serializer';\n\n// The generated proto interfaces for these class are missing the database\n// field. So we add it here.\n// TODO(b/36015800): Remove this once the api generator is fixed.\ninterface BatchGetDocumentsRequest extends api.BatchGetDocumentsRequest {\n database?: string;\n}\ninterface CommitRequest extends api.CommitRequest {\n database?: string;\n}\n\n/**\n * Datastore is a wrapper around the external Google Cloud Datastore grpc API,\n * which provides an interface that is more convenient for the rest of the\n * client SDK architecture to consume.\n */\nexport class Datastore {\n constructor(\n private databaseInfo: DatabaseInfo,\n private queue: AsyncQueue,\n private connection: Connection,\n private credentials: CredentialsProvider,\n private serializer: JsonProtoSerializer,\n private initialBackoffDelay?: number\n ) {}\n\n public newPersistentWriteStream(\n listener: WriteStreamListener\n ): PersistentWriteStream {\n return new PersistentWriteStream(\n this.databaseInfo,\n this.queue,\n this.connection,\n this.credentials,\n this.serializer,\n listener,\n this.initialBackoffDelay\n );\n }\n\n public newPersistentWatchStream(\n listener: WatchStreamListener\n ): PersistentListenStream {\n return new PersistentListenStream(\n this.databaseInfo,\n this.queue,\n this.connection,\n this.credentials,\n this.serializer,\n listener,\n this.initialBackoffDelay\n );\n }\n\n commit(mutations: Mutation[]): Promise {\n const params: CommitRequest = {\n writes: mutations.map(m => this.serializer.toMutation(m))\n };\n return this.invokeRPC(\n 'commit',\n params\n ).then((response: api.CommitResponse) => {\n return this.serializer.fromWriteResults(response.writeResults);\n });\n }\n\n lookup(keys: DocumentKey[]): Promise {\n const params: BatchGetDocumentsRequest = {\n documents: keys.map(k => this.serializer.toName(k))\n };\n return this.invokeRPC(\n 'batchGet',\n params\n ).then((response: api.BatchGetDocumentsResponse[]) => {\n let docs = maybeDocumentMap();\n response.forEach(proto => {\n const doc = this.serializer.fromMaybeDocument(proto);\n docs = docs.insert(doc.key, doc);\n });\n const result: MaybeDocument[] = [];\n keys.forEach(key => {\n const doc = docs.get(key);\n assert(!!doc, 'Missing entity in write response for ' + key);\n result.push(doc!);\n });\n return result;\n });\n }\n\n /** Gets an auth token and invokes the provided RPC. */\n private invokeRPC(rpcName: string, request: any): Promise {\n // TODO(mikelehen): Retry (with backoff) on token failures?\n return this.credentials.getToken(/*forceRefresh=*/ false).then(token => {\n return this.connection.invoke(rpcName, request, token);\n });\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/datastore.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ParsedSetData, ParsedUpdateData } from '../api/user_data_converter';\nimport { SnapshotVersion } from './snapshot_version';\nimport { documentVersionMap } from '../model/collections';\nimport { NoDocument } from '../model/document';\nimport { MaybeDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { DeleteMutation, Mutation, Precondition } from '../model/mutation';\nimport { Datastore } from '../remote/datastore';\nimport { Code, FirestoreError } from '../util/error';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\n/**\n * Internal transaction object responsible for accumulating the mutations to\n * perform and the base versions for any documents read.\n */\nexport class Transaction {\n // The version of each document that was read during this transaction.\n private readVersions = documentVersionMap();\n private mutations: Mutation[] = [];\n private committed = false;\n\n constructor(private datastore: Datastore) {}\n\n private recordVersion(doc: MaybeDocument) {\n let docVersion = doc.version;\n if (doc instanceof NoDocument) {\n // For deleted docs, we must use baseVersion 0 when we overwrite them.\n docVersion = SnapshotVersion.forDeletedDoc();\n }\n const existingVersion = this.readVersions.get(doc.key);\n if (existingVersion !== null) {\n if (!docVersion.equals(existingVersion)) {\n // This transaction will fail no matter what.\n throw new FirestoreError(\n Code.ABORTED,\n 'Document version changed between two reads.'\n );\n }\n } else {\n this.readVersions = this.readVersions.insert(doc.key, docVersion);\n }\n }\n\n lookup(keys: DocumentKey[]): Promise {\n if (this.committed) {\n return Promise.reject(\n 'Transaction has already completed.'\n );\n }\n if (this.mutations.length > 0) {\n return Promise.reject(\n 'Transactions lookups are invalid after writes.'\n );\n }\n return this.datastore.lookup(keys).then(docs => {\n docs.forEach(doc => this.recordVersion(doc));\n return docs;\n });\n }\n\n private write(mutations: Mutation[]) {\n if (this.committed) {\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n 'Transaction has already completed.'\n );\n }\n this.mutations = this.mutations.concat(mutations);\n }\n\n /**\n * Returns the version of this document when it was read in this transaction,\n * as a precondition, or no precondition if it was not read.\n */\n private precondition(key: DocumentKey): Precondition {\n const version = this.readVersions.get(key);\n if (version) {\n return Precondition.updateTime(version);\n } else {\n return Precondition.NONE;\n }\n }\n\n /**\n * Returns the precondition for a document if the operation is an update.\n */\n private preconditionForUpdate(key: DocumentKey): Precondition {\n const version = this.readVersions.get(key);\n if (version && version.equals(SnapshotVersion.forDeletedDoc())) {\n // The document doesn't exist, so fail the transaction.\n throw new FirestoreError(\n Code.FAILED_PRECONDITION,\n \"Can't update a document that doesn't exist.\"\n );\n } else if (version) {\n // Document exists, base precondition on document update time.\n return Precondition.updateTime(version);\n } else {\n // Document was not read, so we just use the preconditions for a blind\n // update.\n return Precondition.exists(true);\n }\n }\n\n set(key: DocumentKey, data: ParsedSetData) {\n this.write(data.toMutations(key, this.precondition(key)));\n }\n\n update(key: DocumentKey, data: ParsedUpdateData) {\n this.write(data.toMutations(key, this.preconditionForUpdate(key)));\n }\n\n delete(key: DocumentKey) {\n this.write([new DeleteMutation(key, this.precondition(key))]);\n // Since the delete will be applied before all following writes, we need to\n // ensure that the precondition for the next write will be exists: false.\n this.readVersions = this.readVersions.insert(\n key,\n SnapshotVersion.forDeletedDoc()\n );\n }\n\n commit(): Promise {\n let unwritten = this.readVersions;\n // For each mutation, note that the doc was written.\n this.mutations.forEach(mutation => {\n unwritten = unwritten.remove(mutation.key);\n });\n if (!unwritten.isEmpty()) {\n return Promise.reject(\n Error('Every document read in a transaction must also be written.')\n );\n }\n return this.datastore.commit(this.mutations).then(() => {\n this.committed = true;\n });\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/transaction.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { User } from '../auth/user';\nimport { DatabaseInfo } from '../core/database_info';\nimport { SnapshotVersion } from '../core/snapshot_version';\nimport { Transaction } from '../core/transaction';\nimport { BatchId, OnlineState, TargetId } from '../core/types';\nimport { LocalStore } from '../local/local_store';\nimport { QueryData, QueryPurpose } from '../local/query_data';\nimport { NoDocument } from '../model/document';\nimport { DocumentKey } from '../model/document_key';\nimport { MutationResult } from '../model/mutation';\nimport {\n BATCHID_UNKNOWN,\n MutationBatch,\n MutationBatchResult\n} from '../model/mutation_batch';\nimport { emptyByteString } from '../platform/platform';\nimport { assert } from '../util/assert';\nimport { AsyncQueue } from '../util/async_queue';\nimport { Code, FirestoreError } from '../util/error';\nimport * as log from '../util/log';\nimport * as objUtils from '../util/obj';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { Datastore } from './datastore';\nimport { ExistenceFilter } from './existence_filter';\nimport {\n PersistentListenStream,\n PersistentWriteStream\n} from './persistent_stream';\nimport { ResetMapping, UpdateMapping } from './remote_event';\nimport { RemoteSyncer } from './remote_syncer';\nimport { isPermanentError } from './rpc_error';\nimport {\n WatchChange,\n WatchChangeAggregator,\n WatchTargetChange,\n WatchTargetChangeState\n} from './watch_change';\n\nconst LOG_TAG = 'RemoteStore';\n\n// TODO(b/35853402): Negotiate this with the stream.\nconst MAX_PENDING_WRITES = 10;\n\n// The RemoteStore notifies an onlineStateHandler with OnlineState.Failed if we\n// fail to connect to the backend. This subsequently triggers get() requests to\n// fail or use cached data, etc. Unfortunately, our connections have\n// historically been subject to various transient failures. So we wait for\n// multiple failures before notifying the onlineStateHandler.\nconst ONLINE_ATTEMPTS_BEFORE_FAILURE = 2;\n\n/**\n * RemoteStore - An interface to remotely stored data, basically providing a\n * wrapper around the Datastore that is more reliable for the rest of the\n * system.\n *\n * RemoteStore is responsible for maintaining the connection to the server.\n * - maintaining a list of active listens.\n * - reconnecting when the connection is dropped.\n * - resuming all the active listens on reconnect.\n *\n * RemoteStore handles all incoming events from the Datastore.\n * - listening to the watch stream and repackaging the events as RemoteEvents\n * - notifying SyncEngine of any changes to the active listens.\n *\n * RemoteStore takes writes from other components and handles them reliably.\n * - pulling pending mutations from LocalStore and sending them to Datastore.\n * - retrying mutations that failed because of network problems.\n * - acking mutations to the SyncEngine once they are accepted or rejected.\n */\nexport class RemoteStore {\n private pendingWrites: MutationBatch[] = [];\n private lastBatchSeen: BatchId = BATCHID_UNKNOWN;\n\n /**\n * A mapping of watched targets that the client cares about tracking and the\n * user has explicitly called a 'listen' for this target.\n *\n * These targets may or may not have been sent to or acknowledged by the\n * server. On re-establishing the listen stream, these targets should be sent\n * to the server. The targets removed with unlistens are removed eagerly\n * without waiting for confirmation from the listen stream.\n */\n private listenTargets: { [targetId: number]: QueryData } = {};\n\n /**\n * A mapping of targetId to pending acks needed.\n *\n * If a targetId is present in this map, then we're waiting for watch to\n * acknowledge a removal or addition of the target. If a target is not in this\n * mapping, and it's in the listenTargets map, then we consider the target to\n * be active.\n *\n * We increment the count here every time we issue a request over the stream\n * to watch or unwatch. We then decrement the count every time we get a target\n * added or target removed message from the server. Once the count is equal to\n * 0 we know that the client and server are in the same state (once this state\n * is reached the targetId is removed from the map to free the memory).\n */\n private pendingTargetResponses: { [targetId: number]: number } = {};\n\n private accumulatedWatchChanges: WatchChange[] = [];\n\n private watchStream: PersistentListenStream;\n private writeStream: PersistentWriteStream;\n\n /**\n * The online state of the watch stream. The state is set to healthy if and\n * only if there are messages received by the backend.\n */\n private watchStreamOnlineState = OnlineState.Unknown;\n\n /** A count of consecutive failures to open the stream. */\n private watchStreamFailures = 0;\n\n constructor(\n private databaseInfo: DatabaseInfo,\n private asyncQueue: AsyncQueue,\n /**\n * The local store, used to fill the write pipeline with outbound\n * mutations and resolve existence filter mismatches.\n */\n private localStore: LocalStore,\n /** The client-side proxy for interacting with the backend. */\n private datastore: Datastore,\n private onlineStateHandler: (onlineState: OnlineState) => void\n ) {}\n\n /** SyncEngine to notify of watch and write events. */\n public syncEngine: RemoteSyncer;\n\n /**\n * Starts up the remote store, creating streams, restoring state from\n * LocalStore, etc.\n */\n start(): Promise {\n return this.setupStreams().then(() => {\n // Resume any writes\n return this.fillWritePipeline();\n });\n }\n\n private setOnlineStateToHealthy(): void {\n this.updateAndBroadcastOnlineState(OnlineState.Healthy);\n }\n\n private setOnlineStateToUnknown(): void {\n // The state is set to unknown when a healthy stream is closed (e.g. due to\n // a token timeout) or when we have no active listens and therefore there's\n // no need to start the stream. Assuming there is (possibly in the future)\n // an active listen, then we will eventually move to state Online or Failed,\n // but we always want to make at least ONLINE_ATTEMPTS_BEFORE_FAILURE\n // attempts before failing, so we reset the count here.\n this.watchStreamFailures = 0;\n this.updateAndBroadcastOnlineState(OnlineState.Unknown);\n }\n\n private updateOnlineStateAfterFailure(): void {\n // The first failure after we are successfully connected moves us to the\n // 'Unknown' state. We then may make multiple attempts (based on\n // ONLINE_ATTEMPTS_BEFORE_FAILURE) before we actually report failure.\n if (this.watchStreamOnlineState === OnlineState.Healthy) {\n this.setOnlineStateToUnknown();\n } else {\n this.watchStreamFailures++;\n if (this.watchStreamFailures >= ONLINE_ATTEMPTS_BEFORE_FAILURE) {\n this.updateAndBroadcastOnlineState(OnlineState.Failed);\n }\n }\n }\n\n private updateAndBroadcastOnlineState(onlineState: OnlineState): void {\n const didChange = this.watchStreamOnlineState !== onlineState;\n this.watchStreamOnlineState = onlineState;\n if (didChange) {\n this.onlineStateHandler(onlineState);\n }\n }\n\n private setupStreams(): Promise {\n this.watchStream = this.datastore.newPersistentWatchStream({\n onOpen: this.onWatchStreamOpen.bind(this),\n onClose: this.onWatchStreamClose.bind(this),\n onWatchChange: this.onWatchStreamChange.bind(this)\n });\n this.writeStream = this.datastore.newPersistentWriteStream({\n onOpen: this.onWriteStreamOpen.bind(this),\n onClose: this.onWriteStreamClose.bind(this),\n onHandshakeComplete: this.onWriteHandshakeComplete.bind(this),\n onMutationResult: this.onMutationResult.bind(this)\n });\n\n // Load any saved stream token from persistent storage\n return this.localStore.getLastStreamToken().then(token => {\n this.writeStream.lastStreamToken = token;\n });\n }\n\n shutdown(): Promise {\n log.debug(LOG_TAG, 'RemoteStore shutting down.');\n this.cleanupWatchStreamState();\n this.writeStream.stop();\n this.watchStream.stop();\n\n return Promise.resolve(undefined);\n }\n\n /** Starts new listen for the given query. Uses resume token if provided */\n listen(queryData: QueryData): void {\n assert(\n !objUtils.contains(this.listenTargets, queryData.targetId),\n 'listen called with duplicate targetId!'\n );\n // Mark this as something the client is currently listening for.\n this.listenTargets[queryData.targetId] = queryData;\n if (this.watchStream.isOpen()) {\n this.sendWatchRequest(queryData);\n } else if (!this.watchStream.isStarted()) {\n // The listen will be sent in onWatchStreamOpen\n this.startWatchStream();\n }\n }\n\n /** Removes the listen from server */\n unlisten(targetId: TargetId): void {\n assert(\n objUtils.contains(this.listenTargets, targetId),\n 'unlisten called without assigned target ID!'\n );\n const queryData = this.listenTargets[targetId];\n delete this.listenTargets[targetId];\n if (this.watchStream.isOpen()) {\n this.sendUnwatchRequest(targetId);\n }\n }\n\n /**\n * We need to increment the the expected number of pending responses we're due\n * from watch so we wait for the ack to process any messages from this target.\n */\n private sendWatchRequest(queryData: QueryData): void {\n this.recordPendingTargetRequest(queryData.targetId);\n this.watchStream.watch(queryData);\n }\n\n /**\n * We need to increment the expected number of pending responses we're due\n * from watch so we wait for the removal on the server before we process any\n * messages from this target.\n */\n private sendUnwatchRequest(targetId: TargetId): void {\n this.recordPendingTargetRequest(targetId);\n this.watchStream.unwatch(targetId);\n }\n\n /**\n * Increment the mapping of how many acks are needed from watch before we can\n * consider the server to be 'in-sync' with the client's active targets.\n */\n private recordPendingTargetRequest(targetId: TargetId): void {\n // For each request we get we need to record we need a response for it.\n this.pendingTargetResponses[targetId] =\n (this.pendingTargetResponses[targetId] || 0) + 1;\n }\n\n private startWatchStream(): void {\n assert(!this.watchStream.isStarted(), \"Can't restart started watch stream\");\n assert(\n this.shouldStartWatchStream(),\n 'Tried to start watch stream even though it should not be started'\n );\n this.watchStream.start();\n }\n\n /**\n * Returns whether the watch stream should be started because there are\n * active targets trying to be listened too\n */\n private shouldStartWatchStream(): boolean {\n return !objUtils.isEmpty(this.listenTargets);\n }\n\n private cleanupWatchStreamState(): void {\n // If the connection is closed then we'll never get a snapshot version for\n // the accumulated changes and so we'll never be able to complete the batch.\n // When we start up again the server is going to resend these changes\n // anyway, so just toss the accumulated state.\n this.accumulatedWatchChanges = [];\n this.pendingTargetResponses = {};\n }\n\n private onWatchStreamOpen(): Promise {\n // TODO(b/35852690): close the stream again (with some timeout?) if no watch\n // targets are active\n objUtils.forEachNumber(this.listenTargets, (targetId, queryData) => {\n this.sendWatchRequest(queryData);\n });\n return Promise.resolve();\n }\n\n private onWatchStreamClose(error: FirestoreError | null): Promise {\n this.cleanupWatchStreamState();\n\n // If there was an error, retry the connection.\n if (this.shouldStartWatchStream()) {\n this.updateOnlineStateAfterFailure();\n this.startWatchStream();\n } else {\n // No need to restart watch stream because there are no active targets.\n // The online state is set to unknown because there is no active attempt\n // at establishing a connection\n this.setOnlineStateToUnknown();\n }\n return Promise.resolve();\n }\n\n private onWatchStreamChange(\n watchChange: WatchChange,\n snapshotVersion: SnapshotVersion\n ): Promise {\n // Mark the connection as healthy because we got a message from the server\n this.setOnlineStateToHealthy();\n\n if (\n watchChange instanceof WatchTargetChange &&\n watchChange.state === WatchTargetChangeState.Removed &&\n watchChange.cause\n ) {\n // There was an error on a target, don't wait for a consistent snapshot\n // to raise events\n return this.handleTargetError(watchChange);\n }\n // Accumulate watch changes but don't process them if there's no\n // snapshotVersion or it's older than a previous snapshot we've processed\n // (can happen after we resume a target using a resume token).\n this.accumulatedWatchChanges.push(watchChange);\n if (\n !snapshotVersion.equals(SnapshotVersion.MIN) &&\n snapshotVersion.compareTo(\n this.localStore.getLastRemoteSnapshotVersion()\n ) >= 0\n ) {\n const changes = this.accumulatedWatchChanges;\n this.accumulatedWatchChanges = [];\n return this.handleWatchChangeBatch(snapshotVersion, changes);\n } else {\n return Promise.resolve();\n }\n }\n\n /**\n * Takes a batch of changes from the Datastore, repackages them as a\n * RemoteEvent, and passes that on to the listener, which is typically the\n * SyncEngine.\n */\n private handleWatchChangeBatch(\n snapshotVersion: SnapshotVersion,\n changes: WatchChange[]\n ): Promise {\n const aggregator = new WatchChangeAggregator(\n snapshotVersion,\n this.listenTargets,\n this.pendingTargetResponses\n );\n aggregator.addChanges(changes);\n const remoteEvent = aggregator.createRemoteEvent();\n // Get the new response counts from the aggregator\n this.pendingTargetResponses = aggregator.pendingTargetResponses;\n\n const promises: Array> = [];\n // Handle existence filters and existence filter mismatches.\n objUtils.forEachNumber(\n aggregator.existenceFilters,\n (targetId: TargetId, filter: ExistenceFilter) => {\n const queryData = this.listenTargets[targetId];\n if (!queryData) {\n // A watched target might have been removed already.\n return;\n }\n const query = queryData.query;\n if (query.isDocumentQuery()) {\n if (filter.count === 0) {\n // The existence filter told us the document does not exist.\n // We need to deduce that this document does not exist and apply\n // a deleted document to our updates. Without applying a deleted\n // document there might be another query that will raise this\n // document as part of a snapshot until it is resolved,\n // essentially exposing inconsistency between queries.\n const key = new DocumentKey(query.path);\n const deletedDoc = new NoDocument(key, snapshotVersion);\n remoteEvent.addDocumentUpdate(deletedDoc);\n } else {\n assert(\n filter.count === 1,\n 'Single document existence filter with count: ' + filter.count\n );\n }\n } else {\n // Not a document query.\n const promise = this.localStore\n .remoteDocumentKeys(targetId)\n .then(trackedRemote => {\n if (remoteEvent.targetChanges[targetId]) {\n const mapping = remoteEvent.targetChanges[targetId].mapping;\n if (mapping !== null) {\n if (mapping instanceof UpdateMapping) {\n trackedRemote = mapping.applyToKeySet(trackedRemote);\n } else {\n assert(\n mapping instanceof ResetMapping,\n 'Expected either reset or update mapping but got something else: ' +\n mapping\n );\n trackedRemote = mapping.documents;\n }\n }\n }\n\n if (trackedRemote.size !== filter.count) {\n // Existence filter mismatch, resetting mapping.\n\n // Make sure the mismatch is exposed in the remote event.\n remoteEvent.handleExistenceFilterMismatch(targetId);\n\n // Clear the resume token for the query, since we're in a\n // known mismatch state.\n const newQueryData = new QueryData(\n query,\n targetId,\n queryData.purpose\n );\n this.listenTargets[targetId] = newQueryData;\n\n // Cause a hard reset by unwatching and rewatching\n // immediately, but deliberately don't send a resume token\n // so that we get a full update.\n // Make sure we expect that this acks are going to happen.\n this.sendUnwatchRequest(targetId);\n\n // Mark the query we send as being on behalf of an existence\n // filter mismatch, but don't actually retain that in\n // listenTargets. This ensures that we flag the first\n // re-listen this way without impacting future listens of\n // this target (that might happen e.g. on reconnect).\n const requestQueryData = new QueryData(\n query,\n targetId,\n QueryPurpose.ExistenceFilterMismatch\n );\n this.sendWatchRequest(requestQueryData);\n }\n });\n promises.push(promise);\n }\n }\n );\n\n return Promise.all(promises).then(() => {\n // Update in-memory resume tokens. LocalStore will update the\n // persistent view of these when applying the completed RemoteEvent.\n objUtils.forEachNumber(remoteEvent.targetChanges, (targetId, change) => {\n if (change.resumeToken.length > 0) {\n const queryData = this.listenTargets[targetId];\n // A watched target might have been removed already.\n if (queryData) {\n this.listenTargets[targetId] = queryData.update({\n resumeToken: change.resumeToken,\n snapshotVersion: change.snapshotVersion\n });\n }\n }\n });\n\n // Finally handle remote event\n return this.syncEngine.applyRemoteEvent(remoteEvent);\n });\n }\n\n /** Handles an error on a target */\n private handleTargetError(watchChange: WatchTargetChange): Promise {\n assert(!!watchChange.cause, 'Handling target error without a cause');\n const error = watchChange.cause!;\n let promiseChain = Promise.resolve();\n watchChange.targetIds.forEach(targetId => {\n promiseChain = promiseChain.then(() => {\n if (objUtils.contains(this.listenTargets, targetId)) {\n delete this.listenTargets[targetId];\n return this.syncEngine.rejectListen(targetId, error);\n } else {\n // A watched target might have been removed already.\n return Promise.resolve();\n }\n });\n });\n return promiseChain;\n }\n\n /**\n * Notifies that there are new mutations to process in the queue. This is\n * typically called by SyncEngine after it has sent mutations to LocalStore.\n *\n */\n fillWritePipeline(): Promise {\n if (!this.canWriteMutations()) {\n return Promise.resolve();\n } else {\n return this.localStore\n .nextMutationBatch(this.lastBatchSeen)\n .then(batch => {\n if (batch === null) {\n return Promise.resolve();\n } else {\n this.commit(batch);\n return this.fillWritePipeline();\n }\n });\n }\n }\n\n /**\n * Returns true if the backend can accept additional write requests.\n *\n * When sending mutations to the write stream (e.g. in fillWritePipeline),\n * call this method first to check if more mutations can be sent.\n *\n * Currently the only thing that can prevent the backend from accepting\n * write requests is if there are too many requests already outstanding. As\n * writes complete the backend will be able to accept more.\n */\n canWriteMutations(): boolean {\n return this.pendingWrites.length < MAX_PENDING_WRITES;\n }\n\n // For testing\n outstandingWrites(): number {\n return this.pendingWrites.length;\n }\n\n /**\n * Given mutations to commit, actually commits them to the Datastore. Note\n * that this does *not* return a Promise specifically because the AsyncQueue\n * should not block operations for this.\n */\n private commit(batch: MutationBatch): void {\n assert(\n this.canWriteMutations(),\n \"commit called when batches can't be written\"\n );\n this.lastBatchSeen = batch.batchId;\n\n this.pendingWrites.push(batch);\n\n if (!this.writeStream.isStarted()) {\n this.startWriteStream();\n } else if (this.writeStream.handshakeComplete) {\n this.writeStream.writeMutations(batch.mutations);\n }\n }\n\n private startWriteStream(): void {\n assert(!this.writeStream.isStarted(), \"Can't restart started write stream\");\n this.writeStream.start();\n }\n\n private onWriteStreamOpen(): Promise {\n this.writeStream.writeHandshake();\n\n return Promise.resolve();\n }\n\n private onWriteHandshakeComplete(): Promise {\n // Record the stream token.\n return this.localStore\n .setLastStreamToken(this.writeStream.lastStreamToken)\n .then(() => {\n // Drain any pending writes.\n //\n // Note that at this point pendingWrites contains mutations that\n // have already been accepted by fillWritePipeline/commitBatch. If\n // the pipeline is full, canWriteMutations will be false, despite\n // the fact that we actually need to send mutations over.\n //\n // This also means that this method indirectly respects the limits\n // imposed by canWriteMutations since writes can't be added to the\n // pendingWrites array when canWriteMutations is false. If the\n // limits imposed by canWriteMutations actually protect us from\n // DOSing ourselves then those limits won't be exceeded here and\n // we'll continue to make progress.\n for (const batch of this.pendingWrites) {\n this.writeStream.writeMutations(batch.mutations);\n }\n });\n }\n\n private onMutationResult(\n commitVersion: SnapshotVersion,\n results: MutationResult[]\n ): Promise {\n // This is a response to a write containing mutations and should be\n // correlated to the first pending write.\n assert(\n this.pendingWrites.length > 0,\n 'Got result for empty pending writes'\n );\n const batch = this.pendingWrites.shift()!;\n const success = MutationBatchResult.from(\n batch,\n commitVersion,\n results,\n this.writeStream.lastStreamToken\n );\n return this.syncEngine.applySuccessfulWrite(success).then(() => {\n // It's possible that with the completion of this mutation another\n // slot has freed up.\n return this.fillWritePipeline();\n });\n }\n\n private onWriteStreamClose(error?: FirestoreError): Promise {\n // Ignore close if there are no pending writes.\n if (this.pendingWrites.length > 0) {\n assert(\n !!error,\n 'We have pending writes, but the write stream closed without an error'\n );\n // A promise that is resolved after we processed the error\n let errorHandling: Promise;\n if (this.writeStream.handshakeComplete) {\n // This error affects the actual write.\n errorHandling = this.handleWriteError(error!);\n } else {\n // If there was an error before the handshake has finished, it's\n // possible that the server is unable to process the stream token\n // we're sending. (Perhaps it's too old?)\n errorHandling = this.handleHandshakeError(error!);\n }\n\n return errorHandling.then(() => {\n // The write stream might have been started by refilling the write\n // pipeline for failed writes\n if (this.pendingWrites.length > 0 && !this.writeStream.isStarted()) {\n this.startWriteStream();\n }\n });\n } else {\n // No pending writes, nothing to do\n return Promise.resolve();\n }\n }\n\n private handleHandshakeError(error: FirestoreError): Promise {\n // Reset the token if it's a permanent error or the error code is\n // ABORTED, signaling the write stream is no longer valid.\n if (isPermanentError(error.code) || error.code === Code.ABORTED) {\n log.debug(\n LOG_TAG,\n 'RemoteStore error before completed handshake; resetting stream token: ',\n this.writeStream.lastStreamToken\n );\n this.writeStream.lastStreamToken = emptyByteString();\n\n return this.localStore.setLastStreamToken(emptyByteString());\n } else {\n // Some other error, don't reset stream token. Our stream logic will\n // just retry with exponential backoff.\n return Promise.resolve();\n }\n }\n\n private handleWriteError(error: FirestoreError): Promise {\n if (isPermanentError(error.code)) {\n // This was a permanent error, the request itself was the problem\n // so it's not going to succeed if we resend it.\n const batch = this.pendingWrites.shift()!;\n\n // In this case it's also unlikely that the server itself is melting\n // down -- this was just a bad request so inhibit backoff on the next\n // restart.\n this.writeStream.inhibitBackoff();\n\n return this.syncEngine\n .rejectFailedWrite(batch.batchId, error)\n .then(() => {\n // It's possible that with the completion of this mutation\n // another slot has freed up.\n return this.fillWritePipeline();\n });\n } else {\n // Transient error, just let the retry logic kick in.\n return Promise.resolve();\n }\n }\n\n createTransaction(): Transaction {\n return new Transaction(this.datastore);\n }\n\n handleUserChange(user: User): Promise {\n log.debug(LOG_TAG, 'RemoteStore changing users: uid=', user.uid);\n\n // Clear pending writes because those are per-user. Watched targets\n // persist across users so don't clear those.\n this.lastBatchSeen = BATCHID_UNKNOWN;\n this.pendingWrites = [];\n\n // Stop the streams. They promise not to call us back.\n this.watchStream.stop();\n this.writeStream.stop();\n\n this.cleanupWatchStreamState();\n\n // Create new streams (but note they're not started yet).\n return this.setupStreams()\n .then(() => {\n // If there are any watchedTargets, properly handle the stream\n // restart now that RemoteStore is ready to handle them.\n if (this.shouldStartWatchStream()) {\n this.startWatchStream();\n }\n\n // Resume any writes\n return this.fillWritePipeline();\n })\n .then(() => {\n // User change moves us back to the unknown state because we might\n // not want to re-open the stream\n this.setOnlineStateToUnknown();\n });\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/remote/remote_store.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CredentialsProvider } from '../api/credentials';\nimport { User } from '../auth/user';\nimport {\n EventManager,\n ListenOptions,\n Observer,\n QueryListener\n} from './event_manager';\nimport { SyncEngine } from './sync_engine';\nimport { EagerGarbageCollector } from '../local/eager_garbage_collector';\nimport { GarbageCollector } from '../local/garbage_collector';\nimport { IndexedDbPersistence } from '../local/indexeddb_persistence';\nimport { LocalStore } from '../local/local_store';\nimport { MemoryPersistence } from '../local/memory_persistence';\nimport { NoOpGarbageCollector } from '../local/no_op_garbage_collector';\nimport { Persistence } from '../local/persistence';\nimport { Mutation } from '../model/mutation';\nimport { Platform } from '../platform/platform';\nimport { Datastore } from '../remote/datastore';\nimport { RemoteStore } from '../remote/remote_store';\nimport { JsonProtoSerializer } from '../remote/serializer';\nimport { AsyncQueue } from '../util/async_queue';\nimport { Code, FirestoreError } from '../util/error';\nimport { debug } from '../util/log';\nimport { Deferred } from '../util/promise';\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { DatabaseId, DatabaseInfo } from './database_info';\nimport { Query } from './query';\nimport { Transaction } from './transaction';\nimport { OnlineState } from './types';\nimport { ViewSnapshot } from './view_snapshot';\n\nconst LOG_TAG = 'FirestoreClient';\n\n/**\n * FirestoreClient is a top-level class that constructs and owns all of the\n * pieces of the client SDK architecture. It is responsible for creating the\n * async queue that is shared by all of the other components in the system.\n */\nexport class FirestoreClient {\n // NOTE: These should technically have '|undefined' in the types, since\n // they're initialized asynchronously rather than in the constructor, but\n // given that all work is done on the async queue and we assert that\n // initialization completes before any other work is queued, we're cheating\n // with the types rather than littering the code with '!' or unnecessary\n // undefined checks.\n private eventMgr: EventManager;\n private garbageCollector: GarbageCollector;\n private persistence: Persistence;\n private localStore: LocalStore;\n private remoteStore: RemoteStore;\n private syncEngine: SyncEngine;\n\n constructor(\n private platform: Platform,\n private databaseInfo: DatabaseInfo,\n private credentials: CredentialsProvider,\n /**\n * Asynchronous queue responsible for all of our internal processing. When\n * we get incoming work from the user (via public API) or the network\n * (incoming GRPC messages), we should always schedule onto this queue.\n * This ensures all of our work is properly serialized (e.g. we don't\n * start processing a new operation while the previous one is waiting for\n * an async I/O to complete).\n */\n private asyncQueue: AsyncQueue\n ) {}\n\n /**\n * Starts up the FirestoreClient, returning only whether or not enabling\n * persistence succeeded.\n *\n * The intent here is to \"do the right thing\" as far as users are concerned.\n * Namely, in cases where offline persistence is requested and possible,\n * enable it, but otherwise fall back to persistence disabled. For the most\n * part we expect this to succeed one way or the other so we don't expect our\n * users to actually wait on the firestore.enablePersistence Promise since\n * they generally won't care.\n *\n * Of course some users actually do care about whether or not persistence\n * was successfully enabled, so the Promise returned from this method\n * indicates this outcome.\n *\n * This presents a problem though: even before enablePersistence resolves or\n * rejects, users may have made calls to e.g. firestore.collection() which\n * means that the FirestoreClient in there will be available and will be\n * enqueuing actions on the async queue.\n *\n * Meanwhile any failure of an operation on the async queue causes it to\n * panic and reject any further work, on the premise that unhandled errors\n * are fatal.\n *\n * Consequently the fallback is handled internally here in start, and if the\n * fallback succeeds we signal success to the async queue even though the\n * start() itself signals failure.\n *\n * @param usePersistence Whether or not to attempt to enable persistence.\n * @returns A deferred result indicating the user-visible result of enabling\n * offline persistence. This method will reject this if IndexedDB fails to\n * start for any reason. If usePersistence is false this is\n * unconditionally resolved.\n */\n public start(usePersistence: boolean): Promise {\n // We defer our initialization until we get the current user from\n // setUserChangeListener(). We block the async queue until we got the\n // initial user and the initialization is completed. This will prevent\n // any scheduled work from happening before initialization is completed.\n //\n // If initializationDone resolved then the FirestoreClient is in a usable\n // state.\n const initializationDone = new Deferred();\n\n // If usePersistence is true, certain classes of errors while starting are\n // recoverable but only by falling back to persistence disabled.\n //\n // If there's an error in the first case but not in recovery we cannot\n // reject the promise blocking the async queue because this will cause the\n // async queue to panic.\n const persistenceResult = new Deferred();\n\n let initialized = false;\n this.credentials.setUserChangeListener(user => {\n if (!initialized) {\n initialized = true;\n\n this.initializePersistence(usePersistence, persistenceResult)\n .then(() => this.initializeRest(user))\n .then(initializationDone.resolve, initializationDone.reject);\n } else {\n this.asyncQueue.schedule(() => {\n return this.handleUserChange(user);\n });\n }\n });\n\n // Block the async queue until initialization is done\n this.asyncQueue.schedule(() => {\n return initializationDone.promise;\n });\n\n // Return only the result of enabling persistence. Note that this does not\n // need to await the completion of initializationDone because the result of\n // this method should not reflect any other kind of failure to start.\n return persistenceResult.promise;\n }\n\n /**\n * Initializes persistent storage, attempting to use IndexedDB if\n * usePersistence is true or memory-only if false.\n *\n * If IndexedDB fails because it's already open in another tab or because the\n * platform can't possibly support our implementation then this method rejects\n * the persistenceResult and falls back on memory-only persistence.\n *\n * @param usePersistence indicates whether or not to use offline persistence\n * @param persistenceResult A deferred result indicating the user-visible\n * result of enabling offline persistence. This method will reject this if\n * IndexedDB fails to start for any reason. If usePersistence is false\n * this is unconditionally resolved.\n * @returns a Promise indicating whether or not initialization should\n * continue, i.e. that one of the persistence implementations actually\n * succeeded.\n */\n private initializePersistence(\n usePersistence: boolean,\n persistenceResult: Deferred\n ): Promise {\n if (usePersistence) {\n return this.startIndexedDbPersistence()\n .then(persistenceResult.resolve)\n .catch((error: FirestoreError) => {\n // Regardless of whether or not the retry succeeds, from an user\n // perspective, offline persistence has failed.\n persistenceResult.reject(error);\n\n // An unknown failure on the first stage shuts everything down.\n if (!this.canFallback(error)) {\n return Promise.reject(error);\n }\n\n console.warn(\n 'Error enabling offline storage. Falling back to' +\n ' storage disabled: ' +\n error\n );\n return this.startMemoryPersistence();\n });\n } else {\n // When usePersistence == false, enabling offline persistence is defined\n // to unconditionally succeed. This allows start() to have the same\n // signature for both cases, despite the fact that the returned promise\n // is only used in the enablePersistence call.\n persistenceResult.resolve();\n return this.startMemoryPersistence();\n }\n }\n\n private canFallback(error: FirestoreError): boolean {\n return (\n error.code === Code.FAILED_PRECONDITION ||\n error.code === Code.UNIMPLEMENTED\n );\n }\n\n /**\n * Starts IndexedDB-based persistence.\n *\n * @returns A promise indicating success or failure.\n */\n private startIndexedDbPersistence(): Promise {\n // TODO(http://b/33384523): For now we just disable garbage collection\n // when persistence is enabled.\n this.garbageCollector = new NoOpGarbageCollector();\n const storagePrefix = IndexedDbPersistence.buildStoragePrefix(\n this.databaseInfo\n );\n // Opt to use proto3 JSON in case the platform doesn't support Uint8Array.\n const serializer = new JsonProtoSerializer(this.databaseInfo.databaseId, {\n useProto3Json: true\n });\n this.persistence = new IndexedDbPersistence(storagePrefix, serializer);\n return this.persistence.start();\n }\n\n /**\n * Starts Memory-backed persistence. In practice this cannot fail.\n *\n * @returns A promise that will successfully resolve.\n */\n private startMemoryPersistence(): Promise {\n this.garbageCollector = new EagerGarbageCollector();\n this.persistence = new MemoryPersistence();\n return this.persistence.start();\n }\n\n /**\n * Initializes the rest of the FirestoreClient, assuming the initial user\n * has been obtained from the credential provider and some persistence\n * implementation is available in this.persistence.\n */\n private initializeRest(user: User): Promise {\n return this.platform\n .loadConnection(this.databaseInfo)\n .then(connection => {\n this.localStore = new LocalStore(\n this.persistence,\n user,\n this.garbageCollector\n );\n const serializer = this.platform.newSerializer(\n this.databaseInfo.databaseId\n );\n const datastore = new Datastore(\n this.databaseInfo,\n this.asyncQueue,\n connection,\n this.credentials,\n serializer\n );\n\n const onlineStateChangedHandler = (onlineState: OnlineState) => {\n this.eventMgr.onOnlineStateChanged(onlineState);\n };\n\n this.remoteStore = new RemoteStore(\n this.databaseInfo,\n this.asyncQueue,\n this.localStore,\n datastore,\n onlineStateChangedHandler\n );\n\n this.syncEngine = new SyncEngine(\n this.localStore,\n this.remoteStore,\n user\n );\n\n // Setup wiring between sync engine and remote store\n this.remoteStore.syncEngine = this.syncEngine;\n\n this.eventMgr = new EventManager(this.syncEngine);\n\n // NOTE: RemoteStore depends on LocalStore (for persisting stream\n // tokens, refilling mutation queue, etc.) so must be started after\n // LocalStore.\n return this.localStore.start();\n })\n .then(() => {\n return this.remoteStore.start();\n });\n }\n\n private handleUserChange(user: User): Promise {\n this.asyncQueue.verifyOperationInProgress();\n\n debug(LOG_TAG, 'User Changed: ' + user.uid);\n return this.syncEngine.handleUserChange(user);\n }\n\n shutdown(): Promise {\n return this.asyncQueue\n .schedule(() => {\n this.credentials.removeUserChangeListener();\n return this.remoteStore.shutdown();\n })\n .then(() => {\n // PORTING NOTE: LocalStore does not need an explicit shutdown on web.\n return this.persistence.shutdown();\n });\n }\n\n listen(\n query: Query,\n observer: Observer,\n options: ListenOptions\n ): QueryListener {\n const listener = new QueryListener(query, observer, options);\n this.asyncQueue.schedule(() => {\n return this.eventMgr.listen(listener);\n });\n return listener;\n }\n\n unlisten(listener: QueryListener): void {\n this.asyncQueue.schedule(() => {\n return this.eventMgr.unlisten(listener);\n });\n }\n\n write(mutations: Mutation[]): Promise {\n const deferred = new Deferred();\n this.asyncQueue.schedule(() => this.syncEngine.write(mutations, deferred));\n return deferred.promise;\n }\n\n databaseId(): DatabaseId {\n return this.databaseInfo.databaseId;\n }\n\n transaction(\n updateFunction: (transaction: Transaction) => Promise\n ): Promise {\n // We have to wait for the async queue to be sure syncEngine is initialized.\n return this.asyncQueue\n .schedule(() => {\n return Promise.resolve();\n })\n .then(() => {\n return this.syncEngine.runTransaction(updateFunction);\n });\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/core/firestore_client.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Observer } from '../core/event_manager';\nimport { EventHandler } from './misc';\n\n/*\n * A wrapper implementation of Observer that will dispatch events\n * asynchronously. To allow immediate silencing, a mute call is added which\n * causes events scheduled to no longer be raised.\n */\nexport class AsyncObserver implements Observer {\n /**\n * When set to true, will not raise future events. Necessary to deal with\n * async detachment of listener.\n */\n private muted = false;\n\n constructor(private observer: Observer) {}\n\n next(value: T): void {\n this.scheduleEvent(this.observer.next, value);\n }\n\n error(error: Error): void {\n this.scheduleEvent(this.observer.error, error);\n }\n\n mute(): void {\n this.muted = true;\n }\n\n private scheduleEvent(eventHandler: EventHandler, event: E): void {\n if (!this.muted) {\n setTimeout(() => {\n if (!this.muted) {\n eventHandler(event);\n }\n }, 0);\n }\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/async_observer.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PromiseImpl as Promise } from '../../utils/promise';\n\nimport { assert, fail } from './assert';\nimport * as log from './log';\nimport { AnyDuringMigration, AnyJs } from './misc';\n\nimport { Deferred } from './promise';\n\nexport class AsyncQueue {\n // The last promise in the queue.\n private tail: Promise = Promise.resolve();\n\n // The number of ops that are queued to be run in the future (i.e. they had a\n // delay that has not yet elapsed).\n private delayedOpCount = 0;\n\n // visible for testing\n failure: Error;\n\n // Flag set while there's an outstanding AsyncQueue operation, used for\n // assertion sanity-checks.\n private operationInProgress = false;\n\n /**\n * Adds a new operation to the queue. Returns a promise that will be resolved\n * when the promise returned by the new operation is (with its value).\n *\n * Can optionally specify a delay to wait before queuing the operation.\n */\n schedule(op: () => Promise, delay?: number): Promise {\n if (this.failure) {\n fail('AsyncQueue is already failed: ' + this.failure.message);\n }\n\n if ((delay || 0) > 0) {\n this.delayedOpCount++;\n const deferred = new Deferred();\n setTimeout(() => {\n this.scheduleInternal(() => {\n return op().then(result => {\n deferred.resolve(result);\n });\n });\n this.delayedOpCount--; // decrement once it's actually queued.\n }, delay);\n return deferred.promise;\n } else {\n return this.scheduleInternal(op);\n }\n }\n\n private scheduleInternal(op: () => Promise): Promise {\n this.tail = this.tail.then(() => {\n this.operationInProgress = true;\n return op()\n .catch(error => {\n this.failure = error;\n this.operationInProgress = false;\n log.error('INTERNAL UNHANDLED ERROR: ', error.stack || error.message);\n throw error;\n })\n .then(() => {\n this.operationInProgress = false;\n });\n });\n return this.tail as AnyDuringMigration;\n }\n\n /**\n * Verifies there's an operation currently in-progress on the AsyncQueue.\n * Unfortunately we can't verify that the running code is in the promise chain\n * of that operation, so this isn't a foolproof check, but it should be enough\n * to catch some bugs.\n */\n verifyOperationInProgress(): void {\n assert(\n this.operationInProgress,\n 'verifyOpInProgress() called when no op in progress on this queue.'\n );\n }\n\n drain(): Promise {\n // TODO(mikelehen): This should perhaps also drain items that are queued to\n // run in the future (perhaps by artificially running them early), but since\n // no tests need that yet, I didn't bother for now.\n assert(this.delayedOpCount === 0, \"draining doesn't handle delayed ops.\");\n return this.schedule(() => Promise.resolve(undefined));\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/util/async_queue.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Simple wrapper around a nullable UID. Mostly exists to make code more\n * readable.\n */\nexport class User {\n /** A user with a null UID. */\n static readonly UNAUTHENTICATED = new User(null);\n\n // TODO(mikelehen): Look into getting a proper uid-equivalent for\n // non-FirebaseAuth providers.\n static readonly GOOGLE_CREDENTIALS = new User('google-credentials-uid');\n static readonly FIRST_PARTY = new User('first-party-uid');\n\n constructor(readonly uid: string | null) {}\n\n isUnauthenticated(): boolean {\n return this.uid == null;\n }\n\n /**\n * Returns a key representing this user, suitable for inclusion in a\n * dictionary.\n */\n toKey(): string {\n if (this.isUnauthenticated()) {\n return 'anonymous-user';\n } else {\n return 'uid:' + this.uid;\n }\n }\n\n equals(otherUser: User): boolean {\n return otherUser.uid === this.uid;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/auth/user.ts","/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as firestore from 'firestore';\n\nimport { makeConstructorPrivate } from '../util/api';\n\n/**\n * An opaque base class for FieldValue sentinel objects in our public API,\n * with public static methods for creating said sentinel objects.\n */\n// tslint:disable-next-line:class-as-namespace We use this as a base class.\nexport abstract class FieldValueImpl implements firestore.FieldValue {\n static delete(): FieldValueImpl {\n return DeleteFieldValueImpl.instance;\n }\n static serverTimestamp(): FieldValueImpl {\n return ServerTimestampFieldValueImpl.instance;\n }\n}\n\nexport class DeleteFieldValueImpl extends FieldValueImpl {\n private constructor() {\n super();\n }\n /** Singleton instance. */\n static instance = new DeleteFieldValueImpl();\n}\n\nexport class ServerTimestampFieldValueImpl extends FieldValueImpl {\n private constructor() {\n super();\n }\n /** Singleton instance. */\n static instance = new ServerTimestampFieldValueImpl();\n}\n\n// Public instance that disallows construction at runtime. This constructor is\n// used when exporting FieldValueImpl on firebase.firestore.FieldValue and will\n// be called FieldValue publicly. Internally we still use FieldValueImpl which\n// has a type-checked private constructor. Note that FieldValueImpl and\n// PublicFieldValue can be used interchangeably in instanceof checks.\n// For our internal TypeScript code PublicFieldValue doesn't exist as a type,\n// and so we need to use FieldValueImpl as type and export it too.\n// tslint:disable-next-line:variable-name We treat this as a class name.\nexport const PublicFieldValue = makeConstructorPrivate(\n FieldValueImpl,\n 'Use FieldValue.() instead.'\n);\n\n\n\n// WEBPACK FOOTER //\n// ./src/firestore/api/field_value.ts","(function() {var g,goog=goog||{},k=this;function l(a){return\"string\"==typeof a}function aa(){}\nfunction ba(a){var b=typeof a;if(\"object\"==b)if(a){if(a instanceof Array)return\"array\";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(\"[object Window]\"==c)return\"object\";if(\"[object Array]\"==c||\"number\"==typeof a.length&&\"undefined\"!=typeof a.splice&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"splice\"))return\"array\";if(\"[object Function]\"==c||\"undefined\"!=typeof a.call&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"call\"))return\"function\"}else return\"null\";\nelse if(\"function\"==b&&\"undefined\"==typeof a.call)return\"object\";return b}function n(a){return\"array\"==ba(a)}function ca(a){var b=ba(a);return\"array\"==b||\"object\"==b&&\"number\"==typeof a.length}function da(a){return\"function\"==ba(a)}function p(a){var b=typeof a;return\"object\"==b&&null!=a||\"function\"==b}var q=\"closure_uid_\"+(1E9*Math.random()>>>0),ea=0;function fa(a,b,c){return a.call.apply(a.bind,arguments)}\nfunction ha(a,b,c){if(!a)throw Error();if(2b?1:0};function na(a,b){b.unshift(a);ja.call(this,ka.apply(null,b));b.shift()}u(na,ja);na.prototype.name=\"AssertionError\";function oa(a,b){throw new na(\"Failure\"+(a?\": \"+a:\"\"),Array.prototype.slice.call(arguments,1));};function w(){0!=qa&&(ra[this[q]||(this[q]=++ea)]=this);this.i=this.i;this.v=this.v}var qa=0,ra={};w.prototype.i=!1;w.prototype.Y=function(){if(!this.i&&(this.i=!0,this.w(),0!=qa)){var a=this[q]||(this[q]=++ea);delete ra[a]}};w.prototype.w=function(){if(this.v)for(;this.v.length;)this.v.shift()()};var sa=Array.prototype.indexOf?function(a,b,c){return Array.prototype.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(l(a))return l(b)&&1==b.length?a.indexOf(b,c):-1;for(;cb?null:l(a)?a.charAt(b):a[b]}function wa(a){if(!n(a))for(var b=a.length-1;0<=b;b--)delete a[b];a.length=0}function xa(a){return Array.prototype.concat.apply([],arguments)}function ya(a){var b=a.length;if(0parseFloat(Qa)){Pa=String(Ta);break a}}Pa=Qa}var Ja={};\nfunction Ua(a){return Ia(a,function(){for(var b=0,c=la(String(Pa)).split(\".\"),d=la(String(a)).split(\".\"),e=Math.max(c.length,d.length),f=0;0==b&&f=a.keyCode)a.keyCode=-1}catch(b){}};var cb=\"closure_listenable_\"+(1E6*Math.random()|0);function db(a){return!(!a||!a[cb])}var eb=0;function fb(a,b,c,d,e){this.listener=a;this.a=null;this.src=b;this.type=c;this.capture=!!d;this.da=e;this.key=++eb;this.X=this.ba=!1}function gb(a){a.X=!0;a.listener=null;a.a=null;a.src=null;a.da=null};function hb(a){this.src=a;this.a={};this.b=0}function ib(a,b,c,d,e,f){var h=b.toString();b=a.a[h];b||(b=a.a[h]=[],a.b++);var m=jb(b,c,e,f);-1d.keyCode||void 0!=d.returnValue)){a:{var e=!1;if(0==d.keyCode)try{d.keyCode=-1;break a}catch(h){e=!0}if(e||void 0==d.returnValue)d.returnValue=!0}d=[];for(e=b.a;e;e=e.parentNode)d.push(e);a=a.type;for(e=d.length-1;0<=e;e--){b.a=d[e];var f=zb(d[e],a,!0,b);c=c&&f}for(e=0;e>>0);function rb(a){if(da(a))return a;a[Bb]||(a[Bb]=function(b){return a.handleEvent(b)});return a[Bb]};function B(){w.call(this);this.c=new hb(this);this.P=this;this.J=null}u(B,w);B.prototype[cb]=!0;g=B.prototype;g.addEventListener=function(a,b,c,d){pb(this,a,b,c,d)};g.removeEventListener=function(a,b,c,d){xb(this,a,b,c,d)};\ng.dispatchEvent=function(a){var b,c=this.J;if(c)for(b=[];c;c=c.J)b.push(c);c=this.P;var d=a.type||a;if(l(a))a=new A(a,c);else if(a instanceof A)a.target=a.target||c;else{var e=a;a=new A(d,c);Ga(a,e)}e=!0;if(b)for(var f=b.length-1;0<=f;f--){var h=a.a=b[f];e=Cb(h,d,!0,a)&&e}h=a.a=c;e=Cb(h,d,!0,a)&&e;e=Cb(h,d,!1,a)&&e;if(b)for(f=0;f=lc(this).value)for(da(b)&&(b=b()),a=new dc(a,String(b),this.f),c&&(a.a=c),c=\"log:\"+a.b,(a=k.console)&&a.timeStamp&&a.timeStamp(c),(a=k.msWriteProfilerMark)&&a(c),c=this;c;)c=c.a};function F(a,b){a.log(gc,b,void 0)}function G(a,b){a.log(hc,b,void 0)}var mc={},nc=null;\nfunction oc(a){nc||(nc=new fc(\"\"),mc[\"\"]=nc,nc.c=jc);var b;if(!(b=mc[a])){b=new fc(a);var c=a.lastIndexOf(\".\"),d=a.substr(c+1);c=oc(a.substr(0,c));c.b||(c.b={});c.b[d]=b;b.a=c;mc[a]=b}return b};function pc(a,b){a&&a.log(ic,b,void 0)}function H(a,b){a&&a.log(kc,b,void 0)};function qc(){this.a=oc(\"goog.labs.net.webChannel.WebChannelDebug\")}function rc(a,b,c,d){if(c)try{var e=JSON.parse(c);if(e)for(var f=0;fh.length)){var m=h[1];if(n(m)&&!(1>m.length)){var v=m[0];if(\"noop\"!=v&&\"stop\"!=v&&\"close\"!=v)for(var Ra=1;Rab||3==b&&!Ka&&!this.a.U())){this.s||4!=b||7==c||uc();Rc(this);var d=this.a.V();this.v=d;var e=this.a.U();e||I(this.b,\"No response text for uri \"+this.g+\" status \"+d);this.c=200==d;I(this.b,\"XMLHTTP RESP (\"+this.f+\") [ attempt \"+this.S+\"]: \"+this.j+\"\\n\"+this.g+\"\\n\"+b+\" \"+d);if(this.c)this.J?(Sc(this,b,e),Ka&&this.c&&3==b&&(this.M.$(this.F,\"tick\",this.fb),this.F.start())):(rc(this.b,this.f,e,null),Tc(this,e)),4==b&&Uc(this),this.c&&\n!this.s&&(4==b?this.m.wa(this):(this.c=!1,Pc(this)));else{if(400==d&&0b.length)return Kc;b=b.substr(d,c);a.C=d+c;return b}g.cancel=function(){this.s=!0;Uc(this)};function Pc(a){a.T=t()+a.P;Xc(a,a.P)}function Xc(a,b){if(null!=a.o)throw Error(\"WatchDog timer not null\");a.o=xc(r(a.eb,a),b)}function Rc(a){a.o&&(k.clearTimeout(a.o),a.o=null)}\ng.eb=function(){this.o=null;var a=t();if(0<=a-this.T)this.c&&(a=this.b.a)&&F(a,\"Received watchdog timeout even though request loaded successfully\"),I(this.b,\"TIMEOUT: \"+this.g),2!=this.I&&(uc(),K()),Uc(this),this.i=2,Vc(this);else{var b=this.b.a;b&&G(b,\"WatchDog timer called too early\");Xc(this,this.T-a)}};function Vc(a){a.m.Ka()||a.s||a.m.wa(a)}function Uc(a){Rc(a);var b=a.G;b&&\"function\"==typeof b.Y&&b.Y();a.G=null;Yb(a.F);cc(a.M);a.a&&(b=a.a,a.a=null,b.abort(),b.Y())}\nfunction Tc(a,b){try{a.m.Na(a,b),uc()}catch(c){sc(a.b,c,\"Error in httprequest callback\")}};function Yc(a){if(a.A&&\"function\"==typeof a.A)return a.A();if(l(a))return a.split(\"\");if(ca(a)){for(var b=[],c=a.length,d=0;d2*a.c&&$c(a),!0):!1}function $c(a){if(a.c!=a.a.length){for(var b=0,c=0;bb)throw Error(\"Bad port number \"+b);a.i=b}else a.i=null}function hd(a,b,c){b instanceof kd?(a.c=b,qd(a.c,a.h)):(c||(b=ld(b,rd)),a.c=new kd(b,0,a.h))}\nfunction R(a,b,c){a.c.set(b,c)}function Qc(a,b,c){n(c)||(c=[String(c)]);sd(a.c,b,c)}function Mc(a){R(a,\"zx\",Math.floor(2147483648*Math.random()).toString(36)+Math.abs(Math.floor(2147483648*Math.random())^t()).toString(36));return a}function td(a){return a instanceof Q?M(a):new Q(a,void 0)}function ud(a,b,c,d){var e=new Q(null,void 0);a&&ed(e,a);b&&fd(e,b);c&&gd(e,c);d&&(e.a=d);return e}function jd(a,b){return a?b?decodeURI(a.replace(/%25/g,\"%2525\")):decodeURIComponent(a):\"\"}\nfunction ld(a,b,c){return l(a)?(a=encodeURI(a).replace(b,vd),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,\"%$1\")),a):null}function vd(a){a=a.charCodeAt(0);return\"%\"+(a>>4&15).toString(16)+(a&15).toString(16)}var md=/[#\\/\\?@]/g,od=/[\\#\\?:]/g,nd=/[\\#\\?]/g,rd=/[\\#\\?@]/g,pd=/#/g;function kd(a,b,c){this.b=this.a=null;this.c=a||null;this.f=!!c}\nfunction S(a){a.a||(a.a=new O,a.b=0,a.c&&dd(a.c,function(b,c){b=decodeURIComponent(b.replace(/\\+/g,\" \"));S(a);a.c=null;b=wd(a,b);var d=a.a.get(b);d||a.a.set(b,d=[]);d.push(c);a.b+=1}))}g=kd.prototype;g.u=function(){S(this);return this.b};function xd(a,b){S(a);b=wd(a,b);P(a.a.b,b)&&(a.c=null,a.b-=a.a.get(b).length,bd(a.a,b))}function yd(a,b){S(a);b=wd(a,b);return P(a.a.b,b)}g.forEach=function(a,b){S(this);this.a.forEach(function(c,d){ta(c,function(c){a.call(b,c,d,this)},this)},this)};\ng.O=function(){S(this);for(var a=this.a.A(),b=this.a.O(),c=[],d=0;d=a.c:!1}function Td(a,b){return a.b?a.b==b:a.a?a.a.contains(b):!1}function Rd(a,b){a.a?a.a.a.set(T(b),b):a.b=b}\nOd.prototype.cancel=function(){this.b?(this.b.cancel(),this.b=null):this.a&&0!=this.a.a.c&&(ta(this.a.A(),function(a){a.cancel()}),ad(this.a.a))};function Ud(a,b){this.a=a;this.b=b};function Vd(a,b){this.a=a;this.b=b}Vd.prototype.stringify=function(a){return k.JSON.stringify(a,this.a)};Vd.prototype.parse=function(a){return k.JSON.parse(a,this.b)};function Wd(){this.a=new Vd}function Xd(a,b,c){var d=c||\"\";try{Zc(a,function(a,c){var e=a;p(a)&&(e=Fb(a));b.push(d+c+\"=\"+encodeURIComponent(e))})}catch(e){throw b.push(d+\"type=\"+encodeURIComponent(\"_badmap\")),e;}};function Yd(a,b){var c=new qc;I(c,\"TestLoadImage: loading \"+a);var d=new Image;d.onload=ia(Zd,c,d,\"TestLoadImage: loaded\",!0,b);d.onerror=ia(Zd,c,d,\"TestLoadImage: error\",!1,b);d.onabort=ia(Zd,c,d,\"TestLoadImage: abort\",!1,b);d.ontimeout=ia(Zd,c,d,\"TestLoadImage: timeout\",!1,b);k.setTimeout(function(){if(d.ontimeout)d.ontimeout()},1E4);d.src=a}function Zd(a,b,c,d,e){try{I(a,c),b.onload=null,b.onerror=null,b.onabort=null,b.ontimeout=null,e(d)}catch(f){sc(a,f)}};function U(a){B.call(this);this.headers=new O;this.G=a||null;this.f=!1;this.F=this.a=null;this.M=this.s=\"\";this.j=0;this.g=\"\";this.h=this.I=this.o=this.H=!1;this.l=0;this.B=null;this.N=$d;this.C=this.m=!1}u(U,B);var $d=\"\";U.prototype.b=oc(\"goog.net.XhrIo\");var ae=/^https?$/i,be=[\"POST\",\"PUT\"];g=U.prototype;\ng.ta=function(a,b,c,d){if(this.a)throw Error(\"[goog.net.XhrIo] Object is active with another request=\"+this.s+\"; newUri=\"+a);b=b?b.toUpperCase():\"GET\";this.s=a;this.g=\"\";this.j=0;this.M=b;this.H=!1;this.f=!0;this.a=this.G?Fc(this.G):Fc(Dc);this.F=this.G?Bc(this.G):Bc(Dc);this.a.onreadystatechange=r(this.Ma,this);try{H(this.b,V(this,\"Opening Xhr\")),this.I=!0,this.a.open(b,String(a),!0),this.I=!1}catch(f){H(this.b,V(this,\"Error opening Xhr: \"+f.message));ce(this,f);return}a=c||\"\";var e=new O(this.headers);\nd&&Zc(d,function(a,b){e.set(b,a)});d=ua(e.O());c=k.FormData&&a instanceof k.FormData;!(0<=sa(be,b))||d||c||e.set(\"Content-Type\",\"application/x-www-form-urlencoded;charset=utf-8\");e.forEach(function(a,b){this.a.setRequestHeader(b,a)},this);this.N&&(this.a.responseType=this.N);\"withCredentials\"in this.a&&this.a.withCredentials!==this.m&&(this.a.withCredentials=this.m);try{de(this),0c&&(c=a.length);d=a.indexOf(\"?\");if(0>d||d>c){d=c;var e=\"\"}else e=a.substring(d+1,c);a=[a.substr(0,d),e,a.substr(c)];c=a[1];a[1]=b?c?c+\"&\"+b:b:c;a=a[0]+(a[1]?\"?\"+a[1]:\"\")+a[2]}return a}R(a,b,c);return a};function ke(a,b,c){this.za=b||0;this.Ba=0;this.h=[];this.l=[];this.a=new qc;this.J=c||new Md;this.ia=this.ya=this.H=this.ja=this.b=this.N=this.j=this.ha=this.f=this.P=this.i=null;this.Va=this.I=0;this.ka=this.C=this.s=this.m=this.o=this.c=null;this.v=this.Aa=this.S=-1;this.ga=this.B=this.G=0;this.T=a&&a.supportsCrossDomainXhr||!1;this.M=\"\";this.g=new Od(a&&a.concurrentRequestLimit);this.la=new Wd;this.F=a&&void 0!==a.backgroundChannelTest?a.backgroundChannelTest:!0;this.Ua=a&&a.fastHandshake||!1}\ng=ke.prototype;g.oa=8;g.D=1;function le(a){I(a.a,\"disconnect()\");me(a);if(3==a.D){var b=a.I++,c=M(a.H);R(c,\"SID\",a.M);R(c,\"RID\",b);R(c,\"TYPE\",\"terminate\");ne(a,c);b=new L(a,a.a,0,b,void 0);b.I=2;b.l=Mc(M(c));c=!1;k.navigator&&k.navigator.sendBeacon&&(c=k.navigator.sendBeacon(b.l.toString(),\"\"));c||((new Image).src=b.l);b.H=t();Pc(b)}oe(a)}\nfunction me(a){a.C&&(a.C.abort(),a.C=null);a.b&&(a.b.cancel(),a.b=null);a.m&&(k.clearTimeout(a.m),a.m=null);pe(a);a.g.cancel();a.o&&(k.clearTimeout(a.o),a.o=null)}function qe(a,b){if(1E3==a.h.length){var c=\"Already have 1000 queued maps upon queueing \"+Fb(b),d=a.a.a;d&&F(d,c)}a.h.push(new Ud(a.Va++,b));3==a.D&&re(a)}g.Ka=function(){return 0==this.D};function re(a){Sd(a.g)||a.o||(a.o=xc(r(a.Pa,a),0),a.G=0)}\ng.Pa=function(a){this.o=null;I(this.a,\"startForwardChannel_\");if(1==this.D)if(a)(a=this.a.a)&&F(a,\"Not supposed to retry the open\");else{I(this.a,\"open_()\");this.I=Math.floor(1E5*Math.random());a=this.I++;var b=new L(this,this.a,0,a,void 0),c=this.i;this.P&&(c?(c=Ea(c),Ga(c,this.P)):c=this.P);null===this.f&&(b.h=c);var d=se(this),e=M(this.H);R(e,\"RID\",a);0b&&this.ka&&0==this.B&&!this.s&&(this.s=xc(r(this.ab,this),6E3)));else I(this.a,\"Bad POST response data returned\"),W(this,11)}else if(this.b==a&&pe(this),!/^[\\s\\xa0]*$/.test(b))for(b=c=this.la.a.parse(b),c=0;cthis.c)throw Error(Je);this.a=new Ge;this.b=new Nd;this.g=null;this.aa()}u(Ie,w);var Je=\"[goog.structs.Pool] Min can not be greater than max\";g=Ie.prototype;g.ca=function(){var a=t();if(!(null!=this.g&&0>a-this.g)){for(var b;0this.c&&0=this.u()){for(var c=this.a,d=0;d>1,a[d].a>c.a)a[b]=a[d],b=d;else break;a[b]=c}Me.prototype.A=function(){for(var a=this.a,b=[],c=a.length,d=0;d=e)f=void 0;else{if(1==e)wa(d);else{d[0]=d.pop();d=0;c=c.a;e=c.length;for(var h=c[d];d>1;){var m=2*d+1,v=2*d+2;m=vh.a)break;c[d]=c[m];d=m}c[d]=h}f=f.b}f.apply(this,[b])}else break}};\ng.ma=function(a){Y.L.ma.call(this,a);this.ua()};g.aa=function(){Y.L.aa.call(this);this.ua()};g.w=function(){Y.L.w.call(this);k.clearTimeout(void 0);wa(this.f.a);this.f=null};function Z(a,b,c,d){this.l=a;this.j=!!d;Y.call(this,b,c)}u(Z,Y);Z.prototype.qa=function(){var a=new U,b=this.l;b&&b.forEach(function(b,d){a.headers.set(d,b)});this.j&&(a.m=!0);return a};Z.prototype.va=function(a){return!a.i&&!a.a};Be.prototype.createWebChannel=Be.prototype.a;X.prototype.send=X.prototype.l;X.prototype.open=X.prototype.j;X.prototype.close=X.prototype.close;yc.NO_ERROR=0;yc.TIMEOUT=8;yc.HTTP_ERROR=6;zc.COMPLETE=\"complete\";Dd.EventType=Ed;Ed.OPEN=\"a\";Ed.CLOSE=\"b\";Ed.ERROR=\"c\";Ed.MESSAGE=\"d\";B.prototype.listen=B.prototype.$;Z.prototype.getObject=Z.prototype.ca;Z.prototype.releaseObject=Z.prototype.hb;U.prototype.listenOnce=U.prototype.Ia;U.prototype.getLastError=U.prototype.$a;U.prototype.getLastErrorCode=U.prototype.Ga;\nU.prototype.getStatus=U.prototype.V;U.prototype.getStatusText=U.prototype.Ha;U.prototype.getResponseJson=U.prototype.Za;U.prototype.getResponseText=U.prototype.U;U.prototype.getResponseText=U.prototype.U;U.prototype.send=U.prototype.ta;module.exports={createWebChannelTransport:Fe,ErrorCode:yc,EventType:zc,WebChannel:Dd,XhrIoPool:Z};}).call(typeof window !== 'undefined' ? window : this)\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/@firebase/webchannel-wrapper/dist/index.js\n// module id = 67\n// module chunks = 1"],"sourceRoot":""}