Files
CTM-Concierge/electron/preload.js
T
2026-07-17 13:02:59 -04:00

72 lines
2.5 KiB
JavaScript

/**
* preload.js
*
* Runs in a privileged context but is sandboxed from the renderer.
* Use contextBridge to expose a safe, narrow API surface to the renderer.
* Never expose raw ipcRenderer — always whitelist specific channels.
*/
const { contextBridge, ipcRenderer } = require('electron')
// ─── Allowed IPC channels ─────────────────────────────────────────────────
// Only messages on these channels will be forwarded.
const ALLOWED_SEND_CHANNELS = [
'patient:update-status',
'patient:fetch-list',
'schedule:fetch',
'app:ready',
]
const ALLOWED_RECEIVE_CHANNELS = [
'patient:status-updated',
'patient:list-response',
'schedule:response',
'app:get-version',
]
// ─── Exposed API ──────────────────────────────────────────────────────────
contextBridge.exposeInMainWorld('api', {
/**
* Send a one-way message to the main process.
* @param {string} channel - Must be in ALLOWED_SEND_CHANNELS
* @param {*} data
*/
send(channel, data) {
if (ALLOWED_SEND_CHANNELS.includes(channel)) {
ipcRenderer.send(channel, data)
} else {
console.warn(`[preload] Blocked send on unknown channel: "${channel}"`)
}
},
/**
* Invoke a main-process handler and await its response.
* @param {string} channel - Must be in ALLOWED_SEND_CHANNELS
* @param {...*} args
* @returns {Promise<*>}
*/
invoke(channel, ...args) {
if (ALLOWED_SEND_CHANNELS.includes(channel) || ALLOWED_RECEIVE_CHANNELS.includes(channel)) {
return ipcRenderer.invoke(channel, ...args)
}
return Promise.reject(new Error(`[preload] Blocked invoke on unknown channel: "${channel}"`))
},
/**
* Subscribe to messages from the main process.
* @param {string} channel - Must be in ALLOWED_RECEIVE_CHANNELS
* @param {Function} callback - Called with (event, ...args) on each message
* @returns {Function} Unsubscribe function — call it to remove the listener
*/
receive(channel, callback) {
if (ALLOWED_RECEIVE_CHANNELS.includes(channel)) {
const handler = (_event, ...args) => callback(...args)
ipcRenderer.on(channel, handler)
// Return cleanup function so React effects can unsubscribe
return () => ipcRenderer.removeListener(channel, handler)
}
console.warn(`[preload] Blocked receive on unknown channel: "${channel}"`)
return () => {}
},
})