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}