Mountain/Track/
EffectCreation.rs

1// File: Mountain/Source/Track/EffectCreation.rs
2// Role: Central routing table for the application.
3// Responsibilities:
4//   - Map string-based command and RPC method names to their strongly-typed
5//     effect constructors from the `Common` crate.
6//   - Create a runnable, type-erased `MappedEffect` for each request.
7
8//! # EffectCreation
9//!
10//! Contains the logic for creating `ActionEffect`s by mapping string-based
11//! command and RPC method names to their strongly-typed effect constructors in
12//! the `Common` crate. This is the central routing table of the application.
13
14#![allow(non_snake_case, non_camel_case_types)]
15
16use std::{future::Future, pin::Pin, sync::Arc};
17
18use Common::{
19	self,
20	Command::{ExecuteCommand::ExecuteCommand, GetAllCommands::GetAllCommands, RegisterCommand::RegisterCommand},
21	Configuration::{
22		ConfigurationInspector::ConfigurationInspector,
23		ConfigurationProvider::ConfigurationProvider,
24		DTO::ConfigurationTarget::ConfigurationTarget,
25		GetConfiguration::GetConfiguration,
26	},
27	CustomEditor::CustomEditorProvider::CustomEditorProvider,
28	Debug::DebugService::DebugService,
29	Diagnostic::DiagnosticManager::DiagnosticManager,
30	Document::{SaveDocument::SaveDocument, SaveDocumentAs::SaveDocumentAs},
31	Effect::{ActionEffect::ActionEffect, ApplicationRunTime::ApplicationRunTime as ApplicationRunTimeTrait},
32	Environment::Requires::Requires,
33	Error::CommonError::CommonError,
34	FileSystem::{
35		Delete::Delete,
36		ReadDirectory::ReadDirectory,
37		ReadFile::ReadFile,
38		StatFile::StatFile,
39		WriteFileBytes::WriteFileBytes,
40	},
41	Keybinding::KeybindingProvider::KeybindingProvider,
42	LanguageFeature::{
43		DTO::ProviderType::ProviderType,
44		LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
45	},
46	Search::SearchProvider::SearchProvider,
47	SourceControlManagement::SourceControlManagementProvider::SourceControlManagementProvider,
48	StatusBar::{DTO::StatusBarEntryDTO::StatusBarEntryDTO, StatusBarProvider::StatusBarProvider},
49	Storage::{GetStorageItem::GetStorageItem, SetStorageItem::SetStorageItem, StorageProvider::StorageProvider},
50	Terminal::TerminalProvider::TerminalProvider,
51	TreeView::TreeViewProvider::TreeViewProvider,
52	UserInterface::{ShowMessage::ShowMessage, ShowOpenDialog::ShowOpenDialog, ShowSaveDialog::ShowSaveDialog},
53	WebView::WebViewProvider::WebViewProvider,
54};
55use serde_json::{Value, from_value, json};
56use tauri::{AppHandle, Runtime};
57use url::Url;
58
59use crate::{
60	Environment::MountainEnvironment::MountainEnvironment,
61	RunTime::ApplicationRunTime::ApplicationRunTime as MountainRunTime,
62};
63
64/// A type alias for a boxed, runnable effect. This is the "type-erased" unit of
65/// work that the dispatch logic can execute.
66pub type MappedEffect =
67	Box<dyn FnOnce(Arc<MountainRunTime>) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> + Send>;
68
69/// A helper macro to reduce boilerplate when getting and deserializing
70/// parameters from a JSON array.
71macro_rules! Parameter {
72	($Parameter:expr, $Current:expr, $Type:ty) => {
73		from_value::<$Type>(
74			$Parameter
75				.get($Current)
76				.cloned()
77				.ok_or_else(|| format!("Missing parameter at index {}", $Current))?,
78		)
79		.map_err(|Error| format!("Invalid parameter at index {}: {}", $Current, Error))
80	};
81}
82
83/// A helper that takes a specific `ActionEffect`, boxes it, and returns a
84/// closure that can be run by the dispatcher. This is used for effects that
85/// follow the declarative pattern.
86fn Map<C, O, E>(Effect:ActionEffect<Arc<C>, E, O>) -> MappedEffect
87where
88	C: ?Sized + Send + Sync + 'static,
89	O: serde::Serialize + Send + Sync + 'static,
90	E: Into<CommonError> + From<CommonError> + Send + Sync + 'static,
91	MountainEnvironment: Requires<C>, {
92	Box::new(move |RunTime:Arc<MountainRunTime>| {
93		Box::pin(async move {
94			let Result = RunTime.Run(Effect).await;
95
96			match Result {
97				Ok(Output) => serde_json::to_value(Output).map_err(|Error| format!("Serialization failed: {}", Error)),
98
99				Err(Error) => {
100					let CommonError:CommonError = Error.into();
101
102					Err(CommonError.to_string())
103				},
104			}
105		})
106	})
107}
108
109/// Creates an `ActionEffect` or a direct provider call for a request from any
110/// source (frontend or sidecar). This function is the primary router for the
111/// entire backend application logic.
112pub fn CreateEffectForRequest<R:Runtime>(
113	_ApplicationHandle:&AppHandle<R>,
114
115	Method:&str,
116
117	Parameters:Value,
118) -> Result<MappedEffect, String> {
119	let ParametersArray = Parameters
120		.as_array()
121		.ok_or_else(|| format!("Parameters for '{}' must be an array.", Method))?;
122
123	// --- Direct Provider Calls (for performance or simplicity) ---
124	// These bypass the `box_effect` helper for direct invocation.
125	match Method {
126		// Configuration
127		"Configuration.Inspect" => {
128			let Key = Parameter!(ParametersArray, 0, String)?;
129
130			let Overrides = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
131
132			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
133				Box::pin(async move {
134					let provider:Arc<dyn ConfigurationInspector> = runtime.Environment.Require();
135
136					let result = provider
137						.InspectConfigurationValue(Key, from_value(Overrides).unwrap_or_default())
138						.await
139						.map_err(|Error| Error.to_string())?;
140
141					Ok(serde_json::to_value(result).unwrap_or(Value::Null))
142				})
143			}));
144		},
145
146		"Configuration.Update" => {
147			let Key = Parameter!(ParametersArray, 0, String)?;
148
149			let ValueToSet = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
150
151			let Target = Parameter!(ParametersArray, 2, ConfigurationTarget)?;
152
153			let Overrides = ParametersArray.get(3).cloned().unwrap_or(Value::Null);
154
155			let ScopeToLang = Parameter!(ParametersArray, 4, Option<bool>)?;
156
157			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
158				Box::pin(async move {
159					let provider:Arc<dyn ConfigurationProvider> = runtime.Environment.Require();
160
161					provider
162						.UpdateConfigurationValue(
163							Key,
164							ValueToSet,
165							Target,
166							from_value(Overrides).unwrap_or_default(),
167							ScopeToLang,
168						)
169						.await
170						.map_err(|Error| Error.to_string())?;
171
172					Ok(Value::Null)
173				})
174			}));
175		},
176
177		// Custom Editor
178		"$resolveCustomEditor" => {
179			let ViewType = Parameter!(ParametersArray, 0, String)?;
180
181			let ResourceURI = Parameter!(ParametersArray, 1, Url)?;
182
183			let WebViewPanelHandle = Parameter!(ParametersArray, 2, String)?;
184
185			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
186				Box::pin(async move {
187					let provider:Arc<dyn CustomEditorProvider> = runtime.Environment.Require();
188
189					provider
190						.ResolveCustomEditor(ViewType, ResourceURI, WebViewPanelHandle)
191						.await
192						.map_err(|Error| Error.to_string())?;
193
194					Ok(Value::Null)
195				})
196			}));
197		},
198
199		// Debug
200		"Debug.Start" => {
201			let folder_uri_val = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
202
203			let config = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
204
205			let folder_uri = if folder_uri_val.is_null() {
206				None
207			} else {
208				Some(from_value(folder_uri_val).map_err(|Error| Error.to_string())?)
209			};
210
211			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
212				Box::pin(async move {
213					let provider:Arc<dyn DebugService> = runtime.Environment.Require();
214
215					let session_id = provider
216						.StartDebugging(folder_uri, config)
217						.await
218						.map_err(|Error| Error.to_string())?;
219
220					Ok(json!(session_id))
221				})
222			}));
223		},
224
225		"Debug.RegisterConfigurationProvider" => {
226			let dbg_type = Parameter!(ParametersArray, 0, String)?;
227
228			let handle = Parameter!(ParametersArray, 1, u32)?;
229
230			let sidecar_id = Parameter!(ParametersArray, 2, String)?;
231
232			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
233				Box::pin(async move {
234					let provider:Arc<dyn DebugService> = runtime.Environment.Require();
235
236					provider
237						.RegisterDebugConfigurationProvider(dbg_type, handle, sidecar_id)
238						.await
239						.map_err(|Error| Error.to_string())?;
240
241					Ok(Value::Null)
242				})
243			}));
244		},
245
246		// Diagnostic
247		"Diagnostic.Set" => {
248			let Owner = Parameter!(ParametersArray, 0, String)?;
249
250			let Entries = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
251
252			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
253				Box::pin(async move {
254					let provider:Arc<dyn DiagnosticManager> = runtime.Environment.Require();
255
256					provider
257						.SetDiagnostics(Owner, Entries)
258						.await
259						.map_err(|Error| Error.to_string())?;
260
261					Ok(Value::Null)
262				})
263			}));
264		},
265
266		"Diagnostic.Clear" => {
267			let Owner = Parameter!(ParametersArray, 0, String)?;
268
269			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
270				Box::pin(async move {
271					let provider:Arc<dyn DiagnosticManager> = runtime.Environment.Require();
272
273					provider.ClearDiagnostics(Owner).await.map_err(|Error| Error.to_string())?;
274
275					Ok(Value::Null)
276				})
277			}));
278		},
279
280		// Keybinding
281		"Keybinding.GetResolved" => {
282			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
283				Box::pin(async move {
284					let provider:Arc<dyn KeybindingProvider> = runtime.Environment.Require();
285
286					provider.GetResolvedKeybinding().await.map_err(|Error| Error.to_string())
287				})
288			}));
289		},
290
291		// Language Features
292		"$languageFeatures:registerProvider" => {
293			let SideCarID = Parameter!(ParametersArray, 0, String)?;
294
295			let ProviderType = Parameter!(ParametersArray, 1, ProviderType)?;
296
297			let Selector = ParametersArray.get(2).cloned().unwrap_or(Value::Null);
298
299			let ExtensionID = ParametersArray.get(3).cloned().unwrap_or(Value::Null);
300
301			let Options = ParametersArray.get(4).cloned();
302
303			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
304				Box::pin(async move {
305					let provider:Arc<dyn LanguageFeatureProviderRegistry> = runtime.Environment.Require();
306
307					let handle = provider
308						.RegisterProvider(SideCarID, ProviderType, Selector, ExtensionID, Options)
309						.await
310						.map_err(|Error| Error.to_string())?;
311
312					Ok(json!(handle))
313				})
314			}));
315		},
316
317		"$languageFeatures:unregisterProvider" => {
318			let Handle = Parameter!(ParametersArray, 0, u32)?;
319
320			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
321				Box::pin(async move {
322					let provider:Arc<dyn LanguageFeatureProviderRegistry> = runtime.Environment.Require();
323
324					provider.UnregisterProvider(Handle).await.map_err(|Error| Error.to_string())?;
325
326					Ok(Value::Null)
327				})
328			}));
329		},
330
331		// Search
332		"Search.TextSearch" => {
333			let Query = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
334
335			let Options = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
336
337			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
338				Box::pin(async move {
339					let provider:Arc<dyn SearchProvider> = runtime.Environment.Require();
340
341					let result = provider.TextSearch(Query, Options).await.map_err(|Error| Error.to_string())?;
342
343					Ok(result)
344				})
345			}));
346		},
347
348		// SourceControlManagement
349		"$scm:createSourceControl" => {
350			let DTO = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
351
352			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
353				Box::pin(async move {
354					let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
355
356					let handle = provider.CreateSourceControl(DTO).await.map_err(|Error| Error.to_string())?;
357
358					Ok(json!(handle))
359				})
360			}));
361		},
362
363		"$scm:updateSourceControl" => {
364			let handle = Parameter!(ParametersArray, 0, u32)?;
365
366			let dto = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
367
368			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
369				Box::pin(async move {
370					let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
371
372					provider
373						.UpdateSourceControl(handle, dto)
374						.await
375						.map_err(|Error| Error.to_string())?;
376
377					Ok(Value::Null)
378				})
379			}));
380		},
381
382		"$scm:updateGroup" => {
383			let handle = Parameter!(ParametersArray, 0, u32)?;
384
385			let dto = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
386
387			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
388				Box::pin(async move {
389					let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
390
391					provider
392						.UpdateSourceControlGroup(handle, dto)
393						.await
394						.map_err(|Error| Error.to_string())?;
395
396					Ok(Value::Null)
397				})
398			}));
399		},
400
401		"$scm:registerInputBox" => {
402			let handle = Parameter!(ParametersArray, 0, u32)?;
403
404			let dto = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
405
406			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
407				Box::pin(async move {
408					let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
409
410					provider
411						.RegisterInputBox(handle, dto)
412						.await
413						.map_err(|Error| Error.to_string())?;
414
415					Ok(Value::Null)
416				})
417			}));
418		},
419
420		// Status Bar
421		"$statusBar:set" => {
422			let EntryDTO = Parameter!(ParametersArray, 0, StatusBarEntryDTO)?;
423
424			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
425				Box::pin(async move {
426					let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
427
428					provider.SetStatusBarEntry(EntryDTO).await.map_err(|Error| Error.to_string())?;
429
430					Ok(Value::Null)
431				})
432			}));
433		},
434
435		"$statusBar:dispose" => {
436			let EntryID = Parameter!(ParametersArray, 0, String)?;
437
438			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
439				Box::pin(async move {
440					let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
441
442					provider
443						.DisposeStatusBarEntry(EntryID)
444						.await
445						.map_err(|Error| Error.to_string())?;
446
447					Ok(Value::Null)
448				})
449			}));
450		},
451
452		"$setStatusBarMessage" => {
453			let ID = Parameter!(ParametersArray, 0, String)?;
454
455			let Text = Parameter!(ParametersArray, 1, String)?;
456
457			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
458				Box::pin(async move {
459					let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
460
461					provider
462						.SetStatusBarMessage(ID, Text)
463						.await
464						.map_err(|Error| Error.to_string())?;
465
466					Ok(Value::Null)
467				})
468			}));
469		},
470
471		"$disposeStatusBarMessage" => {
472			let ID = Parameter!(ParametersArray, 0, String)?;
473
474			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
475				Box::pin(async move {
476					let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
477
478					provider.DisposeStatusBarMessage(ID).await.map_err(|Error| Error.to_string())?;
479
480					Ok(Value::Null)
481				})
482			}));
483		},
484
485		// Storage (Batch)
486		"$storage:getAll" => {
487			let IsGlobal = Parameter!(ParametersArray, 0, bool)?;
488
489			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
490				Box::pin(async move {
491					let provider:Arc<dyn StorageProvider> = runtime.Environment.Require();
492
493					provider.GetAllStorage(IsGlobal).await.map_err(|Error| Error.to_string())
494				})
495			}));
496		},
497
498		"$storage:setAll" => {
499			let IsGlobal = Parameter!(ParametersArray, 0, bool)?;
500
501			let State = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
502
503			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
504				Box::pin(async move {
505					let provider:Arc<dyn StorageProvider> = runtime.Environment.Require();
506
507					provider
508						.SetAllStorage(IsGlobal, State)
509						.await
510						.map_err(|Error| Error.to_string())?;
511
512					Ok(Value::Null)
513				})
514			}));
515		},
516
517		// Terminal
518		"$terminal:create" => {
519			let OptionsValue = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
520
521			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
522				Box::pin(async move {
523					let provider:Arc<dyn TerminalProvider> = runtime.Environment.Require();
524
525					let result = provider.CreateTerminal(OptionsValue).await.map_err(|Error| Error.to_string())?;
526
527					Ok(result)
528				})
529			}));
530		},
531
532		"$terminal:sendText" => {
533			let TerminalId = Parameter!(ParametersArray, 0, u64)?;
534
535			let Text = Parameter!(ParametersArray, 1, String)?;
536
537			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
538				Box::pin(async move {
539					let provider:Arc<dyn TerminalProvider> = runtime.Environment.Require();
540
541					provider
542						.SendTextToTerminal(TerminalId, Text)
543						.await
544						.map_err(|Error| Error.to_string())?;
545
546					Ok(Value::Null)
547				})
548			}));
549		},
550
551		"$terminal:dispose" => {
552			let TerminalId = Parameter!(ParametersArray, 0, u64)?;
553
554			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
555				Box::pin(async move {
556					let provider:Arc<dyn TerminalProvider> = runtime.Environment.Require();
557
558					provider.DisposeTerminal(TerminalId).await.map_err(|Error| Error.to_string())?;
559
560					Ok(Value::Null)
561				})
562			}));
563		},
564
565		// Tree View
566		"$tree:register" => {
567			let ID = Parameter!(ParametersArray, 0, String)?;
568
569			let Options = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
570
571			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
572				Box::pin(async move {
573					let provider:Arc<dyn TreeViewProvider> = runtime.Environment.Require();
574
575					provider
576						.RegisterTreeDataProvider(ID, Options)
577						.await
578						.map_err(|Error| Error.to_string())?;
579
580					Ok(Value::Null)
581				})
582			}));
583		},
584
585		// WebView
586		"$webview:create" => {
587			let ExtData = Parameter!(ParametersArray, 0, Value)?;
588
589			let ViewType = Parameter!(ParametersArray, 1, String)?;
590
591			let Title = Parameter!(ParametersArray, 2, String)?;
592
593			let ShowOpts = Parameter!(ParametersArray, 3, Value)?;
594
595			let PanelOpts = Parameter!(ParametersArray, 4, Value)?;
596
597			let ContentOpts = Parameter!(ParametersArray, 5, Value)?;
598
599			return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
600				Box::pin(async move {
601					let provider:Arc<dyn WebViewProvider> = runtime.Environment.Require();
602
603					let handle = provider
604						.CreateWebViewPanel(ExtData, ViewType, Title, ShowOpts, PanelOpts, ContentOpts)
605						.await
606						.map_err(|Error| Error.to_string())?;
607
608					Ok(json!(handle))
609				})
610			}));
611		},
612
613		// Fall through to effect-based handlers
614		_ => {},
615	}
616
617	// --- ActionEffect-based Handlers ---
618	let effect = match Method {
619		// Command
620		"Command.Execute" => {
621			let ID = Parameter!(ParametersArray, 0, String)?;
622
623			let Args = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
624
625			Map(ExecuteCommand(ID, Args))
626		},
627
628		"Command.GetAll" => Map(GetAllCommands()),
629
630		"Command.Register" => {
631			let SideCarID = Parameter!(ParametersArray, 0, String)?;
632
633			let CommandID = Parameter!(ParametersArray, 1, String)?;
634
635			Map(RegisterCommand(SideCarID, CommandID))
636		},
637
638		// Configuration
639		"Configuration.Get" => {
640			let Section = Parameter!(ParametersArray, 0, Option<String>)?;
641
642			let Overrides = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
643
644			Map(GetConfiguration(Section, Overrides))
645		},
646
647		// Document
648		"Document.Save" => {
649			let uri_str = Parameter!(ParametersArray, 0, String)?;
650
651			let uri = Url::parse(&uri_str).map_err(|Error| format!("Invalid URI parameter: {}", Error))?;
652
653			Map(SaveDocument(uri))
654		},
655
656		"Document.SaveAs" => {
657			let original_uri_str = Parameter!(ParametersArray, 0, String)?;
658
659			let original_uri =
660				Url::parse(&original_uri_str).map_err(|Error| format!("Invalid URI parameter: {}", Error))?;
661
662			Map(SaveDocumentAs(original_uri, None))
663		},
664
665		// FileSystem
666		"FileSystem.ReadFile" => {
667			let Path = Parameter!(ParametersArray, 0, _)?;
668
669			Map(ReadFile(Path))
670		},
671
672		"FileSystem.StatFile" => {
673			let Path = Parameter!(ParametersArray, 0, _)?;
674
675			Map(StatFile(Path))
676		},
677
678		"FileSystem.ReadDirectory" => {
679			let Path = Parameter!(ParametersArray, 0, _)?;
680
681			Map(ReadDirectory(Path))
682		},
683
684		"FileSystem.WriteFile" => {
685			let Path = Parameter!(ParametersArray, 0, _)?;
686
687			let Content = Parameter!(ParametersArray, 1, Vec<u8>)?;
688
689			let Create = Parameter!(ParametersArray, 2, bool)?;
690
691			let Overwrite = Parameter!(ParametersArray, 3, bool)?;
692
693			Map(WriteFileBytes(Path, Content, Create, Overwrite))
694		},
695
696		"FileSystem.Delete" => {
697			let Path = Parameter!(ParametersArray, 0, _)?;
698
699			let Recursive = Parameter!(ParametersArray, 1, bool)?;
700
701			let UseTrash = Parameter!(ParametersArray, 2, bool)?;
702
703			Map(Delete(Path, Recursive, UseTrash))
704		},
705
706		// Storage (Legacy)
707		"Storage.Get" => {
708			let TargetObject = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
709
710			Map(GetStorageItem(TargetObject))
711		},
712
713		"Storage.Set" => {
714			let TargetObject = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
715
716			let ValueToSet = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
717
718			Map(SetStorageItem(TargetObject, ValueToSet))
719		},
720
721		// UserInterface
722		"UserInterface.ShowMessage" => {
723			let Severity = Parameter!(ParametersArray, 0, _)?;
724
725			let Message = Parameter!(ParametersArray, 1, String)?;
726
727			let Options = ParametersArray.get(2).cloned().unwrap_or(Value::Null);
728
729			Map(ShowMessage(Severity, Message, Options))
730		},
731
732		"UserInterface.ShowOpenDialog" => {
733			let Options = Parameter!(ParametersArray, 0, _)?;
734
735			Map(ShowOpenDialog(Options))
736		},
737
738		"UserInterface.ShowSaveDialog" => {
739			let Options = Parameter!(ParametersArray, 0, _)?;
740
741			Map(ShowSaveDialog(Options))
742		},
743
744		_ => return Err(format!("No mapping found for method: {}", Method)),
745	};
746
747	Ok(effect)
748}