-
-
Save michaltakac/d5b655b6e593bf2c46c9b02b9fe1eddc to your computer and use it in GitHub Desktop.
React Redux Meteor middlewares
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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, ...parameters, { | |
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 hidden or 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 hidden or 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 hidden or 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