UNPKG

@zubridge/electron

Version:

A streamlined state management library for Electron applications using Zustand.

255 lines (254 loc) 10.7 kB
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 };