Skip to content

Commit 6c80894

Browse files
DataSnapshot Compat+Exp
1 parent 975da07 commit 6c80894

File tree

9 files changed

+224
-156
lines changed

9 files changed

+224
-156
lines changed

packages/database/src/api/DataSnapshot.ts

Lines changed: 23 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,20 @@
1717

1818
import { validateArgCount, validateCallback } from '@firebase/util';
1919
import { validatePathString } from '../core/util/validation';
20-
import { Path } from '../core/util/Path';
21-
import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex';
22-
import { Node } from '../core/snap/Node';
2320
import { Reference } from './Reference';
24-
import { Index } from '../core/snap/indexes/Index';
25-
import { ChildrenNode } from '../core/snap/ChildrenNode';
21+
import { DataSnapshot as ExpDataSnapshot } from '../exp/DataSnapshot';
22+
23+
// TODO(databaseexp): Import Compat from @firebase/util
24+
export interface Compat<T> {
25+
readonly _delegate: T;
26+
}
2627

2728
/**
2829
* Class representing a firebase data snapshot. It wraps a SnapshotNode and
2930
* surfaces the public methods (val, forEach, etc.) we want to expose.
3031
*/
31-
export class DataSnapshot {
32-
/**
33-
* @param node_ A SnapshotNode to wrap.
34-
* @param ref_ The ref of the location this snapshot came from.
35-
* @param index_ The iteration order for this snapshot
36-
*/
37-
constructor(
38-
private readonly node_: Node,
39-
private readonly ref_: Reference,
40-
private readonly index_: Index
41-
) {}
32+
export class DataSnapshot implements Compat<ExpDataSnapshot> {
33+
constructor(readonly _delegate: ExpDataSnapshot) {}
4234

4335
/**
4436
* Retrieves the snapshot contents as JSON. Returns null if the snapshot is
@@ -48,7 +40,7 @@ export class DataSnapshot {
4840
*/
4941
val(): unknown {
5042
validateArgCount('DataSnapshot.val', 0, 0, arguments.length);
51-
return this.node_.val();
43+
return this._delegate.val();
5244
}
5345

5446
/**
@@ -58,15 +50,15 @@ export class DataSnapshot {
5850
*/
5951
exportVal(): unknown {
6052
validateArgCount('DataSnapshot.exportVal', 0, 0, arguments.length);
61-
return this.node_.val(true);
53+
return this._delegate.exportVal();
6254
}
6355

6456
// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
6557
// for end-users
6658
toJSON(): unknown {
6759
// Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content
6860
validateArgCount('DataSnapshot.toJSON', 0, 1, arguments.length);
69-
return this.exportVal();
61+
return this._delegate.toJSON();
7062
}
7163

7264
/**
@@ -76,7 +68,7 @@ export class DataSnapshot {
7668
*/
7769
exists(): boolean {
7870
validateArgCount('DataSnapshot.exists', 0, 0, arguments.length);
79-
return !this.node_.isEmpty();
71+
return this._delegate.exists();
8072
}
8173

8274
/**
@@ -90,14 +82,7 @@ export class DataSnapshot {
9082
// Ensure the childPath is a string (can be a number)
9183
childPathString = String(childPathString);
9284
validatePathString('DataSnapshot.child', 1, childPathString, false);
93-
94-
const childPath = new Path(childPathString);
95-
const childRef = this.ref_.child(childPath);
96-
return new DataSnapshot(
97-
this.node_.getChild(childPath),
98-
childRef,
99-
PRIORITY_INDEX
100-
);
85+
return new DataSnapshot(this._delegate.child(childPathString));
10186
}
10287

10388
/**
@@ -109,9 +94,7 @@ export class DataSnapshot {
10994
hasChild(childPathString: string): boolean {
11095
validateArgCount('DataSnapshot.hasChild', 1, 1, arguments.length);
11196
validatePathString('DataSnapshot.hasChild', 1, childPathString, false);
112-
113-
const childPath = new Path(childPathString);
114-
return !this.node_.getChild(childPath).isEmpty();
97+
return this._delegate.hasChild(childPathString);
11598
}
11699

117100
/**
@@ -121,9 +104,7 @@ export class DataSnapshot {
121104
*/
122105
getPriority(): string | number | null {
123106
validateArgCount('DataSnapshot.getPriority', 0, 0, arguments.length);
124-
125-
// typecast here because we never return deferred values or internal priorities (MAX_PRIORITY)
126-
return this.node_.getPriority().val() as string | number | null;
107+
return this._delegate.priority;
127108
}
128109

129110
/**
@@ -134,21 +115,12 @@ export class DataSnapshot {
134115
* @return True if forEach was canceled by action returning true for
135116
* one of the child nodes.
136117
*/
137-
forEach(action: (d: DataSnapshot) => boolean | void): boolean {
118+
forEach(action: (snapshot: DataSnapshot) => boolean | void): boolean {
138119
validateArgCount('DataSnapshot.forEach', 1, 1, arguments.length);
139120
validateCallback('DataSnapshot.forEach', 1, action, false);
140-
141-
if (this.node_.isLeafNode()) {
142-
return false;
143-
}
144-
145-
const childrenNode = this.node_ as ChildrenNode;
146-
// Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type...
147-
return !!childrenNode.forEachChild(this.index_, (key, node) => {
148-
return action(
149-
new DataSnapshot(node, this.ref_.child(key), PRIORITY_INDEX)
150-
);
151-
});
121+
return this._delegate.forEach(expDataSnapshot =>
122+
action(new DataSnapshot(expDataSnapshot))
123+
);
152124
}
153125

154126
/**
@@ -157,16 +129,11 @@ export class DataSnapshot {
157129
*/
158130
hasChildren(): boolean {
159131
validateArgCount('DataSnapshot.hasChildren', 0, 0, arguments.length);
160-
161-
if (this.node_.isLeafNode()) {
162-
return false;
163-
} else {
164-
return !this.node_.isEmpty();
165-
}
132+
return this._delegate.hasChildren();
166133
}
167134

168135
get key() {
169-
return this.ref_.getKey();
136+
return this._delegate.key;
170137
}
171138

172139
/**
@@ -175,8 +142,7 @@ export class DataSnapshot {
175142
*/
176143
numChildren(): number {
177144
validateArgCount('DataSnapshot.numChildren', 0, 0, arguments.length);
178-
179-
return this.node_.numChildren();
145+
return this._delegate.size;
180146
}
181147

182148
/**
@@ -185,8 +151,7 @@ export class DataSnapshot {
185151
*/
186152
getRef(): Reference {
187153
validateArgCount('DataSnapshot.ref', 0, 0, arguments.length);
188-
189-
return this.ref_;
154+
return new Reference(this._delegate.ref._repo, this._delegate.ref._path);
190155
}
191156

192157
get ref() {

packages/database/src/api/Query.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { DataSnapshot as ExpDataSnapshot } from '../exp/DataSnapshot';
19+
import { Reference as ExpReference } from '../exp/Reference';
1820
import {
1921
assert,
2022
Deferred,
@@ -45,6 +47,7 @@ import {
4547
import {
4648
ChildEventRegistration,
4749
EventRegistration,
50+
ExpSnapshotCallback,
4851
ValueEventRegistration
4952
} from '../core/view/EventRegistration';
5053

@@ -71,7 +74,7 @@ import { DataSnapshot } from './DataSnapshot';
7174
let __referenceConstructor: new (repo: Repo, path: Path) => Query;
7275

7376
export interface SnapshotCallback {
74-
(a: DataSnapshot, b?: string | null): unknown;
77+
(dataSnapshot: DataSnapshot, previousChildName?: string | null): unknown;
7578
}
7679

7780
/**
@@ -215,19 +218,19 @@ export class Query {
215218
cancelCallbackOrContext,
216219
context
217220
);
218-
221+
const expCallback = new ExpSnapshotCallback(callback);
219222
if (eventType === 'value') {
220-
this.onValueEvent(callback, ret.cancel, ret.context);
223+
this.onValueEvent(expCallback, ret.cancel, ret.context);
221224
} else {
222-
const callbacks: { [k: string]: typeof callback } = {};
223-
callbacks[eventType] = callback;
225+
const callbacks: { [k: string]: ExpSnapshotCallback } = {};
226+
callbacks[eventType] = expCallback;
224227
this.onChildEvent(callbacks, ret.cancel, ret.context);
225228
}
226229
return callback;
227230
}
228231

229232
protected onValueEvent(
230-
callback: (a: DataSnapshot) => void,
233+
callback: ExpSnapshotCallback,
231234
cancelCallback: ((a: Error) => void) | null,
232235
context: object | null
233236
) {
@@ -239,8 +242,8 @@ export class Query {
239242
repoAddEventCallbackForQuery(this.repo, this, container);
240243
}
241244

242-
onChildEvent(
243-
callbacks: { [k: string]: SnapshotCallback },
245+
protected onChildEvent(
246+
callbacks: { [k: string]: ExpSnapshotCallback },
244247
cancelCallback: ((a: Error) => unknown) | null,
245248
context: object | null
246249
) {
@@ -261,20 +264,20 @@ export class Query {
261264
validateEventType('Query.off', 1, eventType, true);
262265
validateCallback('Query.off', 2, callback, true);
263266
validateContextObject('Query.off', 3, context, true);
264-
265267
let container: EventRegistration | null = null;
266-
let callbacks: { [k: string]: typeof callback } | null = null;
268+
let callbacks: { [k: string]: ExpSnapshotCallback } | null = null;
269+
270+
const expCallback = callback ? new ExpSnapshotCallback(callback) : null;
267271
if (eventType === 'value') {
268-
const valueCallback = callback || null;
269272
container = new ValueEventRegistration(
270-
valueCallback,
273+
expCallback,
271274
null,
272275
context || null
273276
);
274277
} else if (eventType) {
275278
if (callback) {
276279
callbacks = {};
277-
callbacks[eventType] = callback;
280+
callbacks[eventType] = expCallback;
278281
}
279282
container = new ChildEventRegistration(callbacks, null, context || null);
280283
}
@@ -285,7 +288,15 @@ export class Query {
285288
* Get the server-value for this query, or return a cached value if not connected.
286289
*/
287290
get(): Promise<DataSnapshot> {
288-
return repoGetValue(this.repo, this);
291+
return repoGetValue(this.repo, this).then(node => {
292+
return new DataSnapshot(
293+
new ExpDataSnapshot(
294+
node,
295+
new ExpReference(this.getRef().repo, this.getRef().path),
296+
this.getQueryParams().getIndex()
297+
)
298+
);
299+
});
289300
}
290301

291302
/**

packages/database/src/api/Reference.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { DataSnapshot as ExpDataSnapshot } from '../exp/DataSnapshot';
19+
import { Node } from '../core/snap/Node';
20+
import { Reference as ExpReference } from '../exp/Reference';
1821
import { OnDisconnect } from './onDisconnect';
1922
import { TransactionResult } from './TransactionResult';
2023
import { warn } from '../core/util/util';
@@ -51,6 +54,7 @@ import { Deferred, validateArgCount, validateCallback } from '@firebase/util';
5154
import { syncPointSetReferenceConstructor } from '../core/SyncPoint';
5255
import { Database } from './Database';
5356
import { DataSnapshot } from './DataSnapshot';
57+
import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex';
5458

5559
export interface ReferenceConstructor {
5660
new (repo: Repo, path: Path): Reference;
@@ -232,7 +236,11 @@ export class Reference extends Query {
232236

233237
transaction(
234238
transactionUpdate: (a: unknown) => unknown,
235-
onComplete?: (a: Error | null, b: boolean, c: DataSnapshot | null) => void,
239+
onComplete?: (
240+
error: Error | null,
241+
committed: boolean,
242+
dataSnapshot: DataSnapshot | null
243+
) => void,
236244
applyLocally?: boolean
237245
): Promise<TransactionResult> {
238246
validateArgCount('Reference.transaction', 1, 3, arguments.length);
@@ -260,18 +268,26 @@ export class Reference extends Query {
260268
deferred.promise.catch(() => {});
261269
}
262270

263-
const promiseComplete = function (
271+
const promiseComplete = (
264272
error: Error,
265273
committed: boolean,
266-
snapshot: DataSnapshot
267-
) {
274+
node: Node | null
275+
) => {
276+
let dataSnapshot: DataSnapshot | null = null;
268277
if (error) {
269278
deferred.reject(error);
270279
} else {
271-
deferred.resolve(new TransactionResult(committed, snapshot));
280+
dataSnapshot = new DataSnapshot(
281+
new ExpDataSnapshot(
282+
node,
283+
new ExpReference(this.repo, this.path),
284+
PRIORITY_INDEX
285+
)
286+
);
287+
deferred.resolve(new TransactionResult(committed, dataSnapshot));
272288
}
273289
if (typeof onComplete === 'function') {
274-
onComplete(error, committed, snapshot);
290+
onComplete(error, committed, dataSnapshot);
275291
}
276292
};
277293
repoStartTransaction(

0 commit comments

Comments
 (0)