@zubridge/electron
Version:
A streamlined state management library for Electron applications using Zustand.
255 lines (254 loc) • 10.7 kB
text/typescript
import { Action, AnyState, BackendBridge, Dispatch, Handler, RootReducer, StateManager, WrapperOrWebContents } from "@zubridge/types";
import { Store } from "redux";
import { StoreApi } from "zustand/vanilla";
import { StoreApi as StoreApi$1 } from "zustand";
//#region src/middleware.d.ts
interface NapiAction {
type: string;
payload?: string;
}
/**
* Interface for the middleware provided by @zubridge/middleware
*/
interface ZubridgeMiddleware {
/**
* Process an action before it's sent to the store
*/
processAction: (action: NapiAction) => Promise<void>;
/**
* Update the middleware's state after a state change
*/
setState: (state: string) => Promise<void>;
/**
* Clean up resources when the bridge is destroyed
*/
destroy?: () => Promise<void>;
trackActionDispatch?: (action: Action) => Promise<void>;
trackActionReceived?: (action: Action) => Promise<void>;
trackStateUpdate?: (action: Action, state: string) => Promise<void>;
trackActionAcknowledged?: (actionId: string) => Promise<void>;
trackBatchReceived?: (batchId: string, actionCount: number, sourceWindowId: number) => Promise<void>;
}
/**
* Helper to create bridge middleware options for Electron bridges
*
* This function integrates Rust-based middleware (@zubridge/middleware) with the Electron bridge.
*
* Note: You typically don't need to use this function directly. You can just pass the middleware
* instance directly to the bridge creation functions.
*
* @example
* ```typescript
* import { createZustandBridge } from '@zubridge/electron';
* import { initZubridgeMiddleware } from '@zubridge/middleware';
*
* // Initialize middleware from @zubridge/middleware (Rust implementation)
* const middleware = initZubridgeMiddleware({
* logging: { enabled: true }
* });
*
* // Create bridge with Rust middleware - just pass middleware directly
* const bridge = createZustandBridge(store, windows, {
* // Your other options
* middleware: middleware
* });
* ```
*
* @internal This function is used internally by bridge creation functions
*/
declare function createMiddlewareOptions(middleware: ZubridgeMiddleware): {
beforeProcessAction: (action: Action) => Promise<Action>;
afterStateChange: (state: AnyState) => Promise<void>;
onBridgeDestroy: () => Promise<void>;
};
//#endregion
//#region src/adapters/redux.d.ts
/**
* Options for the Redux adapter
*/
interface ReduxOptions<_S extends AnyState> {
handlers?: Record<string, Handler | Record<string, unknown>>;
middleware?: ZubridgeMiddleware;
}
//#endregion
//#region src/adapters/zustand.d.ts
/**
* Options for the Zustand bridge and adapter
*/
interface ZustandOptions<S extends AnyState> {
handlers?: Record<string, Handler>;
reducer?: RootReducer<S>;
middleware?: ZubridgeMiddleware;
}
//#endregion
//#region src/types/bridge.d.ts
interface CoreBridgeOptions {
deltas?: {
/** Enable delta updates (default: true) */
enabled?: boolean;
};
middleware?: ZubridgeMiddleware;
beforeProcessAction?: (action: Action, windowId?: number) => Promise<Action> | Action;
afterProcessAction?: (action: Action, processingTime: number, windowId?: number) => Promise<void> | void;
beforeStateChange?: (state: AnyState, windowId?: number) => Promise<void> | void;
afterStateChange?: (state: AnyState, windowId?: number) => Promise<void> | void;
onBridgeDestroy?: () => Promise<void> | void;
resourceManagement?: {
/** Enable periodic cleanup of destroyed window subscription managers (default: true) */
enablePeriodicCleanup?: boolean;
/** Cleanup interval in milliseconds (default: 10 minutes) */
cleanupIntervalMs?: number;
/** Maximum number of subscription managers before forcing cleanup (default: 1000) */
maxSubscriptionManagers?: number;
};
serialization?: {
/** Maximum depth to traverse when sanitizing state (default: 10) */
maxDepth?: number;
};
}
//#endregion
//#region src/bridge/index.d.ts
/**
* Creates a core bridge between the main process and renderer processes
* This implements the Zubridge Electron backend contract without requiring a specific state management library
*/
declare function createCoreBridge<State extends AnyState>(stateManager: StateManager<State>, options?: CoreBridgeOptions): BackendBridge;
/**
* Creates a bridge from a store (either Zustand or Redux)
*/
declare function createBridgeFromStore<S extends AnyState = AnyState>(store: StoreApi$1<S> | Store<S>, options?: ZustandOptions<S> | ReduxOptions<S> | CoreBridgeOptions): BackendBridge;
//#endregion
//#region src/main/dispatch.d.ts
/**
* Creates a dispatch function for the given store
* This automatically gets or creates an appropriate state manager based on the store type
*/
declare function createDispatch<S extends AnyState>(store: StoreApi<S> | Store<S>, options?: ZustandOptions<S> | ReduxOptions<S>): Dispatch<S>;
/**
* Creates a dispatch function using a pre-created state manager
* @internal This overload is intended for internal use by bridge creators
*/
declare function createDispatch<S extends AnyState>(stateManager: StateManager<S>): Dispatch<S>;
//#endregion
//#region src/renderer/actionValidator.d.ts
/**
* Register an action type with the state keys it affects
* @param actionType The action type string
* @param stateKeys Array of state keys this action affects
*/
declare function registerActionMapping(actionType: string, stateKeys: string[]): void;
/**
* Register multiple action mappings at once
* @param mappings Object mapping action types to arrays of state keys
*/
declare function registerActionMappings(mappings: Record<string, string[]>): void;
/**
* Get the state keys affected by an action
* @param actionType The action type string
* @returns Array of state keys this action affects, or empty array if unknown
*/
declare function getAffectedStateKeys(actionType: string): string[];
/**
* Check if a window can dispatch an action based on its subscriptions
* @param action The action to validate
* @returns Promise resolving to boolean indicating if dispatch is allowed
*/
declare function canDispatchAction(action: Action): Promise<boolean>;
/**
* Validate that a window can dispatch an action, throwing if not allowed
* @param action The action to validate
* @throws Error if the window cannot dispatch this action
*/
declare function validateActionDispatch(action: Action): Promise<void>;
//#endregion
//#region src/renderer/subscriptionValidator.d.ts
/**
* Gets the current window's subscriptions from the main process
* @returns Array of state keys this window is subscribed to, or empty array if none
*/
declare function getWindowSubscriptions(): Promise<string[]>;
/**
* Determines if the window is subscribed to a particular state key
* @param key The state key to check
* @returns True if subscribed, false otherwise
*/
declare function isSubscribedToKey(key: string): Promise<boolean>;
/**
* Validates that the window has access to the specified state key
* Throws an error if the window is not subscribed to the key
* @param key The state key to validate
* @param action Optional action to check for bypass flags
* @throws Error if window is not subscribed to the key and not bypassing
*/
declare function validateStateAccess(key: string, action?: Action): Promise<void>;
/**
* Validates that the window can access all of the specified state keys
* @param keys Array of state keys to validate
* @param action Optional action to check for bypass flags
* @throws Error if window is not subscribed to any of the keys and not bypassing
*/
declare function validateStateAccessBatch(keys: string[], action?: Action): Promise<void>;
/**
* Checks if a state key exists in the provided state object
* @param state The state object to check
* @param key The key to look for (can use dot notation)
* @returns True if the key exists, false otherwise
*/
declare function stateKeyExists(state: Record<string, unknown>, key: string): boolean;
/**
* Validates state access with additional check for key existence
* @param state The state object
* @param key The key to validate
* @param action Optional action to check for bypass flags
* @throws Error if the key doesn't exist or the window isn't subscribed
*/
declare function validateStateAccessWithExistence(state: Record<string, unknown>, key: string, action?: Action): Promise<void>;
//#endregion
//#region src/utils/environment.d.ts
/**
* Determines if the application is running in development mode
*
* Uses a combination of checks to ensure consistent behavior:
* 1. Checks if app is packaged (production builds are packaged)
* 2. Checks NODE_ENV environment variable
* 3. Checks ELECTRON_IS_DEV environment variable (set by electron-is-dev or similar utilities)
*
* @returns {boolean} True if running in development mode, false otherwise
*/
declare const isDev: () => Promise<boolean>;
//#endregion
//#region src/main.d.ts
/**
* Interface for a bridge that connects a Zustand store to the main process
*/
interface ZustandBridge<S extends AnyState = AnyState> extends BackendBridge {
subscribe: (windows: WrapperOrWebContents[], keys?: string[]) => {
unsubscribe: () => void;
};
unsubscribe: (...args: unknown[]) => void;
getWindowSubscriptions: (windowId: number) => string[];
dispatch: Dispatch<S>;
destroy: () => void;
}
/**
* Interface for a bridge that connects a Redux store to the main process
*/
interface ReduxBridge<S extends AnyState = AnyState> extends BackendBridge {
subscribe: (windows: WrapperOrWebContents[], keys?: string[]) => {
unsubscribe: () => void;
};
unsubscribe: (...args: unknown[]) => void;
getWindowSubscriptions: (windowId: number) => string[];
dispatch: Dispatch<S>;
destroy: () => void;
}
/**
* Creates a bridge between a Zustand store and the renderer process
*/
declare function createZustandBridge<S extends AnyState>(store: StoreApi<S>, options?: ZustandOptions<S> & CoreBridgeOptions): ZustandBridge<S>;
/**
* Creates a bridge between a Redux store and the renderer process
*/
declare function createReduxBridge<S extends AnyState>(store: Store<S>, options?: ReduxOptions<S> & CoreBridgeOptions): ReduxBridge<S>;
//#endregion
export { type CoreBridgeOptions, ReduxBridge, type ReduxOptions, type ZubridgeMiddleware, ZustandBridge, type ZustandOptions, canDispatchAction, createBridgeFromStore, createCoreBridge, createDispatch, createMiddlewareOptions, createReduxBridge, createZustandBridge, getAffectedStateKeys, getWindowSubscriptions, isDev, isSubscribedToKey, registerActionMapping, registerActionMappings, stateKeyExists, validateActionDispatch, validateStateAccess, validateStateAccessBatch, validateStateAccessWithExistence };