@zubridge/electron
Version:
A streamlined state management library for Electron applications using Zustand.
96 lines (91 loc) • 4.09 kB
JavaScript
;
var electron = require('electron');
/**
* Constants used for IPC communication between main and renderer processes.
* These are internal to the Zubridge electron implementation.
*/
var IpcChannel;
(function (IpcChannel) {
/** Channel for subscribing to state updates */
IpcChannel["SUBSCRIBE"] = "__zubridge_state_update";
/** Channel for getting the current state */
IpcChannel["GET_STATE"] = "__zubridge_get_initial_state";
/** Channel for dispatching actions */
IpcChannel["DISPATCH"] = "__zubridge_dispatch_action";
/** Channel for acknowledging action dispatches */
IpcChannel["DISPATCH_ACK"] = "__zubridge_dispatch_ack";
})(IpcChannel || (IpcChannel = {}));
/**
* Modern preload bridge that implements the new backend contract
*/
const preloadBridge = () => {
const handlers = {
subscribe(callback) {
const listener = (_, state) => callback(state);
electron.ipcRenderer.on(IpcChannel.SUBSCRIBE, listener);
return () => {
electron.ipcRenderer.removeListener(IpcChannel.SUBSCRIBE, listener);
};
},
async getState() {
return electron.ipcRenderer.invoke(IpcChannel.GET_STATE);
},
dispatch(action, payload) {
if (typeof action === 'function') {
// For thunks, we don't do anything in the preload
// The renderer implementation will handle executing them
// This just prevents an error from being thrown
return;
}
else if (typeof action === 'string') {
// Create an action object
const actionObj = {
type: action,
payload: payload,
// Generate a unique ID for this action to track acknowledgment
id: `${Date.now()}_${Math.random().toString(36).slice(2)}`,
};
// Return a promise that resolves when the action is acknowledged
return new Promise((resolve) => {
// Set up one-time listener for acknowledgment with this action ID
const ackListener = (_, ackId) => {
if (ackId === actionObj.id) {
electron.ipcRenderer.removeListener(IpcChannel.DISPATCH_ACK, ackListener);
resolve();
}
};
electron.ipcRenderer.on(IpcChannel.DISPATCH_ACK, ackListener);
electron.ipcRenderer.send(IpcChannel.DISPATCH, actionObj);
});
}
else {
// For regular action objects, add a unique ID if not already present
const actionWithId = {
...action,
id: action.id || `${Date.now()}_${Math.random().toString(36).slice(2)}`,
};
// Return a promise that resolves when the action is acknowledged
return new Promise((resolve) => {
// Set up one-time listener for acknowledgment with this action ID
const ackListener = (_, ackId) => {
if (ackId === actionWithId.id) {
electron.ipcRenderer.removeListener(IpcChannel.DISPATCH_ACK, ackListener);
resolve();
}
};
electron.ipcRenderer.on(IpcChannel.DISPATCH_ACK, ackListener);
electron.ipcRenderer.send(IpcChannel.DISPATCH, actionWithId);
});
}
},
};
return { handlers };
};
/**
* Legacy preload bridge for backward compatibility
* @deprecated This is now an alias for preloadBridge and uses the new IPC channels.
* Please update your code to use preloadBridge directly in the future.
*/
const preloadZustandBridge = preloadBridge;
exports.preloadBridge = preloadBridge;
exports.preloadZustandBridge = preloadZustandBridge;