//! Events fed into the application's update function. //! //! `AppEvent` is the single input type the runtime delivers to //! `App::update`. Synthetic instances drive Tier 3 integration //! tests (see ADR-0008), so the type is plain data with no //! runtime dependency. use crossterm::event::KeyEvent; use crate::db::{ AddColumnResult, ChangeColumnTypeResult, DataResult, DbError, DeleteResult, DropColumnResult, InsertResult, QueryPlan, TableDescription, UpdateResult, }; use crate::dsl::Command; #[derive(Debug, Clone)] pub enum AppEvent { Key(KeyEvent), Resize { cols: u16, rows: u16, }, Tick, /// A DSL command finished successfully. `description` is /// `Some` for commands that produce a table view (create, /// add column) and `None` for commands that don't (drop). DslSucceeded { command: Command, description: Option, }, /// A SQL `CREATE TABLE IF NOT EXISTS` matched an existing table — /// a no-op (ADR-0035 §4). Renders the existing structure plus an /// "already exists — skipped" note. DslCreateSkipped { command: Command, description: TableDescription, }, /// A SQL `DROP TABLE IF EXISTS` matched no table — a no-op /// (ADR-0035 §4, 4c). Renders a "doesn't exist — skipped" note; /// there is no structure to show. DslDropSkipped { command: Command, }, /// A SQL `DROP INDEX IF EXISTS` matched no index — a no-op /// (ADR-0035 §4d). Renders an index-specific "doesn't exist — /// skipped" note; no structure to show. DslDropIndexSkipped { command: Command, }, /// A SQL `CREATE INDEX IF NOT EXISTS` matched an existing index name /// — a no-op (ADR-0035 §4d). `name` is the resolved index name (the /// auto-name is not on the command). Renders "already exists — /// skipped"; no structure to show. DslCreateIndexSkipped { command: Command, name: String, }, /// A `show data` query succeeded. DslDataSucceeded { command: Command, data: DataResult }, /// An `explain …` command succeeded (ADR-0028). `plan` /// carries the captured query plan; nothing was executed. DslExplainSucceeded { command: Command, plan: QueryPlan }, DslInsertSucceeded { command: Command, result: InsertResult, }, DslUpdateSucceeded { command: Command, result: UpdateResult, }, DslDeleteSucceeded { command: Command, result: DeleteResult, }, /// A `change column …` succeeded. `result` carries both the /// post-rebuild description (for the auto-show) and the /// optional `[client-side]` note (ADR-0017 §6). DslChangeColumnSucceeded { command: Command, result: ChangeColumnTypeResult, }, /// An `add column …` succeeded. `result` carries the /// post-add description plus any `[client-side]` notes /// from the auto-fill paths (ADR-0018 §9). DslAddColumnSucceeded { command: Command, result: AddColumnResult, }, /// A `drop column …` succeeded. `result` carries the /// post-drop description plus the names of any indexes /// removed by `--cascade` (ADR-0025). DslDropColumnSucceeded { command: Command, result: DropColumnResult, }, /// A DSL command failed. `error` is the structured /// payload, `facts` is the runtime-built schema-resolved /// enrichment (parent tables, attempted values, /// pinpointed offending rows). App applies its current /// verbosity setting (`messages_verbosity`) when rendering /// through `friendly::translate_error` (ADR-0019 §5, §6). DslFailed { command: Command, error: DbError, facts: crate::friendly::FailureContext, /// The original user-typed source line, retained so the /// App can journal the failed command as an `err` record /// (ADR-0034 §1/§2). The worker only journals successful /// commands, so an execution failure would otherwise be /// lost across sessions. source: String, }, /// Refreshed list of tables in the database. TablesRefreshed(Vec), /// Refreshed schema lookup cache feeding Tab completion /// for identifier slots (ADR-0022 §9 + stage 8d). Runtime /// posts this alongside `TablesRefreshed` after project /// load and after every successful DDL. SchemaCacheRefreshed(crate::completion::SchemaCache), /// A persistence failure occurred (ADR-0015 §8). The /// application surfaces a fatal banner and exits cleanly so /// the message remains above the shell prompt. PersistenceFatal { operation: String, path: std::path::PathBuf, message: String, }, /// Runtime has computed the rebuild summary from /// `project.yaml` + `data/` and is ready for the user to /// confirm. App opens the confirmation modal. RebuildPrepared { summary: String, }, /// Rebuild completed successfully. App closes the modal, /// surfaces a friendly outcome message, and refreshes the /// table list. RebuildSucceeded { summary: String, }, /// Rebuild failed in a non-fatal way (e.g., user-visible /// constraint problem) — surfaced like other DSL failures. RebuildFailed { error: String, }, /// Runtime peeked the snapshot `undo`/`redo` would restore and /// is ready for the user to confirm (ADR-0006 Amendment 1). App /// opens the confirmation modal naming `command`. `is_redo` /// selects undo vs redo wording. UndoPrepared { command: String, timestamp: String, is_redo: bool, }, /// Nothing to undo / redo (the ring or redo stack was empty). /// App surfaces a friendly note. UndoUnavailable { is_redo: bool, }, /// Undo / redo completed. App closes the modal, notes the /// command that was undone/redone; the runtime also refreshes /// the table list + schema cache. UndoSucceeded { command: String, is_redo: bool, }, /// Undo / redo failed (a rare restore error). App closes the /// modal and surfaces the error. UndoFailed { error: String, is_redo: bool, }, /// Runtime has gathered the list of available projects /// for the load picker. App opens the picker modal. LoadPickerReady { entries: Vec, }, /// A project switch (load / new / save-as / import) /// succeeded. Carries the new display name, the temp /// flag (drives the `[TEMP]` status-bar prefix), and the /// seed entries for input-history hydration off the new /// project's `history.log` (I2-persist, ADR-0015 §12). ProjectSwitched { display_name: String, is_temp: bool, history_entries: Vec, }, /// A project switch failed in a non-fatal way (target /// already exists, path unreadable, …). Surfaced as an /// error in the output panel. ProjectSwitchFailed { error: String, }, /// Export wrote a zip successfully. Carries the resolved /// final path so the user gets a "wrote to: …" note. ExportSucceeded { path: std::path::PathBuf, }, /// Export failed in a non-fatal way (target exists, IO /// error, sequence range exhausted, …). ExportFailed { error: String, }, /// A `replay ` finished without error, after running /// `count` non-blank, non-comment commands from the file. /// Surfaced as `[ok] replay — N command(s)` in the output. ReplayCompleted { path: String, count: usize, /// Pre-rendered `[skip]` warnings for app-lifecycle commands /// whose omission can leave the replayed state incomplete — /// `import` and a nested `replay` (ADR-0034). Other skipped /// app commands are silent and do not appear here. warnings: Vec, }, /// A `replay ` aborted at line `line_number`. `command` /// is the line text as it appeared in the file (for the /// user's eyeline so they can locate the failing entry); /// `error` is the rendered parse or runtime error. ReplayFailed { path: String, line_number: usize, command: String, error: String, }, }