-
-
Save churcho/079b2e75bbc8cf1b9d960154a15fd6d8 to your computer and use it in GitHub Desktop.
React Redux Meteor middlewares
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// loading user (compatible with react-router-ssr) | |
export function loadUserData() { | |
return { | |
type: USER_DATA, | |
meteor: { | |
subscribe: { | |
name: 'userData', | |
get: () => Meteor.users.findOne(Meteor.userId()) | |
} | |
} | |
} | |
} | |
// loading elements from collection | |
export function loadPosts() { | |
return { | |
type: POSTS, | |
meteor: { | |
subscribe: { | |
name: 'posts', | |
get: () => Posts.find().fetch() | |
} | |
} | |
} | |
} | |
// dispatching Meteor method | |
export function signIn(email, password) { | |
return { | |
type: USER_SIGNIN, | |
meteor: { | |
call: { | |
method: Meteor.loginWithPassword, | |
params: [email, password] | |
} | |
} | |
} | |
} | |
// dispatching Meteor call | |
export function checkUsername(username) { | |
return { | |
type: USER_CHECKUSERNAME, | |
meteor: { | |
call: { | |
method: 'users.usernameIsFree', | |
params: [{username}] | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function actionTypeBuilder(prefix) { | |
return { | |
type: actionType => `${prefix}/${actionType}`, | |
loading: actionType => `${actionType}/loading`, | |
ready: actionType => `${actionType}/ready`, | |
stopped: actionType => `${actionType}/stopped`, | |
changed: actionType => `${actionType}/changed`, | |
error: actionType => `${actionType}/error`, | |
success: actionType => `${actionType}/success` | |
}; | |
} | |
export default actionTypeBuilder('@myApp'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypeBuilder from './actionTypeBuilder'; | |
const comps = {}; | |
Meteor.comps = comps; | |
export default store => next => action => { | |
if (!action.meteor || (!action.meteor.get && !action.meteor.unsubscribe)) { | |
return next(action); | |
} | |
const { get, unsubscribe } = action.meteor; | |
return new Promise((resolve, reject) => { | |
if (Meteor.isServer) { | |
const data = get(); | |
next({ type: actionTypeBuilder.changed(action.type), data }); | |
return resolve(); | |
} | |
// If we already have an handle for this action | |
if (comps[action.type]) { | |
comps[action.type].stop(); | |
} | |
if (!unsubscribe) { | |
comps[action.type] = Tracker.autorun(() => { | |
const data = get(); | |
next({ type: actionTypeBuilder.changed(action.type), data }); | |
return resolve(); | |
}); | |
} | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypeBuilder from './actionTypeBuilder'; | |
export default store => next => action => { | |
if (!action.meteor || !action.meteor.call) { | |
return next(action); | |
} | |
const { method, params } = action.meteor.call; | |
const parameters = params || []; | |
const meteorMethod = typeof method === 'string' ? Meteor.call : method; | |
if (typeof method === 'string') { | |
parameters.unshift(method); | |
} | |
return new Promise((resolve, reject) => { | |
next({ type: actionTypeBuilder.loading(action.type) }); | |
meteorMethod(...parameters, (error, result) => { | |
if (error) { | |
next({ type: actionTypeBuilder.error(action.type), error }); | |
return reject(error); | |
} | |
next({ type: actionTypeBuilder.success(action.type) }); | |
return resolve(result); | |
}); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypeBuilder from './actionTypeBuilder'; | |
import { SUBSCRIPTIONS } from './subscriptionsActions'; | |
const subs = {}; | |
export default store => next => action => { | |
if (!action.meteor || (!action.meteor.subscribe && !action.meteor.unsubscribe)) { | |
return next(action); | |
} | |
return new Promise((resolve, reject) => { | |
const { name } = action.meteor.subscribe || action.meteor.unsubscribe; | |
const sub = subs[name]; | |
if (action.meteor.unsubscribe) { | |
if (sub) { | |
delete sub.subscribedActions[action.type]; | |
if (_.isEmpty(sub.subscribedActions)) { | |
sub.handle.stop(); | |
next({ type: actionTypeBuilder.stopped(SUBSCRIPTIONS), name } ); | |
} | |
} | |
return resolve(); | |
} | |
const { params, get } = action.meteor.subscribe; | |
const parameters = params || []; | |
if (Meteor.isServer && action.meteor.subscribe) { | |
Meteor.subscribe(name, ...parameters); | |
next({ type: actionTypeBuilder.ready(SUBSCRIPTIONS), name } ); | |
if (get) { | |
return next({ type: action.type, meteor : { get } }).then(() => resolve()); | |
} | |
return resolve(); | |
} | |
const existing = sub && _.isEqual(sub.parameters, parameters); | |
if (existing && sub.handle.ready()) { | |
if (! sub.subscribedActions[action.type]) { | |
sub.subscribedActions[action.type] = 'ready'; | |
} | |
if (get) { | |
return next({ type: action.type, meteor : { get } }).then(() => resolve()); | |
} | |
return resolve(); | |
} | |
if (sub && sub.handle.ready()) { | |
sub.handle.stop(); | |
} | |
next({ type: actionTypeBuilder.loading(SUBSCRIPTIONS), name }); | |
const handle = Meteor.subscribe(name, ...paramters, { | |
onReady: () => { | |
next({ type: actionTypeBuilder.ready(SUBSCRIPTIONS), name } ); | |
if (get) { | |
return next({ type: action.type, meteor : { get } }).then(() => resolve()); | |
} | |
return resolve(); | |
}, | |
onStop: (error) => { | |
if (error) { | |
next({ type: actionTypeBuilder.error(SUBSCRIPTIONS), name } ); | |
reject(error); | |
} | |
next({ type: actionTypeBuilder.stopped(SUBSCRIPTIONS), name } ); | |
delete subs[name]; | |
} | |
}); | |
subs[name] = { | |
subscribedActions: {[action.type]: 'ready'}, | |
parameters: _.clone(parameters), | |
handle: handle | |
}; | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default function(state = [], action) { | |
const { type, data } = action; | |
switch (type) { | |
case actionTypeBuilder.changed(POSTS): | |
return data; | |
default: | |
return state; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypeBuilder from './actionTypeBuilder'; | |
export const SUBSCRIPTIONS = actionTypeBuilder.type('SUBSCRIPTIONS'); | |
export function subscribeTo(name, type, ...params) { | |
return { | |
type: type, | |
meteor: { | |
subscribe: { | |
name: name, | |
params: params | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypeBuilder from './actionTypeBuilder'; | |
import { SUBSCRIPTIONS } from './subscriptionsActions'; | |
const initialState = {}; | |
export default function(state = initialState, action) { | |
const { type, name } = action; | |
switch (type) { | |
case actionTypeBuilder.ready(SUBSCRIPTIONS): | |
return {...state, [name]: {ready: true} }; | |
case actionTypeBuilder.loading(SUBSCRIPTIONS): | |
return {...state, [name]: {ready: false, loading: true} }; | |
case actionTypeBuilder.stopped(SUBSCRIPTIONS): | |
return {...state, [name]: {ready: false, loading: false} }; | |
case actionTypeBuilder.error(SUBSCRIPTIONS): | |
return {...state, [name]: {ready: false, error: true, loading: false} }; | |
default: | |
return state; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment