Skip to main content

txtx_core/std/commands/
mod.rs

1pub mod actions;
2
3use kit::constants::DESCRIPTION;
4use kit::types::AuthorizationContext;
5use txtx_addon_kit::types::commands::return_synchronous_result;
6use txtx_addon_kit::types::frontend::{ActionItemRequestType, ProvideInputRequest};
7use txtx_addon_kit::types::frontend::{
8    Actions, BlockEvent, DisplayOutputRequest, ReviewInputRequest,
9};
10use txtx_addon_kit::types::stores::ValueStore;
11use txtx_addon_kit::types::types::RunbookSupervisionContext;
12use txtx_addon_kit::{
13    define_command,
14    types::{
15        commands::{
16            CommandExecutionFutureResult, CommandExecutionResult, CommandImplementation,
17            CommandSpecification, PreCommandSpecification,
18        },
19        construct_type::ConstructType,
20        diagnostics::Diagnostic,
21        types::Type,
22        ConstructDid,
23    },
24};
25
26use crate::constants::ACTION_ITEM_CHECK_OUTPUT;
27
28pub fn new_module_specification() -> CommandSpecification {
29    let command = define_command! {
30        Module => {
31            name: "Module",
32            matcher: "module",
33            documentation: "Read Construct attribute",
34            implements_signing_capability: false,
35            implements_background_task_capability: false,
36            inputs: [],
37            outputs: [],
38            example: "",
39        }
40    };
41    match command {
42        PreCommandSpecification::Atomic(mut command) => {
43            command.accepts_arbitrary_inputs = true;
44            command.create_output_for_each_input = true;
45            command
46        }
47        PreCommandSpecification::Composite(_) => panic!("module must not be composite"),
48    }
49}
50
51pub struct Module;
52impl CommandImplementation for Module {
53    fn check_instantiability(
54        _ctx: &CommandSpecification,
55        _args: Vec<Type>,
56    ) -> Result<Type, Diagnostic> {
57        unimplemented!()
58    }
59
60    fn check_executability(
61        _construct_id: &ConstructDid,
62        _instance_name: &str,
63        _spec: &CommandSpecification,
64        _values: &ValueStore,
65        _supervision_context: &RunbookSupervisionContext,
66        _auth_context: &AuthorizationContext,
67    ) -> Result<Actions, Diagnostic> {
68        unimplemented!()
69    }
70
71    fn run_execution(
72        _construct_id: &ConstructDid,
73        _spec: &CommandSpecification,
74        _values: &ValueStore,
75        _progress_tx: &txtx_addon_kit::channel::Sender<BlockEvent>,
76        _auth_ctx: &txtx_addon_kit::types::AuthorizationContext,
77    ) -> CommandExecutionFutureResult {
78        let result = CommandExecutionResult::new();
79        return_synchronous_result(Ok(result))
80    }
81}
82
83pub fn new_variable_specification() -> CommandSpecification {
84    let command: PreCommandSpecification = define_command! {
85        Variable => {
86            name: "Variable",
87            matcher: ConstructType::Variable.to_string(),
88            documentation: "A construct designed to store a variable.",
89            implements_signing_capability: false,
90            implements_background_task_capability: false,
91            inputs: [
92                value: {
93                    documentation: "The value of the variable.",
94                    typing: Type::string(),
95                    optional: false,
96                    tainting: true,
97                    internal: false
98                },
99                editable: {
100                    documentation: "Determines if the variable value is editable in the supervisor UI.",
101                    typing: Type::string(),
102                    optional: true,
103                    tainting: false,
104                    internal: false
105                },
106                description: {
107                    documentation: "A description of the variable.",
108                    typing: Type::string(),
109                    optional: true,
110                    tainting: false,
111                    internal: false
112                },
113                type: {
114                    documentation: "The type of the variable. This can usually be inferred from the `value` field.",
115                    typing: Type::string(),
116                    optional: true,
117                    tainting: true,
118                    internal: false
119                }
120            ],
121            outputs: [
122                value: {
123                    documentation: "Value of the variable.",
124                    typing: Type::string()
125                }
126            ],
127            example: "",
128        }
129    };
130    match command {
131        PreCommandSpecification::Atomic(command) => command,
132        PreCommandSpecification::Composite(_) => {
133            panic!("variable should not be composite command specification")
134        }
135    }
136}
137
138pub struct Variable;
139
140impl CommandImplementation for Variable {
141    fn check_instantiability(
142        _ctx: &CommandSpecification,
143        _args: Vec<Type>,
144    ) -> Result<Type, Diagnostic> {
145        unimplemented!()
146    }
147
148    fn check_executability(
149        construct_did: &ConstructDid,
150        instance_name: &str,
151        spec: &CommandSpecification,
152        values: &ValueStore,
153        supervision_context: &RunbookSupervisionContext,
154        auth_context: &AuthorizationContext,
155    ) -> Result<Actions, Diagnostic> {
156        let Some(value) = values.get_value("value") else {
157            return Err(diagnosed_error!(
158                "variable {}: attribute 'value' must be present",
159                instance_name
160            ));
161        };
162        if !supervision_context.review_input_values
163            && !supervision_context.review_input_default_values
164        {
165            return Ok(Actions::none());
166        }
167        for input_spec in spec.inputs.iter() {
168            if input_spec.name == "value" && input_spec.check_performed {
169                return Ok(Actions::none());
170            }
171        }
172
173        let title = instance_name;
174        let description = values.get_string(DESCRIPTION).and_then(|d| Some(d.to_string()));
175        let markdown = values.get_markdown(&auth_context)?;
176
177        let is_editable = values.get_bool("editable").unwrap_or(false);
178        let action = if is_editable {
179            ActionItemRequestType::ProvideInput(ProvideInputRequest {
180                default_value: Some(value.to_owned()),
181                input_name: "value".into(),
182                typing: value.get_type(),
183            })
184            .to_request(title, "provide_input")
185            .with_some_description(description)
186            .with_construct_did(construct_did)
187            .with_some_markdown(markdown)
188        } else {
189            if supervision_context.review_input_values {
190                ReviewInputRequest::new("value", &value)
191                    .to_action_type()
192                    .to_request(title, "check_input")
193                    .with_some_description(description)
194                    .with_construct_did(construct_did)
195                    .with_some_markdown(markdown)
196            } else {
197                return Ok(Actions::none());
198            }
199        };
200        return Ok(Actions::append_item(
201            action,
202            Some("Review and check the variables from the list below"),
203            Some("Variables Review"),
204        ));
205    }
206
207    fn run_execution(
208        _construct_id: &ConstructDid,
209        _spec: &CommandSpecification,
210        values: &ValueStore,
211        _progress_tx: &txtx_addon_kit::channel::Sender<BlockEvent>,
212        _auth_ctx: &txtx_addon_kit::types::AuthorizationContext,
213    ) -> CommandExecutionFutureResult {
214        let mut result = CommandExecutionResult::new();
215        let value = values.get_expected_value("value")?;
216        result.outputs.insert("value".to_string(), value.clone());
217        return_synchronous_result(Ok(result))
218    }
219}
220
221pub fn new_output_specification() -> CommandSpecification {
222    let command = define_command! {
223        Output => {
224            name: "Output",
225            matcher: ConstructType::Output.to_string(),
226            documentation: "Read Construct attribute",
227            implements_signing_capability: false,
228            implements_background_task_capability: false,
229            inputs: [
230                value: {
231                    documentation: "Value of the output",
232                    typing: Type::string(),
233                    optional: true,
234                    tainting: true,
235                    internal: false
236                },
237                description: {
238                    documentation: "Description of the output",
239                    typing: Type::string(),
240                    optional: true,
241                    tainting: false,
242                    internal: false
243                }
244            ],
245            outputs: [
246                value: {
247                    documentation: "Value of the output",
248                    typing: Type::string()
249                }
250            ],
251            example: "",
252        }
253    };
254    match command {
255        PreCommandSpecification::Atomic(command) => command,
256        PreCommandSpecification::Composite(_) => {
257            panic!("output should not be composite command specification")
258        }
259    }
260}
261
262pub struct Output;
263
264impl CommandImplementation for Output {
265    fn check_instantiability(
266        _ctx: &CommandSpecification,
267        _args: Vec<Type>,
268    ) -> Result<Type, Diagnostic> {
269        unimplemented!()
270    }
271
272    fn check_executability(
273        construct_did: &ConstructDid,
274        instance_name: &str,
275        _spec: &CommandSpecification,
276        args: &ValueStore,
277        _supervision_context: &RunbookSupervisionContext,
278        auth_context: &AuthorizationContext,
279    ) -> Result<Actions, Diagnostic> {
280        let value = args.get_expected_value("value")?;
281        let description = args.get_string(DESCRIPTION).and_then(|d| Some(d.to_string()));
282        let markdown = args.get_markdown(&auth_context)?;
283        let actions = Actions::new_sub_group_of_items(
284            None,
285            vec![ActionItemRequestType::DisplayOutput(DisplayOutputRequest {
286                name: instance_name.into(),
287                description: None,
288                value: value.clone(),
289            })
290            .to_request(instance_name, ACTION_ITEM_CHECK_OUTPUT)
291            .with_construct_did(construct_did)
292            .with_some_description(description)
293            .with_some_markdown(markdown)],
294        );
295        Ok(actions)
296    }
297
298    fn run_execution(
299        _construct_id: &ConstructDid,
300        _spec: &CommandSpecification,
301        args: &ValueStore,
302        _progress_tx: &txtx_addon_kit::channel::Sender<BlockEvent>,
303        _auth_ctx: &txtx_addon_kit::types::AuthorizationContext,
304    ) -> CommandExecutionFutureResult {
305        let value = args.get_expected_value("value")?;
306        let mut result = CommandExecutionResult::new();
307        result.outputs.insert("value".to_string(), value.clone());
308        return_synchronous_result(Ok(result))
309    }
310}
311
312pub fn new_runtime_setting() -> CommandSpecification {
313    let command: PreCommandSpecification = define_command! {
314        Runtime => {
315            name: "Runtime",
316            matcher: "runtime",
317            documentation: "Construct designed to import an addon",
318            implements_signing_capability: false,
319            implements_background_task_capability: false,
320            inputs: [
321                defaults: {
322                    documentation: "Value of the input",
323                    typing: Type::arbitrary_object(),
324                    optional: true,
325                    tainting: true,
326                    internal: false
327                }
328            ],
329            outputs: [
330            ],
331            example: "",
332        }
333    };
334    match command {
335        PreCommandSpecification::Atomic(command) => command,
336        PreCommandSpecification::Composite(_) => {
337            panic!("input should not be composite command specification")
338        }
339    }
340}
341
342pub struct Runtime;
343
344impl CommandImplementation for Runtime {
345    fn check_instantiability(
346        _ctx: &CommandSpecification,
347        _args: Vec<Type>,
348    ) -> Result<Type, Diagnostic> {
349        unimplemented!()
350    }
351
352    fn check_executability(
353        _construct_did: &ConstructDid,
354        _instance_name: &str,
355        _spec: &CommandSpecification,
356        _values: &ValueStore,
357        _supervision_context: &RunbookSupervisionContext,
358        _auth_context: &AuthorizationContext,
359    ) -> Result<Actions, Diagnostic> {
360        unimplemented!()
361    }
362
363    fn run_execution(
364        _construct_id: &ConstructDid,
365        _spec: &CommandSpecification,
366        _values: &ValueStore,
367        _progress_tx: &txtx_addon_kit::channel::Sender<BlockEvent>,
368        _auth_ctx: &txtx_addon_kit::types::AuthorizationContext,
369    ) -> CommandExecutionFutureResult {
370        unimplemented!()
371    }
372}