State Management
Trufos primarily manages its application state within the Renderer process using Zustand, a small, fast, and scalable state-management solution. Zustand is chosen for its simplicity, hook-based API, and compatibility with React.
Core Stores
The application state is divided into several stores, each responsible for a specific domain:
- CollectionStore(- src/renderer/state/collectionStore.ts):- Purpose: Manages the state related to the currently loaded collection, including its structure (folders, requests), the currently selected request, and the Monaco editor instance for the request body.
- Key State Properties: - collection: Basic information about the current collection (ID, title, children).
- requests: A- Mapof all requests in the collection, keyed by their ID.
- folders: A- Mapof all folders in the collection, keyed by their ID.
- selectedRequestId: The ID of the request currently being viewed/edited.
- requestEditor: The Monaco editor instance for the request body.
- openFolders: A- Setof folder IDs that are currently expanded in the sidebar’s request list.
 
- Key Actions: - initialize(collection): Loads a new collection into the store, populating- requestsand- foldersmaps.
- changeCollection(collection): Switches to a new collection, ensuring unsaved changes in the current request are persisted.
- addNewRequest(title?, parentId?): Creates a new request, saves it via- RendererEventService, and updates the store.
- updateRequest(updatedRequest, overwrite?): Updates the currently selected request. Can either merge partial updates (marking as draft) or fully overwrite.
- setRequestBody(body): Updates the body of the current request.
- setRequestEditor(editor?): Sets the Monaco editor instance and loads the current request’s body into it. Handles draft status on content change.
- setSelectedRequest(id?): Changes the selected request, saving the previous one if necessary and loading the new one’s body.
- deleteRequest(id): Deletes a request from the store and via- RendererEventService.
- renameRequest(id, title): Renames a request.
- Header and Query Parameter management actions (addHeader,updateHeader,deleteHeader,clearHeaders, etc.).
- setDraftFlag(): Marks the current request as having unsaved changes.
- Folder management actions (addNewFolder,deleteFolder,renameFolder,setFolderOpen,setFolderClose).
 
- IPC Integration: Listens for the 'before-close'IPC event from the main process to save any unsaved changes in therequestEditorbefore the application quits.
 
- ResponseStore(- src/renderer/state/responseStore.ts):- Purpose: Manages the HTTP responses received for requests.
- Key State Properties: - responseInfoMap: A- Record(object) mapping request IDs to their corresponding- TrufosResponseobjects.
- editor: The Monaco editor instance for displaying the response body.
 
- Key Actions: - addResponse(requestId, response): Adds a new response to the map.
- removeResponse(requestId): Removes a response.
- setResponseEditor(editor?): Sets the Monaco editor instance for the response view.
 
 
- VariableStore(- src/renderer/state/variableStore.ts):- Purpose: Manages collection-level variables, primarily for use in the Settings modal. See Variables documentation for more details on variable types and usage.
- Key State Properties: - variables: A- VariableMap(object) representing the collection’s variables.
 
- Key Actions: - initialize(variables): Sets the initial variables when a collection is loaded.
- setVariables(variables): Updates the variables and persists them via- RendererEventService.
 
 
Zustand Configuration
- immerMiddleware: All stores use the- immermiddleware from Zustand (- zustand/middleware/immer). This allows for direct, “mutable” updates to state within action definitions, which Immer then translates into immutable updates.
- enableMapSet(): Called in- src/renderer/index.tsxfrom- immerto enable direct mutation support for- Mapand- Setobjects within Immer-powered reducers/actions.
State Selection and Actions
- Selectors: Each store typically exports selector functions (e.g., selectRequestincollectionStore.ts) to retrieve specific pieces of state.
- useActions()Hook: A utility hook (- src/renderer/state/helper/util.ts) is used to conveniently access all action functions from a store, often with shallow equality checking for performance:- // Example usage const { addNewRequest, updateRequest } = useCollectionActions();
Data Flow
- Initialization: On app start, RendererEventService.loadCollection()fetches the last opened collection. TheCollectionStoreis initialized with this data.VariableStoreis initialized with the collection’s variables.
- User Interaction: User actions in the UI (e.g., typing in URL, changing HTTP method, sending request) call actions in the relevant Zustand store.
- State Update: Store actions update the state immutably (thanks to Immer).
- IPC for Persistence/Operations: If an action requires main process interaction (e.g., saving a request, sending an HTTP request), it calls methods on RendererEventService.
- UI Re-render: React components subscribed to store changes (via hooks like useCollectionStore(...)) re-render with the new state.
- Response Handling: When an HTTP response is received (via RendererEventService), theResponseStore.addResponseaction is called to update the response state.
This architecture keeps the UI reactive to state changes and centralizes business logic within the Zustand stores and associated services.