Skip to content

Commit 36bc391

Browse files
committed
- push is now sync with no value OR async with a value
- added key property to refs - added parent property to refs - added root property to refs - added toString method to refs
1 parent 4960ecd commit 36bc391

File tree

1 file changed

+95
-84
lines changed

1 file changed

+95
-84
lines changed

lib/modules/database/reference.js

Lines changed: 95 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
* @flow
33
*/
44
import { NativeModules } from 'react-native';
5-
import { promisify } from './../../utils';
6-
import { ReferenceBase } from './../base';
7-
import Snapshot from './snapshot.js';
8-
import Disconnect from './disconnect.js';
5+
96
import Query from './query.js';
7+
import Snapshot from './snapshot';
8+
import Disconnect from './disconnect';
9+
import { ReferenceBase } from './../base';
10+
import { promisify, isFunction, isObject, tryJSONParse, tryJSONStringify, generatePushID } from './../../utils';
1011

1112
const FirestackDatabase = NativeModules.FirestackDatabase;
1213

@@ -26,29 +27,12 @@ export default class Reference extends ReferenceBase {
2627
super(db.firestack, path);
2728

2829
this.db = db;
29-
this.query = new Query(this, path, existingModifiers);
30-
this.uid = uid++; // uuid.v4();
30+
this.uid = uid += 1;
3131
this.listeners = {};
32-
33-
// Aliases
34-
this.get = this.getAt;
35-
this.set = this.setAt;
36-
this.update = this.updateAt;
37-
this.remove = this.removeAt;
38-
32+
this.query = new Query(this, path, existingModifiers);
3933
this.log.debug('Created new Reference', this.dbPath(), this.uid);
4034
}
4135

42-
// Parent roots
43-
parent() {
44-
const parentPaths = this.path.slice(0, -1);
45-
return new Reference(this.db, parentPaths);
46-
}
47-
48-
root() {
49-
return new Reference(this.db, []);
50-
}
51-
5236
child(...paths: Array<string>) {
5337
return new Reference(this.db, this.path.concat(paths));
5438
}
@@ -59,38 +43,53 @@ export default class Reference extends ReferenceBase {
5943
}
6044

6145
// Get the value of a ref either with a key
62-
getAt() {
46+
// todo - where is this on the FB JS api - seems just like another random function
47+
get() {
6348
const path = this.dbPath();
6449
const modifiers = this.query.getModifiers();
6550
const modifiersString = this.query.getModifiersString();
6651
return promisify('onOnce', FirestackDatabase)(path, modifiersString, modifiers, 'value');
6752
}
6853

69-
setAt(val: any) {
54+
set(value: any) {
7055
const path = this.dbPath();
71-
const value = this._serializeValue(val);
72-
return promisify('set', FirestackDatabase)(path, value);
56+
const _value = this._serializeAnyType(value);
57+
return promisify('set', FirestackDatabase)(path, _value);
7358
}
7459

75-
updateAt(val: any) {
60+
update(val: Object) {
7661
const path = this.dbPath();
77-
const value = this._serializeValue(val);
62+
const value = this._serializeObject(val);
7863
return promisify('update', FirestackDatabase)(path, value);
7964
}
8065

81-
// TODO - what is key even for here?
82-
removeAt(key: string) {
83-
const path = this.dbPath();
84-
return promisify('remove', FirestackDatabase)(path);
66+
remove() {
67+
return promisify('remove', FirestackDatabase)(this.dbPath());
8568
}
8669

87-
push(val: any = {}) {
70+
/**
71+
*
72+
* @param value
73+
* @param onComplete
74+
* @returns {*}
75+
*/
76+
push(value: any, onComplete: Function) {
77+
if (value === null || value === undefined) {
78+
// todo add server timestamp to push id call.
79+
const _paths = this.path.concat([generatePushID()]);
80+
return new Reference(this.db, _paths);
81+
}
82+
8883
const path = this.dbPath();
89-
const value = this._serializeValue(val);
90-
return promisify('push', FirestackDatabase)(path, value)
84+
const _value = this._serializeAnyType(value);
85+
return promisify('push', FirestackDatabase)(path, _value)
9186
.then(({ ref }) => {
92-
const separator = '/';
93-
return new Reference(this.db, ref.split(separator));
87+
const newRef = new Reference(this.db, ref.split('/'));
88+
if (isFunction(onComplete)) return onComplete(null, newRef);
89+
return newRef;
90+
}).catch((e) => {
91+
if (isFunction(onComplete)) return onComplete(e, null);
92+
return e;
9493
});
9594
}
9695

@@ -100,7 +99,7 @@ export default class Reference extends ReferenceBase {
10099
const modifiersString = this.query.getModifiersString();
101100
this.log.debug('adding reference.on', path, modifiersString, evt);
102101
return this.db.storeRef(this.uid, this).then(() => {
103-
return this.db.on(this.uid, path, modifiersString, modifiers, evt, cb).then(subscriptions => {
102+
return this.db.on(this.uid, path, modifiersString, modifiers, evt, cb).then((subscriptions) => {
104103
this.listeners[evt] = subscriptions;
105104
});
106105
});
@@ -111,12 +110,11 @@ export default class Reference extends ReferenceBase {
111110
const modifiers = this.query.getModifiers();
112111
const modifiersString = this.query.getModifiersString();
113112
return this.db.storeRef(this.uid, this).then(() => {
113+
// todo use event emitter - not callbacks
114114
return promisify('onOnce', FirestackDatabase)(path, modifiersString, modifiers, evt)
115115
.then(({ snapshot }) => new Snapshot(this, snapshot))
116-
.then(snapshot => {
117-
if (cb && typeof cb === 'function') {
118-
cb(snapshot);
119-
}
116+
.then((snapshot) => {
117+
if (isFunction(cb)) cb(snapshot);
120118
return snapshot;
121119
});
122120
});
@@ -128,49 +126,50 @@ export default class Reference extends ReferenceBase {
128126
const modifiersString = this.query.getModifiersString();
129127
this.log.debug('ref.off(): ', path, modifiers, evt);
130128
return this.db.unstoreRef(this.uid).then(() => {
131-
return this.db.off(this.uid, path, modifiersString, modifiers, evt, origCB).then(subscriptions => {
129+
return this.db.off(this.uid, path, modifiersString, modifiers, evt, origCB).then(() => {
130+
// todo urm - whats this?
132131
// delete this.listeners[eventName];
133132
// this.listeners[evt] = subscriptions;
134133
});
135134
});
136135
}
137136

138137
cleanup() {
139-
let promises = Object.keys(this.listeners)
140-
.map(key => this.off(key));
141-
return Promise.all(promises);
142-
}
143-
144-
// Sanitize value
145-
// As Firebase cannot store date objects.
146-
_serializeValue(obj: Object = {}) {
147-
if (!obj) {
148-
return obj;
149-
}
150-
return Object.keys(obj).reduce((sum, key) => {
151-
let val = obj[key];
152-
if (val instanceof Date) {
153-
val = val.toISOString();
154-
}
138+
return Promise.all(Object.keys(this.listeners).map(key => this.off(key)));
139+
}
140+
141+
/**
142+
*
143+
* @param obj
144+
* @returns {Object}
145+
* @private
146+
*/
147+
_serializeObject(obj: Object) {
148+
if (!isObject(obj)) return obj;
149+
150+
// json stringify then parse it calls toString on Objects / Classes
151+
// that support it i.e new Date() becomes a ISO string.
152+
return tryJSONParse(tryJSONStringify(obj));
153+
}
154+
155+
/**
156+
*
157+
* @param value
158+
* @returns {*}
159+
* @private
160+
*/
161+
_serializeAnyType(value: any) {
162+
if (isObject(value)) {
155163
return {
156-
...sum,
157-
[key]: val,
164+
type: 'object',
165+
value: this._serializeObject(value),
158166
};
159-
}, {});
160-
}
167+
}
161168

162-
// TODO this function isn't used anywhere - why is it here?
163-
_deserializeValue(obj: Object = {}) {
164-
return Object.keys(obj).reduce((sum, key) => {
165-
let val = obj[key];
166-
if (val instanceof Date) {
167-
val = val.getTime();
168-
}
169-
return {
170-
...sum,
171-
[key]: val,
172-
};
173-
}, {});
169+
return {
170+
type: typeof value,
171+
value,
172+
};
174173
}
175174

176175
// Modifiers
@@ -242,24 +241,36 @@ export default class Reference extends ReferenceBase {
242241
}
243242

244243
// attributes
245-
get fullPath(): string {
244+
toString(): string {
246245
return this.dbPath();
247246
}
248247

249-
get name(): string {
250-
return this.path.splice(-1);
251-
}
248+
dbPath(paths?: Array<string>): string {
249+
const path = paths || this.path;
250+
const pathStr = (path.length > 0 ? path.join('/') : '/');
252251

253-
dbPath(): string {
254-
let path = this.path;
255-
let pathStr = (path.length > 0 ? path.join('/') : '/');
256252
if (pathStr[0] !== '/') {
257-
pathStr = `/${pathStr}`;
253+
return `/${pathStr}`;
258254
}
255+
259256
return pathStr;
260257
}
261258

262259
get namespace(): string {
263260
return 'firestack:dbRef';
264261
}
262+
263+
get key(): string|null {
264+
if (!this.path.length) return null;
265+
return this.path.slice(this.path.length - 1, this.path.length)[0];
266+
}
267+
268+
get parent(): Reference|null {
269+
if (!this.path.length || this.path.length === 1) return null;
270+
return new Reference(this.db, this.path.slice(0, -1));
271+
}
272+
273+
get root(): Reference {
274+
return new Reference(this.db, []);
275+
}
265276
}

0 commit comments

Comments
 (0)