diff --git a/config/tsconfig.base.json b/config/tsconfig.base.json index ebcee5e168a..913426696dd 100644 --- a/config/tsconfig.base.json +++ b/config/tsconfig.base.json @@ -4,6 +4,7 @@ "declaration": true, "importHelpers": true, "strictNullChecks": true, + "noImplicitAny": true, "lib": [ "es2015", "dom" diff --git a/packages/app/index.node.ts b/packages/app/index.node.ts index fb68cb739c9..25d71972fe6 100644 --- a/packages/app/index.node.ts +++ b/packages/app/index.node.ts @@ -18,8 +18,11 @@ import { FirebaseNamespace } from '@firebase/app-types'; import { _FirebaseNamespace } from '@firebase/app-types/private'; import { createFirebaseNamespace } from './src/firebaseNamespace'; +// Node specific packages. +// @ts-ignore import Storage from 'dom-storage'; -import { XMLHttpRequest } from 'xmlhttprequest'; +// @ts-ignore +import XMLHttpRequest from 'xmlhttprequest'; const _firebase = createFirebaseNamespace() as _FirebaseNamespace; diff --git a/packages/app/src/firebaseNamespaceCore.ts b/packages/app/src/firebaseNamespaceCore.ts index e648e27034f..2067d602bf5 100644 --- a/packages/app/src/firebaseNamespaceCore.ts +++ b/packages/app/src/firebaseNamespaceCore.ts @@ -80,7 +80,8 @@ export function createFirebaseNamespaceCore( // // import * as firebase from 'firebase'; // which becomes: var firebase = require('firebase'); - namespace['default'] = namespace; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (namespace as any)['default'] = namespace; // firebase.apps is a read-only getter. Object.defineProperty(namespace, 'apps', { @@ -108,6 +109,7 @@ export function createFirebaseNamespaceCore( return apps[name]; } + // @ts-ignore app['App'] = firebaseAppImpl; /** * Create a new App instance (name must be unique). @@ -196,6 +198,7 @@ export function createFirebaseNamespaceCore( // The Service namespace is an accessor function ... function serviceNamespace(appArg: FirebaseApp = app()): FirebaseService { + // @ts-ignore if (typeof appArg[name] !== 'function') { // Invalid argument. // This happens in the following case: firebase.storage('gs:/') @@ -205,6 +208,7 @@ export function createFirebaseNamespaceCore( } // Forward service instance lookup to the FirebaseApp. + // @ts-ignore return appArg[name](); } @@ -214,9 +218,11 @@ export function createFirebaseNamespaceCore( } // Monkey-patch the serviceNamespace onto the firebase namespace + // @ts-ignore namespace[name] = serviceNamespace; // Patch the FirebaseAppImpl prototype + // @ts-ignore firebaseAppImpl.prototype[name] = function(...args) { const serviceFxn = this._getService.bind(this, name); return serviceFxn.apply(this, allowMultipleInstances ? args : []); diff --git a/packages/app/test/firebaseApp.test.ts b/packages/app/test/firebaseApp.test.ts index 9d68fef5ad6..2ca8785f173 100644 --- a/packages/app/test/firebaseApp.test.ts +++ b/packages/app/test/firebaseApp.test.ts @@ -314,7 +314,10 @@ function executeFirebaseLiteTests(): void { }); } -function firebaseAppTests(testName, firebaseNamespaceFactory): void { +function firebaseAppTests( + testName: string, + firebaseNamespaceFactory: () => FirebaseNamespace +): void { describe(testName, () => { let firebase: FirebaseNamespace; diff --git a/packages/database/index.node.ts b/packages/database/index.node.ts index 7f695ba3eb8..71bcfa964ea 100644 --- a/packages/database/index.node.ts +++ b/packages/database/index.node.ts @@ -40,7 +40,11 @@ import * as types from '@firebase/database-types'; const ServerValue = Database.ServerValue; -export function initStandalone(app, url, version?: string) { +export function initStandalone( + app: FirebaseApp, + url: string, + version?: string +) { /** * This should allow the firebase-admin package to provide a custom version * to the backend diff --git a/packages/database/src/core/PersistentConnection.ts b/packages/database/src/core/PersistentConnection.ts index 37ed2d1ff62..44731a1b4d8 100644 --- a/packages/database/src/core/PersistentConnection.ts +++ b/packages/database/src/core/PersistentConnection.ts @@ -948,11 +948,14 @@ export class PersistentConnection extends ServerActions { // Puts depend on having received the corresponding data update from the server before they complete, so we must // make sure to send listens before puts. - forEach(this.listens_, (pathString: string, queries: Object) => { - forEach(queries, (key: string, listenSpec: ListenSpec) => { - this.sendListen_(listenSpec); - }); - }); + forEach( + this.listens_, + (pathString: string, queries: { [key: string]: ListenSpec }) => { + forEach(queries, (key: string, listenSpec: ListenSpec) => { + this.sendListen_(listenSpec); + }); + } + ); for (let i = 0; i < this.outstandingPuts_.length; i++) { if (this.outstandingPuts_[i]) this.sendPut_(i); diff --git a/packages/database/src/core/snap/ChildrenNode.ts b/packages/database/src/core/snap/ChildrenNode.ts index 196e5bff410..e57fdbeb8d2 100644 --- a/packages/database/src/core/snap/ChildrenNode.ts +++ b/packages/database/src/core/snap/ChildrenNode.ts @@ -201,7 +201,7 @@ export class ChildrenNode implements Node { val(exportFormat?: boolean): object { if (this.isEmpty()) return null; - const obj: { [k: string]: Object } = {}; + const obj: { [k: string]: unknown } = {}; let numKeys = 0, maxKey = 0, allIntegerKeys = true; @@ -218,7 +218,7 @@ export class ChildrenNode implements Node { if (!exportFormat && allIntegerKeys && maxKey < 2 * numKeys) { // convert to array. - const array: Object[] = []; + const array: unknown[] = []; for (let key in obj) array[(key as any) as number] = obj[key]; return array; diff --git a/packages/database/src/core/snap/IndexMap.ts b/packages/database/src/core/snap/IndexMap.ts index 624d66dcfee..0853dacb5ba 100644 --- a/packages/database/src/core/snap/IndexMap.ts +++ b/packages/database/src/core/snap/IndexMap.ts @@ -75,7 +75,7 @@ export class IndexMap { // regular child map return null; } else { - return sortedMap; + return sortedMap as SortedMap; } } diff --git a/packages/database/src/core/snap/Node.ts b/packages/database/src/core/snap/Node.ts index 052140e135f..de4960600ed 100644 --- a/packages/database/src/core/snap/Node.ts +++ b/packages/database/src/core/snap/Node.ts @@ -119,7 +119,7 @@ export interface Node { * @param {boolean=} exportFormat True for export format (also wire protocol format). * @return {*} Value of this node as JSON. */ - val(exportFormat?: boolean): Object; + val(exportFormat?: boolean): unknown; /** * @return {string} hash representing the node contents. diff --git a/packages/database/src/core/snap/nodeFromJSON.ts b/packages/database/src/core/snap/nodeFromJSON.ts index 84fd3d0d34f..532916266de 100644 --- a/packages/database/src/core/snap/nodeFromJSON.ts +++ b/packages/database/src/core/snap/nodeFromJSON.ts @@ -113,7 +113,7 @@ export function nodeFromJSON( } } else { let node: Node = ChildrenNode.EMPTY_NODE; - const jsonObj = json as object; + const jsonObj = json as { [key: string]: unknown }; forEach(jsonObj, (key: string, childData: any) => { if (contains(jsonObj, key)) { if (key.substring(0, 1) !== '.') { diff --git a/packages/database/src/core/snap/snap.ts b/packages/database/src/core/snap/snap.ts index b94a0d26c32..91eca450fa3 100644 --- a/packages/database/src/core/snap/snap.ts +++ b/packages/database/src/core/snap/snap.ts @@ -47,7 +47,8 @@ export const validatePriorityNode = function(priorityNode: Node) { assert( typeof val === 'string' || typeof val === 'number' || - (typeof val === 'object' && contains(val, '.sv')), + (typeof val === 'object' && + contains(val as { [key: string]: unknown }, '.sv')), 'Priority must be a string or number.' ); } else { diff --git a/packages/database/src/core/util/CountedSet.ts b/packages/database/src/core/util/CountedSet.ts index 6ccc0576772..f88c8009f3d 100644 --- a/packages/database/src/core/util/CountedSet.ts +++ b/packages/database/src/core/util/CountedSet.ts @@ -22,7 +22,7 @@ import { isEmpty, getCount, forEach, contains } from '@firebase/util'; * * @template K, V */ -export class CountedSet { +export class CountedSet { set: { [k: string]: V } = {}; /** @@ -38,7 +38,7 @@ export class CountedSet { * @return {boolean} */ contains(key: K) { - return contains(this.set, key); + return contains(this.set, key as string); } /** @@ -82,8 +82,8 @@ export class CountedSet { * Run a function on each k,v pair in the set * @param {function(K, V)} fn */ - each(fn: (k: K, v: V) => void) { - forEach(this.set, (k: K, v: V) => fn(k, v)); + each(fn: (k: K | string, v: V) => void) { + forEach(this.set, (k: string, v: V) => fn(k, v)); } /** @@ -92,8 +92,8 @@ export class CountedSet { */ keys(): K[] { const keys: K[] = []; - forEach(this.set, (k: K) => { - keys.push(k); + forEach(this.set, (k: string) => { + keys.push(k as K); }); return keys; } diff --git a/packages/database/src/core/util/Tree.ts b/packages/database/src/core/util/Tree.ts index 97263db6979..00cded4c685 100644 --- a/packages/database/src/core/util/Tree.ts +++ b/packages/database/src/core/util/Tree.ts @@ -57,7 +57,7 @@ export class Tree { subTree(pathObj: string | Path): Tree { // TODO: Require pathObj to be Path? let path = pathObj instanceof Path ? pathObj : new Path(pathObj); - let child = this as any, + let child = this as Tree, next; while ((next = path.getFront()) !== null) { const childNode = safeGet(child.node_.children, next) || new TreeNode(); diff --git a/packages/database/tsconfig.json b/packages/database/tsconfig.json index 2260db9d56c..5d390b031c4 100644 --- a/packages/database/tsconfig.json +++ b/packages/database/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../config/tsconfig.base.json", "compilerOptions": { "outDir": "dist", - "strictNullChecks": false + "strictNullChecks": false, + "noImplicitAny": false }, "exclude": [ "dist/**/*" diff --git a/packages/firestore/index.node.ts b/packages/firestore/index.node.ts index 413d4cf5f0f..1393181e72d 100644 --- a/packages/firestore/index.node.ts +++ b/packages/firestore/index.node.ts @@ -16,12 +16,13 @@ */ import firebase from '@firebase/app'; -import './src/platform_node/node_init'; +import { FirebaseNamespace } from '@firebase/app-types'; +import * as types from '@firebase/firestore-types'; import { Firestore } from './src/api/database'; import { configureForFirebase } from './src/platform/config'; -import * as types from '@firebase/firestore-types'; +import './src/platform_node/node_init'; -export function registerFirestore(instance) { +export function registerFirestore(instance: FirebaseNamespace): void { configureForFirebase(instance); } diff --git a/packages/firestore/index.ts b/packages/firestore/index.ts index 841b76b8436..3070762f006 100644 --- a/packages/firestore/index.ts +++ b/packages/firestore/index.ts @@ -16,13 +16,14 @@ */ import firebase from '@firebase/app'; -import './src/platform_browser/browser_init'; +import { FirebaseNamespace } from '@firebase/app-types'; import { Firestore } from './src/api/database'; import { configureForFirebase } from './src/platform/config'; +import './src/platform_browser/browser_init'; import * as types from '@firebase/firestore-types'; -export function registerFirestore(instance) { +export function registerFirestore(instance: FirebaseNamespace): void { configureForFirebase(instance); } diff --git a/packages/firestore/src/api/credentials.ts b/packages/firestore/src/api/credentials.ts index 883d5248675..8346f4b577b 100644 --- a/packages/firestore/src/api/credentials.ts +++ b/packages/firestore/src/api/credentials.ts @@ -263,7 +263,7 @@ export class FirstPartyToken implements Token { constructor(private gapi: Gapi, private sessionIndex: string) {} get authHeaders(): { [header: string]: string } { - const headers = { + const headers: { [header: string]: string } = { 'X-Goog-AuthUser': this.sessionIndex }; const authHeader = this.gapi.auth.getAuthHeaderValueForFirstParty([]); @@ -309,8 +309,8 @@ export function makeCredentialsProvider( switch (credentials.type) { case 'gapi': - const client = credentials.client; - // Make sure this is a Gapi client. + const client = credentials.client as Gapi; + // Make sure this really is a Gapi client. assert( !!( typeof client === 'object' && @@ -321,7 +321,7 @@ export function makeCredentialsProvider( 'unexpected gapi interface' ); return new FirstPartyCredentialsProvider( - client as Gapi, + client, credentials.sessionIndex || '0' ); diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index 2d243410593..db7ca678107 100644 --- a/packages/firestore/src/core/firestore_client.ts +++ b/packages/firestore/src/core/firestore_client.ts @@ -60,7 +60,7 @@ import { AutoId } from '../util/misc'; import { DatabaseId, DatabaseInfo } from './database_info'; import { Query } from './query'; import { Transaction } from './transaction'; -import { OnlineStateSource } from './types'; +import { OnlineState, OnlineStateSource } from './types'; import { ViewSnapshot } from './view_snapshot'; const LOG_TAG = 'FirestoreClient'; @@ -429,12 +429,16 @@ export class FirestoreClient { serializer ); - const remoteStoreOnlineStateChangedHandler = onlineState => + const remoteStoreOnlineStateChangedHandler = ( + onlineState: OnlineState + ) => this.syncEngine.applyOnlineStateChange( onlineState, OnlineStateSource.RemoteStore ); - const sharedClientStateOnlineStateChangedHandler = onlineState => + const sharedClientStateOnlineStateChangedHandler = ( + onlineState: OnlineState + ) => this.syncEngine.applyOnlineStateChange( onlineState, OnlineStateSource.SharedClientState diff --git a/packages/firestore/src/core/sync_engine.ts b/packages/firestore/src/core/sync_engine.ts index 6c25992dab3..a00161ee1ae 100644 --- a/packages/firestore/src/core/sync_engine.ts +++ b/packages/firestore/src/core/sync_engine.ts @@ -433,7 +433,9 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { objUtils.forEach( remoteEvent.targetChanges, (targetId, targetChange) => { - const limboResolution = this.limboResolutionsByTarget[targetId]; + const limboResolution = this.limboResolutionsByTarget[ + Number(targetId) + ]; if (limboResolution) { // Since this is a limbo resolution lookup, it's for a single document // and it could be added, modified, or removed, but not a combination. diff --git a/packages/firestore/src/local/indexeddb_mutation_queue.ts b/packages/firestore/src/local/indexeddb_mutation_queue.ts index 4e3a8333563..2ddfaff34a4 100644 --- a/packages/firestore/src/local/indexeddb_mutation_queue.ts +++ b/packages/firestore/src/local/indexeddb_mutation_queue.ts @@ -476,9 +476,15 @@ export class IndexedDbMutationQueue implements MutationQueue { batch ).next(removedDocuments => { this.removeCachedMutationKeys(batch.batchId); - return PersistencePromise.forEach(removedDocuments, key => { - return this.referenceDelegate.removeMutationReference(transaction, key); - }); + return PersistencePromise.forEach( + removedDocuments, + (key: DocumentKey) => { + return this.referenceDelegate.removeMutationReference( + transaction, + key + ); + } + ); }); } diff --git a/packages/firestore/src/local/indexeddb_persistence.ts b/packages/firestore/src/local/indexeddb_persistence.ts index 843855df396..aaa87e78059 100644 --- a/packages/firestore/src/local/indexeddb_persistence.ts +++ b/packages/firestore/src/local/indexeddb_persistence.ts @@ -116,7 +116,7 @@ const ZOMBIED_CLIENTS_KEY_PREFIX = 'firestore_zombie'; export class IndexedDbTransaction extends PersistenceTransaction { constructor( readonly simpleDbTransaction: SimpleDbTransaction, - readonly currentSequenceNumber + readonly currentSequenceNumber: ListenSequenceNumber ) { super(); } @@ -515,8 +515,10 @@ export class IndexedDbPersistence implements Persistence { }) .next(() => // Delete metadata for clients that are no longer considered active. - PersistencePromise.forEach(inactiveClients, inactiveClient => - metadataStore.delete(inactiveClient.clientId) + PersistencePromise.forEach( + inactiveClients, + (inactiveClient: DbClientMetadata) => + metadataStore.delete(inactiveClient.clientId) ) ) .next(() => { @@ -882,7 +884,9 @@ export class IndexedDbPersistence implements Persistence { * Obtains or extends the new primary lease for the local client. This * method does not verify that the client is eligible for this lease. */ - private acquireOrExtendPrimaryLease(txn): PersistencePromise { + private acquireOrExtendPrimaryLease( + txn: SimpleDbTransaction + ): PersistencePromise { const newPrimary = new DbPrimaryClient( this.clientId, this.allowTabSynchronization, diff --git a/packages/firestore/src/local/indexeddb_query_cache.ts b/packages/firestore/src/local/indexeddb_query_cache.ts index 8925f97dac2..06cf1e9852a 100644 --- a/packages/firestore/src/local/indexeddb_query_cache.ts +++ b/packages/firestore/src/local/indexeddb_query_cache.ts @@ -293,7 +293,7 @@ export class IndexedDbQueryCache implements QueryCache { // PORTING NOTE: The reverse index (documentsTargets) is maintained by // IndexedDb. const store = documentTargetStore(txn); - return PersistencePromise.forEach(keys, key => { + return PersistencePromise.forEach(keys, (key: DocumentKey) => { const path = EncodedResourcePath.encode(key.path); return PersistencePromise.waitFor([ store.delete([targetId, path]), diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index c4be56980a4..a6c72de035e 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -162,7 +162,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter { ); return queuesStore.loadAll().next(queues => { - return PersistencePromise.forEach(queues, queue => { + return PersistencePromise.forEach(queues, (queue: DbMutationQueue) => { const range = IDBKeyRange.bound( [queue.userId, BATCHID_UNKNOWN], [queue.userId, queue.lastAcknowledgedBatchId] @@ -171,17 +171,20 @@ export class SchemaConverter implements SimpleDbSchemaConverter { return mutationsStore .loadAll(DbMutationBatch.userMutationsIndex, range) .next(dbBatches => { - return PersistencePromise.forEach(dbBatches, dbBatch => { - assert( - dbBatch.userId === queue.userId, - `Cannot process batch ${dbBatch.batchId} from unexpected user` - ); - const batch = this.serializer.fromDbMutationBatch(dbBatch); - - return removeMutationBatch(txn, queue.userId, batch).next( - () => {} - ); - }); + return PersistencePromise.forEach( + dbBatches, + (dbBatch: DbMutationBatch) => { + assert( + dbBatch.userId === queue.userId, + `Cannot process batch ${dbBatch.batchId} from unexpected user` + ); + const batch = this.serializer.fromDbMutationBatch(dbBatch); + + return removeMutationBatch(txn, queue.userId, batch).next( + () => {} + ); + } + ); }); }); }); @@ -246,7 +249,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter { // Helper to add an index entry iff we haven't already written it. const cache = new MemoryCollectionParentIndex(); - const addEntry = collectionPath => { + const addEntry = (collectionPath: ResourcePath) => { if (cache.add(collectionPath)) { const collectionId = collectionPath.lastSegment(); const parentPath = collectionPath.popLast(); diff --git a/packages/firestore/src/local/local_documents_view.ts b/packages/firestore/src/local/local_documents_view.ts index 25510580742..8aa0885451d 100644 --- a/packages/firestore/src/local/local_documents_view.ts +++ b/packages/firestore/src/local/local_documents_view.ts @@ -186,7 +186,7 @@ export class LocalDocumentsView { .next(parents => { // Perform a collection query against each parent that contains the // collectionId and aggregate the results. - return PersistencePromise.forEach(parents, parent => { + return PersistencePromise.forEach(parents, (parent: ResourcePath) => { const collectionQuery = query.asCollectionQueryAtPath( parent.child(collectionId) ); diff --git a/packages/firestore/src/local/local_store.ts b/packages/firestore/src/local/local_store.ts index b900e622186..dc9b8c2a55b 100644 --- a/packages/firestore/src/local/local_store.ts +++ b/packages/firestore/src/local/local_store.ts @@ -651,19 +651,24 @@ export class LocalStore { 'notifyLocalViewChanges', 'readwrite', txn => { - return PersistencePromise.forEach(viewChanges, viewChange => { - this.localViewReferences.addReferences( - viewChange.addedKeys, - viewChange.targetId - ); - this.localViewReferences.removeReferences( - viewChange.removedKeys, - viewChange.targetId - ); - return PersistencePromise.forEach(viewChange.removedKeys, key => - this.persistence.referenceDelegate.removeReference(txn, key) - ); - }); + return PersistencePromise.forEach( + viewChanges, + (viewChange: LocalViewChanges) => { + this.localViewReferences.addReferences( + viewChange.addedKeys, + viewChange.targetId + ); + this.localViewReferences.removeReferences( + viewChange.removedKeys, + viewChange.targetId + ); + return PersistencePromise.forEach( + viewChange.removedKeys, + (key: DocumentKey) => + this.persistence.referenceDelegate.removeReference(txn, key) + ); + } + ); } ); } @@ -772,7 +777,7 @@ export class LocalStore { ); delete this.queryDataByTarget[targetId]; if (!keepPersistedQueryData) { - return PersistencePromise.forEach(removed, key => + return PersistencePromise.forEach(removed, (key: DocumentKey) => this.persistence.referenceDelegate.removeReference(txn, key) ).next(() => this.persistence.referenceDelegate.removeTarget( diff --git a/packages/firestore/src/local/lru_garbage_collector.ts b/packages/firestore/src/local/lru_garbage_collector.ts index a74ec8a7b1a..1fd748aa77e 100644 --- a/packages/firestore/src/local/lru_garbage_collector.ts +++ b/packages/firestore/src/local/lru_garbage_collector.ts @@ -371,7 +371,7 @@ export class LruGarbageCollector { activeTargetIds: ActiveTargets ): PersistencePromise { let upperBoundSequenceNumber: number; - let sequenceNumbersToCollect, targetsRemoved: number; + let sequenceNumbersToCollect: number, targetsRemoved: number; // Timestamps for various pieces of the process let startTs: number, countedTargetsTs: number, diff --git a/packages/firestore/src/local/memory_mutation_queue.ts b/packages/firestore/src/local/memory_mutation_queue.ts index c70ae7bca7b..e384d329371 100644 --- a/packages/firestore/src/local/memory_mutation_queue.ts +++ b/packages/firestore/src/local/memory_mutation_queue.ts @@ -303,7 +303,7 @@ export class MemoryMutationQueue implements MutationQueue { this.mutationQueue.shift(); let references = this.batchesByDocumentKey; - return PersistencePromise.forEach(batch.mutations, mutation => { + return PersistencePromise.forEach(batch.mutations, (mutation: Mutation) => { const ref = new DocReference(mutation.key, batch.batchId); references = references.delete(ref); return this.referenceDelegate.removeMutationReference( diff --git a/packages/firestore/src/local/memory_persistence.ts b/packages/firestore/src/local/memory_persistence.ts index f61f2ee1c7e..cc8e1f7a86e 100644 --- a/packages/firestore/src/local/memory_persistence.ts +++ b/packages/firestore/src/local/memory_persistence.ts @@ -261,17 +261,20 @@ export class MemoryEagerDelegate implements ReferenceDelegate { txn: PersistenceTransaction ): PersistencePromise { const cache = this.persistence.getRemoteDocumentCache(); - return PersistencePromise.forEach(this.orphanedDocuments, key => { - return this.isReferenced(txn, key).next(isReferenced => { - if (!isReferenced) { - // Since this is the eager delegate and memory persistence, - // we don't care about the size of documents. We don't track - // the size of the cache for eager GC. - return cache.removeEntry(txn, key).next(() => {}); - } - return PersistencePromise.resolve(); - }); - }); + return PersistencePromise.forEach( + this.orphanedDocuments, + (key: DocumentKey) => { + return this.isReferenced(txn, key).next(isReferenced => { + if (!isReferenced) { + // Since this is the eager delegate and memory persistence, + // we don't care about the size of documents. We don't track + // the size of the cache for eager GC. + return cache.removeEntry(txn, key).next(() => {}); + } + return PersistencePromise.resolve(); + }); + } + ); } updateLimboDocument( diff --git a/packages/firestore/src/local/memory_remote_document_cache.ts b/packages/firestore/src/local/memory_remote_document_cache.ts index 99f75aaa6d1..1848c565562 100644 --- a/packages/firestore/src/local/memory_remote_document_cache.ts +++ b/packages/firestore/src/local/memory_remote_document_cache.ts @@ -191,7 +191,7 @@ export class MemoryRemoteDocumentCache implements RemoteDocumentCache { transaction: PersistenceTransaction, f: (key: DocumentKey) => PersistencePromise ): PersistencePromise { - return PersistencePromise.forEach(this.docs, key => f(key)); + return PersistencePromise.forEach(this.docs, (key: DocumentKey) => f(key)); } getNewDocumentChanges( diff --git a/packages/firestore/src/local/shared_client_state.ts b/packages/firestore/src/local/shared_client_state.ts index fbbb19c6da6..c87b01d290f 100644 --- a/packages/firestore/src/local/shared_client_state.ts +++ b/packages/firestore/src/local/shared_client_state.ts @@ -462,13 +462,13 @@ export class SharedOnlineState { const validData = typeof onlineState === 'object' && - OnlineState[onlineState.onlineState] !== undefined && + onlineState.onlineState in OnlineState && typeof onlineState.clientId === 'string'; if (validData) { return new SharedOnlineState( onlineState.clientId, - OnlineState[onlineState.onlineState] + OnlineState[onlineState.onlineState as keyof typeof OnlineState] ); } else { error(LOG_TAG, `Failed to parse online state: ${value}`); diff --git a/packages/firestore/src/local/simple_db.ts b/packages/firestore/src/local/simple_db.ts index 9362fcb8da2..b3947a2b02c 100644 --- a/packages/firestore/src/local/simple_db.ts +++ b/packages/firestore/src/local/simple_db.ts @@ -579,7 +579,7 @@ export class SimpleDbStore< options = {}; callback = optionsOrCallback as IterateCallback; } else { - options = optionsOrCallback; + options = optionsOrCallback as IterateOptions; } const cursor = this.cursor(options); return this.iterateCursor(cursor, callback); diff --git a/packages/firestore/src/platform_browser/webchannel_connection.ts b/packages/firestore/src/platform_browser/webchannel_connection.ts index 6326674441a..f264d0a4588 100644 --- a/packages/firestore/src/platform_browser/webchannel_connection.ts +++ b/packages/firestore/src/platform_browser/webchannel_connection.ts @@ -20,6 +20,7 @@ import { ErrorCode, EventType, WebChannel, + WebChannelOptions, XhrIo } from '@firebase/webchannel-wrapper'; @@ -46,7 +47,7 @@ const RPC_STREAM_SERVICE = 'google.firestore.v1.Firestore'; const RPC_URL_VERSION = 'v1'; /** Maps RPC names to the corresponding REST endpoint name. */ -const RPC_NAME_REST_MAPPING = { +const RPC_NAME_REST_MAPPING: { [key: string]: string } = { BatchGetDocuments: 'batchGet', Commit: 'commit' }; @@ -192,7 +193,7 @@ export class WebChannelConnection implements Connection { '/channel' ]; const webchannelTransport = createWebChannelTransport(); - const request = { + const request: WebChannelOptions = { // Background channel test avoids the initial two test calls and decreases // initial cold start time. // TODO(dimond): wenboz@ mentioned this might affect use with proxies and @@ -223,7 +224,7 @@ export class WebChannelConnection implements Connection { forceLongPolling: this.forceLongPolling }; - this.modifyHeadersForRequest(request.initMessageHeaders, token); + this.modifyHeadersForRequest(request.initMessageHeaders!, token); // Sending the custom headers we just added to request.initMessageHeaders // (Authorization, etc.) will trigger the browser to make a CORS preflight @@ -243,7 +244,7 @@ export class WebChannelConnection implements Connection { // ReactNative and so we exclude it, which just means ReactNative may be // subject to the extra network roundtrip for CORS preflight. if (!isReactNative()) { - request['httpHeadersOverwriteParam'] = '$httpHeaders'; + request.httpHeadersOverwriteParam = '$httpHeaders'; } const url = urlParts.join(''); @@ -343,9 +344,10 @@ export class WebChannelConnection implements Connection { // (and only errors) to be wrapped in an extra array. To be forward // compatible with the bug we need to check either condition. The latter // can be removed once the fix has been rolled out. + // tslint:disable-next-line:no-any msgData.error is not typed. + const msgDataAsAny: any = msgData; const error = - // tslint:disable-next-line:no-any msgData.error is not typed. - (msgData as any).error || (msgData[0] && msgData[0].error); + msgDataAsAny.error || (msgDataAsAny[0] && msgDataAsAny[0].error); if (error) { log.debug(LOG_TAG, 'WebChannel received error:', error); // error.status will be a string like 'OK' or 'NOT_FOUND'. diff --git a/packages/firestore/src/platform_node/grpc_connection.ts b/packages/firestore/src/platform_node/grpc_connection.ts index 127c985be27..da6b1a7f262 100644 --- a/packages/firestore/src/platform_node/grpc_connection.ts +++ b/packages/firestore/src/platform_node/grpc_connection.ts @@ -86,7 +86,8 @@ export class GrpcConnection implements Connection { private cachedStub: GeneratedGrpcStub | null = null; constructor(protos: grpc.GrpcObject, private databaseInfo: DatabaseInfo) { - this.firestore = protos['google']['firestore']['v1']; + // tslint:disable-next-line:no-any + this.firestore = (protos as any)['google']['firestore']['v1']; } private ensureActiveStub(): GeneratedGrpcStub { diff --git a/packages/firestore/src/util/input_validation.ts b/packages/firestore/src/util/input_validation.ts index b37b109db2a..339c70883f7 100644 --- a/packages/firestore/src/util/input_validation.ts +++ b/packages/firestore/src/util/input_validation.ts @@ -202,7 +202,7 @@ export function validateArrayElements( optionName: string, typeDescription: string, argument: T[], - validator: (T) => boolean + validator: (arg0: T) => boolean ): void { if (!(argument instanceof Array)) { throw new FirestoreError( @@ -229,7 +229,7 @@ export function validateOptionalArrayElements( optionName: string, typeDescription: string, argument: T[] | undefined, - validator: (T) => boolean + validator: (arg0: T) => boolean ): void { if (argument !== undefined) { validateArrayElements( diff --git a/packages/firestore/src/util/misc.ts b/packages/firestore/src/util/misc.ts index 026c5bc34da..ca2750757bb 100644 --- a/packages/firestore/src/util/misc.ts +++ b/packages/firestore/src/util/misc.ts @@ -18,6 +18,7 @@ import { assert } from './assert'; export type EventHandler = (value: E) => void; +export type Indexable = { [k: string]: unknown }; // tslint:disable-next-line:class-as-namespace export class AutoId { diff --git a/packages/firestore/test/integration/api/array_transforms.test.ts b/packages/firestore/test/integration/api/array_transforms.test.ts index 2b2deaf81cc..ab5eb4c513d 100644 --- a/packages/firestore/test/integration/api/array_transforms.test.ts +++ b/packages/firestore/test/integration/api/array_transforms.test.ts @@ -31,7 +31,7 @@ const FieldValue = firebase.firestore!.FieldValue; * together, etc.) and so these tests mostly focus on the array transform * semantics. */ -apiDescribe('Array Transforms:', persistence => { +apiDescribe('Array Transforms:', (persistence: boolean) => { // A document reference to read and write to. let docRef: firestore.DocumentReference; diff --git a/packages/firestore/test/integration/api/batch_writes.test.ts b/packages/firestore/test/integration/api/batch_writes.test.ts index 0c020f642a4..88e21abff5e 100644 --- a/packages/firestore/test/integration/api/batch_writes.test.ts +++ b/packages/firestore/test/integration/api/batch_writes.test.ts @@ -26,7 +26,7 @@ const apiDescribe = integrationHelpers.apiDescribe; const Timestamp = firebase.firestore!.Timestamp; const FieldValue = firebase.firestore!.FieldValue; -apiDescribe('Database batch writes', persistence => { +apiDescribe('Database batch writes', (persistence: boolean) => { it('supports empty batches', () => { return integrationHelpers.withTestDb(persistence, db => { return db.batch().commit(); diff --git a/packages/firestore/test/integration/api/cursor.test.ts b/packages/firestore/test/integration/api/cursor.test.ts index c4d2da1094f..bdc975997ba 100644 --- a/packages/firestore/test/integration/api/cursor.test.ts +++ b/packages/firestore/test/integration/api/cursor.test.ts @@ -30,7 +30,7 @@ import { const Timestamp = firebase.firestore!.Timestamp; const FieldPath = firebase.firestore!.FieldPath; -apiDescribe('Cursors', persistence => { +apiDescribe('Cursors', (persistence: boolean) => { it('can page through items', () => { const testDocs = { a: { v: 'a' }, @@ -242,7 +242,7 @@ apiDescribe('Cursors', persistence => { // Currently, timestamps are truncated to microseconds on the backend, so // don't create timestamps with more precision than that. - const makeTimestamp = (seconds, micros) => + const makeTimestamp = (seconds: number, micros: number) => new Timestamp(seconds, micros * 1000); it('can accept Timestamps as bounds', () => { diff --git a/packages/firestore/test/integration/api/database.test.ts b/packages/firestore/test/integration/api/database.test.ts index 090215b872d..a33b1af0120 100644 --- a/packages/firestore/test/integration/api/database.test.ts +++ b/packages/firestore/test/integration/api/database.test.ts @@ -44,7 +44,7 @@ chai.use(chaiAsPromised); const Timestamp = firebase.firestore!.Timestamp; const FieldValue = firebase.firestore!.FieldValue; -apiDescribe('Database', persistence => { +apiDescribe('Database', (persistence: boolean) => { it('can set a document', () => { return withTestDoc(persistence, docRef => { return docRef.set({ @@ -536,7 +536,7 @@ apiDescribe('Database', persistence => { }); }); - apiDescribe('Queries are validated client-side', persistence => { + apiDescribe('Queries are validated client-side', (persistence: boolean) => { // NOTE: Failure cases are validated in validation_test.ts it('same inequality fields works', () => { diff --git a/packages/firestore/test/integration/api/fields.test.ts b/packages/firestore/test/integration/api/fields.test.ts index cfb41183f5b..e489761e0ba 100644 --- a/packages/firestore/test/integration/api/fields.test.ts +++ b/packages/firestore/test/integration/api/fields.test.ts @@ -35,7 +35,7 @@ const Timestamp = firebase.firestore!.Timestamp; // tslint:disable-next-line:no-any Allow custom types for testing. type AnyTestData = any; -apiDescribe('Nested Fields', persistence => { +apiDescribe('Nested Fields', (persistence: boolean) => { const testData = (n?: number): AnyTestData => { n = n || 1; return { @@ -240,7 +240,7 @@ apiDescribe('Nested Fields', persistence => { // NOTE(mikelehen): I originally combined these tests with the above ones, but // Datastore currently prohibits having nested fields and fields with dots in // the same entity, so I'm separating them. -apiDescribe('Fields with special characters', persistence => { +apiDescribe('Fields with special characters', (persistence: boolean) => { const testData = (n?: number): AnyTestData => { n = n || 1; return { @@ -346,7 +346,7 @@ apiDescribe('Fields with special characters', persistence => { }); }); -apiDescribe('Timestamp Fields in snapshots', persistence => { +apiDescribe('Timestamp Fields in snapshots', (persistence: boolean) => { // tslint:disable-next-line:no-any Figure out how to pass in the Timestamp type const testDataWithTimestamps = (ts: any): AnyTestData => { return { timestamp: ts, nested: { timestamp2: ts } }; diff --git a/packages/firestore/test/integration/api/get_options.test.ts b/packages/firestore/test/integration/api/get_options.test.ts index 1d693f06f88..78b349a4f8e 100644 --- a/packages/firestore/test/integration/api/get_options.test.ts +++ b/packages/firestore/test/integration/api/get_options.test.ts @@ -23,7 +23,7 @@ import { withTestDocAndInitialData } from '../util/helpers'; -apiDescribe('GetOptions', persistence => { +apiDescribe('GetOptions', (persistence: boolean) => { it('get document while online with default get options', () => { const initialData = { key: 'value' }; return withTestDocAndInitialData(persistence, initialData, docRef => { diff --git a/packages/firestore/test/integration/api/numeric_transforms.test.ts b/packages/firestore/test/integration/api/numeric_transforms.test.ts index a498d67ab80..dc522ac8287 100644 --- a/packages/firestore/test/integration/api/numeric_transforms.test.ts +++ b/packages/firestore/test/integration/api/numeric_transforms.test.ts @@ -27,7 +27,7 @@ const FieldValue = firebase.firestore!.FieldValue; const DOUBLE_EPSILON = 0.000001; -apiDescribe('Numeric Transforms:', persistence => { +apiDescribe('Numeric Transforms:', (persistence: boolean) => { // A document reference to read and write to. let docRef: firestore.DocumentReference; diff --git a/packages/firestore/test/integration/api/query.test.ts b/packages/firestore/test/integration/api/query.test.ts index 725607a938c..fc107288f74 100644 --- a/packages/firestore/test/integration/api/query.test.ts +++ b/packages/firestore/test/integration/api/query.test.ts @@ -40,7 +40,7 @@ const FieldPath = firebase.firestore!.FieldPath; const GeoPoint = firebase.firestore!.GeoPoint; const Timestamp = firebase.firestore!.Timestamp; -apiDescribe('Queries', persistence => { +apiDescribe('Queries', (persistence: boolean) => { addEqualityMatcher(); it('can issue limit queries', () => { diff --git a/packages/firestore/test/integration/api/server_timestamp.test.ts b/packages/firestore/test/integration/api/server_timestamp.test.ts index 574ee170d0a..76f44a1a89d 100644 --- a/packages/firestore/test/integration/api/server_timestamp.test.ts +++ b/packages/firestore/test/integration/api/server_timestamp.test.ts @@ -28,7 +28,7 @@ type AnyTestData = any; const Timestamp = firebase.firestore!.Timestamp; const FieldValue = firebase.firestore!.FieldValue; -apiDescribe('Server Timestamps', persistence => { +apiDescribe('Server Timestamps', (persistence: boolean) => { // Data written in tests via set(). const setData = { a: 42, diff --git a/packages/firestore/test/integration/api/smoke.test.ts b/packages/firestore/test/integration/api/smoke.test.ts index dc88f621117..14c19fc660b 100644 --- a/packages/firestore/test/integration/api/smoke.test.ts +++ b/packages/firestore/test/integration/api/smoke.test.ts @@ -22,7 +22,7 @@ import * as integrationHelpers from '../util/helpers'; const apiDescribe = integrationHelpers.apiDescribe; -apiDescribe('Smoke Test', persistence => { +apiDescribe('Smoke Test', (persistence: boolean) => { it('can write a single document', () => { return integrationHelpers.withTestDoc(persistence, ref => { return ref.set({ diff --git a/packages/firestore/test/integration/api/transactions.test.ts b/packages/firestore/test/integration/api/transactions.test.ts index 0175251b58e..074d1e84cfc 100644 --- a/packages/firestore/test/integration/api/transactions.test.ts +++ b/packages/firestore/test/integration/api/transactions.test.ts @@ -23,7 +23,7 @@ import * as integrationHelpers from '../util/helpers'; const apiDescribe = integrationHelpers.apiDescribe; -apiDescribe('Database transactions', persistence => { +apiDescribe('Database transactions', (persistence: boolean) => { // TODO(klimt): Test that transactions don't see latency compensation // changes, using the other kind of integration test. // We currently require every document read to also be written. diff --git a/packages/firestore/test/integration/api/type.test.ts b/packages/firestore/test/integration/api/type.test.ts index 5539e753d9b..8a870baade9 100644 --- a/packages/firestore/test/integration/api/type.test.ts +++ b/packages/firestore/test/integration/api/type.test.ts @@ -21,7 +21,7 @@ import { addEqualityMatcher } from '../../util/equality_matcher'; import firebase from '../util/firebase_export'; import { apiDescribe, withTestDb, withTestDoc } from '../util/helpers'; -apiDescribe('Firestore', persistence => { +apiDescribe('Firestore', (persistence: boolean) => { addEqualityMatcher(); function expectRoundtrip( diff --git a/packages/firestore/test/integration/api/validation.test.ts b/packages/firestore/test/integration/api/validation.test.ts index 6b7d6b1e333..c1e10645f87 100644 --- a/packages/firestore/test/integration/api/validation.test.ts +++ b/packages/firestore/test/integration/api/validation.test.ts @@ -109,7 +109,7 @@ class TestClass { // since it is an untyped language. These tests are not exhaustive as that would // be extremely tedious, but we do try to hit every error template at least // once. -apiDescribe('Validation:', persistence => { +apiDescribe('Validation:', (persistence: boolean) => { describe('FirestoreSettings', () => { // Enabling persistence counts as a use of the firestore instance, meaning // that it will be impossible to verify that a set of settings don't throw, diff --git a/packages/firestore/test/integration/api_internal/idle_timeout.test.ts b/packages/firestore/test/integration/api_internal/idle_timeout.test.ts index c19f3f3ab58..f13df17db04 100644 --- a/packages/firestore/test/integration/api_internal/idle_timeout.test.ts +++ b/packages/firestore/test/integration/api_internal/idle_timeout.test.ts @@ -20,7 +20,7 @@ import { Deferred } from '../../util/promise'; import { apiDescribe, withTestDb } from '../util/helpers'; import { asyncQueue } from '../util/internal_helpers'; -apiDescribe('Idle Timeout', persistence => { +apiDescribe('Idle Timeout', (persistence: boolean) => { it('can write document after idle timeout', () => { return withTestDb(persistence, db => { const docRef = db.collection('test-collection').doc(); diff --git a/packages/firestore/test/integration/util/helpers.ts b/packages/firestore/test/integration/util/helpers.ts index 80528a7c410..429abcffb0b 100644 --- a/packages/firestore/test/integration/util/helpers.ts +++ b/packages/firestore/test/integration/util/helpers.ts @@ -128,7 +128,7 @@ export function toChangesArray( export function toDataMap( docSet: firestore.QuerySnapshot ): { [field: string]: firestore.DocumentData } { - const docsData = {}; + const docsData: { [field: string]: firestore.DocumentData } = {}; docSet.forEach(doc => { docsData[doc.id] = doc.data(); }); diff --git a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts index c331eb9f00c..2e5a73edbc7 100644 --- a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts +++ b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts @@ -54,6 +54,7 @@ import { PersistencePromise } from '../../../src/local/persistence_promise'; import { ClientId } from '../../../src/local/shared_client_state'; import { SimpleDb, SimpleDbTransaction } from '../../../src/local/simple_db'; import { PlatformSupport } from '../../../src/platform/platform'; +import { firestoreV1ApiClientInterfaces } from '../../../src/protos/firestore_proto_api'; import { JsonProtoSerializer } from '../../../src/remote/serializer'; import { AsyncQueue } from '../../../src/util/async_queue'; import { FirestoreError } from '../../../src/util/error'; @@ -68,7 +69,7 @@ import { } from './persistence_test_helpers'; function withDb( - schemaVersion, + schemaVersion: number, fn: (db: IDBDatabase) => Promise ): Promise { const schemaConverter = new SchemaConverter(TEST_SERIALIZER); @@ -310,8 +311,9 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const sdb = new SimpleDb(db); return sdb.runTransaction('readwrite', [DbMutationBatch.store], txn => { const store = txn.store(DbMutationBatch.store); - return PersistencePromise.forEach(testMutations, testMutation => - store.put(testMutation) + return PersistencePromise.forEach( + testMutations, + (testMutation: DbMutationBatch) => store.put(testMutation) ); }); }).then(() => @@ -324,10 +326,12 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const store = txn.store( DbMutationBatch.store ); - let p = PersistencePromise.forEach(testMutations, testMutation => - store.get(testMutation.batchId).next(mutationBatch => { - expect(mutationBatch).to.deep.equal(testMutation); - }) + let p = PersistencePromise.forEach( + testMutations, + (testMutation: DbMutationBatch) => + store.get(testMutation.batchId).next(mutationBatch => { + expect(mutationBatch).to.deep.equal(testMutation); + }) ); p = p.next(() => { store @@ -424,21 +428,27 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbMutationQueue >(DbMutationQueue.store); // Manually populate the mutation queue and create all indicies. - return PersistencePromise.forEach(testMutations, testMutation => { - return mutationBatchStore.put(testMutation).next(() => { - return PersistencePromise.forEach(testMutation.mutations, write => { - const indexKey = DbDocumentMutation.key( - testMutation.userId, - path(write.update!.name!, 5), - testMutation.batchId - ); - return documentMutationStore.put( - indexKey, - DbDocumentMutation.PLACEHOLDER + return PersistencePromise.forEach( + testMutations, + (testMutation: DbMutationBatch) => { + return mutationBatchStore.put(testMutation).next(() => { + return PersistencePromise.forEach( + testMutation.mutations, + (write: firestoreV1ApiClientInterfaces.Write) => { + const indexKey = DbDocumentMutation.key( + testMutation.userId, + path(write.update!.name!, 5), + testMutation.batchId + ); + return documentMutationStore.put( + indexKey, + DbDocumentMutation.PLACEHOLDER + ); + } ); }); - }); - }).next(() => + } + ).next(() => // Populate the mutation queues' metadata PersistencePromise.waitFor([ mutationQueuesStore.put(new DbMutationQueue('foo', 2, '')), @@ -509,8 +519,10 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const store = txn.store( DbRemoteDocument.store ); - return PersistencePromise.forEach(dbRemoteDocs, ({ dbKey, dbDoc }) => - store.put(dbKey, dbDoc) + return PersistencePromise.forEach( + dbRemoteDocs, + ({ dbKey, dbDoc }: { dbKey: string[]; dbDoc: DbRemoteDocument }) => + store.put(dbKey, dbDoc) ); }); }); @@ -652,7 +664,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { >(DbDocumentMutation.store); // We "cheat" and only write the DbDocumentMutation index entries, since that's // all the migration uses. - return PersistencePromise.forEach(writePaths, writePath => { + return PersistencePromise.forEach(writePaths, (writePath: string) => { const indexKey = DbDocumentMutation.key( 'dummy-uid', path(writePath), @@ -664,7 +676,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { ); }).next(() => { // Write the remote document entries. - return PersistencePromise.forEach(remoteDocPaths, path => { + return PersistencePromise.forEach(remoteDocPaths, (path: string) => { const remoteDoc = doc(path, /*version=*/ 1, { data: 1 }); return remoteDocumentStore.put( remoteDoc.key.path.toArray(), @@ -684,7 +696,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbCollectionParent >(DbCollectionParent.store); return collectionParentsStore.loadAll().next(indexEntries => { - const actualParents = {}; + const actualParents: { [key: string]: string[] } = {}; for (const { collectionId, parent } of indexEntries) { let parents = actualParents[collectionId]; if (!parents) { diff --git a/packages/firestore/test/unit/local/local_store.test.ts b/packages/firestore/test/unit/local/local_store.test.ts index 5f1076ab656..97a0009fed1 100644 --- a/packages/firestore/test/unit/local/local_store.test.ts +++ b/packages/firestore/test/unit/local/local_store.test.ts @@ -76,7 +76,7 @@ class LocalStoreTester { private lastChanges: MaybeDocumentMap | null = null; private lastTargetId: TargetId | null = null; private batches: MutationBatch[] = []; - constructor(public localStore: LocalStore, readonly gcIsEager) {} + constructor(public localStore: LocalStore, readonly gcIsEager: boolean) {} after( op: Mutation | Mutation[] | RemoteEvent | LocalViewChanges diff --git a/packages/firestore/test/unit/local/persistence_promise.test.ts b/packages/firestore/test/unit/local/persistence_promise.test.ts index 848f962c84c..abb55b84af7 100644 --- a/packages/firestore/test/unit/local/persistence_promise.test.ts +++ b/packages/firestore/test/unit/local/persistence_promise.test.ts @@ -232,7 +232,7 @@ describe('PersistencePromise', () => { }); it('propagates error for forEach()', () => { - const p = PersistencePromise.forEach([true, false], success => { + const p = PersistencePromise.forEach([true, false], (success: boolean) => { if (success) { return PersistencePromise.resolve(); } else { diff --git a/packages/firestore/test/unit/local/remote_document_cache.test.ts b/packages/firestore/test/unit/local/remote_document_cache.test.ts index 3f2ec690fad..134a016d21b 100644 --- a/packages/firestore/test/unit/local/remote_document_cache.test.ts +++ b/packages/firestore/test/unit/local/remote_document_cache.test.ts @@ -111,7 +111,7 @@ describe('IndexedDbRemoteDocumentCache', () => { docs: MaybeDocument[] ): PersistencePromise { const changeBuffer = cache.newChangeBuffer(); - return PersistencePromise.forEach(docs, doc => + return PersistencePromise.forEach(docs, (doc: MaybeDocument) => changeBuffer.getEntry(txn, doc.key).next(() => {}) ).next(() => { for (const doc of docs) { diff --git a/packages/firestore/test/unit/local/test_remote_document_cache.ts b/packages/firestore/test/unit/local/test_remote_document_cache.ts index 079c77793b6..2fd0814c165 100644 --- a/packages/firestore/test/unit/local/test_remote_document_cache.ts +++ b/packages/firestore/test/unit/local/test_remote_document_cache.ts @@ -56,8 +56,10 @@ export abstract class TestRemoteDocumentCache { 'readwrite-primary', txn => { const changeBuffer = this.cache.newChangeBuffer(); - return PersistencePromise.forEach(maybeDocuments, maybeDocument => - changeBuffer.getEntry(txn, maybeDocument.key).next(() => {}) + return PersistencePromise.forEach( + maybeDocuments, + (maybeDocument: MaybeDocument) => + changeBuffer.getEntry(txn, maybeDocument.key).next(() => {}) ).next(() => { for (const maybeDocument of maybeDocuments) { changeBuffer.addEntry(maybeDocument); diff --git a/packages/firestore/test/unit/local/web_storage_shared_client_state.test.ts b/packages/firestore/test/unit/local/web_storage_shared_client_state.test.ts index 5129b7002e2..e4a15d8f9d4 100644 --- a/packages/firestore/test/unit/local/web_storage_shared_client_state.test.ts +++ b/packages/firestore/test/unit/local/web_storage_shared_client_state.test.ts @@ -165,15 +165,25 @@ describe('WebStorageSharedClientState', () => { const webStorage = window.localStorage; let queue: AsyncQueue; - let primaryClientId; + let primaryClientId: string; let sharedClientState: SharedClientState; let clientSyncer: TestSharedClientSyncer; - let previousAddEventListener; - let previousRemoveEventListener; + let previousAddEventListener: typeof window.addEventListener; + let previousRemoveEventListener: typeof window.removeEventListener; - // tslint:disable-next-line:no-any - let webStorageCallbacks: Array<(this, event) => any> = []; + interface WebStorageOptions { + key: string; + storageArea: Storage; + newValue: string | null; + } + + type WebStorageCallback = ( + this: unknown, + event: WebStorageOptions + ) => unknown; + + let webStorageCallbacks: WebStorageCallback[] = []; function writeToWebStorage(key: string, value: string | null): void { for (const callback of webStorageCallbacks) { @@ -195,9 +205,9 @@ describe('WebStorageSharedClientState', () => { // We capture the listener here so that we can invoke it from the local // client. If we directly relied on WebStorage listeners, we would not // receive events for local writes. - window.addEventListener = (type, callback) => { + window.addEventListener = (type: string, callback: unknown) => { if (type === 'storage') { - webStorageCallbacks.push(callback); + webStorageCallbacks.push(callback as WebStorageCallback); } }; window.removeEventListener = () => {}; diff --git a/packages/firestore/test/unit/remote/node/serializer.test.ts b/packages/firestore/test/unit/remote/node/serializer.test.ts index 7f2860e970e..5f8f5eea681 100644 --- a/packages/firestore/test/unit/remote/node/serializer.test.ts +++ b/packages/firestore/test/unit/remote/node/serializer.test.ts @@ -54,6 +54,7 @@ import { WatchTargetChangeState } from '../../../../src/remote/watch_change'; import { Code, FirestoreError } from '../../../../src/util/error'; +import { Indexable } from '../../../../src/util/misc'; import * as obj from '../../../../src/util/obj'; import * as types from '../../../../src/util/types'; import { addEqualityMatcher } from '../../../util/equality_matcher'; @@ -156,7 +157,9 @@ describe('Serializer', () => { const actualProtobufjsProto: ProtobufJS.Message = ValueMessage.fromObject( actualJsonProto ); - expect(actualProtobufjsProto[valueType]).to.deep.equal(protobufJsValue); + expect((actualProtobufjsProto as Indexable)[valueType]).to.deep.equal( + protobufJsValue + ); // Convert protobufjs back to JSON. const returnJsonProto = ValueMessage.toObject( diff --git a/packages/firestore/test/unit/specs/describe_spec.ts b/packages/firestore/test/unit/specs/describe_spec.ts index 11bc8bea8c2..1953ed73d48 100644 --- a/packages/firestore/test/unit/specs/describe_spec.ts +++ b/packages/firestore/test/unit/specs/describe_spec.ts @@ -83,8 +83,8 @@ export function setSpecJSONHandler(writer: (json: string) => void): void { /** Gets the test runner based on the specified tags. */ function getTestRunner( - tags, - persistenceEnabled + tags: string[], + persistenceEnabled: boolean ): ExclusiveTestFunction | PendingTestFunction { if (tags.indexOf(NO_WEB_TAG) >= 0) { return it.skip; @@ -109,7 +109,7 @@ function getTestRunner( } /** If required, returns a custom test timeout for long-running tests */ -function getTestTimeout(tags): number | undefined { +function getTestTimeout(tags: string[]): number | undefined { if (tags.indexOf(BENCHMARK_TAG) >= 0) { return BENCHMARK_TEST_TIMEOUT_MS; } else { diff --git a/packages/firestore/test/unit/specs/listen_spec.test.ts b/packages/firestore/test/unit/specs/listen_spec.test.ts index be1c7d107a3..d706ba00867 100644 --- a/packages/firestore/test/unit/specs/listen_spec.test.ts +++ b/packages/firestore/test/unit/specs/listen_spec.test.ts @@ -448,7 +448,7 @@ describeSpec('Listens:', [], () => { }); specTest('Listens are reestablished after network disconnect', [], () => { - const expectRequestCount = requestCounts => + const expectRequestCount = (requestCounts: { [type: string]: number }) => requestCounts.addTarget + requestCounts.removeTarget; const query = Query.atPath(path('collection')); diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index 1ad5574a338..c84c28d7f25 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -1247,7 +1247,7 @@ export async function runSpec( const runners: TestRunner[] = []; const outstandingMutations = new SharedWriteTracker(); - const ensureRunner = async clientIndex => { + const ensureRunner = async (clientIndex: number) => { if (!runners[clientIndex]) { const platform = new TestPlatform( PlatformSupport.getPlatform(), diff --git a/packages/firestore/test/unit/specs/write_spec.test.ts b/packages/firestore/test/unit/specs/write_spec.test.ts index 814a4b21251..25b795dfd07 100644 --- a/packages/firestore/test/unit/specs/write_spec.test.ts +++ b/packages/firestore/test/unit/specs/write_spec.test.ts @@ -772,7 +772,7 @@ describeSpec('Writes:', [], () => { ); specTest('Writes are resent after network disconnect', [], () => { - const expectRequestCount = requestCounts => + const expectRequestCount = (requestCounts: { [type: string]: number }) => requestCounts.handshakes + requestCounts.writes + requestCounts.closes; return spec() diff --git a/packages/firestore/test/util/equality_matcher.ts b/packages/firestore/test/util/equality_matcher.ts index 78330b40b1f..d59f4ae175e 100644 --- a/packages/firestore/test/util/equality_matcher.ts +++ b/packages/firestore/test/util/equality_matcher.ts @@ -16,6 +16,7 @@ */ import { use } from 'chai'; +import { Equatable } from '../../src/util/misc'; /** * @file This file provides a helper function to add a matcher that matches @@ -24,12 +25,16 @@ import { use } from 'chai'; * implementation is used. */ -function customDeepEqual(left, right): boolean { +function customDeepEqual(left: unknown, right: unknown): boolean { /** * START: Custom compare logic */ - if (left && typeof left.isEqual === 'function') return left.isEqual(right); - if (right && typeof right.isEqual === 'function') return right.isEqual(left); + if (typeof left === 'object' && left && 'isEqual' in left) { + return (left as Equatable).isEqual(right); + } + if (typeof right === 'object' && right && 'isEqual' in right) { + return (right as Equatable).isEqual(left); + } /** * END: Custom compare logic */ @@ -44,18 +49,21 @@ function customDeepEqual(left, right): boolean { } if (typeof left !== typeof right) return false; // needed for structurally different objects if (Object(left) !== left) return false; // primitive values + // @ts-ignore const keys = Object.keys(left); + // @ts-ignore if (keys.length !== Object.keys(right).length) return false; for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (!Object.prototype.hasOwnProperty.call(right, key)) return false; + // @ts-ignore if (!customDeepEqual(left[key], right[key])) return false; } return true; } /** The original equality function passed in by chai(). */ -let originalFunction: ((r, l) => boolean) | null = null; +let originalFunction: ((r: unknown, l: unknown) => boolean) | null = null; export function addEqualityMatcher(): void { let isActive = true; @@ -64,9 +72,9 @@ export function addEqualityMatcher(): void { use((chai, utils) => { const Assertion = chai.Assertion; - const assertEql = _super => { + const assertEql = (_super: (r: unknown, l: unknown) => boolean) => { originalFunction = originalFunction || _super; - return function(...args): void { + return function(...args: unknown[]): void { if (isActive) { const [expected, msg] = args; utils.flag(this, 'message', msg); diff --git a/packages/functions/index.node.ts b/packages/functions/index.node.ts index 797ed192b76..a0117152ea7 100644 --- a/packages/functions/index.node.ts +++ b/packages/functions/index.node.ts @@ -16,7 +16,10 @@ */ import firebase from '@firebase/app'; import { FirebaseApp } from '@firebase/app-types'; -import { FirebaseServiceFactory } from '@firebase/app-types/private'; +import { + FirebaseServiceFactory, + _FirebaseNamespace +} from '@firebase/app-types/private'; import { Service } from './src/api/service'; import 'isomorphic-fetch'; @@ -29,7 +32,7 @@ function factory(app: FirebaseApp, _unused: unknown, region?: string): Service { return new Service(app, region); } -export function registerFunctions(instance): void { +export function registerFunctions(instance: _FirebaseNamespace): void { const namespaceExports = { // no-inline Functions: Service @@ -45,4 +48,4 @@ export function registerFunctions(instance): void { ); } -registerFunctions(firebase); +registerFunctions(firebase as _FirebaseNamespace); diff --git a/packages/functions/index.ts b/packages/functions/index.ts index 508f4b973a0..a8a43581df7 100644 --- a/packages/functions/index.ts +++ b/packages/functions/index.ts @@ -16,7 +16,10 @@ */ import firebase from '@firebase/app'; import * as appTypes from '@firebase/app-types'; -import { FirebaseServiceFactory } from '@firebase/app-types/private'; +import { + FirebaseServiceFactory, + _FirebaseNamespace +} from '@firebase/app-types/private'; import * as types from '@firebase/functions-types'; import { Service } from './src/api/service'; @@ -33,7 +36,7 @@ function factory( return new Service(app, region); } -export function registerFunctions(instance): void { +export function registerFunctions(instance: _FirebaseNamespace): void { const namespaceExports = { // no-inline Functions: Service @@ -49,7 +52,7 @@ export function registerFunctions(instance): void { ); } -registerFunctions(firebase); +registerFunctions(firebase as _FirebaseNamespace); declare module '@firebase/app-types' { interface FirebaseNamespace { diff --git a/packages/functions/src/serializer.ts b/packages/functions/src/serializer.ts index b349b34d3f7..68e0ee9cb98 100644 --- a/packages/functions/src/serializer.ts +++ b/packages/functions/src/serializer.ts @@ -18,8 +18,11 @@ const LONG_TYPE = 'type.googleapis.com/google.protobuf.Int64Value'; const UNSIGNED_LONG_TYPE = 'type.googleapis.com/google.protobuf.UInt64Value'; -function mapValues(o: object, f: (val: unknown) => unknown): object { - const result = {}; +function mapValues( + o: { [key: string]: unknown }, + f: (arg0: unknown) => unknown +): object { + const result: { [key: string]: unknown } = {}; for (const key in o) { if (o.hasOwnProperty(key)) { result[key] = f(o[key]); @@ -61,19 +64,19 @@ export class Serializer { // Takes data that's been encoded in a JSON-friendly form and returns a form // with richer datatypes, such as Dates, etc. - decode(json: {} | null): {} | null { + decode(json: unknown): unknown { if (json == null) { return json; } - if (json['@type']) { - switch (json['@type']) { + if ((json as { [key: string]: unknown })['@type']) { + switch ((json as { [key: string]: unknown })['@type']) { case LONG_TYPE: // Fall through and handle this the same as unsigned. case UNSIGNED_LONG_TYPE: { // Technically, this could work return a valid number for malformed // data if there was a number followed by garbage. But it's just not // worth all the extra code to detect that case. - const value = Number(json['value']); + const value = Number((json as { [key: string]: unknown })['value']); if (isNaN(value)) { throw new Error('Data cannot be decoded from JSON: ' + json); } @@ -88,7 +91,9 @@ export class Serializer { return json.map(x => this.decode(x)); } if (typeof json === 'function' || typeof json === 'object') { - return mapValues(json, x => this.decode(x as {} | null)); + return mapValues(json as Function | object, x => + this.decode(x as {} | null) + ); } // Anything else is safe to return. return json; diff --git a/packages/logger/src/logger.ts b/packages/logger/src/logger.ts index eacd8412386..c32d35a2e47 100644 --- a/packages/logger/src/logger.ts +++ b/packages/logger/src/logger.ts @@ -141,19 +141,19 @@ export class Logger { * The functions below are all based on the `console` interface */ - debug(...args): void { + debug(...args: unknown[]): void { this._logHandler(this, LogLevel.DEBUG, ...args); } - log(...args): void { + log(...args: unknown[]): void { this._logHandler(this, LogLevel.VERBOSE, ...args); } - info(...args): void { + info(...args: unknown[]): void { this._logHandler(this, LogLevel.INFO, ...args); } - warn(...args): void { + warn(...args: unknown[]): void { this._logHandler(this, LogLevel.WARN, ...args); } - error(...args): void { + error(...args: unknown[]): void { this._logHandler(this, LogLevel.ERROR, ...args); } } diff --git a/packages/logger/test/logger.test.ts b/packages/logger/test/logger.test.ts index 4fe2728aee3..65afa4a0477 100644 --- a/packages/logger/test/logger.test.ts +++ b/packages/logger/test/logger.test.ts @@ -46,7 +46,7 @@ describe('@firebase/logger', () => { spies.errorSpy.restore(); }); - function testLog(message, channel, shouldLog): void { + function testLog(message: string, channel: string, shouldLog: boolean): void { /** * Ensure that `debug` logs assert against the `console.log` function. The * rationale here is explained in `logger.ts`. @@ -56,6 +56,7 @@ describe('@firebase/logger', () => { it(`Should ${ shouldLog ? '' : 'not' } call \`console.${channel}\` if \`.${channel}\` is called`, () => { + // @ts-ignore It's not worth making a dedicated enum for a test. client[channel](message); expect( spies[`${channel}Spy`]!.called, diff --git a/packages/rxfire/database/list/index.ts b/packages/rxfire/database/list/index.ts index 28641eaf8eb..c7fee511f4c 100644 --- a/packages/rxfire/database/list/index.ts +++ b/packages/rxfire/database/list/index.ts @@ -69,7 +69,7 @@ export function listVal( ); } -function positionFor(changes: QueryChange[], key) { +function positionFor(changes: QueryChange[], key: string | null) { const len = changes.length; for (let i = 0; i < len; i++) { if (changes[i].snapshot.key === key) { diff --git a/packages/rxfire/storage/index.ts b/packages/rxfire/storage/index.ts index 4ad10af9963..6513c23c943 100644 --- a/packages/rxfire/storage/index.ts +++ b/packages/rxfire/storage/index.ts @@ -23,7 +23,7 @@ export function fromTask(task: storage.UploadTask) { return new Observable(subscriber => { const progress = (snap: storage.UploadTaskSnapshot) => subscriber.next(snap); - const error = e => subscriber.error(e); + const error = (e: Error) => subscriber.error(e); const complete = () => subscriber.complete(); task.on('state_changed', progress, error, complete); return () => task.cancel(); diff --git a/packages/rxfire/test/database.test.ts b/packages/rxfire/test/database.test.ts index 2457cfd04da..a03b90f162e 100644 --- a/packages/rxfire/test/database.test.ts +++ b/packages/rxfire/test/database.test.ts @@ -30,11 +30,10 @@ const rando = () => .toString(36) .substring(5); -let batch = (items: any[]) => { - let batch = {}; - Object.keys(items).forEach(function(key) { - const itemValue = items[key]; - batch[itemValue.key] = itemValue; +let batch = (items: { name: string; key: string }[]) => { + let batch: { [key: string]: unknown } = {}; + items.forEach(item => { + batch[item.key] = item; }); // make batch immutable to preserve integrity return Object.freeze(batch); diff --git a/packages/rxfire/test/firestore.test.ts b/packages/rxfire/test/firestore.test.ts index a9acda37c4e..f99af8ba628 100644 --- a/packages/rxfire/test/firestore.test.ts +++ b/packages/rxfire/test/firestore.test.ts @@ -52,7 +52,7 @@ const unwrapChange = map((changes: firestore.DocumentChange[]) => { * Create an environment for the tests to run in. The information is returned * from the function for use within the test. */ -const seedTest = firestore => { +const seedTest = (firestore: firestore.Firestore) => { const colRef = createRandomCol(firestore); const davidDoc = colRef.doc('david'); davidDoc.set({ name: 'David' }); diff --git a/packages/storage/index.ts b/packages/storage/index.ts index b1d30ab0ddc..09e0d5aab43 100644 --- a/packages/storage/index.ts +++ b/packages/storage/index.ts @@ -17,7 +17,10 @@ import firebase from '@firebase/app'; import { FirebaseApp } from '@firebase/app-types'; -import { FirebaseServiceFactory } from '@firebase/app-types/private'; +import { + FirebaseServiceFactory, + _FirebaseNamespace +} from '@firebase/app-types/private'; import { StringFormat } from './src/implementation/string'; import { TaskEvent } from './src/implementation/taskenums'; import { TaskState } from './src/implementation/taskenums'; @@ -39,7 +42,7 @@ function factory( return new Service(app, new XhrIoPool(), opt_url) as any; } -export function registerStorage(instance) { +export function registerStorage(instance: _FirebaseNamespace) { let namespaceExports = { // no-inline TaskState: TaskState, @@ -58,7 +61,7 @@ export function registerStorage(instance) { ); } -registerStorage(firebase); +registerStorage(firebase as _FirebaseNamespace); /** * Define extension behavior for `registerStorage` diff --git a/packages/storage/src/implementation/fs.ts b/packages/storage/src/implementation/fs.ts index e216cb7b2d7..d49ea960948 100644 --- a/packages/storage/src/implementation/fs.ts +++ b/packages/storage/src/implementation/fs.ts @@ -21,10 +21,6 @@ */ import * as type from './type'; -declare var IBlobBuilder; -declare var BlobBuilder; -declare var WebKitBlobBuilder; - function getBlobBuilder(): (typeof IBlobBuilder) | undefined { if (typeof BlobBuilder !== 'undefined') { return BlobBuilder; diff --git a/packages/storage/src/implementation/requestinfo.ts b/packages/storage/src/implementation/requestinfo.ts index b06b260df66..052954fcb97 100644 --- a/packages/storage/src/implementation/requestinfo.ts +++ b/packages/storage/src/implementation/requestinfo.ts @@ -17,7 +17,7 @@ import { FirebaseStorageError } from './error'; import { Headers, XhrIo } from './xhrio'; -export type UrlParams = { [name: string]: string }; +export type UrlParams = { [name: string]: string | number }; export class RequestInfo { urlParams: UrlParams = {}; diff --git a/packages/storage/src/implementation/requests.ts b/packages/storage/src/implementation/requests.ts index ac63e997b25..d096709489c 100644 --- a/packages/storage/src/implementation/requests.ts +++ b/packages/storage/src/implementation/requests.ts @@ -163,7 +163,7 @@ export function list( pageToken?: string | null, maxResults?: number | null ): RequestInfo { - let urlParams = {}; + let urlParams: UrlParams = {}; if (location.isRoot) { urlParams['prefix'] = ''; } else { @@ -427,13 +427,13 @@ export function getResumableUploadStatus( function handler(xhr: XhrIo, text: string): ResumableUploadStatus { let status = checkResumeHeader_(xhr, ['active', 'final']); - let sizeString; + let sizeString: string | null = null; try { sizeString = xhr.getResponseHeader('X-Goog-Upload-Size-Received'); } catch (e) { handlerCheck(false); } - let size = parseInt(sizeString, 10); + let size = parseInt(sizeString as string, 10); handlerCheck(!isNaN(size)); return new ResumableUploadStatus(size, blob.size(), status === 'final'); } diff --git a/packages/storage/src/implementation/url.ts b/packages/storage/src/implementation/url.ts index 52a0f1330ad..42160922e13 100644 --- a/packages/storage/src/implementation/url.ts +++ b/packages/storage/src/implementation/url.ts @@ -20,16 +20,17 @@ */ import * as object from './object'; import { DEFAULT_HOST } from './constants'; +import { UrlParams } from './requestinfo'; export function makeUrl(urlPart: string): string { return `https://${DEFAULT_HOST}/v0${urlPart}`; } -export function makeQueryString(params: { [key: string]: string }): string { +export function makeQueryString(params: UrlParams): string { let encode = encodeURIComponent; let queryPart = '?'; object.forEach(params, function(key, val) { - let nextPart = encode(key) + '=' + encode(val); + let nextPart = encode(key) + '=' + encode(val.toString()); queryPart = queryPart + nextPart + '&'; }); diff --git a/packages/storage/test/reference.test.ts b/packages/storage/test/reference.test.ts index e913b9cbaab..5d22cc177b8 100644 --- a/packages/storage/test/reference.test.ts +++ b/packages/storage/test/reference.test.ts @@ -32,7 +32,7 @@ function makeFakeService(app: FirebaseApp, sendHook: SendHook): Service { } function makeStorage(url: string): Reference { - function maker(wrapper, loc) { + function maker(wrapper: unknown, loc: unknown) { return ({} as any) as Reference; } diff --git a/packages/storage/test/request.test.ts b/packages/storage/test/request.test.ts index c609f7cccd2..ff6a99f613b 100644 --- a/packages/storage/test/request.test.ts +++ b/packages/storage/test/request.test.ts @@ -45,7 +45,7 @@ describe('Firebase Storage > Request', () => { body?: ArrayBufferView | Blob | string | null, headers?: Headers ) { - const responseHeaders = {}; + const responseHeaders: Headers = {}; responseHeaders[responseHeader] = responseValue; xhrio.simulateResponse(status, response, responseHeaders); } @@ -75,7 +75,7 @@ describe('Firebase Storage > Request', () => { const args = spiedSend.getCall(0).args; assert.equal(args[1], url); assert.equal(args[2], method); - const expectedHeaders = {}; + const expectedHeaders: Headers = {}; expectedHeaders[requestHeader] = requestValue; expectedHeaders[versionHeaderName] = versionHeaderValue; assert.deepEqual(args[4], expectedHeaders); @@ -224,7 +224,9 @@ describe('Firebase Storage > Request', () => { result => { assert.isTrue(spiedSend.calledOnce); const args = spiedSend.getCall(0).args; - const expectedHeaders = { Authorization: 'Firebase ' + authToken }; + const expectedHeaders: Headers = { + Authorization: 'Firebase ' + authToken + }; expectedHeaders[versionHeaderName] = versionHeaderValue; assert.deepEqual(args[4], expectedHeaders); }, diff --git a/packages/storage/test/task.test.ts b/packages/storage/test/task.test.ts index e244e61ecee..85b9722021a 100644 --- a/packages/storage/test/task.test.ts +++ b/packages/storage/test/task.test.ts @@ -278,7 +278,7 @@ describe('Firebase Storage > Upload Task', () => { // This one will get executed immediately const h3: Unsubscribe = (() => { - let lastState; + let lastState: string; return task.on( TaskEvent.STATE_CHANGED, snapshot => { @@ -324,7 +324,7 @@ describe('Firebase Storage > Upload Task', () => { ); return fbsPromise.make((resolve, reject) => { task.on(TaskEvent.STATE_CHANGED, { - error: err => { + error: (err: Error) => { assert.fail('Unexpected upload failure'); }, complete: () => { @@ -344,7 +344,7 @@ describe('Firebase Storage > Upload Task', () => { blob ); - let resolve, reject; + let resolve: Function, reject: Function; const promise = fbsPromise.make(function(innerResolve, innerReject) { resolve = innerResolve; reject = innerReject; @@ -375,8 +375,8 @@ describe('Firebase Storage > Upload Task', () => { const events: string[] = []; const progress: number[][] = []; let complete = 0; - function addCallbacks(task) { - let lastState; + function addCallbacks(task: UploadTask) { + let lastState: string; task.on( TaskEvent.STATE_CHANGED, snapshot => { @@ -409,7 +409,7 @@ describe('Firebase Storage > Upload Task', () => { addCallbacks(task); (function() { - let lastState; + let lastState: string; task.on(TaskEvent.STATE_CHANGED, function(snapshot) { const state = snapshot.state; if (lastState !== TaskState.PAUSED && state === TaskState.PAUSED) { @@ -467,7 +467,7 @@ describe('Firebase Storage > Upload Task', () => { const events2: string[] = []; (function() { - let lastState; + let lastState: string; task2.on( TaskEvent.STATE_CHANGED, snapshot => { diff --git a/packages/storage/test/xhrio.ts b/packages/storage/test/xhrio.ts index 33d2471f215..875c9d557cd 100644 --- a/packages/storage/test/xhrio.ts +++ b/packages/storage/test/xhrio.ts @@ -38,7 +38,7 @@ export type StringHeaders = { [name: string]: string }; export class TestingXhrIo implements XhrIo { private state: State; private sendPromise: Promise; - private resolve: (XhrIo) => void; + private resolve: (xhrIo: XhrIo) => void; private sendHook: SendHook | null; private status: number; private responseText: string; @@ -121,10 +121,12 @@ export class TestingXhrIo implements XhrIo { } } + // @ts-ignore Remove when implemented. addUploadProgressListener(listener): void { // TODO(andysoto): impl } + // @ts-ignore Remove when implemented. removeUploadProgressListener(listener): void { // TODO(andysoto): impl } diff --git a/packages/testing/src/api/index.ts b/packages/testing/src/api/index.ts index ded08f5af8c..376dae6c3a0 100644 --- a/packages/testing/src/api/index.ts +++ b/packages/testing/src/api/index.ts @@ -115,7 +115,7 @@ function initializeApp( databaseName?: string, projectId?: string ): firebase.app.App { - let appOptions = {}; + let appOptions: { [key: string]: string } = {}; if (databaseName) { appOptions['databaseURL'] = `http://${DATABASE_ADDRESS}?ns=${databaseName}`; } @@ -212,7 +212,8 @@ export function loadFirestoreRules( project: `projects/${options.projectId}`, rules: { files: [{ content: options.rules }] } }, - (err, resp) => { + // @ts-ignore Defined in protobuf. + (err: Error, resp) => { if (err) { reject(err); } else { @@ -247,7 +248,8 @@ export function clearFirestoreData( { database: `projects/${options.projectId}/databases/(default)` }, - (err, resp) => { + // @ts-ignore Defined in protobuf. + (err: Error, resp) => { if (err) { reject(err); } else { diff --git a/packages/util/src/assert.ts b/packages/util/src/assert.ts index a55f2c5410e..dc77d9fe232 100644 --- a/packages/util/src/assert.ts +++ b/packages/util/src/assert.ts @@ -19,10 +19,8 @@ import { CONSTANTS } from './constants'; /** * Throws an error if the provided assertion is falsy - * @param {*} assertion The assertion to be tested for falsiness - * @param {!string} message The message to display if the check fails */ -export const assert = function(assertion, message): void { +export const assert = function(assertion: unknown, message: string): void { if (!assertion) { throw assertionError(message); } @@ -30,10 +28,8 @@ export const assert = function(assertion, message): void { /** * Returns an Error object suitable for throwing. - * @param {string} message - * @return {!Error} */ -export const assertionError = function(message): Error { +export const assertionError = function(message: string): Error { return new Error( 'Firebase Database (' + CONSTANTS.SDK_VERSION + diff --git a/packages/util/src/crypt.ts b/packages/util/src/crypt.ts index 9eb1ede54ec..4b9f38fe374 100644 --- a/packages/util/src/crypt.ts +++ b/packages/util/src/crypt.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -const stringToByteArray = function(str): number[] { +const stringToByteArray = function(str: string): number[] { // TODO(user): Use native implementations if/when available const out: number[] = []; let p = 0; @@ -52,7 +52,7 @@ const stringToByteArray = function(str): number[] { * @param bytes Array of numbers representing characters. * @return Stringification of the array. */ -const byteArrayToString = function(bytes): string { +const byteArrayToString = function(bytes: number[]): string { // TODO(user): Use native implementations if/when available const out: string[] = []; let pos = 0, diff --git a/packages/util/src/deepCopy.ts b/packages/util/src/deepCopy.ts index 8a265f45c59..0f64fede639 100644 --- a/packages/util/src/deepCopy.ts +++ b/packages/util/src/deepCopy.ts @@ -66,9 +66,9 @@ export function deepExtend(target: unknown, source: unknown): unknown { if (!source.hasOwnProperty(prop)) { continue; } - (target as object)[prop] = deepExtend( - (target as object)[prop], - source[prop] + (target as { [key: string]: unknown })[prop] = deepExtend( + (target as { [key: string]: unknown })[prop], + (source as { [key: string]: unknown })[prop] ); } diff --git a/packages/util/src/deferred.ts b/packages/util/src/deferred.ts index 4a8a24aaf95..8a40afa7c29 100644 --- a/packages/util/src/deferred.ts +++ b/packages/util/src/deferred.ts @@ -17,8 +17,8 @@ export class Deferred { promise: Promise; - reject; - resolve; + reject: (value?: unknown) => void; + resolve: (value?: unknown) => void; constructor() { this.promise = new Promise((resolve, reject) => { this.resolve = resolve; @@ -30,10 +30,10 @@ export class Deferred { * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback * and returns a node-style callback which will resolve or reject the Deferred's promise. - * @param {((?function(?(Error)): (?|undefined))| (?function(?(Error),?=): (?|undefined)))=} callback - * @return {!function(?(Error), ?=)} */ - wrapCallback(callback?): (error: unknown, value?: unknown) => void { + wrapCallback( + callback?: (error?: unknown, value?: unknown) => void + ): (error: unknown, value?: unknown) => void { return (error, value?) => { if (error) { this.reject(error); diff --git a/packages/util/src/environment.ts b/packages/util/src/environment.ts index 0e33b246db7..512a3368f05 100644 --- a/packages/util/src/environment.ts +++ b/packages/util/src/environment.ts @@ -42,6 +42,8 @@ export function getUA(): string { export function isMobileCordova(): boolean { return ( typeof window !== 'undefined' && + // @ts-ignore Setting up an broadly applicable index signature for Window + // just to deal with this case would probably be a bad idea. !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) && /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA()) ); diff --git a/packages/util/src/jwt.ts b/packages/util/src/jwt.ts index 7f04ef5394a..f5fd1cf47c7 100644 --- a/packages/util/src/jwt.ts +++ b/packages/util/src/jwt.ts @@ -18,26 +18,34 @@ import { base64Decode } from './crypt'; import { jsonEval } from './json'; +interface Claims { + [key: string]: {}; +} + +interface DecodedToken { + header: object; + claims: Claims; + data: object; + signature: string; +} + /** * Decodes a Firebase auth. token into constituent parts. * * Notes: * - May return with invalid / incomplete claims if there's no native base64 decoding support. * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {{header: *, claims: *, data: *, signature: string}} */ -export const decode = function(token): DecodedToken { +export const decode = function(token: string): DecodedToken { let header = {}, - claims = {}, + claims: Claims = {}, data = {}, signature = ''; try { const parts = token.split('.'); header = jsonEval(base64Decode(parts[0]) || '') as object; - claims = jsonEval(base64Decode(parts[1]) || '') as object; + claims = jsonEval(base64Decode(parts[1]) || '') as Claims; signature = parts[2]; data = claims['d'] || {}; delete claims['d']; @@ -53,7 +61,7 @@ export const decode = function(token): DecodedToken { interface DecodedToken { header: object; - claims: object; + claims: Claims; data: object; signature: string; } @@ -65,24 +73,22 @@ interface DecodedToken { * Notes: * - May return a false negative if there's no native base64 decoding support. * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {boolean} */ -export const isValidTimestamp = function(token): boolean { - const claims = decode(token).claims, - now = Math.floor(new Date().getTime() / 1000); - let validSince, validUntil; +export const isValidTimestamp = function(token: string): boolean { + const claims: Claims = decode(token).claims; + const now: number = Math.floor(new Date().getTime() / 1000); + let validSince: number = 0, + validUntil: number = 0; if (typeof claims === 'object') { if (claims.hasOwnProperty('nbf')) { - validSince = claims['nbf']; + validSince = claims['nbf'] as number; } else if (claims.hasOwnProperty('iat')) { - validSince = claims['iat']; + validSince = claims['iat'] as number; } if (claims.hasOwnProperty('exp')) { - validUntil = claims['exp']; + validUntil = claims['exp'] as number; } else { // token will expire after 24h by default validUntil = validSince + 86400; @@ -90,7 +96,11 @@ export const isValidTimestamp = function(token): boolean { } return ( - now && validSince && validUntil && now >= validSince && now <= validUntil + !!now && + !!validSince && + !!validUntil && + now >= validSince && + now <= validUntil ); }; @@ -100,14 +110,11 @@ export const isValidTimestamp = function(token): boolean { * Notes: * - May return null if there's no native base64 decoding support. * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {?number} */ -export const issuedAtTime = function(token): number | null { - const claims = decode(token).claims; +export const issuedAtTime = function(token: string): number | null { + const claims: Claims = decode(token).claims; if (typeof claims === 'object' && claims.hasOwnProperty('iat')) { - return claims['iat']; + return claims['iat'] as number; } return null; }; @@ -118,11 +125,8 @@ export const issuedAtTime = function(token): number | null { * Notes: * - May return a false negative if there's no native base64 decoding support. * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {boolean} */ -export const isValidFormat = function(token): boolean { +export const isValidFormat = function(token: string): boolean { const decoded = decode(token), claims = decoded.claims; @@ -135,11 +139,8 @@ export const isValidFormat = function(token): boolean { * Notes: * - May return a false negative if there's no native base64 decoding support. * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {boolean} */ -export const isAdmin = function(token): boolean { - const claims = decode(token).claims; +export const isAdmin = function(token: string): boolean { + const claims: Claims = decode(token).claims; return typeof claims === 'object' && claims['admin'] === true; }; diff --git a/packages/util/src/obj.ts b/packages/util/src/obj.ts index 61b6526c496..c5b20dd68a2 100644 --- a/packages/util/src/obj.ts +++ b/packages/util/src/obj.ts @@ -18,12 +18,19 @@ /* eslint-disable */ // will enable after https://github.com/firebase/firebase-js-sdk/pull/1811 is merged +interface UtilObject { + [key: string]: V; +} + // See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ -export const contains = function(obj, key) { +export const contains = function(obj: UtilObject, key: string): boolean { return Object.prototype.hasOwnProperty.call(obj, key); }; -export const safeGet = function(obj, key) { +export const safeGet = function( + obj: UtilObject, + key: string +): V | undefined { if (Object.prototype.hasOwnProperty.call(obj, key)) return obj[key]; // else return undefined. }; @@ -35,8 +42,11 @@ export const safeGet = function(obj, key) { * @param {!function(K, V)} fn Function to call for each key and value. * @template K,V */ -export const forEach = function(obj, fn) { - for (var key in obj) { +export const forEach = function( + obj: UtilObject, + fn: (key: string, value: V) => void +): void { + for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { fn(key, obj[key]); } @@ -49,7 +59,10 @@ export const forEach = function(obj, fn) { * @param {!Object} objFrom * @return {!Object} objTo */ -export const extend = function(objTo, objFrom) { +export const extend = function( + objTo: UtilObject, + objFrom: UtilObject +): UtilObject { forEach(objFrom, function(key, value) { objTo[key] = value; }); @@ -61,29 +74,26 @@ export const extend = function(objTo, objFrom) { * @param {!Object} obj * @return {!Object} cloned obj. */ -export const clone = function(obj) { +export const clone = function(obj: UtilObject) { return extend({}, obj); }; /** * Returns true if obj has typeof "object" and is not null. Unlike goog.isObject(), does not return true * for functions. - * - * @param obj {*} A potential object. - * @returns {boolean} True if it's an object. */ -export const isNonNullObject = function(obj) { +export const isNonNullObject = function(obj: UtilObject): boolean { return typeof obj === 'object' && obj !== null; }; -export const isEmpty = function(obj) { +export const isEmpty = function(obj: UtilObject) { for (var key in obj) { return false; } return true; }; -export const getCount = function(obj) { +export const getCount = function(obj: UtilObject): number { var rv = 0; for (var key in obj) { rv++; @@ -91,36 +101,48 @@ export const getCount = function(obj) { return rv; }; -export const map = function(obj, f, opt_obj?) { - var res = {}; +export const map = function( + obj: UtilObject, + fn: (value: V, key: string | number, obj: UtilObject) => unknown, + context?: unknown +) { + var res: UtilObject = {}; for (var key in obj) { - res[key] = f.call(opt_obj, obj[key], key, obj); + res[key] = fn.call(context, obj[key], key, obj); } return res; }; -export const findKey = function(obj, fn, opt_this?) { +export const findKey = function( + obj: UtilObject, + fn: (value: V, key: string | number, obj: UtilObject) => unknown, + context?: unknown +) { for (var key in obj) { - if (fn.call(opt_this, obj[key], key, obj)) { + if (fn.call(context, obj[key], key, obj)) { return key; } } return undefined; }; -export const findValue = function(obj, fn, opt_this?) { - var key = findKey(obj, fn, opt_this); +export const findValue = function( + obj: UtilObject, + fn: (value: V, key: string | number, obj: UtilObject) => unknown, + context?: unknown +) { + var key = findKey(obj, fn, context); return key && obj[key]; }; -export const getAnyKey = function(obj) { +export const getAnyKey = function(obj: UtilObject) { for (var key in obj) { return key; } }; -export const getValues = function(obj) { - var res: any[] = []; +export const getValues = function(obj: UtilObject) { + var res: V[] = []; var i = 0; for (var key in obj) { res[i++] = obj[key]; @@ -137,7 +159,7 @@ export const getValues = function(obj) { * @template K,V */ export const every = function( - obj: Object, + obj: UtilObject, fn: (k: string, v?: V) => boolean ): boolean { for (let key in obj) { diff --git a/packages/util/src/query.ts b/packages/util/src/query.ts index bb547cacb1a..1c766bb6935 100644 --- a/packages/util/src/query.ts +++ b/packages/util/src/query.ts @@ -21,13 +21,12 @@ import { forEach } from './obj'; * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a params * object (e.g. {arg: 'val', arg2: 'val2'}) * Note: You must prepend it with ? when adding it to a URL. - * - * @param {!Object} querystringParams - * @return {string} */ -export const querystring = function(querystringParams): string { +export const querystring = function(querystringParams: { + [key: string]: string; +}): string { const params: string[] = []; - forEach(querystringParams, (key, value) => { + forEach(querystringParams, (key: string, value) => { if (Array.isArray(value)) { value.forEach(arrayVal => { params.push( @@ -47,8 +46,8 @@ export const querystring = function(querystringParams): string { * @param {string} querystring * @return {!Object} */ -export const querystringDecode = function(querystring): object { - const obj = {}; +export const querystringDecode = function(querystring: string): object { + const obj: { [key: string]: unknown } = {}; const tokens = querystring.replace(/^\?/, '').split('&'); tokens.forEach(token => { diff --git a/packages/util/src/sha1.ts b/packages/util/src/sha1.ts index cf5fc097439..0054ff86ca6 100644 --- a/packages/util/src/sha1.ts +++ b/packages/util/src/sha1.ts @@ -102,13 +102,13 @@ export class Sha1 { /** * Internal compress helper function. - * @param {!number[]|!Uint8Array|string} buf Block to compress. - * @param {number=} optOffset Offset of the block in the buffer. + * @param buf Block to compress. + * @param offset Offset of the block in the buffer. * @private */ - compress_(buf, optOffset?): void { - if (!optOffset) { - optOffset = 0; + compress_(buf: number[] | Uint8Array | string, offset?: number): void { + if (!offset) { + offset = 0; } const W = this.W_; @@ -125,20 +125,20 @@ export class Sha1 { // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and // most clients have been updated. W[i] = - (buf.charCodeAt(optOffset) << 24) | - (buf.charCodeAt(optOffset + 1) << 16) | - (buf.charCodeAt(optOffset + 2) << 8) | - buf.charCodeAt(optOffset + 3); - optOffset += 4; + (buf.charCodeAt(offset) << 24) | + (buf.charCodeAt(offset + 1) << 16) | + (buf.charCodeAt(offset + 2) << 8) | + buf.charCodeAt(offset + 3); + offset += 4; } } else { for (let i = 0; i < 16; i++) { W[i] = - (buf[optOffset] << 24) | - (buf[optOffset + 1] << 16) | - (buf[optOffset + 2] << 8) | - buf[optOffset + 3]; - optOffset += 4; + (buf[offset] << 24) | + (buf[offset + 1] << 16) | + (buf[offset + 2] << 8) | + buf[offset + 3]; + offset += 4; } } @@ -190,24 +190,24 @@ export class Sha1 { this.chain_[4] = (this.chain_[4] + e) & 0xffffffff; } - update(bytes, optLength?): void { + update(bytes?: number[] | Uint8Array | string, length?: number): void { // TODO(johnlenz): tighten the function signature and remove this check if (bytes == null) { return; } - if (optLength === undefined) { - optLength = bytes.length; + if (length === undefined) { + length = bytes.length; } - const lengthMinusBlock = optLength - this.blockSize; + const lengthMinusBlock = length - this.blockSize; let n = 0; // Using local instead of member variables gives ~5% speedup on Firefox 16. const buf = this.buf_; let inbuf = this.inbuf_; // The outer while loop should execute at most twice. - while (n < optLength) { + while (n < length) { // When we have no data in the block to top up, we can directly process the // input buffer (assuming it contains sufficient data). This gives ~25% // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that @@ -220,7 +220,7 @@ export class Sha1 { } if (typeof bytes === 'string') { - while (n < optLength) { + while (n < length) { buf[inbuf] = bytes.charCodeAt(n); ++inbuf; ++n; @@ -232,7 +232,7 @@ export class Sha1 { } } } else { - while (n < optLength) { + while (n < length) { buf[inbuf] = bytes[n]; ++inbuf; ++n; @@ -247,7 +247,7 @@ export class Sha1 { } this.inbuf_ = inbuf; - this.total_ += optLength; + this.total_ += length; } /** @override */ diff --git a/packages/util/src/subscribe.ts b/packages/util/src/subscribe.ts index d705f62293e..70e976ec3f1 100644 --- a/packages/util/src/subscribe.ts +++ b/packages/util/src/subscribe.ts @@ -272,7 +272,10 @@ export function async(fn: Function, onError?: ErrorFn): Function { /** * Return true if the object passed in implements any of the named methods. */ -function implementsAnyMethods(obj: unknown, methods: string[]): boolean { +function implementsAnyMethods( + obj: { [key: string]: unknown }, + methods: string[] +): boolean { if (typeof obj !== 'object' || obj === null) { return false; } diff --git a/packages/util/src/utf8.ts b/packages/util/src/utf8.ts index 85ab3784939..4431727cf28 100644 --- a/packages/util/src/utf8.ts +++ b/packages/util/src/utf8.ts @@ -32,7 +32,7 @@ import { assert } from './assert'; * @param {string} str * @return {Array} */ -export const stringToByteArray = function(str): number[] { +export const stringToByteArray = function(str: string): number[] { const out: number[] = []; let p = 0; for (let i = 0; i < str.length; i++) { @@ -71,7 +71,7 @@ export const stringToByteArray = function(str): number[] { * @param {string} str * @return {number} */ -export const stringLength = function(str): number { +export const stringLength = function(str: string): number { let p = 0; for (let i = 0; i < str.length; i++) { const c = str.charCodeAt(i); diff --git a/packages/util/src/validation.ts b/packages/util/src/validation.ts index a368f09359e..48e985699a6 100644 --- a/packages/util/src/validation.ts +++ b/packages/util/src/validation.ts @@ -19,16 +19,16 @@ * Check to make sure the appropriate number of arguments are provided for a public function. * Throws an error if it fails. * - * @param {!string} fnName The function name - * @param {!number} minCount The minimum number of arguments to allow for the function call - * @param {!number} maxCount The maximum number of argument to allow for the function call - * @param {!number} argCount The actual number of arguments provided. + * @param fnName The function name + * @param minCount The minimum number of arguments to allow for the function call + * @param maxCount The maximum number of argument to allow for the function call + * @param argCount The actual number of arguments provided. */ export const validateArgCount = function( - fnName, - minCount, - maxCount, - argCount + fnName: string, + minCount: number, + maxCount: number, + argCount: number ): void { let argError; if (argCount < minCount) { @@ -52,12 +52,16 @@ export const validateArgCount = function( /** * Generates a string to prefix an error message about failed argument validation * - * @param {!string} fnName The function name - * @param {!number} argumentNumber The index of the argument - * @param {boolean} optional Whether or not the argument is optional - * @return {!string} The prefix to add to the error thrown for validation. + * @param fnName The function name + * @param argumentNumber The index of the argument + * @param optional Whether or not the argument is optional + * @return The prefix to add to the error thrown for validation. */ -export function errorPrefix(fnName, argumentNumber, optional): string { +export function errorPrefix( + fnName: string, + argumentNumber: number, + optional: boolean +): string { let argName = ''; switch (argumentNumber) { case 1: @@ -85,16 +89,16 @@ export function errorPrefix(fnName, argumentNumber, optional): string { } /** - * @param {!string} fnName - * @param {!number} argumentNumber - * @param {!string} namespace - * @param {boolean} optional + * @param fnName + * @param argumentNumber + * @param namespace + * @param optional */ export function validateNamespace( - fnName, - argumentNumber, - namespace, - optional + fnName: string, + argumentNumber: number, + namespace: string, + optional: boolean ): void { if (optional && !namespace) { return; @@ -109,10 +113,10 @@ export function validateNamespace( } export function validateCallback( - fnName, - argumentNumber, - callback, - optional + fnName: string, + argumentNumber: number, + callback: Function, + optional: boolean ): void { if (optional && !callback) { return; @@ -126,10 +130,10 @@ export function validateCallback( } export function validateContextObject( - fnName, - argumentNumber, - context, - optional + fnName: string, + argumentNumber: number, + context: unknown, + optional: boolean ): void { if (optional && !context) { return; diff --git a/packages/webchannel-wrapper/package.json b/packages/webchannel-wrapper/package.json index c1d5e1b485b..93595bd5410 100644 --- a/packages/webchannel-wrapper/package.json +++ b/packages/webchannel-wrapper/package.json @@ -26,6 +26,7 @@ "type": "git", "url": "https://github.com/firebase/firebase-js-sdk.git" }, + "typings": "src/index.d.ts", "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" } diff --git a/packages/webchannel-wrapper/src/index.d.ts b/packages/webchannel-wrapper/src/index.d.ts new file mode 100644 index 00000000000..4aedb1a7c8b --- /dev/null +++ b/packages/webchannel-wrapper/src/index.d.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(mikelehen): Flesh out proper types (or figure out how to generate via +// clutz or something). +export class XhrIo {} +export const ErrorCode: any; +export const EventType: any; +export namespace WebChannel { + export type EventType = any; + export const EventType: any; +} + +type StringMap = { [key: string]: string }; + +export interface WebChannelOptions { + messageHeaders?: StringMap; + initMessageHeaders?: StringMap; + messageContentType?: string; + messageUrlParams?: StringMap; + clientProtocolHeaderRequired?: boolean; + concurrentRequestLimit?: number; + supportsCrossDomainXhr?: boolean; + testUrl?: string; + sendRawJson?: boolean; + httpSessionIdParam?: string; + httpHeadersOverwriteParam?: string; + backgroundChannelTest?: boolean; + forceLongPolling?: boolean; + fastHandshake?: boolean; + disableRedac?: boolean; + clientProfile?: string; + internalChannelParams?: { [key: string]: boolean | number }; + xmlHttpFactory?: unknown; + requestRefreshThresholds?: { [key: string]: number }; +} + +export interface WebChannelTransport { + createWebChannel(url: string, options: WebChannelOptions): any; +} + +export function createWebChannelTransport(): WebChannelTransport; diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index 0437d7e2c3c..fd5904794c7 100644 --- a/scripts/emulator-testing/emulators/emulator.ts +++ b/scripts/emulator-testing/emulators/emulator.ts @@ -15,11 +15,13 @@ * limitations under the License. */ +// @ts-ignore import { spawn } from 'child-process-promise'; import { ChildProcess } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; import * as request from 'request'; +// @ts-ignore import * as tmp from 'tmp'; export interface ChildProcessPromise extends Promise { @@ -40,7 +42,7 @@ export abstract class Emulator { download(): Promise { return new Promise((resolve, reject) => { - tmp.dir((err, dir) => { + tmp.dir((err: Error, dir: string) => { if (err) reject(err); console.log(`Created temporary directory at [${dir}].`); @@ -89,7 +91,7 @@ export abstract class Emulator { const timeout = process.env.TRAVIS ? 100 : 30; // seconds const start: number = Date.now(); - const wait = (resolve, reject) => { + const wait = (resolve: () => void, reject: (arg0: unknown) => void) => { const elapsed = (Date.now() - start) / 1000; if (elapsed > timeout) { reject(`Emulator not ready after ${timeout}s. Exiting ...`); diff --git a/scripts/emulator-testing/emulators/firestore-emulator.ts b/scripts/emulator-testing/emulators/firestore-emulator.ts index 4e82cb7ec39..aa4d68e4576 100644 --- a/scripts/emulator-testing/emulators/firestore-emulator.ts +++ b/scripts/emulator-testing/emulators/firestore-emulator.ts @@ -20,7 +20,7 @@ import { Emulator } from './emulator'; export class FirestoreEmulator extends Emulator { projectId: string; - constructor(port, projectId = 'test-emulator') { + constructor(port: number, projectId = 'test-emulator') { super(port); this.projectId = projectId; this.binaryName = 'firestore-emulator.jar'; diff --git a/scripts/emulator-testing/firestore-test-runner.ts b/scripts/emulator-testing/firestore-test-runner.ts index c3a8669e657..4cfdf55f36f 100644 --- a/scripts/emulator-testing/firestore-test-runner.ts +++ b/scripts/emulator-testing/firestore-test-runner.ts @@ -15,8 +15,10 @@ * limitations under the License. */ +// @ts-ignore import { spawn } from 'child-process-promise'; import * as path from 'path'; +// @ts-ignore import * as freePortFinder from 'find-free-port'; import { ChildProcessPromise } from './emulators/emulator'; @@ -48,9 +50,9 @@ async function run(): Promise { } } -function findFreePort() { +function findFreePort(): Promise { return new Promise((resolve, reject) => { - freePortFinder(10000, (err, port) => { + freePortFinder(10000, (err: Error, port: number) => { return err ? reject(err) : resolve(port); }); });