@devaloop/devalang 0.0.1-alpha.16-hotfix.1 → 0.0.1-alpha.17
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.
- package/.cargo/config.toml +2 -0
- package/.devalang +6 -10
- package/.github/workflows/ci.yml +19 -8
- package/Cargo.toml +18 -2
- package/README.md +80 -33
- package/docs/CHANGELOG.md +56 -0
- package/docs/ROADMAP.md +6 -3
- package/examples/index.deva +52 -35
- package/out-tsc/bin/index.d.ts +2 -0
- package/out-tsc/core/functions/index.d.ts +37 -0
- package/out-tsc/core/functions/index.js +76 -0
- package/out-tsc/core/index.d.ts +6 -0
- package/out-tsc/core/index.js +22 -0
- package/out-tsc/core/types/index.d.ts +4 -0
- package/out-tsc/core/types/index.js +20 -0
- package/out-tsc/core/types/plugin.d.ts +18 -0
- package/out-tsc/core/types/plugin.js +2 -0
- package/out-tsc/core/types/result.d.ts +27 -0
- package/out-tsc/core/types/result.js +2 -0
- package/out-tsc/core/types/statement.d.ts +106 -0
- package/out-tsc/core/types/statement.js +2 -0
- package/out-tsc/core/types/value.d.ts +43 -0
- package/out-tsc/core/types/value.js +2 -0
- package/out-tsc/index.d.ts +7 -0
- package/out-tsc/index.js +41 -2
- package/out-tsc/pkg/devalang_core.d.ts +7 -0
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
- package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
- package/out-tsc/scripts/copy-wasm-dts.js +73 -0
- package/out-tsc/scripts/postinstall.d.ts +1 -0
- package/out-tsc/scripts/postinstall.js +33 -23
- package/out-tsc/scripts/version/bump.d.ts +1 -0
- package/out-tsc/scripts/version/fetch.d.ts +1 -0
- package/out-tsc/scripts/version/index.d.ts +1 -0
- package/out-tsc/scripts/version/sync.d.ts +1 -0
- package/package.json +16 -4
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -0
- package/rust/cli/bank/commands.rs +275 -0
- package/rust/cli/bank/mod.rs +29 -0
- package/rust/cli/build/commands.rs +97 -0
- package/rust/cli/build/mod.rs +2 -0
- package/rust/cli/build/process.rs +146 -0
- package/rust/cli/{check.rs → check/mod.rs} +18 -31
- package/rust/cli/discover/commands.rs +253 -0
- package/rust/cli/discover/config.rs +111 -0
- package/rust/cli/discover/fs.rs +19 -0
- package/rust/cli/discover/install.rs +103 -0
- package/rust/cli/discover/metadata.rs +48 -0
- package/rust/cli/discover/mod.rs +5 -0
- package/rust/cli/{init.rs → init/commands.rs} +88 -87
- package/rust/cli/init/mod.rs +1 -0
- package/rust/{installer → cli/install}/addon.rs +5 -9
- package/rust/cli/install/bank.rs +53 -0
- package/rust/cli/{install.rs → install/commands.rs} +9 -9
- package/rust/{installer → cli/install}/mod.rs +2 -3
- package/rust/cli/install/plugin.rs +61 -0
- package/rust/cli/{login.rs → login/commands.rs} +8 -11
- package/rust/cli/login/mod.rs +1 -0
- package/rust/cli/mod.rs +2 -3
- package/rust/cli/{driver.rs → parser.rs} +19 -2
- package/rust/cli/play/commands.rs +324 -0
- package/rust/cli/play/io.rs +17 -0
- package/rust/cli/play/mod.rs +5 -0
- package/rust/cli/play/process.rs +150 -0
- package/rust/cli/play/realtime.rs +91 -0
- package/rust/cli/play/utils.rs +23 -0
- package/rust/cli/telemetry/commands.rs +22 -0
- package/rust/cli/telemetry/event_creator.rs +80 -0
- package/rust/cli/telemetry/mod.rs +3 -0
- package/rust/cli/telemetry/send.rs +51 -0
- package/rust/cli/{template.rs → template/commands.rs} +1 -1
- package/rust/cli/template/mod.rs +1 -0
- package/rust/cli/{update.rs → update/commands.rs} +6 -6
- package/rust/cli/update/mod.rs +1 -0
- package/rust/config/driver.rs +57 -72
- package/rust/config/mod.rs +1 -2
- package/rust/config/ops.rs +26 -0
- package/rust/config/settings.rs +60 -50
- package/rust/core/audio/engine/helpers.rs +146 -0
- package/rust/core/audio/engine/mod.rs +7 -0
- package/rust/core/audio/engine/sample.rs +298 -0
- package/rust/core/audio/engine/synth.rs +310 -0
- package/rust/core/audio/evaluator.rs +15 -12
- package/rust/core/audio/interpreter/arrow_call.rs +99 -24
- package/rust/core/audio/interpreter/call.rs +81 -60
- package/rust/core/audio/interpreter/condition.rs +3 -2
- package/rust/core/audio/interpreter/driver.rs +206 -151
- package/rust/core/audio/interpreter/let_.rs +1 -1
- package/rust/core/audio/interpreter/load.rs +2 -1
- package/rust/core/audio/interpreter/loop_.rs +7 -6
- package/rust/core/audio/interpreter/sleep.rs +2 -1
- package/rust/core/audio/interpreter/spawn.rs +45 -57
- package/rust/core/audio/interpreter/tempo.rs +31 -10
- package/rust/core/audio/interpreter/trigger.rs +2 -2
- package/rust/core/audio/loader/trigger.rs +4 -7
- package/rust/core/audio/player.rs +6 -0
- package/rust/core/audio/renderer.rs +5 -7
- package/rust/core/audio/special/env.rs +3 -1
- package/rust/core/audio/special/math.rs +4 -4
- package/rust/core/audio/special/modulator.rs +2 -2
- package/rust/core/builder/mod.rs +9 -3
- package/rust/core/debugger/lexer.rs +1 -1
- package/rust/core/debugger/mod.rs +6 -0
- package/rust/core/debugger/module.rs +4 -4
- package/rust/core/debugger/preprocessor.rs +1 -1
- package/rust/core/debugger/store.rs +2 -2
- package/rust/core/error/mod.rs +189 -0
- package/rust/core/lexer/handler/arrow.rs +1 -1
- package/rust/core/lexer/handler/at.rs +1 -1
- package/rust/core/lexer/handler/brace.rs +2 -2
- package/rust/core/lexer/handler/colon.rs +1 -1
- package/rust/core/lexer/handler/comment.rs +1 -1
- package/rust/core/lexer/handler/dot.rs +1 -1
- package/rust/core/lexer/handler/driver.rs +1 -1
- package/rust/core/lexer/handler/identifier.rs +1 -1
- package/rust/core/lexer/handler/mod.rs +1 -2
- package/rust/core/lexer/handler/number.rs +1 -1
- package/rust/core/lexer/handler/operator.rs +1 -1
- package/rust/core/lexer/handler/parenthesis.rs +2 -2
- package/rust/core/lexer/handler/slash.rs +1 -1
- package/rust/core/lexer/handler/string.rs +1 -1
- package/rust/core/lexer/mod.rs +22 -12
- package/rust/core/lexer/token.rs +90 -97
- package/rust/core/mod.rs +0 -1
- package/rust/core/parser/driver.rs +66 -13
- package/rust/core/parser/handler/arrow_call.rs +28 -8
- package/rust/core/parser/handler/at.rs +55 -21
- package/rust/core/parser/handler/bank.rs +14 -4
- package/rust/core/parser/handler/condition.rs +6 -3
- package/rust/core/parser/handler/dot.rs +2 -1
- package/rust/core/parser/handler/identifier/automate.rs +13 -16
- package/rust/core/parser/handler/identifier/call.rs +4 -4
- package/rust/core/parser/handler/identifier/emit.rs +9 -5
- package/rust/core/parser/handler/identifier/function.rs +20 -7
- package/rust/core/parser/handler/identifier/group.rs +11 -7
- package/rust/core/parser/handler/identifier/let_.rs +24 -9
- package/rust/core/parser/handler/identifier/mod.rs +6 -5
- package/rust/core/parser/handler/identifier/on.rs +16 -7
- package/rust/core/parser/handler/identifier/print.rs +6 -9
- package/rust/core/parser/handler/identifier/sleep.rs +12 -5
- package/rust/core/parser/handler/identifier/spawn.rs +4 -4
- package/rust/core/parser/handler/identifier/synth.rs +79 -9
- package/rust/core/parser/handler/loop_.rs +39 -14
- package/rust/core/parser/handler/tempo.rs +9 -5
- package/rust/core/parser/mod.rs +0 -1
- package/rust/core/parser/statement.rs +6 -137
- package/rust/core/plugin/loader.rs +41 -27
- package/rust/core/plugin/runner.rs +68 -17
- package/rust/core/preprocessor/loader.rs +155 -33
- package/rust/core/preprocessor/processor.rs +2 -2
- package/rust/core/preprocessor/resolver/bank.rs +6 -8
- package/rust/core/preprocessor/resolver/call.rs +20 -24
- package/rust/core/preprocessor/resolver/condition.rs +6 -8
- package/rust/core/preprocessor/resolver/driver.rs +14 -16
- package/rust/core/preprocessor/resolver/function.rs +6 -6
- package/rust/core/preprocessor/resolver/group.rs +6 -8
- package/rust/core/preprocessor/resolver/loop_.rs +8 -10
- package/rust/core/preprocessor/resolver/spawn.rs +19 -23
- package/rust/core/preprocessor/resolver/synth.rs +6 -8
- package/rust/core/preprocessor/resolver/tempo.rs +6 -8
- package/rust/core/preprocessor/resolver/trigger.rs +22 -19
- package/rust/core/preprocessor/resolver/value.rs +99 -4
- package/rust/core/store/export.rs +28 -28
- package/rust/core/store/function.rs +6 -0
- package/rust/core/store/global.rs +7 -1
- package/rust/core/store/import.rs +28 -28
- package/rust/core/store/variable.rs +1 -1
- package/rust/core/utils/mod.rs +0 -1
- package/rust/lib.rs +102 -9
- package/rust/main.rs +156 -45
- package/rust/types/Cargo.toml +8 -0
- package/rust/types/src/addons.rs +55 -0
- package/rust/types/src/ast.rs +198 -0
- package/rust/types/src/config.rs +74 -0
- package/rust/types/src/lib.rs +12 -0
- package/rust/types/src/telemetry.rs +85 -0
- package/rust/utils/Cargo.toml +23 -0
- package/rust/utils/{error.rs → src/error.rs} +186 -200
- package/rust/utils/src/file.rs +94 -0
- package/rust/utils/src/first_usage.rs +97 -0
- package/rust/utils/{mod.rs → src/lib.rs} +1 -1
- package/rust/utils/{logger.rs → src/logger.rs} +17 -12
- package/rust/utils/src/path.rs +88 -0
- package/rust/utils/src/signature.rs +41 -0
- package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
- package/rust/utils/src/version.rs +27 -0
- package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
- package/rust/web/api.rs +5 -0
- package/rust/web/cdn.rs +34 -0
- package/templates/minimal/README.md +98 -54
- package/templates/welcome/README.md +98 -54
- package/templates/welcome/src/index.deva +56 -8
- package/templates/welcome/src/variables.deva +2 -4
- package/tests/rust/TODO.md +0 -0
- package/tests/typescript/index.spec.ts +136 -0
- package/tests/typescript/playhead.spec.ts +36 -0
- package/tests/typescript/render_e2e.spec.ts +77 -0
- package/tsconfig.json +1 -1
- package/typescript/core/functions/index.ts +83 -0
- package/typescript/core/index.ts +6 -0
- package/typescript/core/types/index.ts +4 -0
- package/typescript/core/types/plugin.ts +19 -0
- package/typescript/core/types/result.ts +29 -0
- package/typescript/core/types/statement.ts +47 -0
- package/typescript/core/types/value.ts +29 -0
- package/typescript/index.ts +7 -2
- package/typescript/pkg/devalang_core.d.ts +4 -0
- package/typescript/scripts/copy-wasm-dts.ts +41 -0
- package/typescript/scripts/postinstall.ts +45 -32
- package/rust/cli/bank.rs +0 -462
- package/rust/cli/build.rs +0 -252
- package/rust/cli/generator.rs +0 -1
- package/rust/cli/play.rs +0 -1123
- package/rust/cli/telemetry.rs +0 -19
- package/rust/common/api.rs +0 -5
- package/rust/common/cdn.rs +0 -5
- package/rust/config/loader.rs +0 -165
- package/rust/config/stats.rs +0 -257
- package/rust/core/audio/engine.rs +0 -696
- package/rust/core/shared/bank.rs +0 -21
- package/rust/core/shared/duration.rs +0 -9
- package/rust/core/shared/mod.rs +0 -3
- package/rust/core/shared/value.rs +0 -35
- package/rust/core/utils/validation.rs +0 -35
- package/rust/installer/bank.rs +0 -62
- package/rust/installer/plugin.rs +0 -54
- package/rust/installer/utils.rs +0 -56
- package/rust/utils/file.rs +0 -38
- package/rust/utils/first_usage.rs +0 -76
- package/rust/utils/signature.rs +0 -19
- package/rust/utils/telemetry.rs +0 -292
- package/rust/utils/version.rs +0 -15
- /package/rust/{common → web}/mod.rs +0 -0
- /package/rust/{common → web}/sso.rs +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
use crate::cli::install::bank::install_bank;
|
|
2
|
+
use crate::config::ops::load_config;
|
|
3
|
+
use devalang_types::{BankFile, BankInfo};
|
|
4
|
+
use devalang_utils::path as path_utils;
|
|
5
|
+
use std::fs;
|
|
6
|
+
|
|
7
|
+
pub async fn handle_update_bank_command(name: Option<String>) -> Result<(), String> {
|
|
8
|
+
let deva_dir = path_utils::ensure_deva_dir()?;
|
|
9
|
+
let bank_dir = deva_dir.join("banks");
|
|
10
|
+
|
|
11
|
+
if !bank_dir.exists() {
|
|
12
|
+
fs::create_dir_all(bank_dir.clone())
|
|
13
|
+
.map_err(|e| format!("Failed to create bank directory: {}", e))?;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if let Some(name) = name {
|
|
17
|
+
let bank_path = bank_dir.join(&name);
|
|
18
|
+
if !bank_path.exists() {
|
|
19
|
+
return Err(format!("Bank '{}' is not installed", name));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Update specific bank
|
|
23
|
+
let latest_version = match crate::cli::bank::api::fetch_latest_version(name.clone()).await {
|
|
24
|
+
Ok(version) => version,
|
|
25
|
+
Err(err) => {
|
|
26
|
+
eprintln!("❌ Error fetching latest version for '{}': {}", name, err);
|
|
27
|
+
return Err(format!("Failed to fetch latest version for '{}'", name));
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
let local_bank_info_path = bank_path.join("bank.toml");
|
|
32
|
+
let local_version = match fs::read_to_string(&local_bank_info_path)
|
|
33
|
+
.ok()
|
|
34
|
+
.and_then(|content| toml::from_str::<BankFile>(&content).ok())
|
|
35
|
+
.map(|bf| bf.bank.version)
|
|
36
|
+
{
|
|
37
|
+
Some(version) => version,
|
|
38
|
+
None => {
|
|
39
|
+
eprintln!(
|
|
40
|
+
"⚠️ Unable to read local version for '{}', forcing reinstall...",
|
|
41
|
+
name
|
|
42
|
+
);
|
|
43
|
+
"".to_string() // Force update
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if local_version != latest_version.version {
|
|
48
|
+
if let Err(e) = update_bank(&name, &latest_version.version).await {
|
|
49
|
+
eprintln!("❌ Error updating bank '{}': {}", name, e);
|
|
50
|
+
} else {
|
|
51
|
+
println!(
|
|
52
|
+
"✅ Bank '{}' updated to version '{}'",
|
|
53
|
+
name, latest_version.version
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
println!(
|
|
58
|
+
"Bank '{}' is already up-to-date (version {})",
|
|
59
|
+
name, latest_version.version
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Verify if the bank directory exists
|
|
63
|
+
if !bank_path.exists() {
|
|
64
|
+
eprintln!(
|
|
65
|
+
"❌ Bank directory for '{}' does not exist, reinstalling...",
|
|
66
|
+
name
|
|
67
|
+
);
|
|
68
|
+
if let Err(e) = install_bank(&name, &deva_dir).await {
|
|
69
|
+
eprintln!("❌ Error reinstalling bank '{}': {}", name, e);
|
|
70
|
+
} else {
|
|
71
|
+
println!("✅ Bank '{}' reinstalled successfully!", name);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
// Update all banks
|
|
77
|
+
let config_path = path_utils::get_devalang_config_path()?;
|
|
78
|
+
let config = load_config(Some(&config_path))
|
|
79
|
+
.ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
|
|
80
|
+
|
|
81
|
+
let config_banks = config.banks.clone();
|
|
82
|
+
|
|
83
|
+
if let Some(banks) = config_banks {
|
|
84
|
+
for bank in banks {
|
|
85
|
+
let bank_name = bank
|
|
86
|
+
.path
|
|
87
|
+
.strip_prefix("devalang://bank/")
|
|
88
|
+
.unwrap_or(&bank.path)
|
|
89
|
+
.to_string();
|
|
90
|
+
|
|
91
|
+
let latest_version =
|
|
92
|
+
match crate::cli::bank::api::fetch_latest_version(bank_name.clone()).await {
|
|
93
|
+
Ok(version) => version,
|
|
94
|
+
Err(err) => {
|
|
95
|
+
eprintln!(
|
|
96
|
+
"❌ Error fetching latest version for '{}': {}",
|
|
97
|
+
bank_name, err
|
|
98
|
+
);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
if let Some(local_bank_version) = bank.version {
|
|
104
|
+
if latest_version.version != local_bank_version {
|
|
105
|
+
if let Err(e) = update_bank(&bank_name, &latest_version.version).await {
|
|
106
|
+
eprintln!("❌ Error updating bank '{}': {}", bank_name, e);
|
|
107
|
+
} else {
|
|
108
|
+
println!(
|
|
109
|
+
"✅ Bank '{}' updated to version '{}'",
|
|
110
|
+
bank_name, latest_version.version
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
println!(
|
|
115
|
+
"Bank '{}' is already up-to-date (version {})",
|
|
116
|
+
bank_name, local_bank_version
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Verify if the bank directory exists
|
|
120
|
+
let bank_path = bank_dir.join(&bank_name);
|
|
121
|
+
|
|
122
|
+
if !bank_path.exists() {
|
|
123
|
+
eprintln!(
|
|
124
|
+
"❌ Bank directory for '{}' does not exist, reinstalling...",
|
|
125
|
+
bank_name
|
|
126
|
+
);
|
|
127
|
+
if let Err(e) = install_bank(&bank_name, &deva_dir).await {
|
|
128
|
+
eprintln!("❌ Error reinstalling bank '{}': {}", bank_name, e);
|
|
129
|
+
} else {
|
|
130
|
+
println!("✅ Bank '{}' reinstalled successfully!", bank_name);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
// If the bank version is not specified in the config, install it
|
|
136
|
+
if let Err(e) = install_bank(&bank_name, &deva_dir).await {
|
|
137
|
+
eprintln!("❌ Error installing bank '{}': {}", bank_name, e);
|
|
138
|
+
} else {
|
|
139
|
+
println!("✅ Bank '{}' installed successfully!", bank_name);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
Ok(())
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async fn update_bank(bank_name: &str, _latest_version: &str) -> Result<(), String> {
|
|
150
|
+
let deva_dir = path_utils::ensure_deva_dir()?;
|
|
151
|
+
|
|
152
|
+
// First, delete the existing bank directory
|
|
153
|
+
let bank_dir = deva_dir.join("banks").join(bank_name);
|
|
154
|
+
|
|
155
|
+
if bank_dir.exists() {
|
|
156
|
+
std::fs::remove_dir_all(&bank_dir).unwrap_or_else(|_| {
|
|
157
|
+
eprintln!(
|
|
158
|
+
"⚠️ Failed to remove old bank directory for '{}', aborting !",
|
|
159
|
+
bank_name
|
|
160
|
+
);
|
|
161
|
+
std::process::exit(1);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Now, install the new version
|
|
166
|
+
if let Err(e) = install_bank(bank_name, &deva_dir).await {
|
|
167
|
+
eprintln!("❌ Error installing bank '{}': {}", bank_name, e);
|
|
168
|
+
} else {
|
|
169
|
+
println!("✅ Bank '{}' installed successfully!", bank_name);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let config_path = path_utils::get_devalang_config_path()?;
|
|
173
|
+
let _config = load_config(Some(&config_path))
|
|
174
|
+
.ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
|
|
175
|
+
|
|
176
|
+
// TODO Update the bank version in the config
|
|
177
|
+
|
|
178
|
+
Ok(())
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
pub async fn handle_remove_bank_command(name: String) -> Result<(), String> {
|
|
182
|
+
let deva_dir = path_utils::ensure_deva_dir()?;
|
|
183
|
+
let bank_dir = deva_dir.join("banks");
|
|
184
|
+
|
|
185
|
+
let bank_path = bank_dir.join(&name);
|
|
186
|
+
|
|
187
|
+
if !bank_path.exists() {
|
|
188
|
+
return Err(format!("Bank '{}' is not installed", name));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
std::fs::remove_dir_all(&bank_path).map_err(|e| format!("Failed to remove bank: {}", e))?;
|
|
192
|
+
|
|
193
|
+
// Remove the bank from the config
|
|
194
|
+
let config_path = path_utils::get_devalang_config_path()?;
|
|
195
|
+
let _config = load_config(Some(&config_path))
|
|
196
|
+
.ok_or_else(|| format!("Failed to load config from '{}'", config_path.display()))?;
|
|
197
|
+
|
|
198
|
+
// TODO Remove the bank from the config
|
|
199
|
+
|
|
200
|
+
println!("✅ Bank '{}' removed successfully", name);
|
|
201
|
+
|
|
202
|
+
Ok(())
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
pub async fn handle_bank_available_command() -> Result<(), String> {
|
|
206
|
+
let bank_list = match crate::cli::bank::api::list_external_banks().await {
|
|
207
|
+
Ok(list) => list,
|
|
208
|
+
Err(_err) => {
|
|
209
|
+
eprintln!("❌ Error fetching bank list");
|
|
210
|
+
return Err("Failed to fetch bank list".into());
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
println!("Available banks for current project :");
|
|
215
|
+
println!(" ");
|
|
216
|
+
|
|
217
|
+
for bank in bank_list {
|
|
218
|
+
println!("📦 {}", bank.name);
|
|
219
|
+
println!(" - Version: {}", bank.version);
|
|
220
|
+
println!(" - Description: {}", bank.description);
|
|
221
|
+
println!(" - Author: {}", bank.author);
|
|
222
|
+
println!(" ");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
Ok(())
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
pub async fn handle_bank_info_command(
|
|
229
|
+
name: String,
|
|
230
|
+
) -> Result<BankInfo, Box<dyn std::error::Error>> {
|
|
231
|
+
crate::cli::bank::api::handle_bank_info_command(name).await
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
pub async fn handle_bank_list_command() -> Result<(), String> {
|
|
235
|
+
let bank_list = match crate::cli::bank::api::list_installed_banks().await {
|
|
236
|
+
Ok(list) => list,
|
|
237
|
+
Err(_err) => {
|
|
238
|
+
eprintln!("❌ Error fetching bank list");
|
|
239
|
+
return Err("Failed to fetch bank list".into());
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
println!("Installed banks for current project :");
|
|
244
|
+
|
|
245
|
+
for bank_toml in bank_list {
|
|
246
|
+
let latest_version =
|
|
247
|
+
match crate::cli::bank::api::fetch_latest_version(bank_toml.bank.name.clone()).await {
|
|
248
|
+
Ok(version) => version,
|
|
249
|
+
Err(_err) => {
|
|
250
|
+
eprintln!(
|
|
251
|
+
"❌ Error fetching latest version for '{}'",
|
|
252
|
+
bank_toml.bank.name
|
|
253
|
+
);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
let is_latest = if latest_version.version == bank_toml.bank.version {
|
|
259
|
+
"✅"
|
|
260
|
+
} else {
|
|
261
|
+
"❗"
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
println!(" ");
|
|
265
|
+
println!("📦 {}", bank_toml.bank.name);
|
|
266
|
+
println!(
|
|
267
|
+
" - Version: v{} {} (latest: v{})",
|
|
268
|
+
bank_toml.bank.version, is_latest, latest_version.version
|
|
269
|
+
);
|
|
270
|
+
println!(" - Description: {}", bank_toml.bank.description);
|
|
271
|
+
println!(" - Author: {}", bank_toml.bank.author);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
Ok(())
|
|
275
|
+
}
|
|
@@ -0,0 +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
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
use crate::{config::driver::ProjectConfig, core::utils::path::find_entry_file};
|
|
2
|
+
use devalang_utils::logger::{LogLevel, Logger};
|
|
3
|
+
use devalang_utils::watcher::watch_directory;
|
|
4
|
+
|
|
5
|
+
#[cfg(feature = "cli")]
|
|
6
|
+
pub fn handle_build_command(
|
|
7
|
+
config: Option<ProjectConfig>,
|
|
8
|
+
entry: Option<String>,
|
|
9
|
+
output: Option<String>,
|
|
10
|
+
watch: bool,
|
|
11
|
+
debug: bool,
|
|
12
|
+
compress: bool,
|
|
13
|
+
) -> Result<(), String> {
|
|
14
|
+
let fetched_entry = if entry.is_none() {
|
|
15
|
+
config
|
|
16
|
+
.as_ref()
|
|
17
|
+
.and_then(|c| c.defaults.entry.clone())
|
|
18
|
+
.unwrap_or_default()
|
|
19
|
+
} else {
|
|
20
|
+
entry.clone().unwrap_or_default()
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let fetched_output = if output.is_none() {
|
|
24
|
+
config
|
|
25
|
+
.as_ref()
|
|
26
|
+
.and_then(|c| c.defaults.output.clone())
|
|
27
|
+
.unwrap_or_default()
|
|
28
|
+
} else {
|
|
29
|
+
output.clone().unwrap_or_default()
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
let fetched_watch = if watch {
|
|
33
|
+
watch
|
|
34
|
+
} else {
|
|
35
|
+
config
|
|
36
|
+
.as_ref()
|
|
37
|
+
.and_then(|c| c.defaults.watch)
|
|
38
|
+
.unwrap_or(false)
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
let logger = Logger::new();
|
|
42
|
+
|
|
43
|
+
if fetched_entry.is_empty() {
|
|
44
|
+
logger.log_message(
|
|
45
|
+
LogLevel::Error,
|
|
46
|
+
"Entry path is not specified. Please provide a valid entry path.",
|
|
47
|
+
);
|
|
48
|
+
return Err("missing entry path".to_string());
|
|
49
|
+
}
|
|
50
|
+
if fetched_output.is_empty() {
|
|
51
|
+
logger.log_message(
|
|
52
|
+
LogLevel::Error,
|
|
53
|
+
"Output directory is not specified. Please provide a valid output directory.",
|
|
54
|
+
);
|
|
55
|
+
return Err("missing output directory".to_string());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let entry_file = match find_entry_file(&fetched_entry) {
|
|
59
|
+
Some(p) => p,
|
|
60
|
+
None => {
|
|
61
|
+
logger.log_message(
|
|
62
|
+
LogLevel::Error,
|
|
63
|
+
&format!("❌ index.deva not found in directory: {}", fetched_entry),
|
|
64
|
+
);
|
|
65
|
+
return Err("index.deva not found".to_string());
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// SECTION Begin build
|
|
70
|
+
if fetched_watch {
|
|
71
|
+
let _ = crate::cli::build::process::process_build(
|
|
72
|
+
entry_file.clone(),
|
|
73
|
+
fetched_output.clone(),
|
|
74
|
+
debug,
|
|
75
|
+
compress,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
logger.log_message(
|
|
79
|
+
LogLevel::Watcher,
|
|
80
|
+
&format!("Watching for changes in '{}'...", fetched_entry),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
watch_directory(entry_file.clone(), move || {
|
|
84
|
+
logger.log_message(LogLevel::Watcher, "Detected changes, re-building...");
|
|
85
|
+
|
|
86
|
+
let _ = crate::cli::build::process::process_build(
|
|
87
|
+
entry_file.clone(),
|
|
88
|
+
fetched_output.clone(),
|
|
89
|
+
debug,
|
|
90
|
+
compress,
|
|
91
|
+
);
|
|
92
|
+
})
|
|
93
|
+
.unwrap();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
Ok(())
|
|
97
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
use crate::core::{
|
|
2
|
+
builder::Builder,
|
|
3
|
+
debugger::{
|
|
4
|
+
lexer::write_lexer_log_file,
|
|
5
|
+
module::{write_module_function_log_file, write_module_variable_log_file},
|
|
6
|
+
preprocessor::write_preprocessor_log_file,
|
|
7
|
+
store::{write_function_log_file, write_variables_log_file},
|
|
8
|
+
},
|
|
9
|
+
preprocessor::loader::ModuleLoader,
|
|
10
|
+
store::global::GlobalStore,
|
|
11
|
+
utils::path::normalize_path,
|
|
12
|
+
};
|
|
13
|
+
use devalang_utils::{
|
|
14
|
+
logger::{LogLevel, Logger},
|
|
15
|
+
spinner::start_spinner,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
pub struct BuildStatsInput {
|
|
19
|
+
pub statements_by_module:
|
|
20
|
+
std::collections::HashMap<String, Vec<crate::core::parser::statement::Statement>>,
|
|
21
|
+
pub global_store: crate::core::store::global::GlobalStore,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
pub fn process_build(
|
|
25
|
+
entry: String,
|
|
26
|
+
output: String,
|
|
27
|
+
debug: bool,
|
|
28
|
+
compress: bool,
|
|
29
|
+
) -> Result<BuildStatsInput, String> {
|
|
30
|
+
let spinner = start_spinner("Building...");
|
|
31
|
+
|
|
32
|
+
let duration = std::time::Instant::now();
|
|
33
|
+
|
|
34
|
+
let normalized_entry_file = normalize_path(&entry);
|
|
35
|
+
let normalized_output_dir = normalize_path(&output);
|
|
36
|
+
|
|
37
|
+
let mut global_store = GlobalStore::new();
|
|
38
|
+
let module_loader = ModuleLoader::new(&normalized_entry_file, &normalized_output_dir);
|
|
39
|
+
|
|
40
|
+
// SECTION Load
|
|
41
|
+
// NOTE: We use modules in the build command, so we need to load them
|
|
42
|
+
let (modules_tokens, modules_statements) = module_loader.load_all_modules(&mut global_store);
|
|
43
|
+
|
|
44
|
+
// SECTION Write logs
|
|
45
|
+
if debug {
|
|
46
|
+
for (module_path, module) in global_store.modules.clone() {
|
|
47
|
+
write_module_variable_log_file(
|
|
48
|
+
&normalized_output_dir,
|
|
49
|
+
&module_path,
|
|
50
|
+
&module.variable_table,
|
|
51
|
+
);
|
|
52
|
+
write_module_function_log_file(
|
|
53
|
+
&normalized_output_dir,
|
|
54
|
+
&module_path,
|
|
55
|
+
&module.function_table,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
write_lexer_log_file(
|
|
60
|
+
&normalized_output_dir,
|
|
61
|
+
"lexer_tokens.log",
|
|
62
|
+
modules_tokens.clone(),
|
|
63
|
+
);
|
|
64
|
+
write_preprocessor_log_file(
|
|
65
|
+
&normalized_output_dir,
|
|
66
|
+
"resolved_statements.log",
|
|
67
|
+
modules_statements.clone(),
|
|
68
|
+
);
|
|
69
|
+
write_variables_log_file(
|
|
70
|
+
&normalized_output_dir,
|
|
71
|
+
"global_variables.log",
|
|
72
|
+
global_store.variables.clone(),
|
|
73
|
+
);
|
|
74
|
+
write_function_log_file(
|
|
75
|
+
&normalized_output_dir,
|
|
76
|
+
"global_functions.log",
|
|
77
|
+
global_store.functions.clone(),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// SECTION Detect build-time errors prior to building
|
|
82
|
+
let all_errors = crate::core::error::collect_all_errors_with_modules(&modules_statements);
|
|
83
|
+
let (warnings, criticals) = crate::core::error::partition_errors(all_errors);
|
|
84
|
+
crate::core::error::log_errors_with_stack("Build", &warnings, &criticals);
|
|
85
|
+
if !criticals.is_empty() {
|
|
86
|
+
spinner.finish_and_clear();
|
|
87
|
+
return Err(format!(
|
|
88
|
+
"build failed with {} critical error(s): {}",
|
|
89
|
+
criticals.len(),
|
|
90
|
+
criticals[0].message
|
|
91
|
+
));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// SECTION Building AST and Audio
|
|
95
|
+
let builder = Builder::new();
|
|
96
|
+
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
|
+
);
|
|
102
|
+
|
|
103
|
+
// SECTION Logging
|
|
104
|
+
let logger = Logger::new();
|
|
105
|
+
|
|
106
|
+
if debug {
|
|
107
|
+
let modules_loaded = global_store.modules.keys().collect::<Vec<_>>();
|
|
108
|
+
let global_variables_loaded = global_store.variables.variables.keys().collect::<Vec<_>>();
|
|
109
|
+
let global_functions_loaded = global_store.functions.functions.keys().collect::<Vec<_>>();
|
|
110
|
+
|
|
111
|
+
logger.log_message_with_trace(
|
|
112
|
+
LogLevel::Debug,
|
|
113
|
+
&format!("Modules loaded: {}", global_store.modules.len()),
|
|
114
|
+
modules_loaded.iter().map(|s| s.as_str()).collect(),
|
|
115
|
+
);
|
|
116
|
+
logger.log_message_with_trace(
|
|
117
|
+
LogLevel::Debug,
|
|
118
|
+
&format!(
|
|
119
|
+
"Global variables: {}",
|
|
120
|
+
global_store.variables.variables.len()
|
|
121
|
+
),
|
|
122
|
+
global_variables_loaded.iter().map(|s| s.as_str()).collect(),
|
|
123
|
+
);
|
|
124
|
+
logger.log_message_with_trace(
|
|
125
|
+
LogLevel::Debug,
|
|
126
|
+
&format!(
|
|
127
|
+
"Global functions: {}",
|
|
128
|
+
global_store.functions.functions.len()
|
|
129
|
+
),
|
|
130
|
+
global_functions_loaded.iter().map(|s| s.as_str()).collect(),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let success_message = format!(
|
|
135
|
+
"Build completed successfully in {:.2?}. Output files written to: '{}'",
|
|
136
|
+
duration.elapsed(),
|
|
137
|
+
normalized_output_dir
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
spinner.finish_and_clear();
|
|
141
|
+
logger.log_message(LogLevel::Success, &success_message);
|
|
142
|
+
Ok(BuildStatsInput {
|
|
143
|
+
statements_by_module: modules_statements,
|
|
144
|
+
global_store,
|
|
145
|
+
})
|
|
146
|
+
}
|
|
@@ -11,13 +11,13 @@ use crate::{
|
|
|
11
11
|
store::global::GlobalStore,
|
|
12
12
|
utils::path::{find_entry_file, normalize_path},
|
|
13
13
|
},
|
|
14
|
-
utils::{
|
|
15
|
-
logger::{LogLevel, Logger},
|
|
16
|
-
spinner::with_spinner,
|
|
17
|
-
watcher::watch_directory,
|
|
18
|
-
},
|
|
19
14
|
};
|
|
20
|
-
|
|
15
|
+
|
|
16
|
+
use devalang_utils::{
|
|
17
|
+
logger::{LogLevel, Logger},
|
|
18
|
+
spinner::start_spinner,
|
|
19
|
+
watcher::watch_directory,
|
|
20
|
+
};
|
|
21
21
|
|
|
22
22
|
#[cfg(feature = "cli")]
|
|
23
23
|
pub fn handle_check_command(
|
|
@@ -31,18 +31,18 @@ pub fn handle_check_command(
|
|
|
31
31
|
config
|
|
32
32
|
.as_ref()
|
|
33
33
|
.and_then(|c| c.defaults.entry.clone())
|
|
34
|
-
.
|
|
34
|
+
.unwrap_or_default()
|
|
35
35
|
} else {
|
|
36
|
-
entry.clone().
|
|
36
|
+
entry.clone().unwrap_or_default()
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
let fetched_output = if output.is_none() {
|
|
40
40
|
config
|
|
41
41
|
.as_ref()
|
|
42
42
|
.and_then(|c| c.defaults.output.clone())
|
|
43
|
-
.
|
|
43
|
+
.unwrap_or_default()
|
|
44
44
|
} else {
|
|
45
|
-
output.clone().
|
|
45
|
+
output.clone().unwrap_or_default()
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
let fetched_watch = if watch {
|
|
@@ -124,11 +124,9 @@ fn begin_check(
|
|
|
124
124
|
entry: String,
|
|
125
125
|
output: String,
|
|
126
126
|
debug: bool,
|
|
127
|
-
|
|
127
|
+
_config: Option<ProjectConfig>,
|
|
128
128
|
) -> Result<(), String> {
|
|
129
|
-
let spinner =
|
|
130
|
-
thread::sleep(Duration::from_millis(800));
|
|
131
|
-
});
|
|
129
|
+
let spinner = start_spinner("Checking...");
|
|
132
130
|
|
|
133
131
|
let duration = std::time::Instant::now();
|
|
134
132
|
|
|
@@ -145,7 +143,7 @@ fn begin_check(
|
|
|
145
143
|
// Debugging: Log loaded modules and errors
|
|
146
144
|
let logger = Logger::new();
|
|
147
145
|
logger.log_message(LogLevel::Info, "Loaded modules:");
|
|
148
|
-
for
|
|
146
|
+
for module_name in modules.0.keys() {
|
|
149
147
|
logger.log_message(LogLevel::Info, &format!("- {}", module_name));
|
|
150
148
|
}
|
|
151
149
|
|
|
@@ -185,10 +183,10 @@ fn begin_check(
|
|
|
185
183
|
);
|
|
186
184
|
}
|
|
187
185
|
|
|
188
|
-
let all_errors = crate::
|
|
186
|
+
let all_errors = crate::core::error::collect_all_errors_with_modules(&modules.1);
|
|
189
187
|
|
|
190
|
-
let (warnings, criticals) = crate::
|
|
191
|
-
crate::
|
|
188
|
+
let (warnings, criticals) = crate::core::error::partition_errors(all_errors);
|
|
189
|
+
crate::core::error::log_errors_with_stack("Check", &warnings, &criticals);
|
|
192
190
|
|
|
193
191
|
if !criticals.is_empty() {
|
|
194
192
|
spinner.finish_and_clear();
|
|
@@ -196,18 +194,6 @@ fn begin_check(
|
|
|
196
194
|
} else {
|
|
197
195
|
logger.log_message(LogLevel::Success, "No errors detected.");
|
|
198
196
|
|
|
199
|
-
// Compute and persist rich stats
|
|
200
|
-
let stats = crate::config::stats::compute_from(
|
|
201
|
-
&modules.1,
|
|
202
|
-
&global_store,
|
|
203
|
-
&config,
|
|
204
|
-
Some(&normalized_output_dir),
|
|
205
|
-
);
|
|
206
|
-
crate::config::stats::set_memory_stats(stats.clone());
|
|
207
|
-
if let Err(e) = crate::config::stats::save_to_file(&stats) {
|
|
208
|
-
eprintln!("[stats] failed to save: {}", e);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
197
|
let success_message = format!(
|
|
212
198
|
"Check completed successfully in {:.2?}. Output files written to: '{}'",
|
|
213
199
|
duration.elapsed(),
|
|
@@ -216,6 +202,7 @@ fn begin_check(
|
|
|
216
202
|
|
|
217
203
|
spinner.finish_and_clear();
|
|
218
204
|
logger.log_message(LogLevel::Success, &success_message);
|
|
219
|
-
Ok(())
|
|
220
205
|
}
|
|
206
|
+
|
|
207
|
+
Ok(())
|
|
221
208
|
}
|