Skip to content
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

refactor(database): classes for typescript database implementation #55

Merged
merged 3 commits into from
Jun 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
298 changes: 144 additions & 154 deletions src/database/api/DataSnapshot.ts
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 {!Node} node_ A SnapshotNode to wrap.
* @param {!Reference} ref_ The ref of the location this snapshot came from.
* @param {!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('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('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('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('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('DataSnapshot.child', 0, 1, arguments.length);
// Ensure the childPath is a string (can be a number)
childPathString = String(childPathString);
validatePathString('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('DataSnapshot.hasChild', 1, 1, arguments.length);
validatePathString('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('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('DataSnapshot.forEach', 1, 1, arguments.length);
validateCallback('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('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('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('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('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();
}
}
Loading