Created
July 31, 2023 19:15
-
-
Save weeksie/aa72f162e3feaf6cf0e5a6abeb3551a2 to your computer and use it in GitHub Desktop.
Example background script with hand-rolled redux for chrome extensions
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 reloadOnUpdate from "virtual:reload-on-update-in-background-script"; | |
reloadOnUpdate("pages/background"); | |
import { | |
type Store, | |
type StoreApi, | |
type Dispatch, | |
type Listener, | |
} from '@lib/store'; | |
import { auth, productImport } from '@lib/middleware'; | |
import { reducer, type InitialState } from '@lib/reducer'; | |
const middlewares = [ | |
auth, | |
productImport, | |
]; | |
const dispatch: Dispatch = (action) => { | |
console.log(`[root dispatch]: ${action.type}`); | |
Store.state = reducer(Store.state, action); | |
notify(); | |
}; | |
const Store: Store = { | |
state: InitialState, | |
dispatch, | |
getState: () => Store.state, | |
} | |
let middlewareDispatch: Dispatch = () => { | |
throw new Error(`Can't dispatch while constructing middleware`); | |
}; | |
const middlewareApi: StoreApi = { | |
getState: Store.getState, | |
dispatch: (action) => middlewareDispatch(action), | |
}; | |
const chained = middlewares.map(middleware => middleware(middlewareApi)); | |
middlewareDispatch = chained.reduce((a, b) => (next) => a(b(next)))(Store.dispatch); | |
Store.dispatch = middlewareDispatch; | |
const listeners = new Set<Listener>(); | |
const subscribe = (listener: Listener) => { | |
listeners.add(listener); | |
listener(Store.getState()); | |
} | |
const unsubscribe = (listener: Listener) => { | |
listeners.delete(listener); | |
} | |
const notify = () => { | |
for (const listener of listeners) { | |
listener(Store.getState()); | |
} | |
} | |
chrome.runtime.onConnect.addListener((port) => { | |
if (port.name === 'stateSubscription') { | |
const listener: Listener = (state) => { | |
port.postMessage({ state }); | |
} | |
subscribe(listener); | |
port.onDisconnect.addListener(() => { | |
unsubscribe(listener); | |
}); | |
} | |
}) | |
chrome.runtime.onMessage.addListener((request) => { | |
if (request.dispatch) { | |
Store.dispatch(request.action); | |
return; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment