@devaloop/devalang 0.0.1-beta.1 → 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/.devalang +9 -10
  2. package/Cargo.toml +5 -4
  3. package/README.md +7 -5
  4. package/docs/CHANGELOG.md +42 -0
  5. package/docs/ROADMAP.md +5 -1
  6. package/docs/TODO.md +3 -14
  7. package/examples/bus.deva +10 -0
  8. package/examples/effect.deva +2 -0
  9. package/examples/filter.deva +11 -0
  10. package/examples/lfo.deva +9 -0
  11. package/examples/synth.deva +11 -1
  12. package/examples/synth_types.deva +17 -0
  13. package/out-tsc/core/functions/index.d.ts +5 -0
  14. package/out-tsc/core/functions/index.js +11 -0
  15. package/out-tsc/pkg/devalang_core.d.ts +2 -0
  16. package/out-tsc/pkg/devalang_core.js +17 -2
  17. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -7
  18. package/package.json +1 -1
  19. package/project-version.json +3 -3
  20. package/rust/cli/bank/api.rs +122 -122
  21. package/rust/cli/bank/commands.rs +33 -2
  22. package/rust/cli/bank/mod.rs +29 -29
  23. package/rust/cli/build/commands.rs +53 -3
  24. package/rust/cli/build/mod.rs +2 -2
  25. package/rust/cli/build/process.rs +26 -7
  26. package/rust/cli/check/mod.rs +2 -2
  27. package/rust/cli/discover/commands.rs +253 -253
  28. package/rust/cli/discover/config.rs +111 -111
  29. package/rust/cli/discover/fs.rs +19 -19
  30. package/rust/cli/discover/install.rs +103 -103
  31. package/rust/cli/discover/metadata.rs +48 -48
  32. package/rust/cli/discover/mod.rs +5 -5
  33. package/rust/cli/install/addon.rs +118 -118
  34. package/rust/cli/install/bank.rs +22 -3
  35. package/rust/cli/install/commands.rs +35 -35
  36. package/rust/cli/install/mod.rs +4 -4
  37. package/rust/cli/install/plugin.rs +80 -61
  38. package/rust/cli/login/commands.rs +124 -124
  39. package/rust/cli/mod.rs +12 -12
  40. package/rust/cli/parser.rs +46 -1
  41. package/rust/cli/play/commands.rs +71 -20
  42. package/rust/cli/play/mod.rs +5 -5
  43. package/rust/cli/play/process.rs +14 -5
  44. package/rust/cli/play/realtime.rs +91 -91
  45. package/rust/cli/telemetry/commands.rs +22 -22
  46. package/rust/cli/telemetry/event_creator.rs +80 -80
  47. package/rust/cli/telemetry/mod.rs +3 -3
  48. package/rust/cli/telemetry/send.rs +51 -51
  49. package/rust/cli/template/commands.rs +69 -69
  50. package/rust/config/driver.rs +112 -103
  51. package/rust/config/mod.rs +3 -3
  52. package/rust/config/ops.rs +26 -26
  53. package/rust/config/settings.rs +101 -101
  54. package/rust/core/audio/engine/driver.rs +220 -0
  55. package/rust/core/audio/engine/export.rs +169 -0
  56. package/rust/core/audio/engine/helpers.rs +178 -170
  57. package/rust/core/audio/engine/mod.rs +51 -2
  58. package/rust/core/audio/engine/notes/dsp.rs +85 -0
  59. package/rust/core/audio/engine/notes/mod.rs +44 -0
  60. package/rust/core/audio/engine/notes/params.rs +294 -0
  61. package/rust/core/audio/engine/sample/insert.rs +199 -0
  62. package/rust/core/audio/engine/sample/mod.rs +40 -0
  63. package/rust/core/audio/engine/sample/padding.rs +170 -0
  64. package/rust/core/audio/evaluator/condition.rs +61 -0
  65. package/rust/core/audio/evaluator/mod.rs +9 -0
  66. package/rust/core/audio/{evaluator.rs → evaluator/numeric.rs} +1 -159
  67. package/rust/core/audio/evaluator/rhs.rs +16 -0
  68. package/rust/core/audio/evaluator/string_expr.rs +94 -0
  69. package/rust/core/audio/interpreter/driver.rs +55 -23
  70. package/rust/core/audio/interpreter/mod.rs +1 -13
  71. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
  72. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
  73. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
  74. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
  75. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
  76. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
  77. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
  78. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
  79. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
  80. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
  81. package/rust/core/audio/interpreter/{automate.rs → statements/automate.rs} +16 -18
  82. package/rust/core/audio/interpreter/{call.rs → statements/call.rs} +5 -4
  83. package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +2 -1
  84. package/rust/core/audio/interpreter/{function.rs → statements/function.rs} +2 -4
  85. package/rust/core/audio/interpreter/{let_.rs → statements/let_.rs} +2 -4
  86. package/rust/core/audio/interpreter/{load.rs → statements/load.rs} +2 -4
  87. package/rust/core/audio/interpreter/{loop_.rs → statements/loop_.rs} +2 -1
  88. package/rust/core/audio/interpreter/statements/mod.rs +12 -0
  89. package/rust/core/audio/interpreter/{sleep.rs → statements/sleep.rs} +28 -28
  90. package/rust/core/audio/interpreter/{spawn.rs → statements/spawn.rs} +3 -2
  91. package/rust/core/audio/interpreter/{tempo.rs → statements/tempo.rs} +40 -40
  92. package/rust/core/audio/interpreter/{trigger.rs → statements/trigger.rs} +1 -1
  93. package/rust/core/audio/loader/trigger.rs +2 -1
  94. package/rust/core/audio/mod.rs +6 -7
  95. package/rust/core/audio/player.rs +70 -70
  96. package/rust/core/audio/special/easing.rs +189 -189
  97. package/rust/core/audio/special/env.rs +45 -45
  98. package/rust/core/audio/special/math.rs +134 -134
  99. package/rust/core/audio/special/mod.rs +9 -9
  100. package/rust/core/audio/special/modulator.rs +143 -143
  101. package/rust/core/builder/mod.rs +45 -2
  102. package/rust/core/debugger/lexer.rs +27 -27
  103. package/rust/core/debugger/{module.rs → logs.rs} +3 -6
  104. package/rust/core/debugger/mod.rs +30 -30
  105. package/rust/core/debugger/preprocessor.rs +27 -27
  106. package/rust/core/debugger/store.rs +2 -4
  107. package/rust/core/error/mod.rs +269 -269
  108. package/rust/core/lexer/driver.rs +59 -61
  109. package/rust/core/lexer/handler/arrow.rs +82 -82
  110. package/rust/core/lexer/handler/at.rs +21 -21
  111. package/rust/core/lexer/handler/brace.rs +41 -41
  112. package/rust/core/lexer/handler/colon.rs +21 -21
  113. package/rust/core/lexer/handler/comment.rs +30 -30
  114. package/rust/core/lexer/handler/dot.rs +21 -21
  115. package/rust/core/lexer/handler/driver.rs +337 -337
  116. package/rust/core/lexer/handler/identifier.rs +47 -47
  117. package/rust/core/lexer/handler/indent.rs +66 -66
  118. package/rust/core/lexer/handler/mod.rs +15 -15
  119. package/rust/core/lexer/handler/newline.rs +23 -23
  120. package/rust/core/lexer/handler/number.rs +31 -31
  121. package/rust/core/lexer/handler/operator.rs +46 -46
  122. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  123. package/rust/core/lexer/handler/slash.rs +21 -21
  124. package/rust/core/lexer/handler/string.rs +63 -63
  125. package/rust/core/lexer/mod.rs +3 -3
  126. package/rust/core/mod.rs +0 -1
  127. package/rust/core/parser/driver/block.rs +111 -0
  128. package/rust/core/parser/driver/cursor.rs +82 -0
  129. package/rust/core/parser/driver/driver_impl.rs +139 -0
  130. package/rust/core/parser/driver/mod.rs +6 -0
  131. package/rust/core/parser/driver/parse_array.rs +120 -0
  132. package/rust/core/parser/driver/parse_map.rs +223 -0
  133. package/rust/core/parser/driver/parser.rs +160 -0
  134. package/rust/core/parser/handler/arrow_call.rs +28 -4
  135. package/rust/core/parser/handler/at.rs +279 -279
  136. package/rust/core/parser/handler/bank.rs +104 -104
  137. package/rust/core/parser/handler/condition.rs +83 -83
  138. package/rust/core/parser/handler/dot.rs +148 -148
  139. package/rust/core/parser/handler/identifier/automate.rs +254 -254
  140. package/rust/core/parser/handler/identifier/call.rs +91 -91
  141. package/rust/core/parser/handler/identifier/emit.rs +70 -70
  142. package/rust/core/parser/handler/identifier/function.rs +113 -113
  143. package/rust/core/parser/handler/identifier/group.rs +89 -89
  144. package/rust/core/parser/handler/identifier/let_.rs +173 -173
  145. package/rust/core/parser/handler/identifier/mod.rs +55 -55
  146. package/rust/core/parser/handler/identifier/on.rs +107 -107
  147. package/rust/core/parser/handler/identifier/print.rs +49 -49
  148. package/rust/core/parser/handler/identifier/sleep.rs +96 -43
  149. package/rust/core/parser/handler/identifier/spawn.rs +91 -91
  150. package/rust/core/parser/handler/identifier/synth.rs +135 -135
  151. package/rust/core/parser/handler/loop_.rs +194 -194
  152. package/rust/core/parser/handler/mod.rs +9 -9
  153. package/rust/core/parser/handler/pattern.rs +1 -1
  154. package/rust/core/parser/handler/tempo.rs +105 -57
  155. package/rust/core/parser/statement.rs +10 -11
  156. package/rust/core/plugin/loader.rs +1 -1
  157. package/rust/core/plugin/mod.rs +2 -2
  158. package/rust/core/plugin/runner/mod.rs +11 -0
  159. package/rust/core/plugin/{runner.rs → runner/non_wasm.rs} +297 -347
  160. package/rust/core/plugin/runner/wasm32.rs +43 -0
  161. package/rust/core/preprocessor/loader/inject.rs +278 -0
  162. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
  163. package/rust/core/preprocessor/loader/mod.rs +235 -0
  164. package/rust/core/preprocessor/module.rs +2 -7
  165. package/rust/core/preprocessor/{processor.rs → processor/handlers.rs} +6 -13
  166. package/rust/core/preprocessor/processor/mod.rs +1 -0
  167. package/rust/core/preprocessor/resolver/bank.rs +49 -49
  168. package/rust/core/preprocessor/resolver/call.rs +124 -124
  169. package/rust/core/preprocessor/resolver/condition.rs +95 -95
  170. package/rust/core/preprocessor/resolver/driver.rs +324 -324
  171. package/rust/core/preprocessor/resolver/function.rs +2 -2
  172. package/rust/core/preprocessor/resolver/group.rs +46 -18
  173. package/rust/core/preprocessor/resolver/let_.rs +32 -32
  174. package/rust/core/preprocessor/resolver/loop_.rs +318 -318
  175. package/rust/core/preprocessor/resolver/mod.rs +16 -16
  176. package/rust/core/preprocessor/resolver/pattern.rs +83 -83
  177. package/rust/core/preprocessor/resolver/spawn.rs +99 -99
  178. package/rust/core/preprocessor/resolver/synth.rs +54 -54
  179. package/rust/core/preprocessor/resolver/tempo.rs +48 -48
  180. package/rust/core/preprocessor/resolver/trigger.rs +116 -116
  181. package/rust/core/preprocessor/resolver/value.rs +176 -176
  182. package/rust/core/store/global.rs +2 -6
  183. package/rust/core/store/mod.rs +1 -5
  184. package/rust/lib.rs +18 -3
  185. package/rust/main.rs +27 -3
  186. package/rust/types/Cargo.toml +1 -1
  187. package/rust/types/src/addons.rs +55 -55
  188. package/rust/types/src/config.rs +84 -74
  189. package/rust/types/src/lib.rs +15 -12
  190. package/rust/types/src/plugin.rs +20 -0
  191. package/rust/types/src/store.rs +139 -0
  192. package/rust/types/src/telemetry.rs +85 -85
  193. package/rust/utils/Cargo.toml +2 -2
  194. package/rust/utils/src/file.rs +94 -94
  195. package/rust/utils/src/first_usage.rs +97 -97
  196. package/rust/utils/src/lib.rs +9 -9
  197. package/rust/utils/src/logger.rs +200 -200
  198. package/rust/utils/src/path.rs +129 -88
  199. package/rust/utils/src/signature.rs +41 -41
  200. package/rust/utils/src/spinner.rs +20 -20
  201. package/rust/utils/src/version.rs +27 -27
  202. package/rust/utils/src/watcher.rs +46 -46
  203. package/rust/web/api.rs +5 -5
  204. package/rust/web/cdn.rs +34 -34
  205. package/rust/web/mod.rs +3 -3
  206. package/tests/integration.rs +21 -21
  207. package/typescript/core/functions/index.ts +11 -0
  208. package/typescript/pkg/devalang_core.ts +20 -4
  209. package/rust/core/audio/engine/sample.rs +0 -366
  210. package/rust/core/audio/engine/synth.rs +0 -325
  211. package/rust/core/audio/interpreter/arrow_call.rs +0 -311
  212. package/rust/core/audio/renderer.rs +0 -54
  213. package/rust/core/parser/driver.rs +0 -584
  214. package/rust/core/preprocessor/loader.rs +0 -637
  215. package/rust/core/store/export.rs +0 -28
  216. package/rust/core/store/function.rs +0 -40
  217. package/rust/core/store/import.rs +0 -28
  218. package/rust/core/store/variable.rs +0 -51
  219. package/rust/core/utils/mod.rs +0 -1
  220. package/rust/core/utils/path.rs +0 -37
@@ -1,111 +1,111 @@
1
- use devalang_core::config::driver::ProjectConfigExt;
2
- use devalang_types::{AddonWithMetadata, ProjectConfigBankEntry, ProjectConfigPluginEntry};
3
- use devalang_utils::path as path_utils;
4
-
5
- pub async fn add_addons_to_config(addons: Vec<AddonWithMetadata>) -> Result<(), String> {
6
- let config_path = path_utils::get_devalang_config_path()?;
7
- let mut config = crate::config::ops::load_config(Some(&config_path))
8
- .ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
9
-
10
- for addon in addons {
11
- let addon_path_as_devalang_protocol = format!(
12
- "devalang://{}/{}.{}",
13
- addon.addon_type, addon.metadata.author, addon.metadata.name
14
- );
15
-
16
- match addon.addon_type.as_str() {
17
- "bank" => {
18
- if config.banks.is_none() {
19
- config.banks = Some(Vec::new());
20
- }
21
-
22
- let banks = config.banks.as_mut().unwrap();
23
-
24
- let exists = banks
25
- .iter()
26
- .any(|b| b.path == addon_path_as_devalang_protocol);
27
- if exists {
28
- println!("Bank '{}' already in config", addon.name);
29
- continue;
30
- }
31
-
32
- banks.push(ProjectConfigBankEntry {
33
- path: addon_path_as_devalang_protocol,
34
- version: Some(addon.metadata.version.clone()),
35
- });
36
- }
37
-
38
- "plugin" => {
39
- if config.plugins.is_none() {
40
- config.plugins = Some(Vec::new());
41
- }
42
-
43
- let plugins = config.plugins.as_mut().unwrap();
44
-
45
- let exists = plugins
46
- .iter()
47
- .any(|p| p.path == addon_path_as_devalang_protocol);
48
- if exists {
49
- println!("Plugin '{}' already in config", addon.name);
50
- continue;
51
- }
52
-
53
- plugins.push(ProjectConfigPluginEntry {
54
- path: addon_path_as_devalang_protocol,
55
- version: Some(addon.metadata.version.clone()),
56
- });
57
- }
58
-
59
- // "preset" => {
60
- // if config.presets.is_none() {
61
- // config.presets = Some(Vec::new());
62
- // }
63
-
64
- // let presets = config.presets.as_mut().unwrap();
65
-
66
- // let exists = presets.iter().any(|p| p.path == addon_path_as_deva_protocol);
67
- // if exists {
68
- // println!("Preset '{}' already in config", addon.name);
69
- // continue;
70
- // }
71
-
72
- // presets.push(ProjectConfigPresetEntry {
73
- // path: addon_path_as_deva_protocol,
74
- // version: Some(addon.metadata.version.clone()),
75
- // });
76
- // }
77
-
78
- // "template" => {
79
- // if config.templates.is_none() {
80
- // config.templates = Some(Vec::new());
81
- // }
82
-
83
- // let templates = config.templates.as_mut().unwrap();
84
-
85
- // let exists = templates.iter().any(|t| t.path == addon_path_as_deva_protocol);
86
- // if exists {
87
- // println!("Template '{}' already in config", addon.name);
88
- // continue;
89
- // }
90
-
91
- // templates.push(ProjectConfigTemplateEntry {
92
- // path: addon_path_as_deva_protocol,
93
- // version: Some(addon.metadata.version.clone()),
94
- // });
95
- // }
96
- _ => {
97
- println!(
98
- "Unknown addon type '{}' for addon '{}'",
99
- addon.addon_type, addon.name
100
- );
101
- }
102
- }
103
- }
104
-
105
- // Update config with new addons
106
- if let Err(e) = config.write_config(&config) {
107
- return Err(format!("Failed to write config: {}", e));
108
- }
109
-
110
- Ok(())
111
- }
1
+ use devalang_core::config::driver::ProjectConfigExt;
2
+ use devalang_types::{AddonWithMetadata, ProjectConfigBankEntry, ProjectConfigPluginEntry};
3
+ use devalang_utils::path as path_utils;
4
+
5
+ pub async fn add_addons_to_config(addons: Vec<AddonWithMetadata>) -> Result<(), String> {
6
+ let config_path = path_utils::get_devalang_config_path()?;
7
+ let mut config = crate::config::ops::load_config(Some(&config_path))
8
+ .ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
9
+
10
+ for addon in addons {
11
+ let addon_path_as_devalang_protocol = format!(
12
+ "devalang://{}/{}.{}",
13
+ addon.addon_type, addon.metadata.author, addon.metadata.name
14
+ );
15
+
16
+ match addon.addon_type.as_str() {
17
+ "bank" => {
18
+ if config.banks.is_none() {
19
+ config.banks = Some(Vec::new());
20
+ }
21
+
22
+ let banks = config.banks.as_mut().unwrap();
23
+
24
+ let exists = banks
25
+ .iter()
26
+ .any(|b| b.path == addon_path_as_devalang_protocol);
27
+ if exists {
28
+ println!("Bank '{}' already in config", addon.name);
29
+ continue;
30
+ }
31
+
32
+ banks.push(ProjectConfigBankEntry {
33
+ path: addon_path_as_devalang_protocol,
34
+ version: Some(addon.metadata.version.clone()),
35
+ });
36
+ }
37
+
38
+ "plugin" => {
39
+ if config.plugins.is_none() {
40
+ config.plugins = Some(Vec::new());
41
+ }
42
+
43
+ let plugins = config.plugins.as_mut().unwrap();
44
+
45
+ let exists = plugins
46
+ .iter()
47
+ .any(|p| p.path == addon_path_as_devalang_protocol);
48
+ if exists {
49
+ println!("Plugin '{}' already in config", addon.name);
50
+ continue;
51
+ }
52
+
53
+ plugins.push(ProjectConfigPluginEntry {
54
+ path: addon_path_as_devalang_protocol,
55
+ version: Some(addon.metadata.version.clone()),
56
+ });
57
+ }
58
+
59
+ // "preset" => {
60
+ // if config.presets.is_none() {
61
+ // config.presets = Some(Vec::new());
62
+ // }
63
+
64
+ // let presets = config.presets.as_mut().unwrap();
65
+
66
+ // let exists = presets.iter().any(|p| p.path == addon_path_as_deva_protocol);
67
+ // if exists {
68
+ // println!("Preset '{}' already in config", addon.name);
69
+ // continue;
70
+ // }
71
+
72
+ // presets.push(ProjectConfigPresetEntry {
73
+ // path: addon_path_as_deva_protocol,
74
+ // version: Some(addon.metadata.version.clone()),
75
+ // });
76
+ // }
77
+
78
+ // "template" => {
79
+ // if config.templates.is_none() {
80
+ // config.templates = Some(Vec::new());
81
+ // }
82
+
83
+ // let templates = config.templates.as_mut().unwrap();
84
+
85
+ // let exists = templates.iter().any(|t| t.path == addon_path_as_deva_protocol);
86
+ // if exists {
87
+ // println!("Template '{}' already in config", addon.name);
88
+ // continue;
89
+ // }
90
+
91
+ // templates.push(ProjectConfigTemplateEntry {
92
+ // path: addon_path_as_deva_protocol,
93
+ // version: Some(addon.metadata.version.clone()),
94
+ // });
95
+ // }
96
+ _ => {
97
+ println!(
98
+ "Unknown addon type '{}' for addon '{}'",
99
+ addon.addon_type, addon.name
100
+ );
101
+ }
102
+ }
103
+ }
104
+
105
+ // Update config with new addons
106
+ if let Err(e) = config.write_config(&config) {
107
+ return Err(format!("Failed to write config: {}", e));
108
+ }
109
+
110
+ Ok(())
111
+ }
@@ -1,19 +1,19 @@
1
- use std::{fs, io, path::Path};
2
-
3
- pub fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), io::Error> {
4
- if !dst.exists() {
5
- fs::create_dir_all(dst)?;
6
- }
7
- for entry in fs::read_dir(src)? {
8
- let entry = entry?;
9
- let ty = entry.file_type()?;
10
- let from = entry.path();
11
- let to = dst.join(entry.file_name());
12
- if ty.is_dir() {
13
- copy_dir_all(&from, &to)?;
14
- } else {
15
- fs::copy(&from, &to)?;
16
- }
17
- }
18
- Ok(())
19
- }
1
+ use std::{fs, io, path::Path};
2
+
3
+ pub fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), io::Error> {
4
+ if !dst.exists() {
5
+ fs::create_dir_all(dst)?;
6
+ }
7
+ for entry in fs::read_dir(src)? {
8
+ let entry = entry?;
9
+ let ty = entry.file_type()?;
10
+ let from = entry.path();
11
+ let to = dst.join(entry.file_name());
12
+ if ty.is_dir() {
13
+ copy_dir_all(&from, &to)?;
14
+ } else {
15
+ fs::copy(&from, &to)?;
16
+ }
17
+ }
18
+ Ok(())
19
+ }
@@ -1,103 +1,103 @@
1
- use devalang_types::{AddonMetadata, AddonWithMetadata, DiscoveredAddon};
2
- use devalang_utils::path as path_utils;
3
-
4
- pub async fn install_selected_addons(
5
- addons: Vec<DiscoveredAddon>,
6
- ) -> Result<Vec<AddonWithMetadata>, String> {
7
- let mut addons_enriched = Vec::new();
8
-
9
- let tmp_dir = path_utils::ensure_deva_dir()?.join("tmp");
10
-
11
- for addon in addons {
12
- std::fs::create_dir_all(tmp_dir.join(&addon.name))
13
- .map_err(|e| format!("Failed to create directory for addon {}: {}", addon.name, e))?;
14
-
15
- let addon_path = tmp_dir.join(&addon.name);
16
- devalang_utils::file::extract_zip_safely(&addon.path, &addon_path)
17
- .map_err(|e| format!("Failed to extract addon {}: {}", addon.name, e))?;
18
-
19
- let base = path_utils::ensure_deva_dir()?;
20
- let target_addon_dir = match addon.addon_type.as_str() {
21
- "bank" => base.join("banks"),
22
- "plugin" => base.join("plugins"),
23
- "preset" => base.join("presets"),
24
- "template" => base.join("templates"),
25
- _ => {
26
- return Err(format!("Unknown addon type for addon {}", addon.name));
27
- }
28
- };
29
-
30
- std::fs::create_dir_all(&target_addon_dir).map_err(|e| {
31
- format!(
32
- "Failed to create target directory for addon {}: {}",
33
- addon.name, e
34
- )
35
- })?;
36
-
37
- let target_addon_path_dir = target_addon_dir.join(&addon.name);
38
- if target_addon_path_dir.exists() {
39
- println!(
40
- "Target addon directory {} already exists",
41
- target_addon_path_dir.display()
42
- );
43
- continue;
44
- }
45
-
46
- if let Err(e) = std::fs::rename(&addon_path, &target_addon_path_dir) {
47
- crate::cli::discover::fs::copy_dir_all(&addon_path, &target_addon_path_dir).map_err(
48
- |err| {
49
- format!(
50
- "Failed to move addon {}: {} (rename error: {})",
51
- addon.name, err, e
52
- )
53
- },
54
- )?;
55
- let _ = std::fs::remove_dir_all(&addon_path);
56
- }
57
-
58
- let addon_metadata_filename = match addon.addon_type.as_str() {
59
- "bank" => "bank.toml",
60
- "plugin" => "plugin.toml",
61
- "preset" => "preset.toml",
62
- "template" => "template.toml",
63
- _ => {
64
- return Err(format!("Unknown addon type for addon {}", addon.name));
65
- }
66
- };
67
-
68
- let addon_metadata_path = target_addon_path_dir.join(addon_metadata_filename);
69
- let addon_metadata_content = std::fs::read_to_string(&addon_metadata_path)
70
- .map_err(|e| format!("Failed to read metadata for addon {}: {}", addon.name, e))?;
71
-
72
- let parsed_meta = crate::cli::discover::metadata::parse_metadata_file(
73
- &addon.addon_type,
74
- &addon_metadata_content,
75
- )
76
- .unwrap_or(AddonMetadata {
77
- name: addon.name.clone(),
78
- author: "unknown".to_string(),
79
- version: "".to_string(),
80
- description: "".to_string(),
81
- access: "".to_string(),
82
- });
83
-
84
- addons_enriched.push(AddonWithMetadata {
85
- name: addon.name.clone(),
86
- path: addon.path.clone().to_string_lossy().to_string(),
87
- addon_type: addon.addon_type.clone(),
88
- metadata: parsed_meta,
89
- });
90
-
91
- if let Err(e) = std::fs::remove_file(&addon.path) {
92
- eprintln!(
93
- "Failed to remove zipped file for addon {}: {}",
94
- addon.name, e
95
- );
96
- }
97
- }
98
-
99
- // Best-effort cleanup of temporary extraction directory
100
- let _ = std::fs::remove_dir_all(&tmp_dir);
101
-
102
- Ok(addons_enriched)
103
- }
1
+ use devalang_types::{AddonMetadata, AddonWithMetadata, DiscoveredAddon};
2
+ use devalang_utils::path as path_utils;
3
+
4
+ pub async fn install_selected_addons(
5
+ addons: Vec<DiscoveredAddon>,
6
+ ) -> Result<Vec<AddonWithMetadata>, String> {
7
+ let mut addons_enriched = Vec::new();
8
+
9
+ let tmp_dir = path_utils::ensure_deva_dir()?.join("tmp");
10
+
11
+ for addon in addons {
12
+ std::fs::create_dir_all(tmp_dir.join(&addon.name))
13
+ .map_err(|e| format!("Failed to create directory for addon {}: {}", addon.name, e))?;
14
+
15
+ let addon_path = tmp_dir.join(&addon.name);
16
+ devalang_utils::file::extract_zip_safely(&addon.path, &addon_path)
17
+ .map_err(|e| format!("Failed to extract addon {}: {}", addon.name, e))?;
18
+
19
+ let base = path_utils::ensure_deva_dir()?;
20
+ let target_addon_dir = match addon.addon_type.as_str() {
21
+ "bank" => base.join("banks"),
22
+ "plugin" => base.join("plugins"),
23
+ "preset" => base.join("presets"),
24
+ "template" => base.join("templates"),
25
+ _ => {
26
+ return Err(format!("Unknown addon type for addon {}", addon.name));
27
+ }
28
+ };
29
+
30
+ std::fs::create_dir_all(&target_addon_dir).map_err(|e| {
31
+ format!(
32
+ "Failed to create target directory for addon {}: {}",
33
+ addon.name, e
34
+ )
35
+ })?;
36
+
37
+ let target_addon_path_dir = target_addon_dir.join(&addon.name);
38
+ if target_addon_path_dir.exists() {
39
+ println!(
40
+ "Target addon directory {} already exists",
41
+ target_addon_path_dir.display()
42
+ );
43
+ continue;
44
+ }
45
+
46
+ if let Err(e) = std::fs::rename(&addon_path, &target_addon_path_dir) {
47
+ crate::cli::discover::fs::copy_dir_all(&addon_path, &target_addon_path_dir).map_err(
48
+ |err| {
49
+ format!(
50
+ "Failed to move addon {}: {} (rename error: {})",
51
+ addon.name, err, e
52
+ )
53
+ },
54
+ )?;
55
+ let _ = std::fs::remove_dir_all(&addon_path);
56
+ }
57
+
58
+ let addon_metadata_filename = match addon.addon_type.as_str() {
59
+ "bank" => "bank.toml",
60
+ "plugin" => "plugin.toml",
61
+ "preset" => "preset.toml",
62
+ "template" => "template.toml",
63
+ _ => {
64
+ return Err(format!("Unknown addon type for addon {}", addon.name));
65
+ }
66
+ };
67
+
68
+ let addon_metadata_path = target_addon_path_dir.join(addon_metadata_filename);
69
+ let addon_metadata_content = std::fs::read_to_string(&addon_metadata_path)
70
+ .map_err(|e| format!("Failed to read metadata for addon {}: {}", addon.name, e))?;
71
+
72
+ let parsed_meta = crate::cli::discover::metadata::parse_metadata_file(
73
+ &addon.addon_type,
74
+ &addon_metadata_content,
75
+ )
76
+ .unwrap_or(AddonMetadata {
77
+ name: addon.name.clone(),
78
+ author: "unknown".to_string(),
79
+ version: "".to_string(),
80
+ description: "".to_string(),
81
+ access: "".to_string(),
82
+ });
83
+
84
+ addons_enriched.push(AddonWithMetadata {
85
+ name: addon.name.clone(),
86
+ path: addon.path.clone().to_string_lossy().to_string(),
87
+ addon_type: addon.addon_type.clone(),
88
+ metadata: parsed_meta,
89
+ });
90
+
91
+ if let Err(e) = std::fs::remove_file(&addon.path) {
92
+ eprintln!(
93
+ "Failed to remove zipped file for addon {}: {}",
94
+ addon.name, e
95
+ );
96
+ }
97
+ }
98
+
99
+ // Best-effort cleanup of temporary extraction directory
100
+ let _ = std::fs::remove_dir_all(&tmp_dir);
101
+
102
+ Ok(addons_enriched)
103
+ }
@@ -1,48 +1,48 @@
1
- use devalang_types::AddonMetadata;
2
- use toml::Value;
3
-
4
- pub fn parse_metadata_file(addon_type: &str, metadata_content: &str) -> Option<AddonMetadata> {
5
- let parsed = metadata_content.parse::<Value>().ok()?;
6
-
7
- let table = (match addon_type {
8
- "bank" => parsed.get("bank"),
9
- "plugin" => parsed.get("plugin"),
10
- "preset" => parsed.get("preset"),
11
- "template" => parsed.get("template"),
12
- _ => None,
13
- })?;
14
-
15
- let name = table
16
- .get("name")
17
- .and_then(|v| v.as_str())
18
- .unwrap_or("")
19
- .to_string();
20
- let version = table
21
- .get("version")
22
- .and_then(|v| v.as_str())
23
- .unwrap_or("")
24
- .to_string();
25
- let description = table
26
- .get("description")
27
- .and_then(|v| v.as_str())
28
- .unwrap_or("")
29
- .to_string();
30
- let author = table
31
- .get("author")
32
- .and_then(|v| v.as_str())
33
- .unwrap_or("unknown")
34
- .to_string();
35
- let access = table
36
- .get("access")
37
- .and_then(|v| v.as_str())
38
- .unwrap_or("")
39
- .to_string();
40
-
41
- Some(AddonMetadata {
42
- name,
43
- author,
44
- version,
45
- description,
46
- access,
47
- })
48
- }
1
+ use devalang_types::AddonMetadata;
2
+ use toml::Value;
3
+
4
+ pub fn parse_metadata_file(addon_type: &str, metadata_content: &str) -> Option<AddonMetadata> {
5
+ let parsed = metadata_content.parse::<Value>().ok()?;
6
+
7
+ let table = (match addon_type {
8
+ "bank" => parsed.get("bank"),
9
+ "plugin" => parsed.get("plugin"),
10
+ "preset" => parsed.get("preset"),
11
+ "template" => parsed.get("template"),
12
+ _ => None,
13
+ })?;
14
+
15
+ let name = table
16
+ .get("name")
17
+ .and_then(|v| v.as_str())
18
+ .unwrap_or("")
19
+ .to_string();
20
+ let version = table
21
+ .get("version")
22
+ .and_then(|v| v.as_str())
23
+ .unwrap_or("")
24
+ .to_string();
25
+ let description = table
26
+ .get("description")
27
+ .and_then(|v| v.as_str())
28
+ .unwrap_or("")
29
+ .to_string();
30
+ let author = table
31
+ .get("author")
32
+ .and_then(|v| v.as_str())
33
+ .unwrap_or("unknown")
34
+ .to_string();
35
+ let access = table
36
+ .get("access")
37
+ .and_then(|v| v.as_str())
38
+ .unwrap_or("")
39
+ .to_string();
40
+
41
+ Some(AddonMetadata {
42
+ name,
43
+ author,
44
+ version,
45
+ description,
46
+ access,
47
+ })
48
+ }
@@ -1,5 +1,5 @@
1
- pub mod commands;
2
- pub mod config;
3
- pub mod fs;
4
- pub mod install;
5
- pub mod metadata;
1
+ pub mod commands;
2
+ pub mod config;
3
+ pub mod fs;
4
+ pub mod install;
5
+ pub mod metadata;