From 72f58134f097cafbbb454d659725eaf433db6d90 Mon Sep 17 00:00:00 2001 From: Greg Harris Date: Thu, 6 Nov 2025 15:50:41 +0000 Subject: [PATCH 1/2] Rewriting store to handle a runtime configuration --- src/redux/index.ts | 1 + src/redux/store.ts | 100 +++++++++++++++------- src/ui/hooks/useSubscription.ts | 2 +- src/ui/widgets/Tabs/tabContainer.test.tsx | 6 +- 4 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/redux/index.ts b/src/redux/index.ts index 3ec5dc58..659c56c4 100644 --- a/src/redux/index.ts +++ b/src/redux/index.ts @@ -1 +1,2 @@ export { store } from "./store"; +export type { CsWebLibConfig } from "./store"; diff --git a/src/redux/store.ts b/src/redux/store.ts index df12ed81..635e08ef 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -8,39 +8,77 @@ import { SimulatorPlugin } from "../connection/sim"; import { PvwsPlugin } from "../connection/pvws"; import { ConnectionForwarder } from "../connection/forwarder"; -const PVWS_SOCKET = - process.env.VITE_PVWS_SOCKET ?? import.meta.env.VITE_PVWS_SOCKET; -const PVWS_SSL = - (process.env.VITE_PVWS_SSL ?? import.meta.env.VITE_PVWS_SSL) === "true"; -const THROTTLE_PERIOD = parseFloat( - process.env.VITE_THROTTLE_PERIOD ?? - import.meta.env.VITE_THROTTLE_PERIOD ?? - "100" -); - -const simulator = new SimulatorPlugin(); -const plugins: [string, Connection][] = [["sim://", simulator]]; -if (PVWS_SOCKET !== undefined) { - const pvws = new PvwsPlugin(PVWS_SOCKET, PVWS_SSL); - plugins.unshift(["pva://", pvws]); - plugins.unshift(["ca://", pvws]); - plugins.unshift(["loc://", pvws]); - plugins.unshift(["sim://", pvws]); - plugins.unshift(["ssim://", pvws]); - plugins.unshift(["dev://", pvws]); - plugins.unshift(["eq://", pvws]); -} -const connection = new ConnectionForwarder(plugins); +export type CsWebLibConfig = { + PVWS_SOCKET: string | undefined; + PVWS_SSL: boolean | undefined; + THROTTLE_PERIOD: number | undefined; +}; + +// Store singleton +let storeInstance: ReturnType | null = null; +let connectionInstance: ConnectionForwarder | null = null; + +const buildConnection = (config?: CsWebLibConfig) => { + const PVWS_SOCKET = + config?.PVWS_SOCKET ?? + process.env.VITE_PVWS_SOCKET ?? + import.meta.env.VITE_PVWS_SOCKET; + const PVWS_SSL = + (config?.PVWS_SSL ?? + process.env.VITE_PVWS_SSL ?? + import.meta.env.VITE_PVWS_SSL) === "true"; + + const simulator = new SimulatorPlugin(); + const plugins: [string, Connection][] = [["sim://", simulator]]; + + if (PVWS_SOCKET !== undefined) { + const pvws = new PvwsPlugin(PVWS_SOCKET, PVWS_SSL); + plugins.unshift(["pva://", pvws]); + plugins.unshift(["ca://", pvws]); + plugins.unshift(["loc://", pvws]); + plugins.unshift(["sim://", pvws]); + plugins.unshift(["ssim://", pvws]); + plugins.unshift(["dev://", pvws]); + plugins.unshift(["eq://", pvws]); + } + + return new ConnectionForwarder(plugins); +}; const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; -export const store = createStore( - csReducer, - /* preloadedState, */ composeEnhancers( - applyMiddleware( - connectionMiddleware(connection), - throttleMiddleware(new UpdateThrottle(THROTTLE_PERIOD)) +export const store = (config?: CsWebLibConfig) => { + if (storeInstance) { + return storeInstance; + } + + if (!connectionInstance) { + connectionInstance = buildConnection(config); + } + + const THROTTLE_PERIOD: number = parseFloat( + config?.THROTTLE_PERIOD ?? + process.env.VITE_THROTTLE_PERIOD ?? + import.meta.env.VITE_THROTTLE_PERIOD ?? + "100" + ); + + storeInstance = createStore( + csReducer, + /* preloadedState, */ composeEnhancers( + applyMiddleware( + connectionMiddleware(connectionInstance), + throttleMiddleware(new UpdateThrottle(THROTTLE_PERIOD)) + ) ) - ) -); + ); + + return storeInstance; +}; + +// Reset store (for testing) +export const resetStore = () => { + storeInstance = null; + connectionInstance = null; +}; diff --git a/src/ui/hooks/useSubscription.ts b/src/ui/hooks/useSubscription.ts index a355cff4..b5de0b7a 100644 --- a/src/ui/hooks/useSubscription.ts +++ b/src/ui/hooks/useSubscription.ts @@ -44,7 +44,7 @@ export function useSubscription( } export function writePv(pvName: string, value: DType): void { - store.dispatch({ + store().dispatch({ type: WRITE_PV, payload: { pvName: pvName, value: value } }); diff --git a/src/ui/widgets/Tabs/tabContainer.test.tsx b/src/ui/widgets/Tabs/tabContainer.test.tsx index afecb79d..e350edeb 100644 --- a/src/ui/widgets/Tabs/tabContainer.test.tsx +++ b/src/ui/widgets/Tabs/tabContainer.test.tsx @@ -17,7 +17,7 @@ describe("", (): void => { }; const { findByText } = await act(() => { return render( - + ); @@ -32,7 +32,7 @@ describe("", (): void => { log.setLevel("error"); const { findByText } = await act(() => { return render( - + ); @@ -54,7 +54,7 @@ describe("", (): void => { const { findByText } = await act(() => { return render( - + ); From 2b13d826093ca4046434a38e2f1c4baca51cae91 Mon Sep 17 00:00:00 2001 From: Greg Harris Date: Thu, 6 Nov 2025 15:54:46 +0000 Subject: [PATCH 2/2] Bump the package version to 0.9 as there are breaking changes --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 72b11080..6541e7d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@diamondlightsource/cs-web-lib", - "version": "0.8.0", + "version": "0.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@diamondlightsource/cs-web-lib", - "version": "0.8.0", + "version": "0.9.0", "license": "ISC", "dependencies": { "apollo-link-retry": "^2.2.16", diff --git a/package.json b/package.json index 2807cc63..273b36d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@diamondlightsource/cs-web-lib", - "version": "0.8.0", + "version": "0.9.0", "description": "Control system web library", "main": "dist/cjs/index.js", "scripts": {