@signalwire/core
Version:
Shared code for the SignalWire JS SDK
113 lines (102 loc) • 2.87 kB
text/typescript
import { Store } from 'redux'
import createSagaMiddleware, {
channel,
multicastChannel,
Saga,
Task,
} from '@redux-saga/core'
import { configureStore as rtConfigureStore } from './toolkit'
import { rootReducer } from './rootReducer'
import rootSaga from './rootSaga'
import { SDKState, SessionChannel, SwEventChannel } from './interfaces'
import { connect } from './connect'
import {
InternalUserOptions,
SessionConstructor,
InternalChannels,
} from '../utils/interfaces'
import { useSession } from './utils/useSession'
import { useInstanceMap } from './utils/useInstanceMap'
export interface ConfigureStoreOptions {
userOptions: InternalUserOptions
SessionConstructor: SessionConstructor
runRootSaga?: boolean
preloadedState?: Partial<SDKState>
}
export type SDKStore = ReturnType<typeof configureStore>
export type SDKRunSaga = <S extends Saga>(
saga: S,
params?: Parameters<S>[0]
) => Task
const configureStore = (options: ConfigureStoreOptions) => {
const {
userOptions,
SessionConstructor,
preloadedState = {},
runRootSaga = true,
} = options
const sagaMiddleware = createSagaMiddleware({
// @ts-expect-error For testing purposes only
sagaMonitor: userOptions.sagaMonitor,
})
const swEventChannel: SwEventChannel = multicastChannel()
const sessionChannel: SessionChannel = channel()
/**
* List of channels that are gonna be shared across all
* sagas.
*/
const channels: InternalChannels = {
swEventChannel,
sessionChannel,
}
const store = rtConfigureStore({
devTools: userOptions?.devTools ?? true,
reducer: rootReducer,
preloadedState,
middleware: (getDefaultMiddleware) =>
// It is preferrable to use the chainable .concat(...) and
// .prepend(...) methods of the returned MiddlewareArray instead
// of the array spread operator, as the latter can lose valuable
// type information under some circumstances.
// @see https://redux-toolkit.js.org/api/getDefaultMiddleware#intended-usage
getDefaultMiddleware().concat(sagaMiddleware),
}) as Store
const instanceMap = useInstanceMap()
const { initSession, getSession, sessionEmitter } = useSession({
userOptions,
sessionChannel,
SessionConstructor,
})
const runSaga = <T>(
saga: Saga,
args: {
instance: T
runSaga: any
}
) => {
return sagaMiddleware.run(saga, {
...args,
channels,
getSession,
instanceMap,
})
}
if (runRootSaga) {
const saga = rootSaga({
initSession,
sessionEmitter,
})
sagaMiddleware.run(saga, { userOptions, channels })
}
return {
...store,
runSaga,
channels,
instanceMap,
sessionEmitter,
}
}
export { connect, configureStore }
export * from './actions'
export * from './utils/sagaHelpers'
export * from './toolkit'