From 7367b5fd744a0877a566c206d56794545153cca7 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 5 Jun 2019 13:31:21 -0700 Subject: [PATCH 01/15] Start updating files --- config/tsconfig.base.json | 1 + packages/functions/index.node.ts | 6 +++--- packages/functions/index.ts | 6 +++--- packages/functions/src/serializer.ts | 4 ++-- packages/logger/src/logger.ts | 10 +++++----- packages/storage/index.ts | 6 +++--- packages/storage/src/implementation/fs.ts | 4 ---- packages/storage/src/implementation/requests.ts | 9 ++++++--- packages/util/src/assert.ts | 8 ++------ packages/util/src/crypt.ts | 4 ++-- packages/util/src/deferred.ts | 8 +++----- packages/util/src/environment.ts | 2 ++ packages/util/src/json.ts | 4 ++-- packages/util/src/jwt.ts | 2 +- 14 files changed, 35 insertions(+), 39 deletions(-) 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/functions/index.node.ts b/packages/functions/index.node.ts index c6901a3b16f..c324b3ca708 100644 --- a/packages/functions/index.node.ts +++ b/packages/functions/index.node.ts @@ -16,7 +16,7 @@ */ 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 +29,7 @@ function factory(app: FirebaseApp, unused: any, region?: string): Service { return new Service(app, region); } -export function registerFunctions(instance) { +export function registerFunctions(instance: _FirebaseNamespace) { let namespaceExports = { // no-inline Functions: Service @@ -45,4 +45,4 @@ export function registerFunctions(instance) { ); } -registerFunctions(firebase); +registerFunctions(firebase as _FirebaseNamespace); diff --git a/packages/functions/index.ts b/packages/functions/index.ts index 83ab3ba484d..cab6412484a 100644 --- a/packages/functions/index.ts +++ b/packages/functions/index.ts @@ -16,7 +16,7 @@ */ import firebase from '@firebase/app'; import * as app_types 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 +33,7 @@ function factory( return new Service(app, region); } -export function registerFunctions(instance) { +export function registerFunctions(instance: _FirebaseNamespace) { let namespaceExports = { // no-inline Functions: Service @@ -49,7 +49,7 @@ export function registerFunctions(instance) { ); } -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 75e59fcd98b..f8f3d652f2b 100644 --- a/packages/functions/src/serializer.ts +++ b/packages/functions/src/serializer.ts @@ -18,8 +18,8 @@ const LONG_TYPE = 'type.googleapis.com/google.protobuf.Int64Value'; const UNSIGNED_LONG_TYPE = 'type.googleapis.com/google.protobuf.UInt64Value'; -function mapValues(o: object, f: (any) => any): object { - let result = {}; +function mapValues(o: { [key: string]: any }, f: (arg0: any) => any): object { + let result: { [key: string]: any } = {}; for (var key in o) { if (o.hasOwnProperty(key)) { result[key] = f(o[key]); diff --git a/packages/logger/src/logger.ts b/packages/logger/src/logger.ts index 0f258f3616a..7dbd1641707 100644 --- a/packages/logger/src/logger.ts +++ b/packages/logger/src/logger.ts @@ -139,19 +139,19 @@ export class Logger { * The functions below are all based on the `console` interface */ - debug(...args) { + debug(...args: any[]) { this._logHandler(this, LogLevel.DEBUG, ...args); } - log(...args) { + log(...args: any[]) { this._logHandler(this, LogLevel.VERBOSE, ...args); } - info(...args) { + info(...args: any[]) { this._logHandler(this, LogLevel.INFO, ...args); } - warn(...args) { + warn(...args: any[]) { this._logHandler(this, LogLevel.WARN, ...args); } - error(...args) { + error(...args: any[]) { this._logHandler(this, LogLevel.ERROR, ...args); } } diff --git a/packages/storage/index.ts b/packages/storage/index.ts index b1d30ab0ddc..107f5f779c3 100644 --- a/packages/storage/index.ts +++ b/packages/storage/index.ts @@ -17,7 +17,7 @@ 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 +39,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 +58,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/requests.ts b/packages/storage/src/implementation/requests.ts index ac63e997b25..1d94346d3b7 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: { [key: string]: any } = {}; if (location.isRoot) { urlParams['prefix'] = ''; } else { @@ -427,13 +427,16 @@ 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'); + if (sizeString === null) { + handlerCheck(false); + } } 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/util/src/assert.ts b/packages/util/src/assert.ts index 87115d0af62..72fc5a9f868 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) { +export const assert = function(assertion: any, message: string) { if (!assertion) { throw assertionError(message); } @@ -30,10 +28,8 @@ export const assert = function(assertion, message) { /** * Returns an Error object suitable for throwing. - * @param {string} message - * @return {!Error} */ -export const assertionError = function(message) { +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 cc36d915854..af73065a6d3 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) { +const stringToByteArray = function(str: string) { // TODO(user): Use native implementations if/when available var out: number[] = [], p = 0; @@ -52,7 +52,7 @@ const stringToByteArray = function(str) { * @param bytes Array of numbers representing characters. * @return Stringification of the array. */ -const byteArrayToString = function(bytes) { +const byteArrayToString = function(bytes: number[]) { // TODO(user): Use native implementations if/when available var out: string[] = [], pos = 0, diff --git a/packages/util/src/deferred.ts b/packages/util/src/deferred.ts index f7a4a3d5536..1e4cb082bff 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?: R | PromiseLike | Error ) => void; + resolve: (value?: R | PromiseLike) => void; constructor() { this.promise = new Promise((resolve, reject) => { this.resolve = resolve; @@ -30,10 +30,8 @@ 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?) { + wrapCallback(callback?: (error?: Error, value?: any) => void): (error: Error, value?: any) => 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/json.ts b/packages/util/src/json.ts index bb4326e94ab..010a726c072 100644 --- a/packages/util/src/json.ts +++ b/packages/util/src/json.ts @@ -21,7 +21,7 @@ * @param {string} str A string containing JSON. * @return {*} The javascript object representing the specified JSON. */ -export function jsonEval(str) { +export function jsonEval(str: string): { [key: string]: any } { return JSON.parse(str); } @@ -30,6 +30,6 @@ export function jsonEval(str) { * @param {*} data Javascript object to be stringified. * @return {string} The JSON contents of the object. */ -export function stringify(data) { +export function stringify(data: any): string { return JSON.stringify(data); } diff --git a/packages/util/src/jwt.ts b/packages/util/src/jwt.ts index a131978bfe3..23fc515e587 100644 --- a/packages/util/src/jwt.ts +++ b/packages/util/src/jwt.ts @@ -28,7 +28,7 @@ import { jsonEval } from './json'; * @param {?string} token * @return {{header: *, claims: *, data: *, signature: string}} */ -export const decode = function(token) { +export const decode = function(token: string): {} { var header = {}, claims = {}, data = {}, From 611674c035db6c8ba35dc43a85a595389fcefe6a Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 10 Jun 2019 13:27:13 -0700 Subject: [PATCH 02/15] noImplicitAny TS fixes --- config/.eslintrc.json | 3 +- packages/app/index.node.ts | 7 +- packages/app/index.rn.ts | 1 + packages/app/index.ts | 1 + packages/app/package.json | 2 +- packages/app/src/firebaseApp.ts | 3 +- packages/app/src/firebaseNamespace.ts | 10 +- packages/app/src/firebaseNamespaceCore.ts | 41 ++++--- packages/app/src/lite/firebaseAppLite.ts | 2 +- .../app/src/lite/firebaseNamespaceLite.ts | 8 +- packages/app/test/firebaseApp.test.ts | 24 ++-- packages/database/index.node.ts | 2 +- .../database/src/core/PersistentConnection.ts | 2 +- .../database/src/core/snap/ChildrenNode.ts | 4 +- packages/database/src/core/snap/IndexMap.ts | 2 +- packages/database/src/core/snap/Node.ts | 2 +- .../database/src/core/snap/nodeFromJSON.ts | 2 +- packages/database/src/core/snap/snap.ts | 2 +- packages/database/src/core/util/CountedSet.ts | 12 +- packages/database/src/core/util/Tree.ts | 2 +- .../src/realtime/WebSocketConnection.ts | 2 +- packages/database/tsconfig.json | 3 +- packages/firestore/index.node.ts | 7 +- packages/firestore/index.ts | 5 +- packages/firestore/src/api/credentials.ts | 4 +- .../firestore/src/core/firestore_client.ts | 6 +- packages/firestore/src/core/sync_engine.ts | 2 +- .../src/local/indexeddb_mutation_queue.ts | 2 +- .../src/local/indexeddb_persistence.ts | 6 +- .../src/local/indexeddb_query_cache.ts | 2 +- .../firestore/src/local/indexeddb_schema.ts | 6 +- .../src/local/local_documents_view.ts | 2 +- packages/firestore/src/local/local_store.ts | 6 +- .../src/local/lru_garbage_collector.ts | 2 +- .../src/local/memory_mutation_queue.ts | 2 +- .../firestore/src/local/memory_persistence.ts | 2 +- .../src/local/memory_remote_document_cache.ts | 2 +- .../src/local/shared_client_state.ts | 4 +- packages/firestore/src/local/simple_db.ts | 2 +- .../platform_browser/webchannel_connection.ts | 8 +- .../src/platform_node/grpc_connection.ts | 1 + .../firestore/src/util/input_validation.ts | 4 +- .../integration/api/array_transforms.test.ts | 2 +- .../test/integration/api/batch_writes.test.ts | 2 +- .../test/integration/api/cursor.test.ts | 4 +- .../test/integration/api/database.test.ts | 4 +- .../test/integration/api/fields.test.ts | 6 +- .../test/integration/api/get_options.test.ts | 2 +- .../api/numeric_transforms.test.ts | 2 +- .../test/integration/api/query.test.ts | 2 +- .../integration/api/server_timestamp.test.ts | 2 +- .../test/integration/api/smoke.test.ts | 2 +- .../test/integration/api/transactions.test.ts | 2 +- .../test/integration/api/type.test.ts | 2 +- .../test/integration/api/validation.test.ts | 2 +- .../api_internal/idle_timeout.test.ts | 2 +- .../test/integration/util/helpers.ts | 2 +- .../unit/local/indexeddb_persistence.test.ts | 21 ++-- .../test/unit/local/local_store.test.ts | 2 +- .../unit/local/persistence_promise.test.ts | 2 +- .../unit/local/remote_document_cache.test.ts | 2 +- .../unit/local/test_remote_document_cache.ts | 2 +- .../web_storage_shared_client_state.test.ts | 20 ++- .../test/unit/remote/node/serializer.test.ts | 1 + .../test/unit/specs/describe_spec.ts | 6 +- .../test/unit/specs/listen_spec.test.ts | 2 +- .../test/unit/specs/spec_test_runner.ts | 2 +- .../test/unit/specs/write_spec.test.ts | 2 +- .../firestore/test/util/equality_matcher.ts | 13 +- packages/logger/.eslintrc.json | 6 + packages/logger/index.ts | 2 +- packages/logger/package.json | 10 +- packages/logger/src/logger.ts | 18 +-- packages/logger/test/logger.test.ts | 4 +- packages/rxfire/database/list/index.ts | 2 +- packages/rxfire/storage/index.ts | 2 +- packages/testing/src/api/index.ts | 8 +- packages/util/.eslintrc.json | 6 + packages/util/package.json | 10 +- packages/util/src/assert.ts | 2 +- packages/util/src/crypt.ts | 116 +++++++++--------- packages/util/src/deepCopy.ts | 18 ++- packages/util/src/deferred.ts | 6 +- packages/util/src/errors.ts | 1 - packages/util/src/json.ts | 4 +- packages/util/src/jwt.ts | 75 +++++------ packages/util/src/obj.ts | 52 ++++---- packages/util/src/query.ts | 21 ++-- packages/util/src/sha1.ts | 100 +++++++-------- packages/util/src/subscribe.ts | 27 ++-- packages/util/src/utf8.ts | 22 ++-- packages/util/src/validation.ts | 83 ++++++++----- packages/util/test/base64.test.ts | 2 +- packages/util/test/deepCopy.test.ts | 16 +-- packages/util/test/errors.test.ts | 4 +- packages/util/test/subscribe.test.ts | 53 ++++---- 96 files changed, 537 insertions(+), 458 deletions(-) create mode 100644 packages/logger/.eslintrc.json create mode 100644 packages/util/.eslintrc.json diff --git a/config/.eslintrc.json b/config/.eslintrc.json index abe84ee8cbb..a2b63fafa9c 100644 --- a/config/.eslintrc.json +++ b/config/.eslintrc.json @@ -20,7 +20,8 @@ "**/test/**/*.ts" ], "rules": { - "no-unused-expressions": "off" + "no-unused-expressions": "off", + "@typescript-eslint/no-explicit-any": "off" } } ], diff --git a/packages/app/index.node.ts b/packages/app/index.node.ts index 560feb223ff..fead2b76b65 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'; -import Storage from 'dom-storage'; -import { XMLHttpRequest } from 'xmlhttprequest'; +// Node specific packages. +// eslint-disable-next-line @typescript-eslint/no-require-imports +const Storage = require('dom-storage'); +// eslint-disable-next-line @typescript-eslint/no-require-imports +const XMLHttpRequest = require('xmlhttprequest'); const _firebase = createFirebaseNamespace() as _FirebaseNamespace; diff --git a/packages/app/index.rn.ts b/packages/app/index.rn.ts index fc8b85ef14b..a753d2d957b 100644 --- a/packages/app/index.rn.ts +++ b/packages/app/index.rn.ts @@ -24,6 +24,7 @@ import { createFirebaseNamespace } from './src/firebaseNamespace'; * some of our tests because of duplicate symbols, we are using require syntax * here */ +// eslint-disable-next-line const { AsyncStorage } = require('react-native'); const _firebase = createFirebaseNamespace() as _FirebaseNamespace; diff --git a/packages/app/index.ts b/packages/app/index.ts index 631b6155016..9767ffa5722 100644 --- a/packages/app/index.ts +++ b/packages/app/index.ts @@ -29,6 +29,7 @@ if (isBrowser() && 'firebase' in self) { Firebase library is only loaded once. `); + // eslint-disable-next-line const sdkVersion = ((self as any).firebase as FirebaseNamespace).SDK_VERSION; if (sdkVersion && sdkVersion.indexOf('LITE') >= 0) { logger.warn(` diff --git a/packages/app/package.json b/packages/app/package.json index 925548cefd4..873ea6ead42 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -18,7 +18,7 @@ "lint:fix": "eslint --fix -c .eslintrc.json '**/*.ts'", "build": "rollup -c", "dev": "rollup -c -w", - "test": "run-p test:browser test:node", + "test": "run-p lint test:browser test:node", "test:browser": "karma start --single-run", "test:browser:debug": "karma start --browsers Chrome --auto-watch", "test:node": "TS_NODE_CACHE=NO TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha test/**/*.test.* --opts ../../config/mocha.node.opts", diff --git a/packages/app/src/firebaseApp.ts b/packages/app/src/firebaseApp.ts index ef45aa4e26b..8a4235b5117 100644 --- a/packages/app/src/firebaseApp.ts +++ b/packages/app/src/firebaseApp.ts @@ -38,7 +38,7 @@ interface ServicesCache { // An array to capture listeners before the true auth functions // exist -let tokenListeners: any[] = []; +let tokenListeners: Array<(token: string | null) => void> = []; /** * Global context object for a collection of services using @@ -175,6 +175,7 @@ export class FirebaseAppImpl implements FirebaseApp { * Callback function used to extend an App instance at the time * of service instance creation. */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any private extendApp(props: { [name: string]: any }): void { // Copy the object onto the FirebaseAppImpl prototype deepExtend(this, props); diff --git a/packages/app/src/firebaseNamespace.ts b/packages/app/src/firebaseNamespace.ts index 9789c3554fc..78ad157b1da 100644 --- a/packages/app/src/firebaseNamespace.ts +++ b/packages/app/src/firebaseNamespace.ts @@ -32,11 +32,11 @@ export function createFirebaseNamespace(): FirebaseNamespace { const namespace = createFirebaseNamespaceCore(FirebaseAppImpl); (namespace as _FirebaseNamespace).INTERNAL = { ...(namespace as _FirebaseNamespace).INTERNAL, - createFirebaseNamespace: createFirebaseNamespace, - extendNamespace: extendNamespace, - createSubscribe: createSubscribe, - ErrorFactory: ErrorFactory, - deepExtend: deepExtend + createFirebaseNamespace, + extendNamespace, + createSubscribe, + ErrorFactory, + deepExtend }; /** diff --git a/packages/app/src/firebaseNamespaceCore.ts b/packages/app/src/firebaseNamespaceCore.ts index 1673f9915e4..b02c88e46b7 100644 --- a/packages/app/src/firebaseNamespaceCore.ts +++ b/packages/app/src/firebaseNamespaceCore.ts @@ -29,17 +29,13 @@ import { FirebaseServiceNamespace, AppHook } from '@firebase/app-types/private'; -import { deepExtend, patchProperty } from '@firebase/util'; +import { deepExtend, contains } from '@firebase/util'; import { FirebaseAppImpl } from './firebaseApp'; import { ERROR_FACTORY, AppError } from './errors'; import { FirebaseAppLiteImpl } from './lite/firebaseAppLite'; import { DEFAULT_ENTRY_NAME } from './constants'; import { version } from '../../firebase/package.json'; -function contains(obj: object, key: string) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - /** * Because auth can't share code with other components, we attach the utility functions * in an internal namespace to share code. @@ -60,9 +56,11 @@ export function createFirebaseNamespaceCore( // as the firebase namespace. // @ts-ignore __esModule: true, - initializeApp: initializeApp, - app: app as any, - apps: null as any, + initializeApp, + // @ts-ignore + app, + // @ts-ignore + apps: null, SDK_VERSION: version, INTERNAL: { registerService, @@ -82,7 +80,8 @@ export function createFirebaseNamespaceCore( // // import * as firebase from 'firebase'; // which becomes: var firebase = require('firebase'); - patchProperty(namespace, 'default', namespace); + // @ts-ignore + namespace['default'] = namespace; // firebase.apps is a read-only getter. Object.defineProperty(namespace, 'apps', { @@ -105,12 +104,13 @@ export function createFirebaseNamespaceCore( function app(name?: string): FirebaseApp { name = name || DEFAULT_ENTRY_NAME; if (!contains(apps, name)) { - throw ERROR_FACTORY.create(AppError.NO_APP, { name: name }); + throw ERROR_FACTORY.create(AppError.NO_APP, { name }); } return apps[name]; } - patchProperty(app, 'App', firebaseAppImpl); + // @ts-ignore + app['App'] = firebaseAppImpl; /** * Create a new App instance (name must be unique). */ @@ -119,7 +119,10 @@ export function createFirebaseNamespaceCore( config?: FirebaseAppConfig ): FirebaseApp; function initializeApp(options: FirebaseOptions, name?: string): FirebaseApp; - function initializeApp(options: FirebaseOptions, rawConfig = {}) { + function initializeApp( + options: FirebaseOptions, + rawConfig = {} + ): FirebaseApp { if (typeof rawConfig !== 'object' || rawConfig === null) { const name = rawConfig; rawConfig = { name }; @@ -138,7 +141,7 @@ export function createFirebaseNamespaceCore( } if (contains(apps, name)) { - throw ERROR_FACTORY.create(AppError.DUPLICATE_APP, { name: name }); + throw ERROR_FACTORY.create(AppError.DUPLICATE_APP, { name }); } const app = new firebaseAppImpl( @@ -177,7 +180,7 @@ export function createFirebaseNamespaceCore( ): FirebaseServiceNamespace { // Cannot re-register a service that already exists if (factories[name]) { - throw ERROR_FACTORY.create(AppError.DUPLICATE_SERVICE, { name: name }); + throw ERROR_FACTORY.create(AppError.DUPLICATE_SERVICE, { name }); } // Capture the service factory for later service instantiation @@ -194,16 +197,18 @@ export function createFirebaseNamespaceCore( } // The Service namespace is an accessor function ... - function serviceNamespace(appArg: FirebaseApp = app()) { + function serviceNamespace(appArg: FirebaseApp = app()): FirebaseService { + // @ts-ignore if (typeof appArg[name] !== 'function') { // Invalid argument. // This happens in the following case: firebase.storage('gs:/') throw ERROR_FACTORY.create(AppError.INVALID_APP_ARGUMENT, { - name: name + name }); } // Forward service instance lookup to the FirebaseApp. + // @ts-ignore return appArg[name](); } @@ -213,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 : []); @@ -224,7 +231,7 @@ export function createFirebaseNamespaceCore( return serviceNamespace; } - function callAppHooks(app: FirebaseApp, eventName: string) { + function callAppHooks(app: FirebaseApp, eventName: string): void { for (const serviceName of Object.keys(factories)) { // Ignore virtual services const factoryName = useAsService(app, serviceName); diff --git a/packages/app/src/lite/firebaseAppLite.ts b/packages/app/src/lite/firebaseAppLite.ts index 697784b68ef..2e60dbd97f2 100644 --- a/packages/app/src/lite/firebaseAppLite.ts +++ b/packages/app/src/lite/firebaseAppLite.ts @@ -157,7 +157,7 @@ export class FirebaseAppLiteImpl implements FirebaseApp { * Callback function used to extend an App instance at the time * of service instance creation. */ - private extendApp(props: { [name: string]: any }): void { + private extendApp(props: { [name: string]: unknown }): void { // Copy the object onto the FirebaseAppImpl prototype deepExtend(this, props); } diff --git a/packages/app/src/lite/firebaseNamespaceLite.ts b/packages/app/src/lite/firebaseNamespaceLite.ts index 8cc26ae0f83..1083db4c254 100644 --- a/packages/app/src/lite/firebaseNamespaceLite.ts +++ b/packages/app/src/lite/firebaseNamespaceLite.ts @@ -20,7 +20,9 @@ import { _FirebaseApp, _FirebaseNamespace, FirebaseServiceFactory, - AppHook + AppHook, + FirebaseServiceNamespace, + FirebaseService } from '@firebase/app-types/private'; import { FirebaseAppLiteImpl } from './firebaseAppLite'; import { createFirebaseNamespaceCore } from '../firebaseNamespaceCore'; @@ -41,10 +43,10 @@ export function createFirebaseNamespaceLite(): FirebaseNamespace { function registerServiceForLite( name: string, createService: FirebaseServiceFactory, - serviceProperties?: { [prop: string]: any }, + serviceProperties?: { [prop: string]: unknown }, appHook?: AppHook, allowMultipleInstances?: boolean - ) { + ): FirebaseServiceNamespace { // only allow performance to register with firebase lite if (name !== 'performance' && name !== 'installations') { throw Error(`${name} cannot register with the standalone perf instance`); diff --git a/packages/app/test/firebaseApp.test.ts b/packages/app/test/firebaseApp.test.ts index 241e969240a..ac5c319b435 100644 --- a/packages/app/test/firebaseApp.test.ts +++ b/packages/app/test/firebaseApp.test.ts @@ -28,7 +28,7 @@ import { assert } from 'chai'; executeFirebaseTests(); executeFirebaseLiteTests(); -function executeFirebaseTests() { +function executeFirebaseTests(): void { firebaseAppTests('Firebase App Tests', createFirebaseNamespace); describe('Firebase Service Registration', () => { @@ -40,14 +40,13 @@ function executeFirebaseTests() { it('Register App Hook', done => { const events = ['create', 'delete']; let hookEvents = 0; - let app: FirebaseApp; (firebase as _FirebaseNamespace).INTERNAL.registerService( 'test', (app: FirebaseApp) => { return new TestService(app); }, undefined, - (event: string, app: FirebaseApp) => { + (event: string, _app: FirebaseApp) => { assert.equal(event, events[hookEvents]); hookEvents += 1; if (hookEvents === events.length) { @@ -55,9 +54,10 @@ function executeFirebaseTests() { } } ); - app = firebase.initializeApp({}); + const app = firebase.initializeApp({}); // Ensure the hook is called synchronously assert.equal(hookEvents, 1); + // tslint:disable-next-line:no-floating-promises app.delete(); }); @@ -140,7 +140,7 @@ function executeFirebaseTests() { return new TestService(app); }, undefined, - (event: string, app: FirebaseApp) => { + (event: string, _app: FirebaseApp) => { assert.equal(event, events[hookEvents]); hookEvents += 1; if (hookEvents === events.length) { @@ -150,6 +150,7 @@ function executeFirebaseTests() { ); // Ensure the hook is called synchronously assert.equal(hookEvents, 1); + // tslint:disable-next-line:no-floating-promises app.delete(); }); @@ -221,6 +222,7 @@ function executeFirebaseTests() { ); assert.strictEqual(service, service2); }); + it(`Should pass null to the factory method if using default instance`, () => { // Register Multi Instance Service (firebase as _FirebaseNamespace).INTERNAL.registerService( @@ -235,11 +237,8 @@ function executeFirebaseTests() { } ); firebase.initializeApp({}); - - // Capture a given service ref - const serviceIdentifier = 'custom instance identifier'; - const service = (firebase.app() as any).testService(); }); + it(`Should extend INTERNAL per app instance`, () => { let counter: number = 0; (firebase as _FirebaseNamespace).INTERNAL.registerService( @@ -280,7 +279,7 @@ function executeFirebaseTests() { }); } -function executeFirebaseLiteTests() { +function executeFirebaseLiteTests(): void { firebaseAppTests('Firebase App Lite Tests', createFirebaseNamespaceLite); describe('Firebase Lite Service Registration', () => { @@ -291,14 +290,13 @@ function executeFirebaseLiteTests() { }); it('should allow Performance service to register', () => { - let app: FirebaseApp; (firebase as _FirebaseNamespace).INTERNAL.registerService( 'performance', (app: FirebaseApp) => { return new TestService(app); } ); - app = firebase.initializeApp({}); + const app = firebase.initializeApp({}); const perf = (app as any).performance(); assert.isTrue(perf instanceof TestService); }); @@ -316,7 +314,7 @@ function executeFirebaseLiteTests() { }); } -function firebaseAppTests(testName, firebaseNamespaceFactory) { +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..56f35475048 100644 --- a/packages/database/index.node.ts +++ b/packages/database/index.node.ts @@ -40,7 +40,7 @@ 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..772d2c6fecd 100644 --- a/packages/database/src/core/PersistentConnection.ts +++ b/packages/database/src/core/PersistentConnection.ts @@ -948,7 +948,7 @@ 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(this.listens_, (pathString: string, queries: { [key: string]: ListenSpec }) => { forEach(queries, (key: string, listenSpec: ListenSpec) => { this.sendListen_(listenSpec); }); 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..0625229929b 100644 --- a/packages/database/src/core/snap/snap.ts +++ b/packages/database/src/core/snap/snap.ts @@ -47,7 +47,7 @@ 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/src/realtime/WebSocketConnection.ts b/packages/database/src/realtime/WebSocketConnection.ts index b18e1af7b0a..58d9423206d 100644 --- a/packages/database/src/realtime/WebSocketConnection.ts +++ b/packages/database/src/realtime/WebSocketConnection.ts @@ -270,7 +270,7 @@ export class WebSocketConnection implements Transport { if (this.frames.length == this.totalFrames) { const fullMess = this.frames.join(''); this.frames = null; - const jsonMess = jsonEval(fullMess); + const jsonMess = jsonEval(fullMess) as object; //handle the message this.onMessage(jsonMess); 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..8ce10d4c075 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([]); @@ -315,7 +315,9 @@ export function makeCredentialsProvider( !!( typeof client === 'object' && client !== null && + // @ts-ignore client['auth'] && + // @ts-ignore client['auth']['getAuthHeaderValueForFirstParty'] ), 'unexpected gapi interface' diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index 2d243410593..1918138591a 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,12 @@ 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..342e9324cd0 100644 --- a/packages/firestore/src/core/sync_engine.ts +++ b/packages/firestore/src/core/sync_engine.ts @@ -433,7 +433,7 @@ 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 f407182424a..dfc29773035 100644 --- a/packages/firestore/src/local/indexeddb_mutation_queue.ts +++ b/packages/firestore/src/local/indexeddb_mutation_queue.ts @@ -478,7 +478,7 @@ export class IndexedDbMutationQueue implements MutationQueue { batch ).next(removedDocuments => { this.removeCachedMutationKeys(batch.batchId); - return PersistencePromise.forEach(removedDocuments, 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..a2f720d4c60 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,7 +515,7 @@ export class IndexedDbPersistence implements Persistence { }) .next(() => // Delete metadata for clients that are no longer considered active. - PersistencePromise.forEach(inactiveClients, inactiveClient => + PersistencePromise.forEach(inactiveClients, (inactiveClient: DbClientMetadata) => metadataStore.delete(inactiveClient.clientId) ) ) @@ -882,7 +882,7 @@ 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..1e5f4c3221a 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,7 +171,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter { return mutationsStore .loadAll(DbMutationBatch.userMutationsIndex, range) .next(dbBatches => { - return PersistencePromise.forEach(dbBatches, dbBatch => { + return PersistencePromise.forEach(dbBatches, (dbBatch: DbMutationBatch) => { assert( dbBatch.userId === queue.userId, `Cannot process batch ${dbBatch.batchId} from unexpected user` @@ -246,7 +246,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..ed1879e6041 100644 --- a/packages/firestore/src/local/local_store.ts +++ b/packages/firestore/src/local/local_store.ts @@ -651,7 +651,7 @@ export class LocalStore { 'notifyLocalViewChanges', 'readwrite', txn => { - return PersistencePromise.forEach(viewChanges, viewChange => { + return PersistencePromise.forEach(viewChanges, (viewChange: LocalViewChanges) => { this.localViewReferences.addReferences( viewChange.addedKeys, viewChange.targetId @@ -660,7 +660,7 @@ export class LocalStore { viewChange.removedKeys, viewChange.targetId ); - return PersistencePromise.forEach(viewChange.removedKeys, key => + return PersistencePromise.forEach(viewChange.removedKeys, (key: DocumentKey) => this.persistence.referenceDelegate.removeReference(txn, key) ); }); @@ -772,7 +772,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..c7e07df20c3 100644 --- a/packages/firestore/src/local/memory_persistence.ts +++ b/packages/firestore/src/local/memory_persistence.ts @@ -261,7 +261,7 @@ export class MemoryEagerDelegate implements ReferenceDelegate { txn: PersistenceTransaction ): PersistencePromise { const cache = this.persistence.getRemoteDocumentCache(); - return PersistencePromise.forEach(this.orphanedDocuments, key => { + 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, 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..2f4e523b8e7 100644 --- a/packages/firestore/src/local/shared_client_state.ts +++ b/packages/firestore/src/local/shared_client_state.ts @@ -462,13 +462,15 @@ export class SharedOnlineState { const validData = typeof onlineState === 'object' && + // @ts-ignore Should allow arbitrary string index when checking to see + // if that string is a valid enum value. OnlineState[onlineState.onlineState] !== undefined && 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 66536e81514..a5d91c73086 100644 --- a/packages/firestore/src/local/simple_db.ts +++ b/packages/firestore/src/local/simple_db.ts @@ -558,7 +558,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..162a036b456 100644 --- a/packages/firestore/src/platform_browser/webchannel_connection.ts +++ b/packages/firestore/src/platform_browser/webchannel_connection.ts @@ -21,6 +21,7 @@ import { EventType, WebChannel, XhrIo + // @ts-ignore } from '@firebase/webchannel-wrapper'; import { isReactNative } from '@firebase/util'; @@ -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' }; @@ -243,6 +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()) { + // @ts-ignore request['httpHeadersOverwriteParam'] = '$httpHeaders'; } @@ -345,7 +347,9 @@ export class WebChannelConnection implements Connection { // can be removed once the fix has been rolled out. const error = // tslint:disable-next-line:no-any msgData.error is not typed. - (msgData as any).error || (msgData[0] && msgData[0].error); + (msgData as any).error || + // @ts-ignore + (msgData[0] && msgData[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..8567cd87e48 100644 --- a/packages/firestore/src/platform_node/grpc_connection.ts +++ b/packages/firestore/src/platform_node/grpc_connection.ts @@ -86,6 +86,7 @@ export class GrpcConnection implements Connection { private cachedStub: GeneratedGrpcStub | null = null; constructor(protos: grpc.GrpcObject, private databaseInfo: DatabaseInfo) { + // @ts-ignore this.firestore = protos['google']['firestore']['v1']; } 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/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 d69787408f4..1094abdc91f 100644 --- a/packages/firestore/test/integration/api/database.test.ts +++ b/packages/firestore/test/integration/api/database.test.ts @@ -43,7 +43,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({ @@ -535,7 +535,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 7878f19dd54..166285ddbc4 100644 --- a/packages/firestore/test/integration/api/query.test.ts +++ b/packages/firestore/test/integration/api/query.test.ts @@ -37,7 +37,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 1759687c091..550261d6158 100644 --- a/packages/firestore/test/integration/api/validation.test.ts +++ b/packages/firestore/test/integration/api/validation.test.ts @@ -107,7 +107,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 f2f887fa218..14f6b0ff04f 100644 --- a/packages/firestore/test/integration/util/helpers.ts +++ b/packages/firestore/test/integration/util/helpers.ts @@ -132,7 +132,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..f359b6a937f 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,7 +311,7 @@ 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 => + return PersistencePromise.forEach(testMutations, (testMutation: DbMutationBatch) => store.put(testMutation) ); }); @@ -324,7 +325,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const store = txn.store( DbMutationBatch.store ); - let p = PersistencePromise.forEach(testMutations, testMutation => + let p = PersistencePromise.forEach(testMutations, (testMutation: DbMutationBatch) => store.get(testMutation.batchId).next(mutationBatch => { expect(mutationBatch).to.deep.equal(testMutation); }) @@ -424,9 +425,10 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbMutationQueue >(DbMutationQueue.store); // Manually populate the mutation queue and create all indicies. - return PersistencePromise.forEach(testMutations, testMutation => { + return PersistencePromise.forEach(testMutations, (testMutation: DbMutationBatch) => { return mutationBatchStore.put(testMutation).next(() => { - return PersistencePromise.forEach(testMutation.mutations, write => { + return PersistencePromise.forEach(testMutation.mutations, + (write: firestoreV1ApiClientInterfaces.Write) => { const indexKey = DbDocumentMutation.key( testMutation.userId, path(write.update!.name!, 5), @@ -509,7 +511,8 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const store = txn.store( DbRemoteDocument.store ); - return PersistencePromise.forEach(dbRemoteDocs, ({ dbKey, dbDoc }) => + return PersistencePromise.forEach(dbRemoteDocs, + ({ dbKey, dbDoc }: { dbKey: string[], dbDoc: DbRemoteDocument}) => store.put(dbKey, dbDoc) ); }); @@ -652,7 +655,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 +667,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 +687,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..15b61064a94 100644 --- a/packages/firestore/test/unit/local/test_remote_document_cache.ts +++ b/packages/firestore/test/unit/local/test_remote_document_cache.ts @@ -56,7 +56,7 @@ export abstract class TestRemoteDocumentCache { 'readwrite-primary', txn => { const changeBuffer = this.cache.newChangeBuffer(); - return PersistencePromise.forEach(maybeDocuments, maybeDocument => + return PersistencePromise.forEach(maybeDocuments, (maybeDocument: MaybeDocument) => changeBuffer.getEntry(txn, maybeDocument.key).next(() => {}) ).next(() => { for (const maybeDocument of maybeDocuments) { 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..49e9fa7dfc6 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,22 @@ 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,7 +202,8 @@ 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) => { + // @ts-ignore + window.addEventListener = (type: string, callback: WebStorageCallback) => { if (type === 'storage') { webStorageCallbacks.push(callback); } diff --git a/packages/firestore/test/unit/remote/node/serializer.test.ts b/packages/firestore/test/unit/remote/node/serializer.test.ts index 197226a534a..d7a651dc8af 100644 --- a/packages/firestore/test/unit/remote/node/serializer.test.ts +++ b/packages/firestore/test/unit/remote/node/serializer.test.ts @@ -156,6 +156,7 @@ describe('Serializer', () => { const actualProtobufjsProto: ProtobufJS.Message = ValueMessage.fromObject( actualJsonProto ); + // @ts-ignore expect(actualProtobufjsProto[valueType]).to.deep.equal(protobufJsValue); // Convert protobufjs back to JSON. 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..2ded6259fa3 100644 --- a/packages/firestore/test/util/equality_matcher.ts +++ b/packages/firestore/test/util/equality_matcher.ts @@ -24,11 +24,13 @@ import { use } from 'chai'; * implementation is used. */ -function customDeepEqual(left, right): boolean { +function customDeepEqual(left: unknown, right: unknown): boolean { /** * START: Custom compare logic */ + // @ts-ignore if (left && typeof left.isEqual === 'function') return left.isEqual(right); + // @ts-ignore if (right && typeof right.isEqual === 'function') return right.isEqual(left); /** * END: Custom compare logic @@ -44,18 +46,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 +69,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/logger/.eslintrc.json b/packages/logger/.eslintrc.json new file mode 100644 index 00000000000..2b39e9f6f85 --- /dev/null +++ b/packages/logger/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "../../config/.eslintrc.json", + "parserOptions": { + "project": "tsconfig.json" + } +} \ No newline at end of file diff --git a/packages/logger/index.ts b/packages/logger/index.ts index 536a8b4c720..7030f3bc850 100644 --- a/packages/logger/index.ts +++ b/packages/logger/index.ts @@ -17,7 +17,7 @@ import { instances, LogLevel } from './src/logger'; -export function setLogLevel(level: LogLevel) { +export function setLogLevel(level: LogLevel): void { instances.forEach(inst => { inst.logLevel = level; }); diff --git a/packages/logger/package.json b/packages/logger/package.json index 7c71abe27ff..021da45cd8e 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -10,9 +10,11 @@ "dist" ], "scripts": { + "lint": "eslint -c .eslintrc.json '**/*.ts' --ignore-path '../../.gitignore'", + "lint:fix": "eslint --fix -c .eslintrc.json '**/*.ts' --ignore-path '../../.gitignore'", "build": "rollup -c", "dev": "rollup -c -w", - "test": "run-p test:browser test:node", + "test": "run-p lint test:browser test:node", "test:browser": "karma start --single-run", "test:browser:debug": "karma start --browsers Chrome --auto-watch", "test:node": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha test/**/*.test.* --opts ../../config/mocha.node.opts", @@ -40,7 +42,11 @@ "ts-loader": "5.4.5", "ts-node": "8.1.0", "typescript": "3.4.5", - "webpack": "4.30.0" + "webpack": "4.30.0", + "eslint": "5.16.0", + "@typescript-eslint/parser": "1.9.0", + "@typescript-eslint/eslint-plugin": "1.9.0", + "@typescript-eslint/eslint-plugin-tslint": "1.9.0" }, "repository": { "directory": "packages/logger", diff --git a/packages/logger/src/logger.ts b/packages/logger/src/logger.ts index 7dbd1641707..c32d35a2e47 100644 --- a/packages/logger/src/logger.ts +++ b/packages/logger/src/logger.ts @@ -53,7 +53,7 @@ const defaultLogLevel: LogLevel = LogLevel.INFO; export type LogHandler = ( loggerInstance: Logger, logType: LogLevel, - ...args: any[] + ...args: unknown[] ) => void; /** @@ -61,8 +61,10 @@ export type LogHandler = ( * messages on to their corresponding console counterparts (if the log method * is supported by the current log level) */ -const defaultLogHandler: LogHandler = (instance, logType, ...args) => { - if (logType < instance.logLevel) return; +const defaultLogHandler: LogHandler = (instance, logType, ...args): void => { + if (logType < instance.logLevel) { + return; + } const now = new Date().toISOString(); switch (logType) { /** @@ -139,19 +141,19 @@ export class Logger { * The functions below are all based on the `console` interface */ - debug(...args: any[]) { + debug(...args: unknown[]): void { this._logHandler(this, LogLevel.DEBUG, ...args); } - log(...args: any[]) { + log(...args: unknown[]): void { this._logHandler(this, LogLevel.VERBOSE, ...args); } - info(...args: any[]) { + info(...args: unknown[]): void { this._logHandler(this, LogLevel.INFO, ...args); } - warn(...args: any[]) { + warn(...args: unknown[]): void { this._logHandler(this, LogLevel.WARN, ...args); } - error(...args: any[]) { + 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 fb2a2abea14..65afa4a0477 100644 --- a/packages/logger/test/logger.test.ts +++ b/packages/logger/test/logger.test.ts @@ -19,7 +19,6 @@ import { expect } from 'chai'; import { spy as Spy, SinonSpy } from 'sinon'; import { Logger, LogLevel } from '../src/logger'; import { setLogLevel } from '../index'; -import { debug } from 'util'; describe('@firebase/logger', () => { const message = 'Hello there!'; @@ -47,7 +46,7 @@ describe('@firebase/logger', () => { spies.errorSpy.restore(); }); - function testLog(message, channel, shouldLog) { + 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`. @@ -57,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/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/.eslintrc.json b/packages/util/.eslintrc.json new file mode 100644 index 00000000000..2b39e9f6f85 --- /dev/null +++ b/packages/util/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "../../config/.eslintrc.json", + "parserOptions": { + "project": "tsconfig.json" + } +} \ No newline at end of file diff --git a/packages/util/package.json b/packages/util/package.json index 913f02e2d4b..4fcdfe59382 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -11,9 +11,11 @@ "dist" ], "scripts": { + "lint": "eslint -c .eslintrc.json '**/*.ts' --ignore-path '../../.gitignore'", + "lint:fix": "eslint --fix -c .eslintrc.json '**/*.ts' --ignore-path '../../.gitignore'", "build": "rollup -c", "dev": "rollup -c -w", - "test": "run-p test:browser test:node", + "test": "run-p lint test:browser test:node", "test:browser": "karma start --single-run", "test:node": "TS_NODE_CACHE=NO TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha test/**/*.test.* --opts ../../config/mocha.node.opts", "prepare": "yarn build" @@ -43,7 +45,11 @@ "ts-loader": "5.4.5", "ts-node": "8.1.0", "typescript": "3.4.5", - "webpack": "4.30.0" + "webpack": "4.30.0", + "eslint": "5.16.0", + "@typescript-eslint/parser": "1.9.0", + "@typescript-eslint/eslint-plugin": "1.9.0", + "@typescript-eslint/eslint-plugin-tslint": "1.9.0" }, "repository": { "directory": "packages/util", diff --git a/packages/util/src/assert.ts b/packages/util/src/assert.ts index 72fc5a9f868..dc77d9fe232 100644 --- a/packages/util/src/assert.ts +++ b/packages/util/src/assert.ts @@ -20,7 +20,7 @@ import { CONSTANTS } from './constants'; /** * Throws an error if the provided assertion is falsy */ -export const assert = function(assertion: any, message: string) { +export const assert = function(assertion: unknown, message: string): void { if (!assertion) { throw assertionError(message); } diff --git a/packages/util/src/crypt.ts b/packages/util/src/crypt.ts index af73065a6d3..4b9f38fe374 100644 --- a/packages/util/src/crypt.ts +++ b/packages/util/src/crypt.ts @@ -15,21 +15,21 @@ * limitations under the License. */ -const stringToByteArray = function(str: string) { +const stringToByteArray = function(str: string): number[] { // TODO(user): Use native implementations if/when available - var out: number[] = [], - p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); + const out: number[] = []; + let p = 0; + for (let i = 0; i < str.length; i++) { + let c = str.charCodeAt(i); if (c < 128) { out[p++] = c; } else if (c < 2048) { out[p++] = (c >> 6) | 192; out[p++] = (c & 63) | 128; } else if ( - (c & 0xfc00) == 0xd800 && + (c & 0xfc00) === 0xd800 && i + 1 < str.length && - (str.charCodeAt(i + 1) & 0xfc00) == 0xdc00 + (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00 ) { // Surrogate Pair c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff); @@ -52,31 +52,31 @@ const stringToByteArray = function(str: string) { * @param bytes Array of numbers representing characters. * @return Stringification of the array. */ -const byteArrayToString = function(bytes: number[]) { +const byteArrayToString = function(bytes: number[]): string { // TODO(user): Use native implementations if/when available - var out: string[] = [], - pos = 0, + const out: string[] = []; + let pos = 0, c = 0; while (pos < bytes.length) { - var c1 = bytes[pos++]; + const c1 = bytes[pos++]; if (c1 < 128) { out[c++] = String.fromCharCode(c1); } else if (c1 > 191 && c1 < 224) { - var c2 = bytes[pos++]; + const c2 = bytes[pos++]; out[c++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); } else if (c1 > 239 && c1 < 365) { // Surrogate Pair - var c2 = bytes[pos++]; - var c3 = bytes[pos++]; - var c4 = bytes[pos++]; - var u = + const c2 = bytes[pos++]; + const c3 = bytes[pos++]; + const c4 = bytes[pos++]; + const u = (((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)) - 0x10000; out[c++] = String.fromCharCode(0xd800 + (u >> 10)); out[c++] = String.fromCharCode(0xdc00 + (u & 1023)); } else { - var c2 = bytes[pos++]; - var c3 = bytes[pos++]; + const c2 = bytes[pos++]; + const c3 = bytes[pos++]; out[c++] = String.fromCharCode( ((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63) ); @@ -154,34 +154,34 @@ export const base64 = { * * @param input An array of bytes (numbers with * value in [0, 255]) to encode. - * @param opt_webSafe Boolean indicating we should use the + * @param webSafe Boolean indicating we should use the * alternative alphabet. * @return The base64 encoded string. */ - encodeByteArray(input: number[] | Uint8Array, opt_webSafe?: boolean): string { + encodeByteArray(input: number[] | Uint8Array, webSafe?: boolean): string { if (!Array.isArray(input)) { throw Error('encodeByteArray takes an array as a parameter'); } this.init_(); - var byteToCharMap: number[] = opt_webSafe + const byteToCharMap: number[] = webSafe ? this.byteToCharMapWebSafe_ : this.byteToCharMap_; - var output: number[] = []; + const output: number[] = []; - for (var i = 0; i < input.length; i += 3) { - var byte1 = input[i]; - var haveByte2 = i + 1 < input.length; - var byte2 = haveByte2 ? input[i + 1] : 0; - var haveByte3 = i + 2 < input.length; - var byte3 = haveByte3 ? input[i + 2] : 0; + for (let i = 0; i < input.length; i += 3) { + const byte1 = input[i]; + const haveByte2 = i + 1 < input.length; + const byte2 = haveByte2 ? input[i + 1] : 0; + const haveByte3 = i + 2 < input.length; + const byte3 = haveByte3 ? input[i + 2] : 0; - var outByte1 = byte1 >> 2; - var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); - var outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6); - var outByte4 = byte3 & 0x3f; + const outByte1 = byte1 >> 2; + const outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); + let outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6); + let outByte4 = byte3 & 0x3f; if (!haveByte3) { outByte4 = 64; @@ -206,34 +206,34 @@ export const base64 = { * Base64-encode a string. * * @param input A string to encode. - * @param opt_webSafe If true, we should use the + * @param webSafe If true, we should use the * alternative alphabet. * @return The base64 encoded string. */ - encodeString(input: string, opt_webSafe?: boolean): string { + encodeString(input: string, webSafe?: boolean): string { // Shortcut for Mozilla browsers that implement // a native base64 encoder in the form of "btoa/atob" - if (this.HAS_NATIVE_SUPPORT && !opt_webSafe) { + if (this.HAS_NATIVE_SUPPORT && !webSafe) { return btoa(input); } - return this.encodeByteArray(stringToByteArray(input), opt_webSafe); + return this.encodeByteArray(stringToByteArray(input), webSafe); }, /** * Base64-decode a string. * * @param input to decode. - * @param opt_webSafe True if we should use the + * @param webSafe True if we should use the * alternative alphabet. * @return string representing the decoded value. */ - decodeString(input: string, opt_webSafe: boolean): string { + decodeString(input: string, webSafe: boolean): string { // Shortcut for Mozilla browsers that implement // a native base64 encoder in the form of "btoa/atob" - if (this.HAS_NATIVE_SUPPORT && !opt_webSafe) { + if (this.HAS_NATIVE_SUPPORT && !webSafe) { return atob(input); } - return byteArrayToString(this.decodeStringToByteArray(input, opt_webSafe)); + return byteArrayToString(this.decodeStringToByteArray(input, webSafe)); }, /** @@ -248,46 +248,46 @@ export const base64 = { * to one byte. If the group has three characters, it decodes to two bytes. * * @param input Input to decode. - * @param opt_webSafe True if we should use the web-safe alphabet. + * @param webSafe True if we should use the web-safe alphabet. * @return bytes representing the decoded value. */ - decodeStringToByteArray(input: string, opt_webSafe: boolean): number[] { + decodeStringToByteArray(input: string, webSafe: boolean): number[] { this.init_(); - var charToByteMap = opt_webSafe + const charToByteMap = webSafe ? this.charToByteMapWebSafe_ : this.charToByteMap_; - var output: number[] = []; + const output: number[] = []; - for (var i = 0; i < input.length; ) { - var byte1 = charToByteMap[input.charAt(i++)]; + for (let i = 0; i < input.length; ) { + const byte1 = charToByteMap[input.charAt(i++)]; - var haveByte2 = i < input.length; - var byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0; + const haveByte2 = i < input.length; + const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0; ++i; - var haveByte3 = i < input.length; - var byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64; + const haveByte3 = i < input.length; + const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64; ++i; - var haveByte4 = i < input.length; - var byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64; + const haveByte4 = i < input.length; + const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64; ++i; if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) { throw Error(); } - var outByte1 = (byte1 << 2) | (byte2 >> 4); + const outByte1 = (byte1 << 2) | (byte2 >> 4); output.push(outByte1); - if (byte3 != 64) { - var outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2); + if (byte3 !== 64) { + const outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2); output.push(outByte2); - if (byte4 != 64) { - var outByte3 = ((byte3 << 6) & 0xc0) | byte4; + if (byte4 !== 64) { + const outByte3 = ((byte3 << 6) & 0xc0) | byte4; output.push(outByte3); } } @@ -309,7 +309,7 @@ export const base64 = { this.charToByteMapWebSafe_ = {}; // We want quick mappings back and forth, so we precompute two maps. - for (var i = 0; i < this.ENCODED_VALS.length; i++) { + for (let i = 0; i < this.ENCODED_VALS.length; i++) { this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i); this.charToByteMap_[this.byteToCharMap_[i]] = i; this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i); diff --git a/packages/util/src/deepCopy.ts b/packages/util/src/deepCopy.ts index 2086b57f0c3..0f64fede639 100644 --- a/packages/util/src/deepCopy.ts +++ b/packages/util/src/deepCopy.ts @@ -19,7 +19,7 @@ * Do a deep-copy of basic JavaScript Objects or Arrays. */ export function deepCopy(value: T): T { - return deepExtend(undefined, value); + return deepExtend(undefined, value) as T; } /** @@ -34,7 +34,7 @@ export function deepCopy(value: T): T { * Note that the target can be a function, in which case the properties in * the source Object are copied onto it as static properties of the Function. */ -export function deepExtend(target: any, source: any): any { +export function deepExtend(target: unknown, source: unknown): unknown { if (!(source instanceof Object)) { return source; } @@ -43,7 +43,7 @@ export function deepExtend(target: any, source: any): any { case Date: // Treat Dates like scalars; if the target date object had any child // properties - they will be lost! - let dateValue = (source as any) as Date; + const dateValue = source as Date; return new Date(dateValue.getTime()); case Object: @@ -62,17 +62,15 @@ export function deepExtend(target: any, source: any): any { return source; } - for (let prop in source) { + for (const prop in source) { if (!source.hasOwnProperty(prop)) { continue; } - target[prop] = deepExtend(target[prop], source[prop]); + (target as { [key: string]: unknown })[prop] = deepExtend( + (target as { [key: string]: unknown })[prop], + (source as { [key: string]: unknown })[prop] + ); } return target; } - -// TODO: Really needed (for JSCompiler type checking)? -export function patchProperty(obj: any, prop: string, value: any) { - obj[prop] = value; -} diff --git a/packages/util/src/deferred.ts b/packages/util/src/deferred.ts index 1e4cb082bff..4a3d9a24c19 100644 --- a/packages/util/src/deferred.ts +++ b/packages/util/src/deferred.ts @@ -17,8 +17,8 @@ export class Deferred { promise: Promise; - reject: (value?: R | PromiseLike | Error ) => void; - resolve: (value?: R | PromiseLike) => void; + reject: (value?: unknown) => void; + resolve: (value?: unknown) => void; constructor() { this.promise = new Promise((resolve, reject) => { this.resolve = resolve; @@ -31,7 +31,7 @@ export class Deferred { * 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. */ - wrapCallback(callback?: (error?: Error, value?: any) => void): (error: Error, value?: any) => 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/errors.ts b/packages/util/src/errors.ts index d8ffa258bd0..1891a27592d 100644 --- a/packages/util/src/errors.ts +++ b/packages/util/src/errors.ts @@ -54,7 +54,6 @@ * } * } */ -import { isEmpty } from './obj'; export type ErrorMap = { readonly [K in ErrorCode]: string diff --git a/packages/util/src/json.ts b/packages/util/src/json.ts index 010a726c072..67844c6abd0 100644 --- a/packages/util/src/json.ts +++ b/packages/util/src/json.ts @@ -21,7 +21,7 @@ * @param {string} str A string containing JSON. * @return {*} The javascript object representing the specified JSON. */ -export function jsonEval(str: string): { [key: string]: any } { +export function jsonEval(str: string): unknown { return JSON.parse(str); } @@ -30,6 +30,6 @@ export function jsonEval(str: string): { [key: string]: any } { * @param {*} data Javascript object to be stringified. * @return {string} The JSON contents of the object. */ -export function stringify(data: any): string { +export function stringify(data: unknown): string { return JSON.stringify(data); } diff --git a/packages/util/src/jwt.ts b/packages/util/src/jwt.ts index 23fc515e587..6a51b16c3db 100644 --- a/packages/util/src/jwt.ts +++ b/packages/util/src/jwt.ts @@ -18,36 +18,42 @@ import { base64Decode } from './crypt'; import { jsonEval } from './json'; +interface Claims { [key: string]: object | number | string | boolean }; + +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: string): {} { - var header = {}, - claims = {}, +export const decode = function(token: string): DecodedToken { + let header = {}, + claims: Claims = {}, data = {}, signature = ''; try { - var parts = token.split('.'); - header = jsonEval(base64Decode(parts[0]) || ''); - claims = jsonEval(base64Decode(parts[1]) || ''); + const parts = token.split('.'); + header = jsonEval(base64Decode(parts[0]) || '') as object; + claims = jsonEval(base64Decode(parts[1]) || '') as Claims; signature = parts[2]; data = claims['d'] || {}; delete claims['d']; } catch (e) {} return { - header: header, - claims: claims, - data: data, - signature: signature + header, + claims, + data, + signature }; }; @@ -58,25 +64,21 @@ export const decode = function(token: string): {} { * 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) { - var claims = decode(token).claims, - now = Math.floor(new Date().getTime() / 1000), - 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; @@ -84,7 +86,7 @@ export const isValidTimestamp = function(token) { } return ( - now && validSince && validUntil && now >= validSince && now <= validUntil + !!now && !!validSince && !!validUntil && now >= validSince && now <= validUntil ); }; @@ -94,14 +96,11 @@ export const isValidTimestamp = function(token) { * 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) { - var 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 | null; } return null; }; @@ -112,12 +111,9 @@ export const issuedAtTime = function(token) { * 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) { - var decoded = decode(token), +export const isValidFormat = function(token: string): boolean { + const decoded = decode(token), claims = decoded.claims; return !!claims && typeof claims === 'object' && claims.hasOwnProperty('iat'); @@ -129,11 +125,8 @@ export const isValidFormat = function(token) { * 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) { - var 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 c9198043f52..ea3c62f42d6 100644 --- a/packages/util/src/obj.ts +++ b/packages/util/src/obj.ts @@ -15,13 +15,20 @@ * limitations under the License. */ -// See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ +/* eslint-disable */ +// will enable after https://github.com/firebase/firebase-js-sdk/pull/1811 is merged + +interface UtilObject { + [key: string]: V; + [index: number]: V; +} -export const contains = function(obj, key) { +// See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ +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. }; @@ -33,8 +40,8 @@ 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]); } @@ -47,7 +54,7 @@ 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; }); @@ -59,29 +66,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++; @@ -89,36 +93,36 @@ 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]; @@ -135,7 +139,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 20805316ffa..8e4a242eb89 100644 --- a/packages/util/src/query.ts +++ b/packages/util/src/query.ts @@ -21,15 +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) { - var params: string[] = []; - forEach(querystringParams, function(key, value) { +export const querystring = function(querystringParams: { [key: string]: string }): string { + const params: string[] = []; + forEach(querystringParams, (key: string, value) => { if (Array.isArray(value)) { - value.forEach(function(arrayVal) { + value.forEach(arrayVal => { params.push( encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal) ); @@ -47,13 +44,13 @@ export const querystring = function(querystringParams) { * @param {string} querystring * @return {!Object} */ -export const querystringDecode = function(querystring) { - var obj = {}; - var tokens = querystring.replace(/^\?/, '').split('&'); +export const querystringDecode = function(querystring: string): object { + const obj: { [key: string]: unknown } = {}; + const tokens = querystring.replace(/^\?/, '').split('&'); - tokens.forEach(function(token) { + tokens.forEach(token => { if (token) { - var key = token.split('='); + const key = token.split('='); obj[key[0]] = key[1]; } }); diff --git a/packages/util/src/sha1.ts b/packages/util/src/sha1.ts index e80e88431fc..e8d93079d8b 100644 --- a/packages/util/src/sha1.ts +++ b/packages/util/src/sha1.ts @@ -82,14 +82,14 @@ export class Sha1 { this.blockSize = 512 / 8; this.pad_[0] = 128; - for (var i = 1; i < this.blockSize; ++i) { + for (let i = 1; i < this.blockSize; ++i) { this.pad_[i] = 0; } this.reset(); } - reset() { + reset(): void { this.chain_[0] = 0x67452301; this.chain_[1] = 0xefcdab89; this.chain_[2] = 0x98badcfe; @@ -103,19 +103,19 @@ export class Sha1 { /** * Internal compress helper function. * @param {!number[]|!Uint8Array|string} buf Block to compress. - * @param {number=} opt_offset Offset of the block in the buffer. + * @param {number=} offset Offset of the block in the buffer. * @private */ - compress_(buf, opt_offset?) { - if (!opt_offset) { - opt_offset = 0; + compress_(buf: number[] | Uint8Array | string, offset?: number): void { + if (!offset) { + offset = 0; } - var W = this.W_; + const W = this.W_; // get 16 big endian words if (typeof buf === 'string') { - for (var i = 0; i < 16; i++) { + for (let i = 0; i < 16; i++) { // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS // have a bug that turns the post-increment ++ operator into pre-increment // during JIT compilation. We have code that depends heavily on SHA-1 for @@ -125,38 +125,38 @@ 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(opt_offset) << 24) | - (buf.charCodeAt(opt_offset + 1) << 16) | - (buf.charCodeAt(opt_offset + 2) << 8) | - buf.charCodeAt(opt_offset + 3); - opt_offset += 4; + (buf.charCodeAt(offset) << 24) | + (buf.charCodeAt(offset + 1) << 16) | + (buf.charCodeAt(offset + 2) << 8) | + buf.charCodeAt(offset + 3); + offset += 4; } } else { - for (var i = 0; i < 16; i++) { + for (let i = 0; i < 16; i++) { W[i] = - (buf[opt_offset] << 24) | - (buf[opt_offset + 1] << 16) | - (buf[opt_offset + 2] << 8) | - buf[opt_offset + 3]; - opt_offset += 4; + (buf[offset] << 24) | + (buf[offset + 1] << 16) | + (buf[offset + 2] << 8) | + buf[offset + 3]; + offset += 4; } } // expand to 80 words - for (var i = 16; i < 80; i++) { - var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + for (let i = 16; i < 80; i++) { + const t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff; } - var a = this.chain_[0]; - var b = this.chain_[1]; - var c = this.chain_[2]; - var d = this.chain_[3]; - var e = this.chain_[4]; - var f, k; + let a = this.chain_[0]; + let b = this.chain_[1]; + let c = this.chain_[2]; + let d = this.chain_[3]; + let e = this.chain_[4]; + let f, k; // TODO(user): Try to unroll this loop to speed up the computation. - for (var i = 0; i < 80; i++) { + for (let i = 0; i < 80; i++) { if (i < 40) { if (i < 20) { f = d ^ (b & (c ^ d)); @@ -175,7 +175,7 @@ export class Sha1 { } } - var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff; + const t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff; e = d; d = c; c = ((b << 30) | (b >>> 2)) & 0xffffffff; @@ -190,29 +190,29 @@ export class Sha1 { this.chain_[4] = (this.chain_[4] + e) & 0xffffffff; } - update(bytes, opt_length?) { + update(bytes?: number[] | Uint8Array | string, length?: number): void { // TODO(johnlenz): tighten the function signature and remove this check if (bytes == null) { return; } - if (opt_length === undefined) { - opt_length = bytes.length; + if (length === undefined) { + length = bytes.length; } - var lengthMinusBlock = opt_length - this.blockSize; - var n = 0; + const lengthMinusBlock = length - this.blockSize; + let n = 0; // Using local instead of member variables gives ~5% speedup on Firefox 16. - var buf = this.buf_; - var inbuf = this.inbuf_; + const buf = this.buf_; + let inbuf = this.inbuf_; // The outer while loop should execute at most twice. - while (n < opt_length) { + 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 // the data is provided in large chunks (or in multiples of 64 bytes). - if (inbuf == 0) { + if (inbuf === 0) { while (n <= lengthMinusBlock) { this.compress_(bytes, n); n += this.blockSize; @@ -220,11 +220,11 @@ export class Sha1 { } if (typeof bytes === 'string') { - while (n < opt_length) { + while (n < length) { buf[inbuf] = bytes.charCodeAt(n); ++inbuf; ++n; - if (inbuf == this.blockSize) { + if (inbuf === this.blockSize) { this.compress_(buf); inbuf = 0; // Jump to the outer loop so we use the full-block optimization. @@ -232,11 +232,11 @@ export class Sha1 { } } } else { - while (n < opt_length) { + while (n < length) { buf[inbuf] = bytes[n]; ++inbuf; ++n; - if (inbuf == this.blockSize) { + if (inbuf === this.blockSize) { this.compress_(buf); inbuf = 0; // Jump to the outer loop so we use the full-block optimization. @@ -247,13 +247,13 @@ export class Sha1 { } this.inbuf_ = inbuf; - this.total_ += opt_length; + this.total_ += length; } /** @override */ - digest() { - var digest: number[] = []; - var totalBits = this.total_ * 8; + digest(): number[] { + const digest: number[] = []; + let totalBits = this.total_ * 8; // Add pad 0x80 0x00*. if (this.inbuf_ < 56) { @@ -263,16 +263,16 @@ export class Sha1 { } // Add # bits. - for (var i = this.blockSize - 1; i >= 56; i--) { + for (let i = this.blockSize - 1; i >= 56; i--) { this.buf_[i] = totalBits & 255; totalBits /= 256; // Don't use bit-shifting here! } this.compress_(this.buf_); - var n = 0; - for (var i = 0; i < 5; i++) { - for (var j = 24; j >= 0; j -= 8) { + let n = 0; + for (let i = 0; i < 5; i++) { + for (let j = 24; j >= 0; j -= 8) { digest[n] = (this.chain_[i] >> j) & 255; ++n; } diff --git a/packages/util/src/subscribe.ts b/packages/util/src/subscribe.ts index f1c19aa5c44..21181574a70 100644 --- a/packages/util/src/subscribe.ts +++ b/packages/util/src/subscribe.ts @@ -62,7 +62,7 @@ export function createSubscribe( executor: Executor, onNoObservers?: Executor ): Subscribe { - let proxy = new ObserverProxy(executor, onNoObservers); + const proxy = new ObserverProxy(executor, onNoObservers); return proxy.subscribe.bind(proxy); } @@ -99,20 +99,20 @@ class ObserverProxy implements Observer { }); } - next(value: T) { + next(value: T): void { this.forEachObserver((observer: Observer) => { observer.next(value); }); } - error(error: Error) { + error(error: Error): void { this.forEachObserver((observer: Observer) => { observer.error(error); }); this.close(error); } - complete() { + complete(): void { this.forEachObserver((observer: Observer) => { observer.complete(); }); @@ -145,9 +145,9 @@ class ObserverProxy implements Observer { observer = nextOrObserver as Observer; } else { observer = { - next: (nextOrObserver as any) as NextFn, - error: error, - complete: complete + next: nextOrObserver as NextFn, + error, + complete } as Observer; } @@ -161,12 +161,13 @@ class ObserverProxy implements Observer { observer.complete = noop as CompleteFn; } - let unsub = this.unsubscribeOne.bind(this, this.observers!.length); + const unsub = this.unsubscribeOne.bind(this, this.observers!.length); // Attempt to subscribe to a terminated Observable - we // just respond to the Observer with the final error or complete // event. if (this.finalized) { + // tslint:disable-next-line:no-floating-promises this.task.then(() => { try { if (this.finalError) { @@ -188,7 +189,7 @@ class ObserverProxy implements Observer { // Unsubscribe is synchronous - we guarantee that no events are sent to // any unsubscribed Observer. - private unsubscribeOne(i: number) { + private unsubscribeOne(i: number): void { if (this.observers === undefined || this.observers[i] === undefined) { return; } @@ -219,6 +220,7 @@ class ObserverProxy implements Observer { // function had been queued. private sendOne(i: number, fn: (observer: Observer) => void): void { // Execute the callback asynchronously + // tslint:disable-next-line:no-floating-promises this.task.then(() => { if (this.observers !== undefined && this.observers[i] !== undefined) { try { @@ -244,6 +246,7 @@ class ObserverProxy implements Observer { this.finalError = err; } // Proxy is no longer needed - garbage collect references + // tslint:disable-next-line:no-floating-promises this.task.then(() => { this.observers = undefined; this.onNoObservers = undefined; @@ -253,7 +256,7 @@ class ObserverProxy implements Observer { /** Turn synchronous function into one called asynchronously. */ export function async(fn: Function, onError?: ErrorFn): Function { - return (...args: any[]) => { + return (...args: unknown[]) => { Promise.resolve(true) .then(() => { fn(...args); @@ -269,12 +272,12 @@ export function async(fn: Function, onError?: ErrorFn): Function { /** * Return true if the object passed in implements any of the named methods. */ -function implementsAnyMethods(obj: any, methods: string[]): boolean { +function implementsAnyMethods(obj: { [key: string]: unknown }, methods: string[]): boolean { if (typeof obj !== 'object' || obj === null) { return false; } - for (let method of methods) { + for (const method of methods) { if (method in obj && typeof obj[method] === 'function') { return true; } diff --git a/packages/util/src/utf8.ts b/packages/util/src/utf8.ts index 80d018930ce..4431727cf28 100644 --- a/packages/util/src/utf8.ts +++ b/packages/util/src/utf8.ts @@ -32,18 +32,18 @@ import { assert } from './assert'; * @param {string} str * @return {Array} */ -export const stringToByteArray = function(str) { - var out: number[] = [], - p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); +export const stringToByteArray = function(str: string): number[] { + const out: number[] = []; + let p = 0; + for (let i = 0; i < str.length; i++) { + let c = str.charCodeAt(i); // Is this the lead surrogate in a surrogate pair? if (c >= 0xd800 && c <= 0xdbff) { - var high = c - 0xd800; // the high 10 bits. + const high = c - 0xd800; // the high 10 bits. i++; assert(i < str.length, 'Surrogate pair missing trail surrogate.'); - var low = str.charCodeAt(i) - 0xdc00; // the low 10 bits. + const low = str.charCodeAt(i) - 0xdc00; // the low 10 bits. c = 0x10000 + (high << 10) + low; } @@ -71,10 +71,10 @@ export const stringToByteArray = function(str) { * @param {string} str * @return {number} */ -export const stringLength = function(str) { - var p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); +export const stringLength = function(str: string): number { + let p = 0; + for (let i = 0; i < str.length; i++) { + const c = str.charCodeAt(i); if (c < 128) { p++; } else if (c < 2048) { diff --git a/packages/util/src/validation.ts b/packages/util/src/validation.ts index 6380555c3d7..0cbe72a7ca1 100644 --- a/packages/util/src/validation.ts +++ b/packages/util/src/validation.ts @@ -19,20 +19,25 @@ * 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) { - var argError; +export const validateArgCount = function( + fnName: string, + minCount: number, + maxCount: number, + argCount: number +): void { + let argError; if (argCount < minCount) { argError = 'at least ' + minCount; } else if (argCount > maxCount) { argError = maxCount === 0 ? 'none' : 'no more than ' + maxCount; } if (argError) { - var error = + const error = fnName + ' failed: Was called with ' + argCount + @@ -47,13 +52,13 @@ export const validateArgCount = function(fnName, minCount, maxCount, argCount) { /** * 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) { - var argName = ''; +export function errorPrefix(fnName: string, argumentNumber: number, optional: boolean): string { + let argName = ''; switch (argumentNumber) { case 1: argName = optional ? 'first' : 'First'; @@ -73,20 +78,27 @@ export function errorPrefix(fnName, argumentNumber, optional) { ); } - var error = fnName + ' failed: '; + let error = fnName + ' failed: '; error += argName + ' argument '; return error; } /** - * @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) { - if (optional && !namespace) return; +export function validateNamespace( + fnName: string, + argumentNumber: number, + namespace: string, + optional: boolean +): void { + if (optional && !namespace) { + return; + } if (typeof namespace !== 'string') { //TODO: I should do more validation here. We only allow certain chars in namespaces. throw new Error( @@ -96,25 +108,36 @@ export function validateNamespace(fnName, argumentNumber, namespace, optional) { } } -export function validateCallback(fnName, argumentNumber, callback, optional) { - if (optional && !callback) return; - if (typeof callback !== 'function') +export function validateCallback( + fnName: string, + argumentNumber: number, + callback: Function, + optional: boolean +): void { + if (optional && !callback) { + return; + } + if (typeof callback !== 'function') { throw new Error( errorPrefix(fnName, argumentNumber, optional) + 'must be a valid function.' ); + } } export function validateContextObject( - fnName, - argumentNumber, - context, - optional -) { - if (optional && !context) return; - if (typeof context !== 'object' || context === null) + fnName: string, + argumentNumber: number, + context: unknown, + optional: boolean +): void { + if (optional && !context) { + return; + } + if (typeof context !== 'object' || context === null) { throw new Error( errorPrefix(fnName, argumentNumber, optional) + 'must be a valid context object.' ); + } } diff --git a/packages/util/test/base64.test.ts b/packages/util/test/base64.test.ts index 735a9e6f4f1..1a4f2bfeb7d 100644 --- a/packages/util/test/base64.test.ts +++ b/packages/util/test/base64.test.ts @@ -19,7 +19,7 @@ import { base64Encode, base64Decode } from '../src/crypt'; describe('base64', () => { it('bijective', () => { - let cases = ['$', '¢', '€', '𐍈']; // 1, 2, 3, and 4 byte characters + const cases = ['$', '¢', '€', '𐍈']; // 1, 2, 3, and 4 byte characters cases.forEach(str => { assert.strictEqual(base64Decode(base64Encode(str)), str); }); diff --git a/packages/util/test/deepCopy.test.ts b/packages/util/test/deepCopy.test.ts index 88af4cf36f3..282152aadd6 100644 --- a/packages/util/test/deepCopy.test.ts +++ b/packages/util/test/deepCopy.test.ts @@ -25,7 +25,7 @@ describe('deepCopy()', () => { }); it('Date', () => { - let d = new Date(); + const d = new Date(); assert.deepEqual(deepCopy(d), d); }); @@ -50,7 +50,7 @@ describe('deepExtend', () => { }); it('Date', () => { - let d = new Date(); + const d = new Date(); assert.deepEqual(deepExtend(new Date(), d), d); }); @@ -73,8 +73,8 @@ describe('deepExtend', () => { }); it('Array is copied - not referenced', () => { - let o1 = { a: [1] }; - let o2 = { a: [2] }; + const o1 = { a: [1] }; + const o2 = { a: [2] }; assert.deepEqual(deepExtend(o1, o2), { a: [2] }); o2.a.push(3); @@ -82,17 +82,17 @@ describe('deepExtend', () => { }); it('Array with undefined elements', () => { - let a: any = []; + const a: any = []; a[3] = '3'; - let b = deepExtend(undefined, a); + const b = deepExtend(undefined, a); assert.deepEqual(b, [, , , '3']); }); it('Function', () => { - let source: any = () => { + const source: any = (): void => { /*_*/ }; - let target: any = deepExtend( + const target: any = deepExtend( { a: () => { /*_*/ diff --git a/packages/util/test/errors.test.ts b/packages/util/test/errors.test.ts index 9b922018421..4d51bf01c6a 100644 --- a/packages/util/test/errors.test.ts +++ b/packages/util/test/errors.test.ts @@ -121,10 +121,10 @@ describe('FirebaseError', () => { }); }); -function dummy1() { +function dummy1(): void { dummy2(); } -function dummy2() { +function dummy2(): void { throw ERROR_FACTORY.create('generic-error'); } diff --git a/packages/util/test/subscribe.test.ts b/packages/util/test/subscribe.test.ts index 42b6852f9fc..01547d8f70e 100644 --- a/packages/util/test/subscribe.test.ts +++ b/packages/util/test/subscribe.test.ts @@ -17,18 +17,9 @@ import { assert } from 'chai'; import * as sinon from 'sinon'; -import { - async, - CompleteFn, - createSubscribe, - ErrorFn, - NextFn, - Observer, - Subscribe, - Unsubscribe -} from '../src/subscribe'; +import { async, createSubscribe, Observer, Subscribe } from '../src/subscribe'; -describe('createSubscribe', function() { +describe('createSubscribe', () => { let spy: any; beforeEach(() => { // Listen to console.error calls. @@ -40,11 +31,11 @@ describe('createSubscribe', function() { }); it('Creation', done => { - let subscribe = createSubscribe((observer: Observer) => { + const subscribe = createSubscribe((observer: Observer) => { observer.next(123); }); - let unsub = subscribe((value: number) => { + const unsub = subscribe((value: number) => { unsub(); assert.equal(value, 123); done(); @@ -52,8 +43,8 @@ describe('createSubscribe', function() { }); it('Logging observer error to console', done => { - let uncatchableError = new Error('uncatchable'); - let subscribe = createSubscribe((observer: Observer) => { + const uncatchableError = new Error('uncatchable'); + const subscribe = createSubscribe((observer: Observer) => { observer.next(123); observer.complete(); }); @@ -74,18 +65,18 @@ describe('createSubscribe', function() { }); it('Well-defined subscription order', done => { - let subscribe = createSubscribe(observer => { + const subscribe = createSubscribe(observer => { observer.next(123); // Subscription after value emitted should NOT be received. subscribe({ - next(value) { + next(_value) { assert.ok(false); } }); }); // Subscription before value emitted should be recieved. subscribe({ - next(value) { + next(_value) { done(); } }); @@ -93,7 +84,7 @@ describe('createSubscribe', function() { it('Subscribing to already complete Subscribe', done => { let seq = 0; - let subscribe = createSubscribe(observer => { + const subscribe = createSubscribe(observer => { observer.next(456); observer.complete(); }); @@ -115,7 +106,7 @@ describe('createSubscribe', function() { it('Subscribing to errored Subscribe', done => { let seq = 0; - let subscribe = createSubscribe(observer => { + const subscribe = createSubscribe(observer => { observer.next(246); observer.error(new Error('failure')); }); @@ -127,7 +118,7 @@ describe('createSubscribe', function() { error(e) { assert.equal(seq++, 1); subscribe({ - error(e2) { + error(_e2) { assert.equal(seq++, 2); assert.equal(e.message, 'failure'); done(); @@ -141,7 +132,7 @@ describe('createSubscribe', function() { }); it('Delayed value', done => { - let subscribe = createSubscribe((observer: Observer) => { + const subscribe = createSubscribe((observer: Observer) => { setTimeout(() => observer.next(123), 10); }); @@ -155,7 +146,7 @@ describe('createSubscribe', function() { // It's an application error to throw an exception in the executor - // but since it is called asynchronously, our only option is // to emit that Error and terminate the Subscribe. - let subscribe = createSubscribe((observer: Observer) => { + const subscribe = createSubscribe((_observer: Observer) => { throw new Error('Executor throws'); }); subscribe({ @@ -166,7 +157,7 @@ describe('createSubscribe', function() { }); it('Sequence', done => { - let subscribe = makeCounter(10); + const subscribe = makeCounter(10); let j = 1; subscribe({ @@ -181,7 +172,7 @@ describe('createSubscribe', function() { }); it('unlisten', done => { - let subscribe = makeCounter(10); + const subscribe = makeCounter(10); subscribe({ complete: () => { @@ -190,7 +181,7 @@ describe('createSubscribe', function() { }); let j = 1; - let unsub = subscribe({ + const unsub = subscribe({ next: (value: number) => { assert.ok(value <= 5); assert.equal(value, j++); @@ -205,10 +196,10 @@ describe('createSubscribe', function() { }); it('onNoObservers', done => { - let subscribe = makeCounter(10); + const subscribe = makeCounter(10); let j = 1; - let unsub = subscribe({ + const unsub = subscribe({ next: (value: number) => { assert.ok(value <= 5); assert.equal(value, j++); @@ -225,9 +216,9 @@ describe('createSubscribe', function() { // TODO(koss): Add test for partial Observer (missing methods). it('Partial Observer', done => { - let subscribe = makeCounter(10); + const subscribe = makeCounter(10); - let unsub = subscribe({ + const _unsub = subscribe({ complete: () => { done(); } @@ -252,7 +243,7 @@ function makeCounter(maxCount: number, ms = 10): Subscribe { } }, ms); }, - (observer: Observer) => { + (_observer: Observer) => { clearInterval(id); id = undefined; } From b553168b00e9fd0dd949a9a41264c1cc0f2375f2 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 10 Jun 2019 13:27:25 -0700 Subject: [PATCH 03/15] [AUTOMATED]: Prettier Code Styling --- packages/app/test/firebaseApp.test.ts | 5 +- packages/database/index.node.ts | 6 +- .../database/src/core/PersistentConnection.ts | 13 +++-- packages/database/src/core/snap/snap.ts | 3 +- .../firestore/src/core/firestore_client.ts | 8 ++- packages/firestore/src/core/sync_engine.ts | 4 +- .../src/local/indexeddb_mutation_queue.ts | 12 +++- .../src/local/indexeddb_persistence.ts | 10 +++- .../firestore/src/local/indexeddb_schema.ts | 25 +++++---- packages/firestore/src/local/local_store.ts | 31 ++++++----- .../firestore/src/local/memory_persistence.ts | 25 +++++---- .../unit/local/indexeddb_persistence.test.ts | 55 +++++++++++-------- .../unit/local/test_remote_document_cache.ts | 6 +- .../web_storage_shared_client_state.test.ts | 5 +- packages/functions/index.node.ts | 5 +- packages/functions/index.ts | 5 +- packages/storage/index.ts | 5 +- packages/util/src/deferred.ts | 4 +- packages/util/src/jwt.ts | 13 ++++- packages/util/src/obj.ts | 33 +++++++++-- packages/util/src/query.ts | 4 +- packages/util/src/subscribe.ts | 5 +- packages/util/src/validation.ts | 6 +- 23 files changed, 194 insertions(+), 94 deletions(-) diff --git a/packages/app/test/firebaseApp.test.ts b/packages/app/test/firebaseApp.test.ts index ac5c319b435..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: string, firebaseNamespaceFactory: () => FirebaseNamespace): 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 56f35475048..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: FirebaseApp, url: string, 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 772d2c6fecd..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: { [key: string]: ListenSpec }) => { - 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/snap.ts b/packages/database/src/core/snap/snap.ts index 0625229929b..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 as {[key:string]: unknown}, '.sv')), + (typeof val === 'object' && + contains(val as { [key: string]: unknown }, '.sv')), 'Priority must be a string or number.' ); } else { diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index 1918138591a..db7ca678107 100644 --- a/packages/firestore/src/core/firestore_client.ts +++ b/packages/firestore/src/core/firestore_client.ts @@ -429,12 +429,16 @@ export class FirestoreClient { serializer ); - const remoteStoreOnlineStateChangedHandler = (onlineState: OnlineState) => + const remoteStoreOnlineStateChangedHandler = ( + onlineState: OnlineState + ) => this.syncEngine.applyOnlineStateChange( onlineState, OnlineStateSource.RemoteStore ); - const sharedClientStateOnlineStateChangedHandler = (onlineState: 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 342e9324cd0..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[Number(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 dfc29773035..21394698e57 100644 --- a/packages/firestore/src/local/indexeddb_mutation_queue.ts +++ b/packages/firestore/src/local/indexeddb_mutation_queue.ts @@ -478,9 +478,15 @@ export class IndexedDbMutationQueue implements MutationQueue { batch ).next(removedDocuments => { this.removeCachedMutationKeys(batch.batchId); - return PersistencePromise.forEach(removedDocuments, (key: DocumentKey) => { - 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 a2f720d4c60..aaa87e78059 100644 --- a/packages/firestore/src/local/indexeddb_persistence.ts +++ b/packages/firestore/src/local/indexeddb_persistence.ts @@ -515,8 +515,10 @@ export class IndexedDbPersistence implements Persistence { }) .next(() => // Delete metadata for clients that are no longer considered active. - PersistencePromise.forEach(inactiveClients, (inactiveClient: DbClientMetadata) => - 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: SimpleDbTransaction): PersistencePromise { + private acquireOrExtendPrimaryLease( + txn: SimpleDbTransaction + ): PersistencePromise { const newPrimary = new DbPrimaryClient( this.clientId, this.allowTabSynchronization, diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index 1e5f4c3221a..a6c72de035e 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -171,17 +171,20 @@ export class SchemaConverter implements SimpleDbSchemaConverter { return mutationsStore .loadAll(DbMutationBatch.userMutationsIndex, range) .next(dbBatches => { - 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( - () => {} - ); - }); + 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( + () => {} + ); + } + ); }); }); }); diff --git a/packages/firestore/src/local/local_store.ts b/packages/firestore/src/local/local_store.ts index ed1879e6041..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: 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) - ); - }); + 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) + ); + } + ); } ); } diff --git a/packages/firestore/src/local/memory_persistence.ts b/packages/firestore/src/local/memory_persistence.ts index c7e07df20c3..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: 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(); - }); - }); + 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/test/unit/local/indexeddb_persistence.test.ts b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts index f359b6a937f..2e5a73edbc7 100644 --- a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts +++ b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts @@ -311,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: DbMutationBatch) => - store.put(testMutation) + return PersistencePromise.forEach( + testMutations, + (testMutation: DbMutationBatch) => store.put(testMutation) ); }); }).then(() => @@ -325,10 +326,12 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const store = txn.store( DbMutationBatch.store ); - let p = PersistencePromise.forEach(testMutations, (testMutation: DbMutationBatch) => - 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 @@ -425,22 +428,27 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbMutationQueue >(DbMutationQueue.store); // Manually populate the mutation queue and create all indicies. - 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 + 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, '')), @@ -511,9 +519,10 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const store = txn.store( DbRemoteDocument.store ); - return PersistencePromise.forEach(dbRemoteDocs, - ({ dbKey, dbDoc }: { dbKey: string[], dbDoc: DbRemoteDocument}) => - store.put(dbKey, dbDoc) + return PersistencePromise.forEach( + dbRemoteDocs, + ({ dbKey, dbDoc }: { dbKey: string[]; dbDoc: DbRemoteDocument }) => + store.put(dbKey, dbDoc) ); }); }); 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 15b61064a94..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: 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 49e9fa7dfc6..6b173f85cca 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 @@ -178,7 +178,10 @@ describe('WebStorageSharedClientState', () => { newValue: string | null; } - type WebStorageCallback = (this: unknown, event: WebStorageOptions) => unknown; + type WebStorageCallback = ( + this: unknown, + event: WebStorageOptions + ) => unknown; let webStorageCallbacks: WebStorageCallback[] = []; diff --git a/packages/functions/index.node.ts b/packages/functions/index.node.ts index c324b3ca708..ad422b7d557 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, _FirebaseNamespace } from '@firebase/app-types/private'; +import { + FirebaseServiceFactory, + _FirebaseNamespace +} from '@firebase/app-types/private'; import { Service } from './src/api/service'; import 'isomorphic-fetch'; diff --git a/packages/functions/index.ts b/packages/functions/index.ts index cab6412484a..7acbcaac3f2 100644 --- a/packages/functions/index.ts +++ b/packages/functions/index.ts @@ -16,7 +16,10 @@ */ import firebase from '@firebase/app'; import * as app_types from '@firebase/app-types'; -import { FirebaseServiceFactory, _FirebaseNamespace } 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'; diff --git a/packages/storage/index.ts b/packages/storage/index.ts index 107f5f779c3..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, _FirebaseNamespace } 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'; diff --git a/packages/util/src/deferred.ts b/packages/util/src/deferred.ts index 4a3d9a24c19..8a40afa7c29 100644 --- a/packages/util/src/deferred.ts +++ b/packages/util/src/deferred.ts @@ -31,7 +31,9 @@ export class Deferred { * 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. */ - wrapCallback(callback?: (error?: unknown, value?: unknown) => void): (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/jwt.ts b/packages/util/src/jwt.ts index 6a51b16c3db..ec9f837ac5c 100644 --- a/packages/util/src/jwt.ts +++ b/packages/util/src/jwt.ts @@ -18,7 +18,9 @@ import { base64Decode } from './crypt'; import { jsonEval } from './json'; -interface Claims { [key: string]: object | number | string | boolean }; +interface Claims { + [key: string]: object | number | string | boolean; +} interface DecodedToken { header: object; @@ -68,7 +70,8 @@ export const decode = function(token: string): DecodedToken { 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; + let validSince: number = 0, + validUntil: number = 0; if (typeof claims === 'object') { if (claims.hasOwnProperty('nbf')) { @@ -86,7 +89,11 @@ export const isValidTimestamp = function(token: string): boolean { } return ( - !!now && !!validSince && !!validUntil && now >= validSince && now <= validUntil + !!now && + !!validSince && + !!validUntil && + now >= validSince && + now <= validUntil ); }; diff --git a/packages/util/src/obj.ts b/packages/util/src/obj.ts index ea3c62f42d6..7e66550958b 100644 --- a/packages/util/src/obj.ts +++ b/packages/util/src/obj.ts @@ -28,7 +28,10 @@ export const contains = function(obj: UtilObject, key: string): boolean { return Object.prototype.hasOwnProperty.call(obj, key); }; -export const safeGet = function(obj: UtilObject, key: string) : V | undefined { +export const safeGet = function( + obj: UtilObject, + key: string +): V | undefined { if (Object.prototype.hasOwnProperty.call(obj, key)) return obj[key]; // else return undefined. }; @@ -40,7 +43,10 @@ export const safeGet = function(obj: UtilObject, key: string) : V | undefi * @param {!function(K, V)} fn Function to call for each key and value. * @template K,V */ -export const forEach = function(obj: UtilObject, fn: (key: string, value: V) => void): void { +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]); @@ -54,7 +60,10 @@ export const forEach = function(obj: UtilObject, fn: (key: string, value: * @param {!Object} objFrom * @return {!Object} objTo */ -export const extend = function(objTo: UtilObject, objFrom: UtilObject): UtilObject { +export const extend = function( + objTo: UtilObject, + objFrom: UtilObject +): UtilObject { forEach(objFrom, function(key, value) { objTo[key] = value; }); @@ -93,7 +102,11 @@ export const getCount = function(obj: UtilObject): number { return rv; }; -export const map = function(obj: UtilObject, fn: (value: V, key: string | number, obj: UtilObject) => unknown, context?: unknown) { +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] = fn.call(context, obj[key], key, obj); @@ -101,7 +114,11 @@ export const map = function(obj: UtilObject, fn: (value: V, key: string | return res; }; -export const findKey = function(obj: UtilObject, fn: (value: V, key: string | number, obj: UtilObject) => unknown, context?: unknown) { +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(context, obj[key], key, obj)) { return key; @@ -110,7 +127,11 @@ export const findKey = function(obj: UtilObject, fn: (value: V, key: strin return undefined; }; -export const findValue = function(obj: UtilObject, fn: (value: V, key: string | number, obj: UtilObject) => unknown, context?: unknown) { +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]; }; diff --git a/packages/util/src/query.ts b/packages/util/src/query.ts index 8e4a242eb89..1c766bb6935 100644 --- a/packages/util/src/query.ts +++ b/packages/util/src/query.ts @@ -22,7 +22,9 @@ import { forEach } from './obj'; * object (e.g. {arg: 'val', arg2: 'val2'}) * Note: You must prepend it with ? when adding it to a URL. */ -export const querystring = function(querystringParams: { [key: string]: string }): string { +export const querystring = function(querystringParams: { + [key: string]: string; +}): string { const params: string[] = []; forEach(querystringParams, (key: string, value) => { if (Array.isArray(value)) { diff --git a/packages/util/src/subscribe.ts b/packages/util/src/subscribe.ts index 21181574a70..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: { [key: string]: 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/validation.ts b/packages/util/src/validation.ts index 0cbe72a7ca1..48e985699a6 100644 --- a/packages/util/src/validation.ts +++ b/packages/util/src/validation.ts @@ -57,7 +57,11 @@ export const validateArgCount = function( * @param optional Whether or not the argument is optional * @return The prefix to add to the error thrown for validation. */ -export function errorPrefix(fnName: string, argumentNumber: number, optional: boolean): string { +export function errorPrefix( + fnName: string, + argumentNumber: number, + optional: boolean +): string { let argName = ''; switch (argumentNumber) { case 1: From 6aa0b426e615faddde41f7334efcf62bc5e9bd88 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 10 Jun 2019 13:58:14 -0700 Subject: [PATCH 04/15] Merge conflicts --- packages/app/src/firebaseNamespaceCore.ts | 3 --- packages/app/test/firebaseApp.test.ts | 4 ---- packages/util/src/crypt.ts | 8 -------- packages/util/src/deepCopy.ts | 6 ------ packages/util/src/deferred.ts | 4 ---- packages/util/src/obj.ts | 6 ------ packages/util/src/query.ts | 11 ----------- packages/util/src/utf8.ts | 8 -------- 8 files changed, 50 deletions(-) diff --git a/packages/app/src/firebaseNamespaceCore.ts b/packages/app/src/firebaseNamespaceCore.ts index 93fb21d719e..b02c88e46b7 100644 --- a/packages/app/src/firebaseNamespaceCore.ts +++ b/packages/app/src/firebaseNamespaceCore.ts @@ -198,10 +198,7 @@ export function createFirebaseNamespaceCore( // The Service namespace is an accessor function ... function serviceNamespace(appArg: FirebaseApp = app()): FirebaseService { -<<<<<<< HEAD // @ts-ignore -======= ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 if (typeof appArg[name] !== 'function') { // Invalid argument. // This happens in the following case: firebase.storage('gs:/') diff --git a/packages/app/test/firebaseApp.test.ts b/packages/app/test/firebaseApp.test.ts index 81fb0703e62..2ca8785f173 100644 --- a/packages/app/test/firebaseApp.test.ts +++ b/packages/app/test/firebaseApp.test.ts @@ -314,14 +314,10 @@ function executeFirebaseLiteTests(): void { }); } -<<<<<<< HEAD function firebaseAppTests( testName: string, firebaseNamespaceFactory: () => FirebaseNamespace ): void { -======= -function firebaseAppTests(testName, firebaseNamespaceFactory): void { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 describe(testName, () => { let firebase: FirebaseNamespace; diff --git a/packages/util/src/crypt.ts b/packages/util/src/crypt.ts index cf7ff30a222..4b9f38fe374 100644 --- a/packages/util/src/crypt.ts +++ b/packages/util/src/crypt.ts @@ -15,11 +15,7 @@ * limitations under the License. */ -<<<<<<< HEAD const stringToByteArray = function(str: string): number[] { -======= -const stringToByteArray = function(str): number[] { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 // TODO(user): Use native implementations if/when available const out: number[] = []; let p = 0; @@ -56,11 +52,7 @@ const stringToByteArray = function(str): number[] { * @param bytes Array of numbers representing characters. * @return Stringification of the array. */ -<<<<<<< HEAD const byteArrayToString = function(bytes: number[]): string { -======= -const byteArrayToString = function(bytes): string { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 // 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 2077a0de690..0f64fede639 100644 --- a/packages/util/src/deepCopy.ts +++ b/packages/util/src/deepCopy.ts @@ -66,15 +66,9 @@ export function deepExtend(target: unknown, source: unknown): unknown { if (!source.hasOwnProperty(prop)) { continue; } -<<<<<<< HEAD (target as { [key: string]: unknown })[prop] = deepExtend( (target as { [key: string]: unknown })[prop], (source as { [key: string]: unknown })[prop] -======= - (target as object)[prop] = deepExtend( - (target as object)[prop], - source[prop] ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 ); } diff --git a/packages/util/src/deferred.ts b/packages/util/src/deferred.ts index 603d1ea1431..8a40afa7c29 100644 --- a/packages/util/src/deferred.ts +++ b/packages/util/src/deferred.ts @@ -31,13 +31,9 @@ export class Deferred { * 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. */ -<<<<<<< HEAD wrapCallback( callback?: (error?: unknown, value?: unknown) => void ): (error: unknown, value?: unknown) => void { -======= - wrapCallback(callback?): (error: unknown, value?: unknown) => void { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 return (error, value?) => { if (error) { this.reject(error); diff --git a/packages/util/src/obj.ts b/packages/util/src/obj.ts index dacb2e6ae3f..7e66550958b 100644 --- a/packages/util/src/obj.ts +++ b/packages/util/src/obj.ts @@ -17,7 +17,6 @@ /* eslint-disable */ // will enable after https://github.com/firebase/firebase-js-sdk/pull/1811 is merged -<<<<<<< HEAD interface UtilObject { [key: string]: V; @@ -26,11 +25,6 @@ interface UtilObject { // See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ export const contains = function(obj: UtilObject, key: string): boolean { -======= - -// See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ -export const contains = function(obj, key) { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 return Object.prototype.hasOwnProperty.call(obj, key); }; diff --git a/packages/util/src/query.ts b/packages/util/src/query.ts index ff211353182..1c766bb6935 100644 --- a/packages/util/src/query.ts +++ b/packages/util/src/query.ts @@ -22,17 +22,11 @@ import { forEach } from './obj'; * object (e.g. {arg: 'val', arg2: 'val2'}) * Note: You must prepend it with ? when adding it to a URL. */ -<<<<<<< HEAD export const querystring = function(querystringParams: { [key: string]: string; }): string { const params: string[] = []; forEach(querystringParams, (key: string, value) => { -======= -export const querystring = function(querystringParams): string { - const params: string[] = []; - forEach(querystringParams, (key, value) => { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 if (Array.isArray(value)) { value.forEach(arrayVal => { params.push( @@ -52,13 +46,8 @@ export const querystring = function(querystringParams): string { * @param {string} querystring * @return {!Object} */ -<<<<<<< HEAD export const querystringDecode = function(querystring: string): object { const obj: { [key: string]: unknown } = {}; -======= -export const querystringDecode = function(querystring): object { - const obj = {}; ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 const tokens = querystring.replace(/^\?/, '').split('&'); tokens.forEach(token => { diff --git a/packages/util/src/utf8.ts b/packages/util/src/utf8.ts index c38bf254909..4431727cf28 100644 --- a/packages/util/src/utf8.ts +++ b/packages/util/src/utf8.ts @@ -32,11 +32,7 @@ import { assert } from './assert'; * @param {string} str * @return {Array} */ -<<<<<<< HEAD export const stringToByteArray = function(str: string): number[] { -======= -export const stringToByteArray = function(str): number[] { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 const out: number[] = []; let p = 0; for (let i = 0; i < str.length; i++) { @@ -75,11 +71,7 @@ export const stringToByteArray = function(str): number[] { * @param {string} str * @return {number} */ -<<<<<<< HEAD export const stringLength = function(str: string): number { -======= -export const stringLength = function(str): number { ->>>>>>> 76539be9b3ab19f5be70275f2334bee9b022e3c4 let p = 0; for (let i = 0; i < str.length; i++) { const c = str.charCodeAt(i); From 514e9fa37a14e2f9be4960382f662f26186d5ca6 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 11 Jun 2019 12:30:33 -0700 Subject: [PATCH 05/15] Address PR comments --- packages/storage/src/implementation/requests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/storage/src/implementation/requests.ts b/packages/storage/src/implementation/requests.ts index 1d94346d3b7..28bac2e5747 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: { [key: string]: any } = {}; + let urlParams: UrlParams = {}; if (location.isRoot) { urlParams['prefix'] = ''; } else { @@ -176,7 +176,7 @@ export function list( urlParams['pageToken'] = pageToken; } if (maxResults) { - urlParams['maxResults'] = maxResults; + urlParams['maxResults'] = maxResults.toString(); } const urlPart = location.bucketOnlyServerUrl(); const url = UrlUtils.makeUrl(urlPart); From bf776027ea5d88eb840aa3b7aac603dbec15fb48 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 11 Jun 2019 15:03:51 -0700 Subject: [PATCH 06/15] Make UrlParams type a little more flexible --- packages/storage/src/implementation/requestinfo.ts | 2 +- packages/storage/src/implementation/requests.ts | 2 +- packages/storage/test/requests.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 28bac2e5747..500fe63c16e 100644 --- a/packages/storage/src/implementation/requests.ts +++ b/packages/storage/src/implementation/requests.ts @@ -176,7 +176,7 @@ export function list( urlParams['pageToken'] = pageToken; } if (maxResults) { - urlParams['maxResults'] = maxResults.toString(); + urlParams['maxResults'] = maxResults; } const urlPart = location.bucketOnlyServerUrl(); const url = UrlUtils.makeUrl(urlPart); diff --git a/packages/storage/test/requests.test.ts b/packages/storage/test/requests.test.ts index 267aee7b2e0..ea581e8942d 100644 --- a/packages/storage/test/requests.test.ts +++ b/packages/storage/test/requests.test.ts @@ -231,7 +231,7 @@ describe('Firebase Storage > Requests', () => { [locationEscapes, locationEscapesNoObjUrl] ]; const pageToken = 'pageToken-afeafeagef'; - const maxResults = 13; + const maxResults = '13'; for (const [location, locationNoObjectUrl] of maps) { const requestInfo = requests.list( authWrapper, From 012700a8aff1eebea88b7b8e0f8ed93ae6ed68c9 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 11 Jun 2019 15:23:39 -0700 Subject: [PATCH 07/15] Fix test files --- packages/storage/src/implementation/url.ts | 5 +++-- packages/storage/test/reference.test.ts | 2 +- packages/storage/test/request.test.ts | 6 +++--- packages/storage/test/requests.test.ts | 2 +- packages/storage/test/task.test.ts | 14 +++++++------- packages/storage/test/xhrio.ts | 4 +++- 6 files changed, 18 insertions(+), 15 deletions(-) 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..791ae517581 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,7 @@ 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/requests.test.ts b/packages/storage/test/requests.test.ts index ea581e8942d..267aee7b2e0 100644 --- a/packages/storage/test/requests.test.ts +++ b/packages/storage/test/requests.test.ts @@ -231,7 +231,7 @@ describe('Firebase Storage > Requests', () => { [locationEscapes, locationEscapesNoObjUrl] ]; const pageToken = 'pageToken-afeafeagef'; - const maxResults = '13'; + const maxResults = 13; for (const [location, locationNoObjectUrl] of maps) { const requestInfo = requests.list( authWrapper, 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 } From 84005490710430dd65d64552762d1a68cd8cc376 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 11 Jun 2019 15:23:51 -0700 Subject: [PATCH 08/15] [AUTOMATED]: Prettier Code Styling --- packages/storage/test/request.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/storage/test/request.test.ts b/packages/storage/test/request.test.ts index 791ae517581..ff6a99f613b 100644 --- a/packages/storage/test/request.test.ts +++ b/packages/storage/test/request.test.ts @@ -224,7 +224,9 @@ describe('Firebase Storage > Request', () => { result => { assert.isTrue(spiedSend.calledOnce); const args = spiedSend.getCall(0).args; - const expectedHeaders: Headers = { Authorization: 'Firebase ' + authToken }; + const expectedHeaders: Headers = { + Authorization: 'Firebase ' + authToken + }; expectedHeaders[versionHeaderName] = versionHeaderValue; assert.deepEqual(args[4], expectedHeaders); }, From de51d86228d0d6371f55b6d5725c6c0423c877ac Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 17 Jun 2019 10:19:21 -0700 Subject: [PATCH 09/15] Change ts-ignore to eslint ignores --- packages/app/src/firebaseNamespaceCore.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/firebaseNamespaceCore.ts b/packages/app/src/firebaseNamespaceCore.ts index b02c88e46b7..2067d602bf5 100644 --- a/packages/app/src/firebaseNamespaceCore.ts +++ b/packages/app/src/firebaseNamespaceCore.ts @@ -80,8 +80,8 @@ export function createFirebaseNamespaceCore( // // import * as firebase from 'firebase'; // which becomes: var firebase = require('firebase'); - // @ts-ignore - 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', { From 4a36e0dd623f0d8768cb2f716b23e1cf853ae835 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 17 Jun 2019 10:43:33 -0700 Subject: [PATCH 10/15] Addressing some PR comments --- packages/app/index.node.ts | 8 ++++---- packages/functions/index.node.ts | 2 +- packages/functions/index.ts | 4 ++-- packages/functions/src/serializer.ts | 16 ++++++++-------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/app/index.node.ts b/packages/app/index.node.ts index 7f88a89c114..25d71972fe6 100644 --- a/packages/app/index.node.ts +++ b/packages/app/index.node.ts @@ -19,10 +19,10 @@ import { FirebaseNamespace } from '@firebase/app-types'; import { _FirebaseNamespace } from '@firebase/app-types/private'; import { createFirebaseNamespace } from './src/firebaseNamespace'; // Node specific packages. -// eslint-disable-next-line @typescript-eslint/no-require-imports -const Storage = require('dom-storage'); -// eslint-disable-next-line @typescript-eslint/no-require-imports -const XMLHttpRequest = require('xmlhttprequest'); +// @ts-ignore +import Storage from 'dom-storage'; +// @ts-ignore +import XMLHttpRequest from 'xmlhttprequest'; const _firebase = createFirebaseNamespace() as _FirebaseNamespace; diff --git a/packages/functions/index.node.ts b/packages/functions/index.node.ts index 5cddf7b81a4..a0117152ea7 100644 --- a/packages/functions/index.node.ts +++ b/packages/functions/index.node.ts @@ -33,7 +33,7 @@ function factory(app: FirebaseApp, _unused: unknown, region?: string): Service { } export function registerFunctions(instance: _FirebaseNamespace): void { - let namespaceExports = { + const namespaceExports = { // no-inline Functions: Service }; diff --git a/packages/functions/index.ts b/packages/functions/index.ts index ae22193118f..a8a43581df7 100644 --- a/packages/functions/index.ts +++ b/packages/functions/index.ts @@ -15,7 +15,7 @@ * limitations under the License. */ import firebase from '@firebase/app'; -import * as app_types from '@firebase/app-types'; +import * as appTypes from '@firebase/app-types'; import { FirebaseServiceFactory, _FirebaseNamespace @@ -29,7 +29,7 @@ import { Service } from './src/api/service'; const FUNCTIONS_TYPE = 'functions'; function factory( - app: app_types.FirebaseApp, + app: appTypes.FirebaseApp, _unused: unknown, region?: string ): Service { diff --git a/packages/functions/src/serializer.ts b/packages/functions/src/serializer.ts index 1a045f6998c..bdccec8f1e4 100644 --- a/packages/functions/src/serializer.ts +++ b/packages/functions/src/serializer.ts @@ -18,9 +18,9 @@ const LONG_TYPE = 'type.googleapis.com/google.protobuf.Int64Value'; const UNSIGNED_LONG_TYPE = 'type.googleapis.com/google.protobuf.UInt64Value'; -function mapValues(o: { [key: string]: any }, f: (arg0: any) => any): object { - let result: { [key: string]: any } = {}; - for (var key in o) { +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 +61,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: { [key: string]: unknown } | 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 +88,7 @@ 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; From 3e72dadc8e2a8e711fc043d151edefa8cd3e7f85 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 17 Jun 2019 10:46:25 -0700 Subject: [PATCH 11/15] More comments --- packages/storage/src/implementation/requests.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/storage/src/implementation/requests.ts b/packages/storage/src/implementation/requests.ts index 500fe63c16e..d096709489c 100644 --- a/packages/storage/src/implementation/requests.ts +++ b/packages/storage/src/implementation/requests.ts @@ -430,9 +430,6 @@ export function getResumableUploadStatus( let sizeString: string | null = null; try { sizeString = xhr.getResponseHeader('X-Goog-Upload-Size-Received'); - if (sizeString === null) { - handlerCheck(false); - } } catch (e) { handlerCheck(false); } From 38a4617f4b8f11e33674c288b71710852d916457 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 17 Jun 2019 10:46:35 -0700 Subject: [PATCH 12/15] [AUTOMATED]: Prettier Code Styling --- packages/functions/src/serializer.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/functions/src/serializer.ts b/packages/functions/src/serializer.ts index bdccec8f1e4..68e0ee9cb98 100644 --- a/packages/functions/src/serializer.ts +++ b/packages/functions/src/serializer.ts @@ -18,7 +18,10 @@ const LONG_TYPE = 'type.googleapis.com/google.protobuf.Int64Value'; const UNSIGNED_LONG_TYPE = 'type.googleapis.com/google.protobuf.UInt64Value'; -function mapValues(o: { [key: string]: unknown }, f: (arg0: unknown) => unknown): object { +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)) { @@ -65,15 +68,15 @@ export class Serializer { if (json == null) { return json; } - if ((json as {[key: string]: unknown})['@type']) { - switch ((json as {[key: string]: unknown})['@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 as {[key: string]: unknown})['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 as Function | object), 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; From 4f28adbcd0eb981e295ba2a8731e92d737c77a2b Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 17 Jun 2019 11:56:49 -0700 Subject: [PATCH 13/15] Fix failing tests --- packages/rxfire/test/database.test.ts | 9 ++++----- packages/rxfire/test/firestore.test.ts | 2 +- packages/util/src/jwt.ts | 4 ++-- packages/util/src/obj.ts | 1 - scripts/emulator-testing/emulators/emulator.ts | 6 ++++-- scripts/emulator-testing/emulators/firestore-emulator.ts | 2 +- scripts/emulator-testing/firestore-test-runner.ts | 6 ++++-- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/rxfire/test/database.test.ts b/packages/rxfire/test/database.test.ts index 2457cfd04da..a361c80cfcf 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/util/src/jwt.ts b/packages/util/src/jwt.ts index 6b526aa71be..f5fd1cf47c7 100644 --- a/packages/util/src/jwt.ts +++ b/packages/util/src/jwt.ts @@ -19,7 +19,7 @@ import { base64Decode } from './crypt'; import { jsonEval } from './json'; interface Claims { - [key: string]: object | number | string | boolean; + [key: string]: {}; } interface DecodedToken { @@ -114,7 +114,7 @@ export const isValidTimestamp = function(token: string): boolean { export const issuedAtTime = function(token: string): number | null { const claims: Claims = decode(token).claims; if (typeof claims === 'object' && claims.hasOwnProperty('iat')) { - return claims['iat'] as number | null; + return claims['iat'] as number; } return null; }; diff --git a/packages/util/src/obj.ts b/packages/util/src/obj.ts index 7e66550958b..c5b20dd68a2 100644 --- a/packages/util/src/obj.ts +++ b/packages/util/src/obj.ts @@ -20,7 +20,6 @@ interface UtilObject { [key: string]: V; - [index: number]: V; } // See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index 0437d7e2c3c..bd446121c36 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..25087b8ad66 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); }); }); From fe87a296813e46dca0bbd6e619a4918a632b3221 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Mon, 17 Jun 2019 11:56:59 -0700 Subject: [PATCH 14/15] [AUTOMATED]: Prettier Code Styling --- packages/rxfire/test/database.test.ts | 2 +- scripts/emulator-testing/emulators/emulator.ts | 2 +- scripts/emulator-testing/firestore-test-runner.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rxfire/test/database.test.ts b/packages/rxfire/test/database.test.ts index a361c80cfcf..a03b90f162e 100644 --- a/packages/rxfire/test/database.test.ts +++ b/packages/rxfire/test/database.test.ts @@ -30,7 +30,7 @@ const rando = () => .toString(36) .substring(5); -let batch = (items: { name: string, key: string }[]) => { +let batch = (items: { name: string; key: string }[]) => { let batch: { [key: string]: unknown } = {}; items.forEach(item => { batch[item.key] = item; diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index bd446121c36..fd5904794c7 100644 --- a/scripts/emulator-testing/emulators/emulator.ts +++ b/scripts/emulator-testing/emulators/emulator.ts @@ -15,7 +15,7 @@ * limitations under the License. */ - // @ts-ignore +// @ts-ignore import { spawn } from 'child-process-promise'; import { ChildProcess } from 'child_process'; import * as fs from 'fs'; diff --git a/scripts/emulator-testing/firestore-test-runner.ts b/scripts/emulator-testing/firestore-test-runner.ts index 25087b8ad66..4cfdf55f36f 100644 --- a/scripts/emulator-testing/firestore-test-runner.ts +++ b/scripts/emulator-testing/firestore-test-runner.ts @@ -15,7 +15,7 @@ * limitations under the License. */ - // @ts-ignore +// @ts-ignore import { spawn } from 'child-process-promise'; import * as path from 'path'; // @ts-ignore From 1c28ffe06571efdd956b00c36256c55a6c1f9739 Mon Sep 17 00:00:00 2001 From: Michael Lehenbauer Date: Mon, 17 Jun 2019 12:45:28 -0700 Subject: [PATCH 15/15] Fix packages/firestore/ usages of @ts-ignore. (#1882) * Fix packages/firestore/ usages of @ts-ignore. I left the equality_matcher.ts ones for the code we copy/pasted in, but fixed the rest. --- packages/firestore/src/api/credentials.ts | 8 +-- .../src/local/shared_client_state.ts | 4 +- .../platform_browser/webchannel_connection.ts | 16 +++--- .../src/platform_node/grpc_connection.ts | 4 +- packages/firestore/src/util/misc.ts | 1 + .../web_storage_shared_client_state.test.ts | 5 +- .../test/unit/remote/node/serializer.test.ts | 6 +- .../firestore/test/util/equality_matcher.ts | 11 ++-- packages/webchannel-wrapper/package.json | 1 + packages/webchannel-wrapper/src/index.d.ts | 56 +++++++++++++++++++ 10 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 packages/webchannel-wrapper/src/index.d.ts diff --git a/packages/firestore/src/api/credentials.ts b/packages/firestore/src/api/credentials.ts index 8ce10d4c075..8346f4b577b 100644 --- a/packages/firestore/src/api/credentials.ts +++ b/packages/firestore/src/api/credentials.ts @@ -309,21 +309,19 @@ 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' && client !== null && - // @ts-ignore client['auth'] && - // @ts-ignore client['auth']['getAuthHeaderValueForFirstParty'] ), 'unexpected gapi interface' ); return new FirstPartyCredentialsProvider( - client as Gapi, + client, credentials.sessionIndex || '0' ); diff --git a/packages/firestore/src/local/shared_client_state.ts b/packages/firestore/src/local/shared_client_state.ts index 2f4e523b8e7..c87b01d290f 100644 --- a/packages/firestore/src/local/shared_client_state.ts +++ b/packages/firestore/src/local/shared_client_state.ts @@ -462,9 +462,7 @@ export class SharedOnlineState { const validData = typeof onlineState === 'object' && - // @ts-ignore Should allow arbitrary string index when checking to see - // if that string is a valid enum value. - OnlineState[onlineState.onlineState] !== undefined && + onlineState.onlineState in OnlineState && typeof onlineState.clientId === 'string'; if (validData) { diff --git a/packages/firestore/src/platform_browser/webchannel_connection.ts b/packages/firestore/src/platform_browser/webchannel_connection.ts index 162a036b456..f264d0a4588 100644 --- a/packages/firestore/src/platform_browser/webchannel_connection.ts +++ b/packages/firestore/src/platform_browser/webchannel_connection.ts @@ -20,8 +20,8 @@ import { ErrorCode, EventType, WebChannel, + WebChannelOptions, XhrIo - // @ts-ignore } from '@firebase/webchannel-wrapper'; import { isReactNative } from '@firebase/util'; @@ -193,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 @@ -224,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 @@ -244,8 +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()) { - // @ts-ignore - request['httpHeadersOverwriteParam'] = '$httpHeaders'; + request.httpHeadersOverwriteParam = '$httpHeaders'; } const url = urlParts.join(''); @@ -345,11 +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 || - // @ts-ignore - (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 8567cd87e48..da6b1a7f262 100644 --- a/packages/firestore/src/platform_node/grpc_connection.ts +++ b/packages/firestore/src/platform_node/grpc_connection.ts @@ -86,8 +86,8 @@ export class GrpcConnection implements Connection { private cachedStub: GeneratedGrpcStub | null = null; constructor(protos: grpc.GrpcObject, private databaseInfo: DatabaseInfo) { - // @ts-ignore - 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/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/unit/local/web_storage_shared_client_state.test.ts b/packages/firestore/test/unit/local/web_storage_shared_client_state.test.ts index 6b173f85cca..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 @@ -205,10 +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. - // @ts-ignore - window.addEventListener = (type: string, callback: WebStorageCallback) => { + 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 b2de0327f1a..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,8 +157,9 @@ describe('Serializer', () => { const actualProtobufjsProto: ProtobufJS.Message = ValueMessage.fromObject( actualJsonProto ); - // @ts-ignore - 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/util/equality_matcher.ts b/packages/firestore/test/util/equality_matcher.ts index 2ded6259fa3..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 @@ -28,10 +29,12 @@ function customDeepEqual(left: unknown, right: unknown): boolean { /** * START: Custom compare logic */ - // @ts-ignore - if (left && typeof left.isEqual === 'function') return left.isEqual(right); - // @ts-ignore - 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 */ 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;