Last active
January 25, 2022 09:02
-
-
Save dbismut/35b89185998d68bc18fd 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 loadUserLoggingIn() { | |
return { | |
type: USER_LOGGING_IN, | |
meteor: { | |
get: () => Meteor.loggingIn() | |
} | |
}; | |
} | |
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 = {}; | |
export default store => next => action => { | |
if (!action.meteor || (!action.meteor.get && !action.meteor.unsubscribe)) { | |
return next(action); | |
} | |
const { get, unsubscribe } = action.meteor; | |
if (Meteor.isServer) { | |
const data = get(); | |
next({ type: actionTypeBuilder.changed(action.type), data }); | |
return Promise.resolve(); | |
} | |
// If we already have an handle for this action | |
if (comps[action.type]) { | |
if (unsubscribe) { | |
comps[action.type].stop(); | |
} | |
const data = get(); | |
next({ type: actionTypeBuilder.changed(action.type), data }); | |
return Promise.resolve(); | |
} | |
return new Promise((resolve, reject) => { | |
comps[action.type] = Tracker.autorun(() => { | |
const data = get(); | |
next({ type: actionTypeBuilder.changed(action.type), data }); | |
return resolve(); | |
}); | |
comps[action.type].onStop(() => { | |
next({ type: actionTypeBuilder.stopped(action.type), name } ); | |
delete comps[action.type]; | |
}); | |
}); | |
}; |
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, showError } = 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, function(error, result) { | |
if (error) { | |
next({ type: actionTypeBuilder.error(action.type), error }); | |
if(showError) { | |
next(showNotification(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); | |
} | |
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(); | |
} | |
} | |
return Promise.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 } }); | |
} | |
return Promise.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 } }); | |
} | |
return Promise.resolve(); | |
} | |
if (sub && sub.handle.ready()) { | |
sub.handle.stop(); | |
} | |
return new Promise((resolve, reject) => { | |
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) => { | |
next({ type: actionTypeBuilder.stopped(SUBSCRIPTIONS), name } ); | |
delete subs[name]; | |
if (error) { | |
next({ type: actionTypeBuilder.error(SUBSCRIPTIONS), name, error } ); | |
reject(error); | |
} | |
} | |
}); | |
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
Btw thank you very much for this gist!