@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.
- package/.devalang +9 -10
- package/Cargo.toml +5 -4
- package/README.md +7 -5
- package/docs/CHANGELOG.md +42 -0
- package/docs/ROADMAP.md +5 -1
- package/docs/TODO.md +3 -14
- package/examples/bus.deva +10 -0
- package/examples/effect.deva +2 -0
- package/examples/filter.deva +11 -0
- package/examples/lfo.deva +9 -0
- package/examples/synth.deva +11 -1
- package/examples/synth_types.deva +17 -0
- package/out-tsc/core/functions/index.d.ts +5 -0
- package/out-tsc/core/functions/index.js +11 -0
- package/out-tsc/pkg/devalang_core.d.ts +2 -0
- package/out-tsc/pkg/devalang_core.js +17 -2
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -7
- package/package.json +1 -1
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -122
- package/rust/cli/bank/commands.rs +33 -2
- package/rust/cli/bank/mod.rs +29 -29
- package/rust/cli/build/commands.rs +53 -3
- package/rust/cli/build/mod.rs +2 -2
- package/rust/cli/build/process.rs +26 -7
- package/rust/cli/check/mod.rs +2 -2
- package/rust/cli/discover/commands.rs +253 -253
- package/rust/cli/discover/config.rs +111 -111
- package/rust/cli/discover/fs.rs +19 -19
- package/rust/cli/discover/install.rs +103 -103
- package/rust/cli/discover/metadata.rs +48 -48
- package/rust/cli/discover/mod.rs +5 -5
- package/rust/cli/install/addon.rs +118 -118
- package/rust/cli/install/bank.rs +22 -3
- package/rust/cli/install/commands.rs +35 -35
- package/rust/cli/install/mod.rs +4 -4
- package/rust/cli/install/plugin.rs +80 -61
- package/rust/cli/login/commands.rs +124 -124
- package/rust/cli/mod.rs +12 -12
- package/rust/cli/parser.rs +46 -1
- package/rust/cli/play/commands.rs +71 -20
- package/rust/cli/play/mod.rs +5 -5
- package/rust/cli/play/process.rs +14 -5
- package/rust/cli/play/realtime.rs +91 -91
- package/rust/cli/telemetry/commands.rs +22 -22
- package/rust/cli/telemetry/event_creator.rs +80 -80
- package/rust/cli/telemetry/mod.rs +3 -3
- package/rust/cli/telemetry/send.rs +51 -51
- package/rust/cli/template/commands.rs +69 -69
- package/rust/config/driver.rs +112 -103
- package/rust/config/mod.rs +3 -3
- package/rust/config/ops.rs +26 -26
- package/rust/config/settings.rs +101 -101
- package/rust/core/audio/engine/driver.rs +220 -0
- package/rust/core/audio/engine/export.rs +169 -0
- package/rust/core/audio/engine/helpers.rs +178 -170
- package/rust/core/audio/engine/mod.rs +51 -2
- package/rust/core/audio/engine/notes/dsp.rs +85 -0
- package/rust/core/audio/engine/notes/mod.rs +44 -0
- package/rust/core/audio/engine/notes/params.rs +294 -0
- package/rust/core/audio/engine/sample/insert.rs +199 -0
- package/rust/core/audio/engine/sample/mod.rs +40 -0
- package/rust/core/audio/engine/sample/padding.rs +170 -0
- package/rust/core/audio/evaluator/condition.rs +61 -0
- package/rust/core/audio/evaluator/mod.rs +9 -0
- package/rust/core/audio/{evaluator.rs → evaluator/numeric.rs} +1 -159
- package/rust/core/audio/evaluator/rhs.rs +16 -0
- package/rust/core/audio/evaluator/string_expr.rs +94 -0
- package/rust/core/audio/interpreter/driver.rs +55 -23
- package/rust/core/audio/interpreter/mod.rs +1 -13
- package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
- package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
- package/rust/core/audio/interpreter/{automate.rs → statements/automate.rs} +16 -18
- package/rust/core/audio/interpreter/{call.rs → statements/call.rs} +5 -4
- package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +2 -1
- package/rust/core/audio/interpreter/{function.rs → statements/function.rs} +2 -4
- package/rust/core/audio/interpreter/{let_.rs → statements/let_.rs} +2 -4
- package/rust/core/audio/interpreter/{load.rs → statements/load.rs} +2 -4
- package/rust/core/audio/interpreter/{loop_.rs → statements/loop_.rs} +2 -1
- package/rust/core/audio/interpreter/statements/mod.rs +12 -0
- package/rust/core/audio/interpreter/{sleep.rs → statements/sleep.rs} +28 -28
- package/rust/core/audio/interpreter/{spawn.rs → statements/spawn.rs} +3 -2
- package/rust/core/audio/interpreter/{tempo.rs → statements/tempo.rs} +40 -40
- package/rust/core/audio/interpreter/{trigger.rs → statements/trigger.rs} +1 -1
- package/rust/core/audio/loader/trigger.rs +2 -1
- package/rust/core/audio/mod.rs +6 -7
- package/rust/core/audio/player.rs +70 -70
- package/rust/core/audio/special/easing.rs +189 -189
- package/rust/core/audio/special/env.rs +45 -45
- package/rust/core/audio/special/math.rs +134 -134
- package/rust/core/audio/special/mod.rs +9 -9
- package/rust/core/audio/special/modulator.rs +143 -143
- package/rust/core/builder/mod.rs +45 -2
- package/rust/core/debugger/lexer.rs +27 -27
- package/rust/core/debugger/{module.rs → logs.rs} +3 -6
- package/rust/core/debugger/mod.rs +30 -30
- package/rust/core/debugger/preprocessor.rs +27 -27
- package/rust/core/debugger/store.rs +2 -4
- package/rust/core/error/mod.rs +269 -269
- package/rust/core/lexer/driver.rs +59 -61
- package/rust/core/lexer/handler/arrow.rs +82 -82
- package/rust/core/lexer/handler/at.rs +21 -21
- package/rust/core/lexer/handler/brace.rs +41 -41
- package/rust/core/lexer/handler/colon.rs +21 -21
- package/rust/core/lexer/handler/comment.rs +30 -30
- package/rust/core/lexer/handler/dot.rs +21 -21
- package/rust/core/lexer/handler/driver.rs +337 -337
- package/rust/core/lexer/handler/identifier.rs +47 -47
- package/rust/core/lexer/handler/indent.rs +66 -66
- package/rust/core/lexer/handler/mod.rs +15 -15
- package/rust/core/lexer/handler/newline.rs +23 -23
- package/rust/core/lexer/handler/number.rs +31 -31
- package/rust/core/lexer/handler/operator.rs +46 -46
- package/rust/core/lexer/handler/parenthesis.rs +41 -41
- package/rust/core/lexer/handler/slash.rs +21 -21
- package/rust/core/lexer/handler/string.rs +63 -63
- package/rust/core/lexer/mod.rs +3 -3
- package/rust/core/mod.rs +0 -1
- package/rust/core/parser/driver/block.rs +111 -0
- package/rust/core/parser/driver/cursor.rs +82 -0
- package/rust/core/parser/driver/driver_impl.rs +139 -0
- package/rust/core/parser/driver/mod.rs +6 -0
- package/rust/core/parser/driver/parse_array.rs +120 -0
- package/rust/core/parser/driver/parse_map.rs +223 -0
- package/rust/core/parser/driver/parser.rs +160 -0
- package/rust/core/parser/handler/arrow_call.rs +28 -4
- package/rust/core/parser/handler/at.rs +279 -279
- package/rust/core/parser/handler/bank.rs +104 -104
- package/rust/core/parser/handler/condition.rs +83 -83
- package/rust/core/parser/handler/dot.rs +148 -148
- package/rust/core/parser/handler/identifier/automate.rs +254 -254
- package/rust/core/parser/handler/identifier/call.rs +91 -91
- package/rust/core/parser/handler/identifier/emit.rs +70 -70
- package/rust/core/parser/handler/identifier/function.rs +113 -113
- package/rust/core/parser/handler/identifier/group.rs +89 -89
- package/rust/core/parser/handler/identifier/let_.rs +173 -173
- package/rust/core/parser/handler/identifier/mod.rs +55 -55
- package/rust/core/parser/handler/identifier/on.rs +107 -107
- package/rust/core/parser/handler/identifier/print.rs +49 -49
- package/rust/core/parser/handler/identifier/sleep.rs +96 -43
- package/rust/core/parser/handler/identifier/spawn.rs +91 -91
- package/rust/core/parser/handler/identifier/synth.rs +135 -135
- package/rust/core/parser/handler/loop_.rs +194 -194
- package/rust/core/parser/handler/mod.rs +9 -9
- package/rust/core/parser/handler/pattern.rs +1 -1
- package/rust/core/parser/handler/tempo.rs +105 -57
- package/rust/core/parser/statement.rs +10 -11
- package/rust/core/plugin/loader.rs +1 -1
- package/rust/core/plugin/mod.rs +2 -2
- package/rust/core/plugin/runner/mod.rs +11 -0
- package/rust/core/plugin/{runner.rs → runner/non_wasm.rs} +297 -347
- package/rust/core/plugin/runner/wasm32.rs +43 -0
- package/rust/core/preprocessor/loader/inject.rs +278 -0
- package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
- package/rust/core/preprocessor/loader/mod.rs +235 -0
- package/rust/core/preprocessor/module.rs +2 -7
- package/rust/core/preprocessor/{processor.rs → processor/handlers.rs} +6 -13
- package/rust/core/preprocessor/processor/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/bank.rs +49 -49
- package/rust/core/preprocessor/resolver/call.rs +124 -124
- package/rust/core/preprocessor/resolver/condition.rs +95 -95
- package/rust/core/preprocessor/resolver/driver.rs +324 -324
- package/rust/core/preprocessor/resolver/function.rs +2 -2
- package/rust/core/preprocessor/resolver/group.rs +46 -18
- package/rust/core/preprocessor/resolver/let_.rs +32 -32
- package/rust/core/preprocessor/resolver/loop_.rs +318 -318
- package/rust/core/preprocessor/resolver/mod.rs +16 -16
- package/rust/core/preprocessor/resolver/pattern.rs +83 -83
- package/rust/core/preprocessor/resolver/spawn.rs +99 -99
- package/rust/core/preprocessor/resolver/synth.rs +54 -54
- package/rust/core/preprocessor/resolver/tempo.rs +48 -48
- package/rust/core/preprocessor/resolver/trigger.rs +116 -116
- package/rust/core/preprocessor/resolver/value.rs +176 -176
- package/rust/core/store/global.rs +2 -6
- package/rust/core/store/mod.rs +1 -5
- package/rust/lib.rs +18 -3
- package/rust/main.rs +27 -3
- package/rust/types/Cargo.toml +1 -1
- package/rust/types/src/addons.rs +55 -55
- package/rust/types/src/config.rs +84 -74
- package/rust/types/src/lib.rs +15 -12
- package/rust/types/src/plugin.rs +20 -0
- package/rust/types/src/store.rs +139 -0
- package/rust/types/src/telemetry.rs +85 -85
- package/rust/utils/Cargo.toml +2 -2
- package/rust/utils/src/file.rs +94 -94
- package/rust/utils/src/first_usage.rs +97 -97
- package/rust/utils/src/lib.rs +9 -9
- package/rust/utils/src/logger.rs +200 -200
- package/rust/utils/src/path.rs +129 -88
- package/rust/utils/src/signature.rs +41 -41
- package/rust/utils/src/spinner.rs +20 -20
- package/rust/utils/src/version.rs +27 -27
- package/rust/utils/src/watcher.rs +46 -46
- package/rust/web/api.rs +5 -5
- package/rust/web/cdn.rs +34 -34
- package/rust/web/mod.rs +3 -3
- package/tests/integration.rs +21 -21
- package/typescript/core/functions/index.ts +11 -0
- package/typescript/pkg/devalang_core.ts +20 -4
- package/rust/core/audio/engine/sample.rs +0 -366
- package/rust/core/audio/engine/synth.rs +0 -325
- package/rust/core/audio/interpreter/arrow_call.rs +0 -311
- package/rust/core/audio/renderer.rs +0 -54
- package/rust/core/parser/driver.rs +0 -584
- package/rust/core/preprocessor/loader.rs +0 -637
- package/rust/core/store/export.rs +0 -28
- package/rust/core/store/function.rs +0 -40
- package/rust/core/store/import.rs +0 -28
- package/rust/core/store/variable.rs +0 -51
- package/rust/core/utils/mod.rs +0 -1
- 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
|
+
}
|
package/rust/cli/discover/fs.rs
CHANGED
|
@@ -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
|
+
}
|
package/rust/cli/discover/mod.rs
CHANGED
|
@@ -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;
|