@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,122 +1,122 @@
1
- use crate::web::cdn::get_cdn_url;
2
- use devalang_types::{BankFile, BankInfo};
3
- use serde::Deserialize;
4
-
5
- #[derive(Debug, Deserialize)]
6
- pub struct BankList {
7
- pub bank: Vec<BankInfo>,
8
- }
9
-
10
- #[derive(Debug, Deserialize)]
11
- pub struct BankVersion {
12
- pub version: String,
13
- }
14
-
15
- pub async fn handle_bank_info_command(
16
- name: String,
17
- ) -> Result<BankInfo, Box<dyn std::error::Error>> {
18
- let cdn_url = get_cdn_url();
19
- let url = format!("{}/bank/{}/info", cdn_url, name);
20
-
21
- let response = reqwest::get(&url).await?;
22
-
23
- if !response.status().is_success() {
24
- return Err(format!("Failed to fetch bank info: HTTP {}", response.status()).into());
25
- }
26
-
27
- let bytes = response.bytes().await?;
28
-
29
- let parsed: BankInfo = serde_json::from_slice(&bytes)?;
30
-
31
- println!("📦 Bank Info for '{}':", name);
32
- println!(" - Name: {}", parsed.name);
33
- println!(" - Version: {}", parsed.version);
34
- println!(" - Description: {}", parsed.description);
35
- println!(" - Author: {}", parsed.author);
36
-
37
- Ok(parsed)
38
- }
39
-
40
- pub async fn fetch_latest_version(
41
- bank_name: String,
42
- ) -> Result<BankVersion, Box<dyn std::error::Error>> {
43
- let cdn_url = get_cdn_url();
44
- let url = format!("{}/bank/{}/version", cdn_url, bank_name);
45
-
46
- let response = reqwest::get(url).await?;
47
-
48
- if !response.status().is_success() {
49
- return Err(format!("❌ Failed to fetch version: HTTP {}", response.status()).into());
50
- }
51
-
52
- let bytes = response.bytes().await?;
53
-
54
- let version: BankVersion = serde_json::from_slice(&bytes)?;
55
-
56
- Ok(version)
57
- }
58
-
59
- pub async fn list_external_banks() -> Result<Vec<BankInfo>, Box<dyn std::error::Error>> {
60
- let cdn_url = get_cdn_url();
61
- let url = format!("{}/bank/list", cdn_url);
62
-
63
- let response = reqwest::get(url).await?;
64
-
65
- if !response.status().is_success() {
66
- return Err(format!("❌ Failed to fetch bank list: HTTP {}", response.status()).into());
67
- }
68
-
69
- let bytes = response.bytes().await?;
70
-
71
- let parsed: BankList = serde_json::from_slice(&bytes)?;
72
-
73
- Ok(parsed.bank)
74
- }
75
-
76
- pub async fn list_installed_banks() -> Result<Vec<BankFile>, String> {
77
- let deva_dir = devalang_utils::path::ensure_deva_dir()?;
78
- let bank_dir = deva_dir.join("banks");
79
-
80
- let mut banks = Vec::new();
81
-
82
- if !bank_dir.exists() {
83
- return Ok(banks); // No banks installed
84
- }
85
-
86
- let config_path = devalang_utils::path::get_devalang_config_path()?;
87
- let config = crate::config::ops::load_config(Some(&config_path))
88
- .ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
89
-
90
- let config_banks = config.banks.clone();
91
-
92
- if let Some(banks_in_toml) = config_banks {
93
- for bank in banks_in_toml {
94
- let bank_name = bank
95
- .path
96
- .strip_prefix("devalang://bank/")
97
- .unwrap_or(&bank.path)
98
- .to_string();
99
-
100
- let bank_path = bank_dir.join(&bank_name);
101
- if bank_path.exists() {
102
- let bank_info_path = bank_path.join("bank.toml");
103
-
104
- if bank_info_path.exists() {
105
- let content = std::fs::read_to_string(&bank_info_path)
106
- .map_err(|e| format!("Failed to read bank info: {}", e))?;
107
-
108
- match toml::from_str::<BankFile>(&content) {
109
- Ok(bank_info) => banks.push(bank_info),
110
- Err(_err) => {
111
- eprintln!("❌ Error parsing bank info for '{}'", bank_name);
112
- }
113
- }
114
- } else {
115
- eprintln!("❌ Bank info file not found for '{}'", bank_name);
116
- }
117
- }
118
- }
119
- }
120
-
121
- Ok(banks)
122
- }
1
+ use crate::web::cdn::get_cdn_url;
2
+ use devalang_types::{BankFile, BankInfo};
3
+ use serde::Deserialize;
4
+
5
+ #[derive(Debug, Deserialize)]
6
+ pub struct BankList {
7
+ pub bank: Vec<BankInfo>,
8
+ }
9
+
10
+ #[derive(Debug, Deserialize)]
11
+ pub struct BankVersion {
12
+ pub version: String,
13
+ }
14
+
15
+ pub async fn handle_bank_info_command(
16
+ name: String,
17
+ ) -> Result<BankInfo, Box<dyn std::error::Error>> {
18
+ let cdn_url = get_cdn_url();
19
+ let url = format!("{}/bank/{}/info", cdn_url, name);
20
+
21
+ let response = reqwest::get(&url).await?;
22
+
23
+ if !response.status().is_success() {
24
+ return Err(format!("Failed to fetch bank info: HTTP {}", response.status()).into());
25
+ }
26
+
27
+ let bytes = response.bytes().await?;
28
+
29
+ let parsed: BankInfo = serde_json::from_slice(&bytes)?;
30
+
31
+ println!("📦 Bank Info for '{}':", name);
32
+ println!(" - Name: {}", parsed.name);
33
+ println!(" - Version: {}", parsed.version);
34
+ println!(" - Description: {}", parsed.description);
35
+ println!(" - Author: {}", parsed.author);
36
+
37
+ Ok(parsed)
38
+ }
39
+
40
+ pub async fn fetch_latest_version(
41
+ bank_name: String,
42
+ ) -> Result<BankVersion, Box<dyn std::error::Error>> {
43
+ let cdn_url = get_cdn_url();
44
+ let url = format!("{}/bank/{}/version", cdn_url, bank_name);
45
+
46
+ let response = reqwest::get(url).await?;
47
+
48
+ if !response.status().is_success() {
49
+ return Err(format!("❌ Failed to fetch version: HTTP {}", response.status()).into());
50
+ }
51
+
52
+ let bytes = response.bytes().await?;
53
+
54
+ let version: BankVersion = serde_json::from_slice(&bytes)?;
55
+
56
+ Ok(version)
57
+ }
58
+
59
+ pub async fn list_external_banks() -> Result<Vec<BankInfo>, Box<dyn std::error::Error>> {
60
+ let cdn_url = get_cdn_url();
61
+ let url = format!("{}/bank/list", cdn_url);
62
+
63
+ let response = reqwest::get(url).await?;
64
+
65
+ if !response.status().is_success() {
66
+ return Err(format!("❌ Failed to fetch bank list: HTTP {}", response.status()).into());
67
+ }
68
+
69
+ let bytes = response.bytes().await?;
70
+
71
+ let parsed: BankList = serde_json::from_slice(&bytes)?;
72
+
73
+ Ok(parsed.bank)
74
+ }
75
+
76
+ pub async fn list_installed_banks() -> Result<Vec<BankFile>, String> {
77
+ let deva_dir = devalang_utils::path::ensure_deva_dir()?;
78
+ let bank_dir = deva_dir.join("banks");
79
+
80
+ let mut banks = Vec::new();
81
+
82
+ if !bank_dir.exists() {
83
+ return Ok(banks); // No banks installed
84
+ }
85
+
86
+ let config_path = devalang_utils::path::get_devalang_config_path()?;
87
+ let config = crate::config::ops::load_config(Some(&config_path))
88
+ .ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
89
+
90
+ let config_banks = config.banks.clone();
91
+
92
+ if let Some(banks_in_toml) = config_banks {
93
+ for bank in banks_in_toml {
94
+ let bank_name = bank
95
+ .path
96
+ .strip_prefix("devalang://bank/")
97
+ .unwrap_or(&bank.path)
98
+ .to_string();
99
+
100
+ let bank_path = bank_dir.join(&bank_name);
101
+ if bank_path.exists() {
102
+ let bank_info_path = bank_path.join("bank.toml");
103
+
104
+ if bank_info_path.exists() {
105
+ let content = std::fs::read_to_string(&bank_info_path)
106
+ .map_err(|e| format!("Failed to read bank info: {}", e))?;
107
+
108
+ match toml::from_str::<BankFile>(&content) {
109
+ Ok(bank_info) => banks.push(bank_info),
110
+ Err(_err) => {
111
+ eprintln!("❌ Error parsing bank info for '{}'", bank_name);
112
+ }
113
+ }
114
+ } else {
115
+ eprintln!("❌ Bank info file not found for '{}'", bank_name);
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ Ok(banks)
122
+ }
@@ -1,5 +1,6 @@
1
1
  use crate::cli::install::bank::install_bank;
2
2
  use crate::config::ops::load_config;
3
+ use devalang_core::config::driver::ProjectConfigExt;
3
4
  use devalang_types::{BankFile, BankInfo};
4
5
  use devalang_utils::path as path_utils;
5
6
  use std::fs;
@@ -173,7 +174,25 @@ async fn update_bank(bank_name: &str, _latest_version: &str) -> Result<(), Strin
173
174
  let _config = load_config(Some(&config_path))
174
175
  .ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
175
176
 
176
- // TODO Update the bank version in the config
177
+ // Update the bank version in the config
178
+ if let Some(mut config) = crate::config::ops::load_config(Some(&config_path)) {
179
+ if let Some(banks) = config.banks.as_mut() {
180
+ for bank in banks.iter_mut() {
181
+ if bank
182
+ .path
183
+ .strip_prefix("devalang://bank/")
184
+ .unwrap_or(&bank.path)
185
+ == bank_name
186
+ {
187
+ bank.version = Some(_latest_version.to_string());
188
+ }
189
+ }
190
+
191
+ if let Err(e) = config.write_config(&config) {
192
+ eprintln!("Warning: failed to write updated config: {}", e);
193
+ }
194
+ }
195
+ }
177
196
 
178
197
  Ok(())
179
198
  }
@@ -195,7 +214,19 @@ pub async fn handle_remove_bank_command(name: String) -> Result<(), String> {
195
214
  let _config = load_config(Some(&config_path))
196
215
  .ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
197
216
 
198
- // TODO Remove the bank from the config
217
+ // Remove the bank from the config
218
+ if let Some(mut config) = crate::config::ops::load_config(Some(&config_path)) {
219
+ if let Some(banks) = config.banks.as_mut() {
220
+ banks.retain(|b| {
221
+ let name_in_path = b.path.strip_prefix("devalang://bank/").unwrap_or(&b.path);
222
+ name_in_path != name
223
+ });
224
+
225
+ if let Err(e) = config.write_config(&config) {
226
+ eprintln!("Warning: failed to write updated config: {}", e);
227
+ }
228
+ }
229
+ }
199
230
 
200
231
  println!("✅ Bank '{}' removed successfully", name);
201
232
 
@@ -1,29 +1,29 @@
1
- use devalang_types::BankInfo;
2
- use serde::Deserialize;
3
-
4
- pub mod api;
5
- pub mod commands;
6
-
7
- #[derive(Debug, Deserialize)]
8
- pub struct BankList {
9
- pub bank: Vec<BankInfo>,
10
- }
11
-
12
- #[derive(Debug, Deserialize)]
13
- pub struct BankInfoFetched {
14
- pub name: String,
15
- pub version: String,
16
- pub description: String,
17
- pub author: String,
18
- pub latest_version: String,
19
- }
20
-
21
- #[derive(Debug, Deserialize)]
22
- pub struct BankVersion {
23
- pub version: String,
24
- }
25
-
26
- pub use commands::{
27
- handle_bank_available_command, handle_bank_info_command, handle_bank_list_command,
28
- handle_remove_bank_command, handle_update_bank_command,
29
- };
1
+ use devalang_types::BankInfo;
2
+ use serde::Deserialize;
3
+
4
+ pub mod api;
5
+ pub mod commands;
6
+
7
+ #[derive(Debug, Deserialize)]
8
+ pub struct BankList {
9
+ pub bank: Vec<BankInfo>,
10
+ }
11
+
12
+ #[derive(Debug, Deserialize)]
13
+ pub struct BankInfoFetched {
14
+ pub name: String,
15
+ pub version: String,
16
+ pub description: String,
17
+ pub author: String,
18
+ pub latest_version: String,
19
+ }
20
+
21
+ #[derive(Debug, Deserialize)]
22
+ pub struct BankVersion {
23
+ pub version: String,
24
+ }
25
+
26
+ pub use commands::{
27
+ handle_bank_available_command, handle_bank_info_command, handle_bank_list_command,
28
+ handle_remove_bank_command, handle_update_bank_command,
29
+ };
@@ -1,5 +1,6 @@
1
- use crate::{config::driver::ProjectConfig, core::utils::path::find_entry_file};
1
+ use crate::config::driver::ProjectConfig;
2
2
  use devalang_utils::logger::{LogLevel, Logger};
3
+ use devalang_utils::path::find_entry_file;
3
4
  use devalang_utils::watcher::watch_directory;
4
5
 
5
6
  #[cfg(feature = "cli")]
@@ -7,10 +8,14 @@ pub fn handle_build_command(
7
8
  config: Option<ProjectConfig>,
8
9
  entry: Option<String>,
9
10
  output: Option<String>,
11
+ output_format: Vec<crate::cli::parser::OutputFormat>,
12
+ audio_format: crate::cli::parser::AudioFormat,
13
+ sample_rate: u32,
10
14
  watch: bool,
11
15
  debug: bool,
12
16
  compress: bool,
13
17
  ) -> Result<(), String> {
18
+ // determine fetched values from config or CLI
14
19
  let fetched_entry = if entry.is_none() {
15
20
  config
16
21
  .as_ref()
@@ -40,6 +45,38 @@ pub fn handle_build_command(
40
45
 
41
46
  let logger = Logger::new();
42
47
 
48
+ // Determine final audio_format: prefer CLI, else config default if present
49
+ let mut final_audio_format = audio_format;
50
+ if let Some(cfg) = config.as_ref() {
51
+ if let Some(af) = cfg.defaults.audio_format.as_ref() {
52
+ // Only override if CLI provided an empty/placeholder — clap provides a default, so we only override when CLI wasn't explicit (rare).
53
+ // We'll accept values: "wav16", "wav24", "wav32" (case-insensitive)
54
+ let af_low = af.to_lowercase();
55
+ final_audio_format = match af_low.as_str() {
56
+ "wav24" => crate::cli::parser::AudioFormat::Wav24,
57
+ "wav32" => crate::cli::parser::AudioFormat::Wav32,
58
+ _ => crate::cli::parser::AudioFormat::Wav16,
59
+ };
60
+ }
61
+ }
62
+
63
+ // Determine final output_format: prefer CLI vector, else config default list
64
+ let mut final_output_format: Vec<crate::cli::parser::OutputFormat> = output_format.clone();
65
+ if final_output_format.is_empty() {
66
+ if let Some(cfg) = config.as_ref() {
67
+ if let Some(ofs) = cfg.defaults.output_format.as_ref() {
68
+ for s in ofs {
69
+ match s.to_lowercase().as_str() {
70
+ "mid" | "midi" => {
71
+ final_output_format.push(crate::cli::parser::OutputFormat::Mid);
72
+ }
73
+ _ => final_output_format.push(crate::cli::parser::OutputFormat::Wav),
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+
43
80
  if fetched_entry.is_empty() {
44
81
  logger.log_message(
45
82
  LogLevel::Error,
@@ -71,6 +108,9 @@ pub fn handle_build_command(
71
108
  let _ = crate::cli::build::process::process_build(
72
109
  entry_file.clone(),
73
110
  fetched_output.clone(),
111
+ final_output_format.clone(),
112
+ final_audio_format,
113
+ sample_rate,
74
114
  debug,
75
115
  compress,
76
116
  );
@@ -86,14 +126,24 @@ pub fn handle_build_command(
86
126
  let _ = crate::cli::build::process::process_build(
87
127
  entry_file.clone(),
88
128
  fetched_output.clone(),
129
+ final_output_format.clone(),
130
+ final_audio_format,
131
+ sample_rate,
89
132
  debug,
90
133
  compress,
91
134
  );
92
135
  })
93
136
  .unwrap();
94
137
  } else {
95
- let res =
96
- crate::cli::build::process::process_build(entry_file, fetched_output, debug, compress);
138
+ let res = crate::cli::build::process::process_build(
139
+ entry_file,
140
+ fetched_output,
141
+ final_output_format,
142
+ final_audio_format,
143
+ sample_rate,
144
+ debug,
145
+ compress,
146
+ );
97
147
  if let Err(e) = res {
98
148
  return Err(e);
99
149
  }
@@ -1,2 +1,2 @@
1
- pub mod commands;
2
- pub mod process;
1
+ pub mod commands;
2
+ pub mod process;
@@ -2,14 +2,14 @@ use crate::core::{
2
2
  builder::Builder,
3
3
  debugger::{
4
4
  lexer::write_lexer_log_file,
5
- module::{write_module_function_log_file, write_module_variable_log_file},
5
+ logs::{write_module_function_log_file, write_module_variable_log_file},
6
6
  preprocessor::write_preprocessor_log_file,
7
7
  store::{write_function_log_file, write_variables_log_file},
8
8
  },
9
9
  preprocessor::loader::ModuleLoader,
10
10
  store::global::GlobalStore,
11
- utils::path::normalize_path,
12
11
  };
12
+ use devalang_utils::path::normalize_path;
13
13
  use devalang_utils::{
14
14
  logger::{LogLevel, Logger},
15
15
  spinner::start_spinner,
@@ -24,6 +24,9 @@ pub struct BuildStatsInput {
24
24
  pub fn process_build(
25
25
  entry: String,
26
26
  output: String,
27
+ output_format: Vec<crate::cli::parser::OutputFormat>,
28
+ audio_format: crate::cli::parser::AudioFormat,
29
+ sample_rate: u32,
27
30
  debug: bool,
28
31
  compress: bool,
29
32
  ) -> Result<BuildStatsInput, String> {
@@ -94,11 +97,27 @@ pub fn process_build(
94
97
  // SECTION Building AST and Audio
95
98
  let builder = Builder::new();
96
99
  builder.build_ast(&modules_statements, &normalized_output_dir, compress);
97
- builder.build_audio(
98
- &modules_statements,
99
- &normalized_output_dir,
100
- &mut global_store,
101
- );
100
+
101
+ // generate audio output if requested
102
+ if output_format.contains(&crate::cli::parser::OutputFormat::Wav) {
103
+ let audio_format_str = format!("{:?}", audio_format);
104
+ builder.build_audio(
105
+ &modules_statements,
106
+ &normalized_output_dir,
107
+ &mut global_store,
108
+ Some(audio_format_str),
109
+ Some(sample_rate),
110
+ );
111
+ }
112
+
113
+ // generate midi output if requested
114
+ if output_format.contains(&crate::cli::parser::OutputFormat::Mid) {
115
+ builder.build_midi(
116
+ &modules_statements,
117
+ &normalized_output_dir,
118
+ &mut global_store,
119
+ );
120
+ }
102
121
 
103
122
  // SECTION Logging
104
123
  let logger = Logger::new();
@@ -3,15 +3,15 @@ use crate::{
3
3
  core::{
4
4
  debugger::{
5
5
  lexer::write_lexer_log_file,
6
- module::{write_module_function_log_file, write_module_variable_log_file},
6
+ logs::{write_module_function_log_file, write_module_variable_log_file},
7
7
  preprocessor::write_preprocessor_log_file,
8
8
  store::{write_function_log_file, write_variables_log_file},
9
9
  },
10
10
  preprocessor::loader::ModuleLoader,
11
11
  store::global::GlobalStore,
12
- utils::path::{find_entry_file, normalize_path},
13
12
  },
14
13
  };
14
+ use devalang_utils::path::{find_entry_file, normalize_path};
15
15
 
16
16
  use devalang_utils::{
17
17
  logger::{LogLevel, Logger},