Skip to content

Commit 56cde3c

Browse files
jsayoljshcrowthe
authored andcommitted
refactor(database): classes for typescript database implementation (#55)
* refactor(database): classes for typescript database implementation * refactor(database): requested changes & other improvements
1 parent 1c19c29 commit 56cde3c

33 files changed

+2285
-2346
lines changed

src/database/api/DataSnapshot.ts

Lines changed: 144 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,177 @@
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";
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';
69

710
/**
811
* Class representing a firebase data snapshot. It wraps a SnapshotNode and
912
* 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
1513
*/
16-
export const DataSnapshot = function(node, ref, index) {
14+
export class DataSnapshot {
1715
/**
18-
* @private
19-
* @const
20-
* @type {!fb.core.snap.Node}
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
2119
*/
22-
this.node_ = node;
20+
constructor(private readonly node_: Node,
21+
private readonly ref_: Reference,
22+
private readonly index_: Index) {
23+
}
2324

2425
/**
25-
* @private
26-
* @type {!Firebase}
27-
* @const
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.
2830
*/
29-
this.query_ = ref;
31+
val(): any {
32+
validateArgCount('DataSnapshot.val', 0, 0, arguments.length);
33+
return this.node_.val();
34+
}
3035

3136
/**
32-
* @const
33-
* @type {!fb.core.snap.Index}
34-
* @private
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.
3540
*/
36-
this.index_ = index;
37-
};
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+
}
3853

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+
}
3963

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-
};
50-
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-
};
68-
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-
};
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);
7875

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);
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+
}
9080

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-
};
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);
9590

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);
91+
const childPath = new Path(childPathString);
92+
return !this.node_.getChild(childPath).isEmpty();
93+
}
10594

106-
var childPath = new Path(childPathString);
107-
return !this.node_.getChild(childPath).isEmpty();
108-
};
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);
109102

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);
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+
}
117106

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-
};
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);
121118

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);
119+
if (this.node_.isLeafNode())
120+
return false;
133121

134-
if (this.node_.isLeafNode())
135-
return false;
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+
}
136128

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-
};
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);
144135

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);
136+
if (this.node_.isLeafNode())
137+
return false;
138+
else
139+
return !this.node_.isEmpty();
140+
}
151141

152-
if (this.node_.isLeafNode())
153-
return false;
154-
else
155-
return !this.node_.isEmpty();
156-
};
142+
/**
143+
* @return {?string} The key of the location this snapshot's data came from.
144+
*/
145+
getKey(): string | null {
146+
validateArgCount('DataSnapshot.key', 0, 0, arguments.length);
157147

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);
148+
return this.ref_.getKey();
149+
}
163150

164-
return this.query_.getKey();
165-
};
166-
exportPropGetter(DataSnapshot.prototype, 'key', DataSnapshot.prototype.getKey);
151+
get key() {
152+
return this.getKey();
153+
}
167154

155+
/**
156+
* Returns the number of children for this DataSnapshot.
157+
* @return {number} The number of children that this DataSnapshot contains.
158+
*/
159+
numChildren(): number {
160+
validateArgCount('DataSnapshot.numChildren', 0, 0, arguments.length);
168161

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);
162+
return this.node_.numChildren();
163+
}
175164

176-
return this.node_.numChildren();
177-
};
165+
/**
166+
* @return {Reference} The Firebase reference for the location this snapshot's data came from.
167+
*/
168+
getRef(): Reference {
169+
validateArgCount('DataSnapshot.ref', 0, 0, arguments.length);
178170

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);
171+
return this.ref_;
172+
}
184173

185-
return this.query_;
186-
};
187-
exportPropGetter(DataSnapshot.prototype, 'ref', DataSnapshot.prototype.getRef);
174+
get ref() {
175+
return this.getRef();
176+
}
177+
}

0 commit comments

Comments
 (0)