Skip to content

Commit a92520a

Browse files
committed
refactor(database): Add types to several classes and utility methods
* refactor(database): Several classes and utility methods * WIP: fix tests with recent type changes * refactor(database): Type casting format for TSX support * refactor(database): Add 'noImplicitAny' support Adds support for the 'noImplicitAny' Typescript compiler option to the database implementation.
1 parent 58fc4c9 commit a92520a

File tree

96 files changed

+4502
-4616
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+4502
-4616
lines changed

src/database.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import * as INTERNAL from './database/api/internal';
2525
import * as TEST_ACCESS from './database/api/test_access';
2626
import { isNodeSdk } from "./utils/environment";
2727

28-
export function registerDatabase(instance) {
28+
export function registerDatabase(instance: FirebaseNamespace) {
2929
// Register the Database Service with the 'firebase' namespace.
3030
const namespace = instance.INTERNAL.registerService(
3131
'database',

src/database/api/DataSnapshot.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export class DataSnapshot {
117117
validateArgCount('DataSnapshot.getPriority', 0, 0, arguments.length);
118118

119119
// typecast here because we never return deferred values or internal priorities (MAX_PRIORITY)
120-
return /**@type {string|number|null} */ <string | number | null>(this.node_.getPriority().val());
120+
return (this.node_.getPriority().val() as string | number | null);
121121
}
122122

123123
/**
@@ -128,14 +128,14 @@ export class DataSnapshot {
128128
* @return {boolean} True if forEach was canceled by action returning true for
129129
* one of the child nodes.
130130
*/
131-
forEach(action: (d: DataSnapshot) => any): boolean {
131+
forEach(action: (d: DataSnapshot) => void): boolean {
132132
validateArgCount('DataSnapshot.forEach', 1, 1, arguments.length);
133133
validateCallback('DataSnapshot.forEach', 1, action, false);
134134

135135
if (this.node_.isLeafNode())
136136
return false;
137137

138-
const childrenNode = /**@type {ChildrenNode} */ <ChildrenNode>(this.node_);
138+
const childrenNode = (this.node_ as ChildrenNode);
139139
// Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type...
140140
return !!childrenNode.forEachChild(this.index_, (key, node) => {
141141
return action(new DataSnapshot(node, this.ref_.child(key), PRIORITY_INDEX));

src/database/api/Database.ts

+63-73
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,56 @@
11
/**
2-
* Copyright 2017 Google Inc.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
17-
import { fatal } from "../core/util/util";
18-
import { parseRepoInfo } from "../core/util/libs/parser";
19-
import { Path } from "../core/util/Path";
20-
import { PromiseImpl } from "../../utils/promise";
21-
import { Reference } from "./Reference";
22-
import { Repo } from "../core/Repo";
23-
import { RepoManager } from "../core/RepoManager";
24-
import { validateArgCount } from "../../utils/validation";
25-
import { FirebaseApp } from "../../app/firebase_app";
26-
import { validateUrl } from "../core/util/validation";
2+
* Copyright 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { fatal } from '../core/util/util';
18+
import { parseRepoInfo } from '../core/util/libs/parser';
19+
import { Path } from '../core/util/Path';
20+
import { PromiseImpl } from '../../utils/promise';
21+
import { Reference } from './Reference';
22+
import { Repo } from '../core/Repo';
23+
import { RepoManager } from '../core/RepoManager';
24+
import { validateArgCount } from '../../utils/validation';
25+
import { validateUrl } from '../core/util/validation';
26+
import { FirebaseApp, FirebaseService } from '../../app/firebase_app';
27+
import { RepoInfo } from '../core/RepoInfo';
2728

2829
/**
2930
* Class representing a firebase database.
30-
* @implements {firebase.Service}
31+
* @implements {FirebaseService}
3132
*/
32-
export class Database {
33-
repo_: Repo;
34-
root_: Reference;
35-
INTERNAL;
36-
37-
static ServerValue = {
33+
export class Database implements FirebaseService {
34+
INTERNAL: DatabaseInternals;
35+
private root_: Reference;
36+
37+
static readonly ServerValue = {
3838
'TIMESTAMP': {
39-
'.sv' : 'timestamp'
39+
'.sv': 'timestamp'
4040
}
41-
}
41+
};
4242

4343
/**
4444
* The constructor should not be called by users of our public API.
45-
* @param {!Repo} repo
45+
* @param {!Repo} repo_
4646
*/
47-
constructor(repo) {
48-
if (!(repo instanceof Repo)) {
49-
fatal("Don't call new Database() directly - please use firebase.database().");
47+
constructor(private repo_: Repo) {
48+
if (!(repo_ instanceof Repo)) {
49+
fatal('Don\'t call new Database() directly - please use firebase.database().');
5050
}
5151

52-
/** @type {Repo} */
53-
this.repo_ = repo;
54-
55-
/** @type {Firebase} */
56-
this.root_ = new Reference(repo, Path.Empty);
52+
/** @type {Reference} */
53+
this.root_ = new Reference(repo_, Path.Empty);
5754

5855
this.INTERNAL = new DatabaseInternals(this);
5956
}
@@ -65,7 +62,7 @@ export class Database {
6562
/**
6663
* Returns a reference to the root or the path specified in opt_pathString.
6764
* @param {string=} pathString
68-
* @return {!Firebase} Firebase reference.
65+
* @return {!Reference} Firebase reference.
6966
*/
7067
ref(pathString?: string): Reference {
7168
this.checkDeleted_('ref');
@@ -79,20 +76,21 @@ export class Database {
7976
* We throw a exception if the url is not in the same domain as the
8077
* current repo.
8178
* @param {string} url
82-
* @return {!Firebase} Firebase reference.
79+
* @return {!Reference} Firebase reference.
8380
*/
84-
refFromURL(url) {
81+
refFromURL(url: string): Reference {
8582
/** @const {string} */
86-
var apiName = 'database.refFromURL';
83+
const apiName = 'database.refFromURL';
8784
this.checkDeleted_(apiName);
8885
validateArgCount(apiName, 1, 1, arguments.length);
89-
var parsedURL = parseRepoInfo(url);
86+
const parsedURL = parseRepoInfo(url);
9087
validateUrl(apiName, 1, parsedURL);
9188

92-
var repoInfo = parsedURL.repoInfo;
93-
if (repoInfo.host !== this.repo_.repoInfo_.host) {
94-
fatal(apiName + ": Host name does not match the current database: " +
95-
"(found " + repoInfo.host + " but expected " + this.repo_.repoInfo_.host + ")");
89+
const repoInfo = parsedURL.repoInfo;
90+
if (repoInfo.host !== ((this.repo_ as any).repoInfo_ as RepoInfo).host) {
91+
fatal(apiName + ': Host name does not match the current database: ' +
92+
'(found ' + repoInfo.host + ' but expected ' +
93+
((this.repo_ as any).repoInfo_ as RepoInfo).host + ')');
9694
}
9795

9896
return this.ref(parsedURL.path.toString());
@@ -101,9 +99,9 @@ export class Database {
10199
/**
102100
* @param {string} apiName
103101
*/
104-
private checkDeleted_(apiName) {
102+
private checkDeleted_(apiName: string) {
105103
if (this.repo_ === null) {
106-
fatal("Cannot call " + apiName + " on a deleted database.");
104+
fatal('Cannot call ' + apiName + ' on a deleted database.');
107105
}
108106
}
109107

@@ -114,36 +112,28 @@ export class Database {
114112
this.repo_.interrupt();
115113
}
116114

117-
goOnline () {
115+
goOnline() {
118116
validateArgCount('database.goOnline', 0, 0, arguments.length);
119117
this.checkDeleted_('goOnline');
120118
this.repo_.resume();
121119
}
122-
};
123-
124-
Object.defineProperty(Repo.prototype, 'database', {
125-
get() {
126-
return this.__database || (this.__database = new Database(this));
127-
}
128-
});
120+
}
129121

130-
class DatabaseInternals {
131-
database
122+
export class DatabaseInternals {
132123
/** @param {!Database} database */
133-
constructor(database) {
134-
this.database = database;
124+
constructor(public database: Database) {
135125
}
136126

137-
/** @return {firebase.Promise<void>} */
138-
delete() {
139-
this.database.checkDeleted_('delete');
140-
RepoManager.getInstance().deleteRepo(/** @type {!Repo} */ (this.database.repo_));
127+
/** @return {Promise<void>} */
128+
delete(): Promise<void> {
129+
(this.database as any).checkDeleted_('delete');
130+
RepoManager.getInstance().deleteRepo((this.database as any).repo_ as Repo);
141131

142-
this.database.repo_ = null;
143-
this.database.root_ = null;
132+
(this.database as any).repo_ = null;
133+
(this.database as any).root_ = null;
144134
this.database.INTERNAL = null;
145135
this.database = null;
146136
return PromiseImpl.resolve();
147137
}
148-
};
138+
}
149139

src/database/api/Query.ts

+15-13
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
validateKey,
3030
} from '../core/util/validation';
3131
import { errorPrefix, validateArgCount, validateCallback, validateContextObject } from '../../utils/validation';
32-
import { ValueEventRegistration, ChildEventRegistration } from '../core/view/EventRegistration';
32+
import { ValueEventRegistration, ChildEventRegistration, EventRegistration } from '../core/view/EventRegistration';
3333
import { Deferred, attachDummyErrorHandler } from '../../utils/promise';
3434
import { Repo } from '../core/Repo';
3535
import { QueryParams } from '../core/view/QueryParams';
@@ -153,7 +153,7 @@ export class Query {
153153
// This is a slight hack. We cannot goog.require('fb.api.Firebase'), since Firebase requires fb.api.Query.
154154
// However, we will always export 'Firebase' to the global namespace, so it's guaranteed to exist by the time this
155155
// method gets called.
156-
return <Reference>(new Query.__referenceConstructor(this.repo, this.path));
156+
return (new Query.__referenceConstructor(this.repo, this.path) as Reference);
157157
}
158158

159159
/**
@@ -174,7 +174,7 @@ export class Query {
174174
if (eventType === 'value') {
175175
this.onValueEvent(callback, ret.cancel, ret.context);
176176
} else {
177-
const callbacks = {};
177+
const callbacks: { [k: string]: typeof callback } = {};
178178
callbacks[eventType] = callback;
179179
this.onChildEvent(callbacks, ret.cancel, ret.context);
180180
}
@@ -187,7 +187,7 @@ export class Query {
187187
* @param {?Object} context
188188
* @protected
189189
*/
190-
onValueEvent(callback: (a: DataSnapshot) => any, cancelCallback: ((a: Error) => any) | null, context: Object | null) {
190+
protected onValueEvent(callback: (a: DataSnapshot) => void, cancelCallback: ((a: Error) => void) | null, context: Object | null) {
191191
const container = new ValueEventRegistration(callback, cancelCallback || null, context || null);
192192
this.repo.addEventCallbackForQuery(this, container);
193193
}
@@ -196,6 +196,7 @@ export class Query {
196196
* @param {!Object.<string, !function(!DataSnapshot, ?string)>} callbacks
197197
* @param {?function(Error)} cancelCallback
198198
* @param {?Object} context
199+
* @protected
199200
*/
200201
onChildEvent(callbacks: { [k: string]: SnapshotCallback },
201202
cancelCallback: ((a: Error) => any) | null, context: Object | null) {
@@ -214,10 +215,10 @@ export class Query {
214215
validateCallback('Query.off', 2, callback, true);
215216
validateContextObject('Query.off', 3, context, true);
216217

217-
let container = null;
218-
let callbacks = null;
218+
let container: EventRegistration | null = null;
219+
let callbacks: { [k: string]: typeof callback } | null = null;
219220
if (eventType === 'value') {
220-
const valueCallback = /** @type {function(!DataSnapshot)} */ (callback) || null;
221+
const valueCallback = callback || null;
221222
container = new ValueEventRegistration(valueCallback, null, context || null);
222223
} else if (eventType) {
223224
if (callback) {
@@ -239,7 +240,8 @@ export class Query {
239240
*/
240241
once(eventType: string,
241242
userCallback?: SnapshotCallback,
242-
cancelOrContext?, context?: Object): Promise<DataSnapshot> {
243+
cancelOrContext?: ((a: Error) => void) | Object,
244+
context?: Object): Promise<DataSnapshot> {
243245
validateArgCount('Query.once', 1, 4, arguments.length);
244246
validateEventType('Query.once', 1, eventType, false);
245247
validateCallback('Query.once', 2, userCallback, true);
@@ -254,7 +256,7 @@ export class Query {
254256
const deferred = new Deferred();
255257
attachDummyErrorHandler(deferred.promise);
256258

257-
const onceCallback = (snapshot) => {
259+
const onceCallback = (snapshot: DataSnapshot) => {
258260
// NOTE: Even though we unsubscribe, we may get called multiple times if a single action (e.g. set() with JSON)
259261
// triggers multiple events (e.g. child_added or child_changed).
260262
if (firstCall) {
@@ -508,11 +510,11 @@ export class Query {
508510
* @return {{cancel: ?function(Error), context: ?Object}}
509511
* @private
510512
*/
511-
private static getCancelAndContextArgs_(fnName: string, cancelOrContext?: ((a: Error) => any) | Object,
512-
context?: Object): { cancel: ((a: Error) => any) | null, context: Object | null } {
513-
const ret = {cancel: null, context: null};
513+
private static getCancelAndContextArgs_(fnName: string, cancelOrContext?: ((a: Error) => void) | Object,
514+
context?: Object): { cancel: ((a: Error) => void) | null, context: Object | null } {
515+
const ret: { cancel: ((a: Error) => void) | null, context: Object | null } = {cancel: null, context: null};
514516
if (cancelOrContext && context) {
515-
ret.cancel = /** @type {function(Error)} */ (cancelOrContext);
517+
ret.cancel = (cancelOrContext as (a: Error) => void);
516518
validateCallback(fnName, 3, ret.cancel, true);
517519

518520
ret.context = context;

0 commit comments

Comments
 (0)