//! Actions returned by the application's update function. //! //! `update` is pure with respect to the runtime: it mutates //! state in place and returns a list of `Action`s for the //! runtime to enact (quit, dispatch a DSL command to the //! database, etc.). Side effects belong here, not in update //! itself, which keeps update directly testable without a Tokio //! runtime, a real terminal, or a database. use crate::app::EffectiveMode; use crate::dsl::Command; #[derive(Debug, Clone, PartialEq, Eq)] pub enum Action { /// Stop the event loop and exit cleanly. Quit, /// Hand a parsed DSL command to the database worker. /// /// `command` is the parsed AST that the worker executes; /// `source` is the original user-typed text, retained for /// `history.log` per ADR-0015 §5. The runtime feeds the /// result back as `AppEvent::DslSucceeded` / /// `AppEvent::DslFailed`. ExecuteDsl { command: Command, source: String, /// The effective mode the line was submitted under (ADR-0037): /// `Simple` / `AdvancedPersistent` / `AdvancedOneShot`. Output-only /// — execution semantics do not depend on it; the runtime uses it /// to gate the DSL → SQL teaching echo (ADR-0038), which fires for /// DSL-form commands submitted in an advanced effective mode. submission_mode: EffectiveMode, }, /// Record a *failed* submission to `history.log` as an `err` /// record (ADR-0034 §1/§2). Emitted by the pure-sync `App` /// for both failure kinds — a line that failed to parse (at /// submit) and a command the worker rejected (on /// `AppEvent::DslFailed`) — because the App does no I/O. The /// runtime appends best-effort: a failure to record a failure /// must never escalate a user error into a fatal (ADR-0034 /// §4). `source` is the original user-typed text. JournalFailure { source: String, }, /// User issued the `rebuild` app-level command (ADR-0015 /// §7, §11). Runtime computes a summary from /// `project.yaml` + `data/` and posts back as /// `AppEvent::RebuildPrepared`, which opens the /// confirmation modal. PrepareRebuild, /// User confirmed the rebuild from inside the modal. /// Runtime wipes the current schema/data and reconstructs /// from text sources. Rebuild { source: String, }, /// Open the load-picker modal. Runtime lists projects in /// the active data root and posts back as /// `AppEvent::LoadPickerReady`. OpenLoadPicker, /// Switch to the project at `path` (absolute or relative /// to the active data root). Runtime drops the current /// project, opens the new one, refreshes app state. LoadProject { path: std::path::PathBuf, source: String, }, /// Save the current project to `target` and switch to it. /// `target` is a name or absolute path; relative names /// resolve against `/projects/` per ADR-0015 §1. SaveAs { target: String, source: String, }, /// Close the current project (auto-save guarantees state /// is on disk) and create a fresh auto-named temp. NewProject { source: String, }, /// Export the current project to a zip file. `target` is /// `None` for the default filename /// (`YYYYMMDD--export-NN.zip`) under the /// active data root, or `Some(path)` for an explicit /// target. Relative paths resolve under /// `/`. Per ADR-0015 §11 the zip excludes /// `playground.db` and `history.log`. Export { target: Option, source: String, }, /// Import a previously-exported zip and switch to the /// resulting project. `zip_path` is the user-typed path to /// the source archive (relative to CWD or absolute). /// `as_target` is the optional user-supplied destination /// name; when `None`, the destination is derived from the /// zip's top-level folder. Collisions auto-suffix `-NN` /// (ADR-0015 §11 amendment). Import { zip_path: String, as_target: Option, source: String, }, /// Replay a script of DSL commands from a file. The runtime /// reads the file, iterates non-blank/non-comment lines, and /// dispatches each through the same path as interactive /// input. On per-line failure the runtime reports the line /// number and stops (no rollback). On success it reports the /// number of commands run. /// /// `path` is the literal user-typed path; the runtime /// resolves relative paths against the active project's root /// so `replay history.log` works inside any project. Replay /// itself is NOT written to `history.log` — only the /// individual commands it dispatches are, since they are /// what mutate state. Replay { path: String, }, /// User issued `undo` (`PrepareUndo`) or `redo` (`PrepareRedo`) /// (ADR-0006 Amendment 1). The runtime peeks the snapshot the /// command would restore and posts `AppEvent::UndoPrepared` /// (opening the confirmation modal) or `AppEvent::UndoUnavailable` /// (nothing to undo/redo). Only emitted when undo is enabled — /// the `App` notes "undo is off" itself under `--no-undo`. PrepareUndo, PrepareRedo, /// User confirmed `undo` / `redo` from inside the modal. The /// runtime restores the snapshot through the worker, then /// refreshes the table list + schema cache. Undo, Redo, }