Skip to main content

jellyflow_runtime/runtime/delete/
store.rs

1use keyboard_types::Code as KeyCode;
2
3use crate::rules::DeletePlan;
4use crate::runtime::store::{DispatchOutcome, NodeGraphStore};
5
6use super::planner::{
7    delete_selection_transaction_from_plan, plan_delete_elements, plan_delete_selection,
8    plan_delete_selection_for_key, prepare_delete_selection, prepare_delete_selection_for_key,
9};
10use super::types::{DeleteElements, DeleteSelectionError, PreDeleteRequest, PreDeleteResolution};
11
12impl NodeGraphStore {
13    /// Plans deletion for the store's current node/edge selection.
14    pub fn plan_delete_selection(&self) -> DeletePlan {
15        let interaction = self.resolved_interaction_state();
16        plan_delete_selection(self.graph(), self.view_state(), &interaction)
17    }
18
19    /// Plans deletion for the current selection when the configured delete key matches.
20    pub fn plan_delete_selection_for_key(&self, key: KeyCode) -> Option<DeletePlan> {
21        let interaction = self.resolved_interaction_state();
22        plan_delete_selection_for_key(self.graph(), self.view_state(), &interaction, key)
23    }
24
25    /// Plans deletion for explicit node/edge ids through the store's resolved interaction policy.
26    pub fn plan_delete_elements(&self, elements: &DeleteElements) -> DeletePlan {
27        let interaction = self.resolved_interaction_state();
28        plan_delete_elements(self.graph(), &interaction, elements)
29    }
30
31    /// Prepares the current selection for an adapter-owned async pre-delete hook.
32    pub fn prepare_delete_selection(
33        &self,
34    ) -> Result<Option<PreDeleteRequest>, DeleteSelectionError> {
35        let interaction = self.resolved_interaction_state();
36        prepare_delete_selection(self.graph(), self.view_state(), &interaction)
37    }
38
39    /// Prepares a key-gated selection delete for an adapter-owned async pre-delete hook.
40    pub fn prepare_delete_selection_for_key(
41        &self,
42        key: KeyCode,
43    ) -> Result<Option<PreDeleteRequest>, DeleteSelectionError> {
44        let interaction = self.resolved_interaction_state();
45        prepare_delete_selection_for_key(self.graph(), self.view_state(), &interaction, key)
46    }
47
48    /// Commits deletion for the current node/edge selection through normal store dispatch.
49    pub fn apply_delete_selection(
50        &mut self,
51    ) -> Result<Option<DispatchOutcome>, DeleteSelectionError> {
52        let plan = self.plan_delete_selection();
53        self.apply_delete_selection_plan(plan)
54    }
55
56    /// Commits deletion for the current selection when the configured delete key matches.
57    pub fn apply_delete_selection_for_key(
58        &mut self,
59        key: KeyCode,
60    ) -> Result<Option<DispatchOutcome>, DeleteSelectionError> {
61        let Some(plan) = self.plan_delete_selection_for_key(key) else {
62            return Ok(None);
63        };
64
65        self.apply_delete_selection_plan(plan)
66    }
67
68    /// Applies an adapter-owned pre-delete hook result through normal delete policy and dispatch.
69    pub fn apply_pre_delete_resolution(
70        &mut self,
71        request: &PreDeleteRequest,
72        resolution: PreDeleteResolution,
73    ) -> Result<Option<DispatchOutcome>, DeleteSelectionError> {
74        let elements = match resolution {
75            PreDeleteResolution::Accept => request.planned().clone(),
76            PreDeleteResolution::Veto => return Ok(None),
77            PreDeleteResolution::Replace { elements } => elements,
78        };
79
80        self.apply_delete_elements(elements)
81    }
82
83    /// Commits explicit node/edge ids through normal delete policy and store dispatch.
84    pub fn apply_delete_elements(
85        &mut self,
86        elements: DeleteElements,
87    ) -> Result<Option<DispatchOutcome>, DeleteSelectionError> {
88        let plan = self.plan_delete_elements(&elements);
89        self.apply_delete_selection_plan(plan)
90    }
91
92    fn apply_delete_selection_plan(
93        &mut self,
94        plan: DeletePlan,
95    ) -> Result<Option<DispatchOutcome>, DeleteSelectionError> {
96        if plan.is_reject() {
97            return Err(DeleteSelectionError::Rejected {
98                diagnostics: plan.diagnostics,
99            });
100        }
101
102        let Some(transaction) = delete_selection_transaction_from_plan(plan) else {
103            return Ok(None);
104        };
105
106        self.dispatch_transaction(&transaction)
107            .map(Some)
108            .map_err(DeleteSelectionError::from)
109    }
110}