Skip to content

Commit 87511de

Browse files
jshcrowthejsayol
authored andcommitted
refactor(database): add typescript implementation
1 parent bb80d31 commit 87511de

39 files changed

+2407
-2388
lines changed

src/database.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@ import { enableLogging } from "./database/core/util/util";
2323
import { RepoManager } from "./database/core/RepoManager";
2424
import * as INTERNAL from './database/api/internal';
2525
import * as TEST_ACCESS from './database/api/test_access';
26-
import { isNodeSdk } from "./utils/environment";
2726

2827
export function registerDatabase(instance) {
2928
// Register the Database Service with the 'firebase' namespace.
30-
const namespace = instance.INTERNAL.registerService(
29+
instance.INTERNAL.registerService(
3130
'database',
3231
app => RepoManager.getInstance().databaseFromApp(app),
3332
// firebase.database namespace properties
@@ -41,10 +40,6 @@ export function registerDatabase(instance) {
4140
TEST_ACCESS
4241
}
4342
);
44-
45-
if (isNodeSdk()) {
46-
module.exports = namespace;
47-
}
4843
}
4944

5045
/**
@@ -62,4 +57,4 @@ declare module './app/firebase_app' {
6257
}
6358
}
6459

65-
registerDatabase(firebase);
60+
registerDatabase(firebase);

src/database/api/DataSnapshot.ts

Lines changed: 156 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,168 +1,187 @@
1-
import { validateArgCount, validateCallback } from '../../utils/validation';
2-
import { validatePathString } from '../core/util/validation';
3-
import { Path } from '../core/util/Path';
4-
import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex';
5-
import { Node } from '../core/snap/Node';
6-
import { Reference } from './Reference';
7-
import { Index } from '../core/snap/indexes/Index';
8-
import { ChildrenNode } from '../core/snap/ChildrenNode';
1+
import { validateArgCount, validateCallback } from "../../utils/validation";
2+
import { validatePathString } from "../core/util/validation";
3+
import { Path } from "../core/util/Path";
4+
import { exportPropGetter } from "../core/util/util";
5+
import { PRIORITY_INDEX } from "../core/snap/indexes/PriorityIndex";
96

107
/**
118
* Class representing a firebase data snapshot. It wraps a SnapshotNode and
129
* surfaces the public methods (val, forEach, etc.) we want to expose.
10+
*
11+
* @constructor
12+
* @param {!fb.core.snap.Node} node A SnapshotNode to wrap.
13+
* @param {!Firebase} ref The ref of the location this snapshot came from.
14+
* @param {!fb.core.snap.Index} index The iteration order for this snapshot
1315
*/
14-
export class DataSnapshot {
16+
export const DataSnapshot = function(node, ref, index) {
1517
/**
16-
* @param {!Node} node_ A SnapshotNode to wrap.
17-
* @param {!Reference} ref_ The ref of the location this snapshot came from.
18-
* @param {!Index} index_ The iteration order for this snapshot
18+
* @private
19+
* @const
20+
* @type {!fb.core.snap.Node}
1921
*/
20-
constructor(private readonly node_: Node,
21-
private readonly ref_: Reference,
22-
private readonly index_: Index) {
23-
}
22+
this.node_ = node;
2423

2524
/**
26-
* Retrieves the snapshot contents as JSON. Returns null if the snapshot is
27-
* empty.
28-
*
29-
* @return {*} JSON representation of the DataSnapshot contents, or null if empty.
25+
* @private
26+
* @type {!Firebase}
27+
* @const
3028
*/
31-
val(): any {
32-
validateArgCount('DataSnapshot.val', 0, 0, arguments.length);
33-
return this.node_.val();
34-
}
29+
this.query_ = ref;
3530

3631
/**
37-
* Returns the snapshot contents as JSON, including priorities of node. Suitable for exporting
38-
* the entire node contents.
39-
* @return {*} JSON representation of the DataSnapshot contents, or null if empty.
32+
* @const
33+
* @type {!fb.core.snap.Index}
34+
* @private
4035
*/
41-
exportVal(): any {
42-
validateArgCount('DataSnapshot.exportVal', 0, 0, arguments.length);
43-
return this.node_.val(true);
44-
}
45-
46-
// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
47-
// for end-users
48-
toJSON(): any {
49-
// Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content
50-
validateArgCount('DataSnapshot.toJSON', 0, 1, arguments.length);
51-
return this.exportVal();
52-
}
36+
this.index_ = index;
37+
};
5338

54-
/**
55-
* Returns whether the snapshot contains a non-null value.
56-
*
57-
* @return {boolean} Whether the snapshot contains a non-null value, or is empty.
58-
*/
59-
exists(): boolean {
60-
validateArgCount('DataSnapshot.exists', 0, 0, arguments.length);
61-
return !this.node_.isEmpty();
62-
}
6339

64-
/**
65-
* Returns a DataSnapshot of the specified child node's contents.
66-
*
67-
* @param {!string} childPathString Path to a child.
68-
* @return {!DataSnapshot} DataSnapshot for child node.
69-
*/
70-
child(childPathString: string): DataSnapshot {
71-
validateArgCount('DataSnapshot.child', 0, 1, arguments.length);
72-
// Ensure the childPath is a string (can be a number)
73-
childPathString = String(childPathString);
74-
validatePathString('DataSnapshot.child', 1, childPathString, false);
40+
/**
41+
* Retrieves the snapshot contents as JSON. Returns null if the snapshot is
42+
* empty.
43+
*
44+
* @return {*} JSON representation of the DataSnapshot contents, or null if empty.
45+
*/
46+
DataSnapshot.prototype.val = function() {
47+
validateArgCount('Firebase.DataSnapshot.val', 0, 0, arguments.length);
48+
return this.node_.val();
49+
};
7550

76-
const childPath = new Path(childPathString);
77-
const childRef = this.ref_.child(childPath);
78-
return new DataSnapshot(this.node_.getChild(childPath), childRef, PRIORITY_INDEX);
79-
}
51+
/**
52+
* Returns the snapshot contents as JSON, including priorities of node. Suitable for exporting
53+
* the entire node contents.
54+
* @return {*} JSON representation of the DataSnapshot contents, or null if empty.
55+
*/
56+
DataSnapshot.prototype.exportVal = function() {
57+
validateArgCount('Firebase.DataSnapshot.exportVal', 0, 0, arguments.length);
58+
return this.node_.val(true);
59+
};
60+
61+
// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
62+
// for end-users
63+
DataSnapshot.prototype.toJSON = function() {
64+
// Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content
65+
validateArgCount('Firebase.DataSnapshot.toJSON', 0, 1, arguments.length);
66+
return this.exportVal();
67+
};
8068

81-
/**
82-
* Returns whether the snapshot contains a child at the specified path.
83-
*
84-
* @param {!string} childPathString Path to a child.
85-
* @return {boolean} Whether the child exists.
86-
*/
87-
hasChild(childPathString: string): boolean {
88-
validateArgCount('DataSnapshot.hasChild', 1, 1, arguments.length);
89-
validatePathString('DataSnapshot.hasChild', 1, childPathString, false);
69+
/**
70+
* Returns whether the snapshot contains a non-null value.
71+
*
72+
* @return {boolean} Whether the snapshot contains a non-null value, or is empty.
73+
*/
74+
DataSnapshot.prototype.exists = function() {
75+
validateArgCount('Firebase.DataSnapshot.exists', 0, 0, arguments.length);
76+
return !this.node_.isEmpty();
77+
};
9078

91-
const childPath = new Path(childPathString);
92-
return !this.node_.getChild(childPath).isEmpty();
93-
}
79+
/**
80+
* Returns a DataSnapshot of the specified child node's contents.
81+
*
82+
* @param {!string} childPathString Path to a child.
83+
* @return {!DataSnapshot} DataSnapshot for child node.
84+
*/
85+
DataSnapshot.prototype.child = function(childPathString) {
86+
validateArgCount('Firebase.DataSnapshot.child', 0, 1, arguments.length);
87+
// Ensure the childPath is a string (can be a number)
88+
childPathString = String(childPathString);
89+
validatePathString('Firebase.DataSnapshot.child', 1, childPathString, false);
9490

95-
/**
96-
* Returns the priority of the object, or null if no priority was set.
97-
*
98-
* @return {string|number|null} The priority.
99-
*/
100-
getPriority(): string | number | null {
101-
validateArgCount('DataSnapshot.getPriority', 0, 0, arguments.length);
91+
var childPath = new Path(childPathString);
92+
var childRef = this.query_.child(childPath);
93+
return new DataSnapshot(this.node_.getChild(childPath), childRef, PRIORITY_INDEX);
94+
};
10295

103-
// typecast here because we never return deferred values or internal priorities (MAX_PRIORITY)
104-
return /**@type {string|number|null} */ <string | number | null>(this.node_.getPriority().val());
105-
}
96+
/**
97+
* Returns whether the snapshot contains a child at the specified path.
98+
*
99+
* @param {!string} childPathString Path to a child.
100+
* @return {boolean} Whether the child exists.
101+
*/
102+
DataSnapshot.prototype.hasChild = function(childPathString) {
103+
validateArgCount('Firebase.DataSnapshot.hasChild', 1, 1, arguments.length);
104+
validatePathString('Firebase.DataSnapshot.hasChild', 1, childPathString, false);
106105

107-
/**
108-
* Iterates through child nodes and calls the specified action for each one.
109-
*
110-
* @param {function(!DataSnapshot)} action Callback function to be called
111-
* for each child.
112-
* @return {boolean} True if forEach was canceled by action returning true for
113-
* one of the child nodes.
114-
*/
115-
forEach(action: (d: DataSnapshot) => any): boolean {
116-
validateArgCount('DataSnapshot.forEach', 1, 1, arguments.length);
117-
validateCallback('DataSnapshot.forEach', 1, action, false);
106+
var childPath = new Path(childPathString);
107+
return !this.node_.getChild(childPath).isEmpty();
108+
};
109+
110+
/**
111+
* Returns the priority of the object, or null if no priority was set.
112+
*
113+
* @return {string|number|null} The priority.
114+
*/
115+
DataSnapshot.prototype.getPriority = function() {
116+
validateArgCount('Firebase.DataSnapshot.getPriority', 0, 0, arguments.length);
118117

119-
if (this.node_.isLeafNode())
120-
return false;
118+
// typecast here because we never return deferred values or internal priorities (MAX_PRIORITY)
119+
return /**@type {string|number|null} */ (this.node_.getPriority().val());
120+
};
121121

122-
const childrenNode = /**@type {ChildrenNode} */ <ChildrenNode>(this.node_);
123-
// Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type...
124-
return !!childrenNode.forEachChild(this.index_, (key, node) => {
125-
return action(new DataSnapshot(node, this.ref_.child(key), PRIORITY_INDEX));
126-
});
127-
}
122+
/**
123+
* Iterates through child nodes and calls the specified action for each one.
124+
*
125+
* @param {function(!DataSnapshot)} action Callback function to be called
126+
* for each child.
127+
* @return {boolean} True if forEach was canceled by action returning true for
128+
* one of the child nodes.
129+
*/
130+
DataSnapshot.prototype.forEach = function(action) {
131+
validateArgCount('Firebase.DataSnapshot.forEach', 1, 1, arguments.length);
132+
validateCallback('Firebase.DataSnapshot.forEach', 1, action, false);
128133

129-
/**
130-
* Returns whether this DataSnapshot has children.
131-
* @return {boolean} True if the DataSnapshot contains 1 or more child nodes.
132-
*/
133-
hasChildren(): boolean {
134-
validateArgCount('DataSnapshot.hasChildren', 0, 0, arguments.length);
134+
if (this.node_.isLeafNode())
135+
return false;
135136

136-
if (this.node_.isLeafNode())
137-
return false;
138-
else
139-
return !this.node_.isEmpty();
140-
}
137+
var childrenNode = /** @type {!fb.core.snap.ChildrenNode} */ (this.node_);
138+
var self = this;
139+
// Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type...
140+
return !!childrenNode.forEachChild(this.index_, function(key, node) {
141+
return action(new DataSnapshot(node, self.query_.child(key), PRIORITY_INDEX));
142+
});
143+
};
141144

142-
get key() {
143-
return this.ref_.getKey();
144-
}
145+
/**
146+
* Returns whether this DataSnapshot has children.
147+
* @return {boolean} True if the DataSnapshot contains 1 or more child nodes.
148+
*/
149+
DataSnapshot.prototype.hasChildren = function() {
150+
validateArgCount('Firebase.DataSnapshot.hasChildren', 0, 0, arguments.length);
145151

146-
/**
147-
* Returns the number of children for this DataSnapshot.
148-
* @return {number} The number of children that this DataSnapshot contains.
149-
*/
150-
numChildren(): number {
151-
validateArgCount('DataSnapshot.numChildren', 0, 0, arguments.length);
152+
if (this.node_.isLeafNode())
153+
return false;
154+
else
155+
return !this.node_.isEmpty();
156+
};
152157

153-
return this.node_.numChildren();
154-
}
158+
/**
159+
* @return {?string} The key of the location this snapshot's data came from.
160+
*/
161+
DataSnapshot.prototype.getKey = function() {
162+
validateArgCount('Firebase.DataSnapshot.key', 0, 0, arguments.length);
163+
164+
return this.query_.getKey();
165+
};
166+
exportPropGetter(DataSnapshot.prototype, 'key', DataSnapshot.prototype.getKey);
155167

156-
/**
157-
* @return {Reference} The Firebase reference for the location this snapshot's data came from.
158-
*/
159-
getRef(): Reference {
160-
validateArgCount('DataSnapshot.ref', 0, 0, arguments.length);
161168

162-
return this.ref_;
163-
}
169+
/**
170+
* Returns the number of children for this DataSnapshot.
171+
* @return {number} The number of children that this DataSnapshot contains.
172+
*/
173+
DataSnapshot.prototype.numChildren = function() {
174+
validateArgCount('Firebase.DataSnapshot.numChildren', 0, 0, arguments.length);
175+
176+
return this.node_.numChildren();
177+
};
178+
179+
/**
180+
* @return {Firebase} The Firebase reference for the location this snapshot's data came from.
181+
*/
182+
DataSnapshot.prototype.getRef = function() {
183+
validateArgCount('Firebase.DataSnapshot.ref', 0, 0, arguments.length);
164184

165-
get ref() {
166-
return this.getRef();
167-
}
168-
}
185+
return this.query_;
186+
};
187+
exportPropGetter(DataSnapshot.prototype, 'ref', DataSnapshot.prototype.getRef);

0 commit comments

Comments
 (0)