-
Notifications
You must be signed in to change notification settings - Fork 951
refactor(database): classes for typescript database implementation #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jshcrowthe
merged 3 commits into
firebase:ts-database/add-new-impl
from
jsayol:db-classes
Jun 17, 2017
Merged
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,187 +1,177 @@ | ||
import { validateArgCount, validateCallback } from "../../utils/validation"; | ||
import { validatePathString } from "../core/util/validation"; | ||
import { Path } from "../core/util/Path"; | ||
import { exportPropGetter } from "../core/util/util"; | ||
import { PRIORITY_INDEX } from "../core/snap/indexes/PriorityIndex"; | ||
import { validateArgCount, validateCallback } from '../../utils/validation'; | ||
import { validatePathString } from '../core/util/validation'; | ||
import { Path } from '../core/util/Path'; | ||
import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex'; | ||
import { Node } from '../core/snap/Node'; | ||
import { Reference } from './Reference'; | ||
import { Index } from '../core/snap/indexes/Index'; | ||
import { ChildrenNode } from '../core/snap/ChildrenNode'; | ||
|
||
/** | ||
* Class representing a firebase data snapshot. It wraps a SnapshotNode and | ||
* surfaces the public methods (val, forEach, etc.) we want to expose. | ||
* | ||
* @constructor | ||
* @param {!fb.core.snap.Node} node A SnapshotNode to wrap. | ||
* @param {!Firebase} ref The ref of the location this snapshot came from. | ||
* @param {!fb.core.snap.Index} index The iteration order for this snapshot | ||
*/ | ||
export const DataSnapshot = function(node, ref, index) { | ||
export class DataSnapshot { | ||
/** | ||
* @private | ||
* @const | ||
* @type {!fb.core.snap.Node} | ||
* @param {!fb.core.snap.Node} node_ A SnapshotNode to wrap. | ||
* @param {!Reference} ref_ The ref of the location this snapshot came from. | ||
* @param {!fb.core.snap.Index} index_ The iteration order for this snapshot | ||
*/ | ||
this.node_ = node; | ||
constructor(private readonly node_: Node, | ||
private readonly ref_: Reference, | ||
private readonly index_: Index) { | ||
} | ||
|
||
/** | ||
* @private | ||
* @type {!Firebase} | ||
* @const | ||
* Retrieves the snapshot contents as JSON. Returns null if the snapshot is | ||
* empty. | ||
* | ||
* @return {*} JSON representation of the DataSnapshot contents, or null if empty. | ||
*/ | ||
this.query_ = ref; | ||
val(): any { | ||
validateArgCount('firebase.database.DataSnapshot.val', 0, 0, arguments.length); | ||
return this.node_.val(); | ||
} | ||
|
||
/** | ||
* @const | ||
* @type {!fb.core.snap.Index} | ||
* @private | ||
* Returns the snapshot contents as JSON, including priorities of node. Suitable for exporting | ||
* the entire node contents. | ||
* @return {*} JSON representation of the DataSnapshot contents, or null if empty. | ||
*/ | ||
this.index_ = index; | ||
}; | ||
exportVal(): any { | ||
validateArgCount('firebase.database.DataSnapshot.exportVal', 0, 0, arguments.length); | ||
return this.node_.val(true); | ||
} | ||
|
||
// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary | ||
// for end-users | ||
toJSON(): any { | ||
// Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content | ||
validateArgCount('firebase.database.DataSnapshot.toJSON', 0, 1, arguments.length); | ||
return this.exportVal(); | ||
} | ||
|
||
/** | ||
* Returns whether the snapshot contains a non-null value. | ||
* | ||
* @return {boolean} Whether the snapshot contains a non-null value, or is empty. | ||
*/ | ||
exists(): boolean { | ||
validateArgCount('firebase.database.DataSnapshot.exists', 0, 0, arguments.length); | ||
return !this.node_.isEmpty(); | ||
} | ||
|
||
/** | ||
* Retrieves the snapshot contents as JSON. Returns null if the snapshot is | ||
* empty. | ||
* | ||
* @return {*} JSON representation of the DataSnapshot contents, or null if empty. | ||
*/ | ||
DataSnapshot.prototype.val = function() { | ||
validateArgCount('Firebase.DataSnapshot.val', 0, 0, arguments.length); | ||
return this.node_.val(); | ||
}; | ||
|
||
/** | ||
* Returns the snapshot contents as JSON, including priorities of node. Suitable for exporting | ||
* the entire node contents. | ||
* @return {*} JSON representation of the DataSnapshot contents, or null if empty. | ||
*/ | ||
DataSnapshot.prototype.exportVal = function() { | ||
validateArgCount('Firebase.DataSnapshot.exportVal', 0, 0, arguments.length); | ||
return this.node_.val(true); | ||
}; | ||
|
||
// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary | ||
// for end-users | ||
DataSnapshot.prototype.toJSON = function() { | ||
// Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content | ||
validateArgCount('Firebase.DataSnapshot.toJSON', 0, 1, arguments.length); | ||
return this.exportVal(); | ||
}; | ||
|
||
/** | ||
* Returns whether the snapshot contains a non-null value. | ||
* | ||
* @return {boolean} Whether the snapshot contains a non-null value, or is empty. | ||
*/ | ||
DataSnapshot.prototype.exists = function() { | ||
validateArgCount('Firebase.DataSnapshot.exists', 0, 0, arguments.length); | ||
return !this.node_.isEmpty(); | ||
}; | ||
/** | ||
* Returns a DataSnapshot of the specified child node's contents. | ||
* | ||
* @param {!string} childPathString Path to a child. | ||
* @return {!DataSnapshot} DataSnapshot for child node. | ||
*/ | ||
child(childPathString: string): DataSnapshot { | ||
validateArgCount('firebase.database.DataSnapshot.child', 0, 1, arguments.length); | ||
// Ensure the childPath is a string (can be a number) | ||
childPathString = String(childPathString); | ||
validatePathString('firebase.database.DataSnapshot.child', 1, childPathString, false); | ||
|
||
/** | ||
* Returns a DataSnapshot of the specified child node's contents. | ||
* | ||
* @param {!string} childPathString Path to a child. | ||
* @return {!DataSnapshot} DataSnapshot for child node. | ||
*/ | ||
DataSnapshot.prototype.child = function(childPathString) { | ||
validateArgCount('Firebase.DataSnapshot.child', 0, 1, arguments.length); | ||
// Ensure the childPath is a string (can be a number) | ||
childPathString = String(childPathString); | ||
validatePathString('Firebase.DataSnapshot.child', 1, childPathString, false); | ||
const childPath = new Path(childPathString); | ||
const childRef = this.ref_.child(childPath); | ||
return new DataSnapshot(this.node_.getChild(childPath), childRef, PRIORITY_INDEX); | ||
} | ||
|
||
var childPath = new Path(childPathString); | ||
var childRef = this.query_.child(childPath); | ||
return new DataSnapshot(this.node_.getChild(childPath), childRef, PRIORITY_INDEX); | ||
}; | ||
/** | ||
* Returns whether the snapshot contains a child at the specified path. | ||
* | ||
* @param {!string} childPathString Path to a child. | ||
* @return {boolean} Whether the child exists. | ||
*/ | ||
hasChild(childPathString: string): boolean { | ||
validateArgCount('firebase.database.DataSnapshot.hasChild', 1, 1, arguments.length); | ||
validatePathString('firebase.database.DataSnapshot.hasChild', 1, childPathString, false); | ||
|
||
/** | ||
* Returns whether the snapshot contains a child at the specified path. | ||
* | ||
* @param {!string} childPathString Path to a child. | ||
* @return {boolean} Whether the child exists. | ||
*/ | ||
DataSnapshot.prototype.hasChild = function(childPathString) { | ||
validateArgCount('Firebase.DataSnapshot.hasChild', 1, 1, arguments.length); | ||
validatePathString('Firebase.DataSnapshot.hasChild', 1, childPathString, false); | ||
const childPath = new Path(childPathString); | ||
return !this.node_.getChild(childPath).isEmpty(); | ||
} | ||
|
||
var childPath = new Path(childPathString); | ||
return !this.node_.getChild(childPath).isEmpty(); | ||
}; | ||
/** | ||
* Returns the priority of the object, or null if no priority was set. | ||
* | ||
* @return {string|number|null} The priority. | ||
*/ | ||
getPriority(): string | number | null { | ||
validateArgCount('firebase.database.DataSnapshot.getPriority', 0, 0, arguments.length); | ||
|
||
/** | ||
* Returns the priority of the object, or null if no priority was set. | ||
* | ||
* @return {string|number|null} The priority. | ||
*/ | ||
DataSnapshot.prototype.getPriority = function() { | ||
validateArgCount('Firebase.DataSnapshot.getPriority', 0, 0, arguments.length); | ||
// typecast here because we never return deferred values or internal priorities (MAX_PRIORITY) | ||
return /**@type {string|number|null} */ <string | number | null>(this.node_.getPriority().val()); | ||
} | ||
|
||
// typecast here because we never return deferred values or internal priorities (MAX_PRIORITY) | ||
return /**@type {string|number|null} */ (this.node_.getPriority().val()); | ||
}; | ||
/** | ||
* Iterates through child nodes and calls the specified action for each one. | ||
* | ||
* @param {function(!DataSnapshot)} action Callback function to be called | ||
* for each child. | ||
* @return {boolean} True if forEach was canceled by action returning true for | ||
* one of the child nodes. | ||
*/ | ||
forEach(action: (d: DataSnapshot) => any): boolean { | ||
validateArgCount('firebase.database.DataSnapshot.forEach', 1, 1, arguments.length); | ||
validateCallback('firebase.database.DataSnapshot.forEach', 1, action, false); | ||
|
||
/** | ||
* Iterates through child nodes and calls the specified action for each one. | ||
* | ||
* @param {function(!DataSnapshot)} action Callback function to be called | ||
* for each child. | ||
* @return {boolean} True if forEach was canceled by action returning true for | ||
* one of the child nodes. | ||
*/ | ||
DataSnapshot.prototype.forEach = function(action) { | ||
validateArgCount('Firebase.DataSnapshot.forEach', 1, 1, arguments.length); | ||
validateCallback('Firebase.DataSnapshot.forEach', 1, action, false); | ||
if (this.node_.isLeafNode()) | ||
return false; | ||
|
||
if (this.node_.isLeafNode()) | ||
return false; | ||
const childrenNode = /**@type {ChildrenNode} */ <ChildrenNode>(this.node_); | ||
// Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type... | ||
return !!childrenNode.forEachChild(this.index_, (key, node) => { | ||
return action(new DataSnapshot(node, this.ref_.child(key), PRIORITY_INDEX)); | ||
}); | ||
} | ||
|
||
var childrenNode = /** @type {!fb.core.snap.ChildrenNode} */ (this.node_); | ||
var self = this; | ||
// Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type... | ||
return !!childrenNode.forEachChild(this.index_, function(key, node) { | ||
return action(new DataSnapshot(node, self.query_.child(key), PRIORITY_INDEX)); | ||
}); | ||
}; | ||
/** | ||
* Returns whether this DataSnapshot has children. | ||
* @return {boolean} True if the DataSnapshot contains 1 or more child nodes. | ||
*/ | ||
hasChildren(): boolean { | ||
validateArgCount('firebase.database.DataSnapshot.hasChildren', 0, 0, arguments.length); | ||
|
||
/** | ||
* Returns whether this DataSnapshot has children. | ||
* @return {boolean} True if the DataSnapshot contains 1 or more child nodes. | ||
*/ | ||
DataSnapshot.prototype.hasChildren = function() { | ||
validateArgCount('Firebase.DataSnapshot.hasChildren', 0, 0, arguments.length); | ||
if (this.node_.isLeafNode()) | ||
return false; | ||
else | ||
return !this.node_.isEmpty(); | ||
} | ||
|
||
if (this.node_.isLeafNode()) | ||
return false; | ||
else | ||
return !this.node_.isEmpty(); | ||
}; | ||
/** | ||
* @return {?string} The key of the location this snapshot's data came from. | ||
*/ | ||
getKey(): string | null { | ||
validateArgCount('firebase.database.DataSnapshot.key', 0, 0, arguments.length); | ||
|
||
/** | ||
* @return {?string} The key of the location this snapshot's data came from. | ||
*/ | ||
DataSnapshot.prototype.getKey = function() { | ||
validateArgCount('Firebase.DataSnapshot.key', 0, 0, arguments.length); | ||
return this.ref_.getKey(); | ||
} | ||
|
||
return this.query_.getKey(); | ||
}; | ||
exportPropGetter(DataSnapshot.prototype, 'key', DataSnapshot.prototype.getKey); | ||
get key() { | ||
return this.getKey(); | ||
} | ||
|
||
/** | ||
* Returns the number of children for this DataSnapshot. | ||
* @return {number} The number of children that this DataSnapshot contains. | ||
*/ | ||
numChildren(): number { | ||
validateArgCount('firebase.database.DataSnapshot.numChildren', 0, 0, arguments.length); | ||
|
||
/** | ||
* Returns the number of children for this DataSnapshot. | ||
* @return {number} The number of children that this DataSnapshot contains. | ||
*/ | ||
DataSnapshot.prototype.numChildren = function() { | ||
validateArgCount('Firebase.DataSnapshot.numChildren', 0, 0, arguments.length); | ||
return this.node_.numChildren(); | ||
} | ||
|
||
return this.node_.numChildren(); | ||
}; | ||
/** | ||
* @return {Reference} The Firebase reference for the location this snapshot's data came from. | ||
*/ | ||
getRef(): Reference { | ||
validateArgCount('firebase.database.DataSnapshot.ref', 0, 0, arguments.length); | ||
|
||
/** | ||
* @return {Firebase} The Firebase reference for the location this snapshot's data came from. | ||
*/ | ||
DataSnapshot.prototype.getRef = function() { | ||
validateArgCount('Firebase.DataSnapshot.ref', 0, 0, arguments.length); | ||
return this.ref_; | ||
} | ||
|
||
return this.query_; | ||
}; | ||
exportPropGetter(DataSnapshot.prototype, 'ref', DataSnapshot.prototype.getRef); | ||
get ref() { | ||
return this.getRef(); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we refactor the fb.*.*.* comments? These all have clear analogs in the classes that we reference.