Skip to content

Commit

Permalink
change the scope of the contextBridge bindings to only expose high le…
Browse files Browse the repository at this point in the history
…vel API
  • Loading branch information
matmalkowski committed May 28, 2021
1 parent debd89a commit 5c1b94e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 49 deletions.
50 changes: 42 additions & 8 deletions src/preload.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { contextBridge } from 'electron'
import { StoreEnhancer, Action } from 'redux'
import { createComposer } from './composeWithStateSync'
import { RendererStateSyncEnhancerOptions } from './options/RendererStateSyncEnhancerOptions'
import { StateSyncOptions } from './options/StateSyncOptions'
import { fetchInitialState } from './renderer/fetchInitialState'
import { fetchInitialStateAsync } from './renderer/fetchInitialStateAsync'
import { forwardActionToMain } from './renderer/forwardActionToMain'
import { subscribeToIPCAction } from './renderer/subscribeToIPCAction'
import { preventDoubleInitialization, stopForwarding } from './utils'
import { forwardAction } from './utils/forwardAction'
import { withStoreReplacer, replaceState } from './utils/replaceState'

declare global {
interface Bridge {
fetchInitialState: typeof fetchInitialState
fetchInitialStateAsync: typeof fetchInitialStateAsync
forwardActionToMain: typeof forwardActionToMain
subscribeToIPCAction: typeof subscribeToIPCAction
stateSyncEnhancer: typeof stateSyncEnhancer
composeWithStateSync: typeof composeWithStateSync
}
interface Window {
__ElectronReduxBridge: Bridge
Expand All @@ -18,12 +23,41 @@ declare global {
const __ElectronReduxBridge: Bridge
}

const stateSyncEnhancer = (options: RendererStateSyncEnhancerOptions = {}): StoreEnhancer => (
createStore
) => {
preventDoubleInitialization()

return (reducer, state) => {
const initialState = options.lazyInit ? state : fetchInitialState<typeof state>(options)

const store = createStore(
options.lazyInit ? withStoreReplacer(reducer) : reducer,
initialState
)

if (options.lazyInit) {
fetchInitialStateAsync(options, (asyncState) => {
store.dispatch(replaceState(asyncState) as never)
})
}

// When receiving an action from main
subscribeToIPCAction((action: Action) => store.dispatch(stopForwarding(action)))

return forwardAction(store, forwardActionToMain, options)
}
}

const composeWithStateSync = (
firstFuncOrOpts: StoreEnhancer | StateSyncOptions,
...funcs: StoreEnhancer[]
) => createComposer(stateSyncEnhancer, forwardActionToMain)(firstFuncOrOpts, ...funcs)

export const preload = (): void => {
const bridge = {
fetchInitialState,
fetchInitialStateAsync,
forwardActionToMain,
subscribeToIPCAction,
stateSyncEnhancer,
composeWithStateSync,
}

try {
Expand Down
58 changes: 17 additions & 41 deletions src/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Action, StoreEnhancer } from 'redux'
import { forwardAction } from './utils/forwardAction'
import { replaceState, withStoreReplacer } from './utils/replaceState'
import { StoreEnhancer } from 'redux'
import { RendererStateSyncEnhancerOptions } from './options/RendererStateSyncEnhancerOptions'
import { preventDoubleInitialization, stopForwarding } from './utils'
import { preventDoubleInitialization } from './utils'
import { StateSyncOptions } from './options/StateSyncOptions'
import { createComposer } from './composeWithStateSync'

/**
* Creates new instance of renderer process redux enhancer.
Expand All @@ -15,46 +12,25 @@ import { createComposer } from './composeWithStateSync'
*/
export const stateSyncEnhancer = (
options: RendererStateSyncEnhancerOptions = {}
): StoreEnhancer => (createStore) => {
): StoreEnhancer => {
preventDoubleInitialization()

return (reducer, state) => {
if (typeof __ElectronReduxBridge === undefined) {
throw new Error(
'Looks like this renderer process has not been configured properly. Did you forgot to include preload script?'
)
}

const initialState = options.lazyInit
? state
: __ElectronReduxBridge.fetchInitialState<typeof state>(options)

const store = createStore(
options.lazyInit ? withStoreReplacer(reducer) : reducer,
initialState
)

if (options.lazyInit) {
__ElectronReduxBridge.fetchInitialStateAsync(options, (asyncState) => {
store.dispatch(replaceState(asyncState) as never)
})
}

// When receiving an action from main
__ElectronReduxBridge.subscribeToIPCAction((action: Action) =>
store.dispatch(stopForwarding(action))
)

return forwardAction(store, __ElectronReduxBridge.forwardActionToMain, options)
}
assertElectronReduxBridgeAvailability()
return __ElectronReduxBridge.stateSyncEnhancer(options)
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const composeWithStateSync = (
firstFuncOrOpts: StoreEnhancer | StateSyncOptions,
...funcs: StoreEnhancer[]
) =>
createComposer(stateSyncEnhancer, __ElectronReduxBridge.forwardActionToMain)(
firstFuncOrOpts,
...funcs
)
) => {
assertElectronReduxBridgeAvailability()
return __ElectronReduxBridge.composeWithStateSync(firstFuncOrOpts, ...funcs)
}

const assertElectronReduxBridgeAvailability = () => {
if (typeof __ElectronReduxBridge === undefined) {
throw new Error(
'Looks like this renderer process has not been configured properly. Did you forgot to include preload script?'
)
}
}

0 comments on commit 5c1b94e

Please sign in to comment.