Skip to content

Commit 87d605e

Browse files
committed
merge firebase 3.0 changes
1 parent 0cb23f8 commit 87d605e

File tree

9 files changed

+139
-46
lines changed

9 files changed

+139
-46
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"browserify": "^6.3.2",
3030
"browserify-shim": "^3.8.0",
3131
"firebase-auto-ids": "~1.1.0",
32-
"lodash": "~2.4.1"
32+
"lodash": "~2.4.1",
33+
"rsvp": "^3.3.3"
3334
},
3435
"devDependencies": {
3536
"chai": "~1.9.1",

src/auth.js

Lines changed: 111 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
var _ = require('lodash');
44
var format = require('util').format;
5+
var rsvp = require('rsvp');
56

67
function FirebaseAuth () {
8+
this.currentUser = null;
79
this._auth = {
8-
userData: null,
910
listeners: [],
1011
completionListeners: [],
1112
users: [],
@@ -15,13 +16,34 @@ function FirebaseAuth () {
1516

1617
FirebaseAuth.prototype.changeAuthState = function (userData) {
1718
this._defer('changeAuthState', _.toArray(arguments), function() {
18-
if (!_.isEqual(this._auth.userData, userData)) {
19-
this._auth.userData = _.isObject(userData) ? userData : null;
19+
if (!_.isEqual(this.currentUser, userData)) {
20+
this.currentUser = _.isObject(userData) ? userData : null;
2021
this._triggerAuthEvent();
2122
}
2223
});
2324
};
2425

26+
FirebaseAuth.prototype.onAuthStateChanged = function (callback) {
27+
var self = this;
28+
var currentUser = this.currentUser;
29+
this._auth.listeners.push({fn: callback});
30+
31+
defer();
32+
return destroy;
33+
34+
function destroy() {
35+
self.offAuth(callback);
36+
}
37+
38+
function defer() {
39+
self._defer('onAuthStateChanged', _.toArray(arguments), function() {
40+
if (!_.isEqual(self.currentUser, currentUser)) {
41+
self._triggerAuthEvent();
42+
}
43+
});
44+
}
45+
};
46+
2547
FirebaseAuth.prototype.getEmailUser = function (email) {
2648
var users = this._auth.users;
2749
return users.hasOwnProperty(email) ? _.clone(users[email]) : null;
@@ -46,12 +68,66 @@ Object.keys(authMethods)
4668
};
4769
});
4870

71+
var signinMethods = {
72+
signInWithCustomToken: function(authToken) {
73+
return {
74+
isAnonymous: false
75+
};
76+
},
77+
signInAnonymously: function() {
78+
return {
79+
isAnonymous: true
80+
};
81+
},
82+
signInWithEmailAndPassword: function(email, password) {
83+
return {
84+
isAnonymous: false,
85+
email: email
86+
};
87+
},
88+
signInWithPopup: function(provider) {
89+
return {
90+
isAnonymous: false,
91+
providerData: [provider]
92+
};
93+
},
94+
signInWithRedirect: function(provider) {
95+
return {
96+
isAnonymous: false,
97+
providerData: [provider]
98+
};
99+
},
100+
signInWithCredential: function(credential) {
101+
return {
102+
isAnonymous: false
103+
};
104+
}
105+
};
106+
107+
Object.keys(signinMethods)
108+
.forEach(function (method) {
109+
var getUser = signinMethods[method];
110+
FirebaseAuth.prototype[method] = function () {
111+
var self = this;
112+
var user = getUser.apply(this, arguments);
113+
var promise = new rsvp.Promise(function(resolve, reject) {
114+
self._authEvent(method, function(err) {
115+
if (err) reject(err);
116+
self.currentUser = user;
117+
resolve(user);
118+
self._triggerAuthEvent();
119+
}, true);
120+
});
121+
return promise;
122+
};
123+
});
124+
49125
FirebaseAuth.prototype.auth = function (token, callback) {
50126
console.warn('FIREBASE WARNING: FirebaseRef.auth() being deprecated. Please use FirebaseRef.authWithCustomToken() instead.');
51127
this._authEvent('auth', callback);
52128
};
53129

54-
FirebaseAuth.prototype._authEvent = function (method, callback) {
130+
FirebaseAuth.prototype._authEvent = function (method, callback, defercallback) {
55131
var err = this._nextErr(method);
56132
if (!callback) return;
57133
if (err) {
@@ -62,26 +138,33 @@ FirebaseAuth.prototype._authEvent = function (method, callback) {
62138
});
63139
}
64140
else {
65-
// if there is no error, then we just add our callback to the listener
66-
// stack and wait for the next changeAuthState() call.
67-
this._auth.completionListeners.push({fn: callback});
141+
if (defercallback) {
142+
this._defer(method, _.toArray(arguments), function() {
143+
callback();
144+
});
145+
} else {
146+
// if there is no error, then we just add our callback to the listener
147+
// stack and wait for the next changeAuthState() call.
148+
this._auth.completionListeners.push({fn: callback});
149+
}
68150
}
69151
};
70152

71153
FirebaseAuth.prototype._triggerAuthEvent = function () {
72154
var completionListeners = this._auth.completionListeners;
73155
this._auth.completionListeners = [];
74-
var user = this._auth.userData;
156+
var user = this.currentUser;
75157
completionListeners.forEach(function (parts) {
76158
parts.fn.call(parts.context, null, _.cloneDeep(user));
77159
});
78-
this._auth.listeners.forEach(function (parts) {
160+
var listeners = _.cloneDeep(this._auth.listeners);
161+
listeners.forEach(function (parts) {
79162
parts.fn.call(parts.context, _.cloneDeep(user));
80163
});
81164
};
82165

83166
FirebaseAuth.prototype.getAuth = function () {
84-
return this._auth.userData;
167+
return this.currentUser;
85168
};
86169

87170
FirebaseAuth.prototype.onAuth = function (onComplete, context) {
@@ -102,12 +185,28 @@ FirebaseAuth.prototype.offAuth = function (onComplete, context) {
102185
};
103186

104187
FirebaseAuth.prototype.unauth = function () {
105-
if (this._auth.userData !== null) {
106-
this._auth.userData = null;
188+
if (this.currentUser !== null) {
189+
this.currentUser = null;
107190
this._triggerAuthEvent();
108191
}
109192
};
110193

194+
FirebaseAuth.prototype.signOut = function () {
195+
var self = this, updateuser = this.currentUser !== null;
196+
var promise = new rsvp.Promise(function(resolve, reject) {
197+
self._authEvent('signOut', function(err) {
198+
if (err) reject(err);
199+
self.currentUser = null;
200+
resolve();
201+
202+
if (updateuser) {
203+
self._triggerAuthEvent();
204+
}
205+
}, true);
206+
});
207+
return promise;
208+
};
209+
111210
FirebaseAuth.prototype.createUser = function (credentials, onComplete) {
112211
validateCredentials('createUser', credentials, [
113212
'email',

src/firebase.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ var Auth = require('./auth');
1111
var validate = require('./validators');
1212

1313
function MockFirebase (path, data, parent, name) {
14+
this.ref = this;
1415
this.path = path || 'Mock://';
1516
this.errs = {};
1617
this.priority = null;
@@ -198,10 +199,6 @@ MockFirebase.prototype.name = function () {
198199
return this.key.apply(this, arguments);
199200
};
200201

201-
MockFirebase.prototype.ref = function () {
202-
return this;
203-
};
204-
205202
MockFirebase.prototype.parent = function () {
206203
return this.parentRef;
207204
};
@@ -299,7 +296,7 @@ MockFirebase.prototype.off = function (event, callback, context) {
299296
});
300297
}
301298
else {
302-
this._events[event] = [];
299+
this._events[event] = [];
303300
}
304301
}
305302
};
@@ -376,7 +373,7 @@ MockFirebase.prototype._dataChanged = function (unparsedData) {
376373
keysToChange.forEach(function(key) {
377374
var childData = unparsedData[key];
378375
if (utils.isServerTimestamp(childData)) {
379-
childData = getServerTime();
376+
childData = getServerTime();
380377
}
381378
this._updateOrAdd(key, childData, events);
382379
}, this);

src/query.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,20 @@ var utils = require('./utils');
66
var validate = require('./validators');
77

88
function MockQuery (ref) {
9-
this.ref = function () {
10-
return ref;
11-
};
9+
this.ref = ref;
1210
this._events = [];
1311
// startPri, endPri, startKey, endKey, and limit
1412
this._q = {};
1513
}
1614

1715
MockQuery.prototype.flush = function () {
18-
var ref = this.ref();
16+
var ref = this.ref;
1917
ref.flush.apply(ref, arguments);
2018
return this;
2119
};
2220

2321
MockQuery.prototype.autoFlush = function () {
24-
var ref = this.ref();
22+
var ref = this.ref;
2523
ref.autoFlush.apply(ref, arguments);
2624
return this;
2725
};
@@ -57,7 +55,7 @@ MockQuery.prototype.on = function (event, callback, cancelCallback, context) {
5755
var lastSlice = this.slice();
5856
var map;
5957
function handleRefEvent (snap, prevChild) {
60-
var slice = new Slice(self, event === 'value' ? snap : utils.makeRefSnap(snap.ref().parent()));
58+
var slice = new Slice(self, event === 'value' ? snap : utils.makeRefSnap(snap.ref.parent()));
6159
switch (event) {
6260
case 'value':
6361
if (isFirst || !lastSlice.equals(slice)) {
@@ -104,11 +102,11 @@ MockQuery.prototype.on = function (event, callback, cancelCallback, context) {
104102
lastSlice = slice;
105103
}
106104
this._events.push([event, callback, context, handleRefEvent]);
107-
this.ref().on(event, handleRefEvent, _.bind(cancelCallback, context));
105+
this.ref.on(event, handleRefEvent, _.bind(cancelCallback, context));
108106
};
109107

110108
MockQuery.prototype.off = function (event, callback, context) {
111-
var ref = this.ref();
109+
var ref = this.ref;
112110
_.each(this._events, function (parts) {
113111
if( parts[0] === event && parts[1] === callback && parts[2] === context ) {
114112
ref.off(event, parts[3]);
@@ -133,21 +131,21 @@ MockQuery.prototype.limit = function (intVal) {
133131
if( typeof intVal !== 'number' ) {
134132
throw new Error('Query.limit: First argument must be a positive integer.');
135133
}
136-
var q = new MockQuery(this.ref());
134+
var q = new MockQuery(this.ref);
137135
_.extend(q._q, this._q, {limit: intVal});
138136
return q;
139137
};
140138

141139
MockQuery.prototype.startAt = function (priority, key) {
142140
assertQuery('Query.startAt', priority, key);
143-
var q = new MockQuery(this.ref());
141+
var q = new MockQuery(this.ref);
144142
_.extend(q._q, this._q, {startKey: key, startPri: priority});
145143
return q;
146144
};
147145

148146
MockQuery.prototype.endAt = function (priority, key) {
149147
assertQuery('Query.endAt', priority, key);
150-
var q = new MockQuery(this.ref());
148+
var q = new MockQuery(this.ref);
151149
_.extend(q._q, this._q, {endKey: key, endPri: priority});
152150
return q;
153151
};

src/slice.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ var Snapshot = require('./snapshot');
55
var utils = require('./utils');
66

77
function Slice (queue, snap) {
8-
var data = snap? snap.val() : queue.ref().getData();
9-
this.ref = snap? snap.ref() : queue.ref();
8+
var data = snap? snap.val() : queue.ref.getData();
9+
this.ref = snap? snap.ref : queue.ref;
1010
this.priority = snap? snap.getPriority() : this.ref.priority;
1111
this.pris = {};
1212
this.data = {};

src/snapshot.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
var _ = require('lodash');
44

55
function MockDataSnapshot (ref, data, priority) {
6-
this.ref = function () {
7-
return ref;
8-
};
6+
this.ref = ref;
97
data = _.cloneDeep(data);
108
if (_.isObject(data) && _.isEmpty(data)) {
119
data = null;
@@ -19,9 +17,9 @@ function MockDataSnapshot (ref, data, priority) {
1917
}
2018

2119
MockDataSnapshot.prototype.child = function (key) {
22-
var ref = this.ref().child(key);
20+
var ref = this.ref.child(key);
2321
var data = this.hasChild(key) ? this.val()[key] : null;
24-
var priority = this.ref().child(key).priority;
22+
var priority = this.ref.child(key).priority;
2523
return new MockDataSnapshot(ref, data, priority);
2624
};
2725

@@ -44,7 +42,7 @@ MockDataSnapshot.prototype.hasChildren = function () {
4442
};
4543

4644
MockDataSnapshot.prototype.key = function () {
47-
return this.ref().key();
45+
return this.ref.key();
4846
};
4947

5048
MockDataSnapshot.prototype.name = function () {

test/unit/firebase.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ describe('MockFirebase', function () {
199199
ref.flush();
200200
expect(spy.callCount).to.equal(1);
201201
var snapshot = spy.firstCall.args[0];
202-
expect(snapshot.ref()).to.equal(ref);
202+
expect(snapshot.ref).to.equal(ref);
203203
expect(snapshot.val()).to.deep.equal(data);
204204
expect(snapshot.getPriority()).to.equal(null);
205205
});
@@ -215,7 +215,7 @@ describe('MockFirebase', function () {
215215
ref.flush();
216216
expect(spy.callCount).to.equal(1);
217217
var snapshot = spy.firstCall.args[0];
218-
expect(snapshot.ref()).to.equal(ref.child('theKey'));
218+
expect(snapshot.ref).to.equal(ref.child('theKey'));
219219
expect(spy.firstCall.args[1]).to.equal('prevChild');
220220
expect(snapshot.getPriority()).to.equal(1);
221221
});
@@ -270,7 +270,7 @@ describe('MockFirebase', function () {
270270
describe('#ref', function () {
271271

272272
it('returns itself', function () {
273-
expect(ref.ref()).to.equal(ref);
273+
expect(ref.ref).to.equal(ref);
274274
});
275275

276276
});

0 commit comments

Comments
 (0)