UNPKG

2.65 kBJavaScriptView Raw
1import { createSelector } from 'redux-bundler'
2
3const FIREBASE_CONNECTED = 'FIREBASE_CONNECTED'
4const FIREBASE_DISCONNECTED = 'FIREBASE_DISCONNECTED'
5const FIREBASE_AUTHED = 'FIREBASE_AUTHED'
6const FIREBASE_AUTHENTICATING = 'FIREBASE_AUTHENTICATING'
7export const FIREBASE_TOKEN_FAILED = 'FIREBASE_TOKEN_FAILED'
8
9export default (fb) => ({
10 name: 'firebase',
11 selectFirebaseState: state => state.firebase,
12 selectFirebaseConnected: state => state.firebase.connected,
13 selectFirebaseAuthed: state => state.firebase.authed,
14 selectFirebaseAuthUserId: createSelector(
15 'selectFirebaseAuthed',
16 (fbAuthed) => {
17 const { currentUser } = fb.auth()
18 return currentUser && currentUser.uid
19 }
20 ),
21 doFirebaseAuth: (fbToken) => ({dispatch}) => {
22 dispatch({type: FIREBASE_AUTHENTICATING})
23 fb.auth().signInWithCustomToken(fbToken).then((user) => {
24 dispatch({type: FIREBASE_AUTHED})
25 })
26 .catch((error) => {
27 if (error.code === 'auth/invalid-custom-token') {
28 dispatch({type: FIREBASE_TOKEN_FAILED})
29 }
30 })
31 },
32 getReducer: () => {
33 const initialState = {
34 connected: false,
35 authed: !!fb.auth().currentUser,
36 disconnectedAt: null,
37 connectedAt: null,
38 loggingIn: false
39 }
40 return (state = initialState, {type}) => {
41 if (type === FIREBASE_DISCONNECTED) {
42 return Object.assign({}, state, {
43 connected: false,
44 disconnectedAt: Date.now()
45 })
46 }
47 if (type === FIREBASE_CONNECTED) {
48 return Object.assign({}, state, {
49 connected: true,
50 connectedAt: Date.now()
51 })
52 }
53 if (type === FIREBASE_AUTHED) {
54 return Object.assign({}, state, {
55 authed: true,
56 loggingIn: false
57 })
58 }
59 if (type === FIREBASE_TOKEN_FAILED) {
60 return Object.assign({}, state, {
61 authed: false,
62 loggingIn: false
63 })
64 }
65 if (type === FIREBASE_AUTHENTICATING) {
66 return Object.assign({}, state, {
67 loggingIn: true
68 })
69 }
70 return state
71 }
72 },
73 init: (store) => {
74 fb.database().ref('.info/connected').on('value', (snap) => {
75 if (snap.val()) {
76 store.dispatch({type: FIREBASE_CONNECTED})
77 } else if (store.selectFirebaseConnected()) {
78 store.dispatch({type: FIREBASE_DISCONNECTED})
79 }
80 })
81 },
82 reactShouldAuthFirebase: createSelector(
83 'selectFirebaseToken',
84 'selectFirebaseState',
85 (token, fb) => {
86 if (token && !fb.authed && !fb.loggingIn) {
87 return {actionCreator: 'doFirebaseAuth', args: [token]}
88 }
89 }
90 )
91})