@devaloop/devalang 0.0.1-alpha.16-hotfix.1 → 0.0.1-alpha.16-hotfix.3
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/.github/workflows/ci.yml +20 -8
- package/Cargo.toml +1 -1
- package/README.md +5 -3
- package/docs/CHANGELOG.md +10 -0
- package/docs/ROADMAP.md +1 -1
- package/package.json +1 -1
- package/rust/cli/driver.rs +12 -0
- package/rust/cli/mod.rs +0 -1
- package/rust/cli/telemetry.rs +22 -19
- package/rust/config/settings.rs +31 -19
- package/rust/utils/first_usage.rs +19 -12
- package/typescript/scripts/postinstall.ts +45 -32
- package/rust/cli/generator.rs +0 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
name: CI & Release
|
|
2
2
|
|
|
3
|
+
permissions:
|
|
4
|
+
contents: write
|
|
5
|
+
|
|
3
6
|
on:
|
|
4
7
|
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
8
|
tags:
|
|
8
9
|
- "v*"
|
|
9
|
-
pull_request:
|
|
10
10
|
|
|
11
11
|
jobs:
|
|
12
12
|
build:
|
|
@@ -77,16 +77,28 @@ jobs:
|
|
|
77
77
|
Copy-Item "target\${{ matrix.target }}\release\devalang${{ matrix.bin_ext }}" "out-tsc\bin\devalang-${{ matrix.target }}${{ matrix.bin_ext }}" -Force
|
|
78
78
|
|
|
79
79
|
- name: Upload artifact (CI)
|
|
80
|
-
if: startsWith(github.ref, 'refs/heads/')
|
|
81
80
|
uses: actions/upload-artifact@v4
|
|
82
81
|
with:
|
|
83
82
|
name: devalang-${{ matrix.target }}
|
|
84
83
|
path: out-tsc/bin/*
|
|
85
84
|
|
|
85
|
+
release:
|
|
86
|
+
name: Create GitHub Release
|
|
87
|
+
runs-on: ubuntu-latest
|
|
88
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
89
|
+
needs: build
|
|
90
|
+
steps:
|
|
91
|
+
- name: Download all build artifacts
|
|
92
|
+
uses: actions/download-artifact@v4
|
|
93
|
+
with:
|
|
94
|
+
path: dist
|
|
95
|
+
pattern: devalang-*
|
|
96
|
+
merge-multiple: true
|
|
97
|
+
|
|
98
|
+
- name: List files
|
|
99
|
+
run: ls -la dist
|
|
100
|
+
|
|
86
101
|
- name: Upload to GitHub Release
|
|
87
|
-
if: startsWith(github.ref, 'refs/tags/')
|
|
88
102
|
uses: softprops/action-gh-release@v2
|
|
89
103
|
with:
|
|
90
|
-
files:
|
|
91
|
-
env:
|
|
92
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
104
|
+
files: dist/*
|
package/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "devalang"
|
|
3
|
-
version = "0.0.1-alpha.16-hotfix.
|
|
3
|
+
version = "0.0.1-alpha.16-hotfix.3"
|
|
4
4
|
authors = ["Devaloop <contact@devaloop.com>"]
|
|
5
5
|
description = "Write music like code. Devalang is a domain-specific language (DSL) for sound designers and music hackers. Compose, automate, and control sound — in plain text."
|
|
6
6
|
license = "MIT"
|
package/README.md
CHANGED
|
@@ -32,7 +32,9 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
32
32
|
>
|
|
33
33
|
> Includes synthesis, playback, and rendering features, but is still in early development.
|
|
34
34
|
>
|
|
35
|
-
> NEW:
|
|
35
|
+
> NEW: [Devaforge is now available for creating addons](https://github.com/devaloop-labs/devaforge).
|
|
36
|
+
>
|
|
37
|
+
> NEW: Devalang is now available for **Windows**, **Linux**, and **macOS**.
|
|
36
38
|
|
|
37
39
|
## 📚 Quick Access
|
|
38
40
|
|
|
@@ -43,7 +45,8 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
43
45
|
- [📜 Changelog](./docs/CHANGELOG.md)
|
|
44
46
|
- [💡 Examples](./examples/)
|
|
45
47
|
- [🌐 Project Website](https://devalang.com)
|
|
46
|
-
- [📦
|
|
48
|
+
- [📦 Devaforge on npm](https://www.npmjs.com/package/@devaloop/devaforge)
|
|
49
|
+
- [📦 Devalang on npm](https://www.npmjs.com/package/@devaloop/devalang)
|
|
47
50
|
|
|
48
51
|
## ⏱️ Try it now !
|
|
49
52
|
|
|
@@ -59,7 +62,6 @@ npm install -g @devaloop/devalang@latest
|
|
|
59
62
|
|
|
60
63
|
# Create a new Devalang project
|
|
61
64
|
devalang init --name my-project --template minimal
|
|
62
|
-
cd my-project
|
|
63
65
|
```
|
|
64
66
|
|
|
65
67
|
Create a new Devalang file `src/index.deva` in the project directory:
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
+
## Version 0.0.1-alpha.16-hotfix.2 (2025-08-29)
|
|
8
|
+
|
|
9
|
+
### 🌎 Ecosystem
|
|
10
|
+
|
|
11
|
+
- Published `@devaloop/devaforge` on npm. A tool for creating and managing Devalang addons.
|
|
12
|
+
|
|
13
|
+
### 🔎 Telemetry
|
|
14
|
+
|
|
15
|
+
- Patched first usage and user configuration.
|
|
16
|
+
|
|
7
17
|
## Version 0.0.1-alpha.16-hotfix.1 (2025-08-29)
|
|
8
18
|
|
|
9
19
|
### 🌎 Ecosystem
|
package/docs/ROADMAP.md
CHANGED
|
@@ -22,10 +22,10 @@ Devalang is a work in progress. Here’s what we’re planning next:
|
|
|
22
22
|
- ✅ **Sample loading**: Add `@load` assignment to load samples (.mp3, .wav) for use as values.
|
|
23
23
|
- ✅ **WASM support**: Compile Devalang to WebAssembly for use in web applications and other environments.
|
|
24
24
|
- ✅ **VSCode extension**: Create a VSCode extension for syntax highlighting and code completion.
|
|
25
|
+
- ✅ **Addon generator**: Implement addon generation for creating reusable plugins, banks and presets.
|
|
25
26
|
|
|
26
27
|
## Upcoming
|
|
27
28
|
|
|
28
|
-
- ⏳ **Addon generator**: Implement addon generation for creating reusable plugins, banks and presets.
|
|
29
29
|
- ⏳ **Smart modules**: Let Devalang detect and use groups, samples, and variables without needing to import them manually.
|
|
30
30
|
- ⏳ **Other statements**: Implement `pattern`, and other control structures.
|
|
31
31
|
- ⏳ **Testing**: Expand test coverage for all features.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devaloop/devalang",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.1-alpha.16-hotfix.
|
|
4
|
+
"version": "0.0.1-alpha.16-hotfix.3",
|
|
5
5
|
"description": "Write music like code. Devalang is a domain-specific language (DSL) for sound designers and music hackers. Compose, automate, and control sound — in plain text.",
|
|
6
6
|
"main": "out-tsc/index.js",
|
|
7
7
|
"bin": {
|
package/rust/cli/driver.rs
CHANGED
|
@@ -287,6 +287,18 @@ pub enum Commands {
|
|
|
287
287
|
command: TelemetryCommand,
|
|
288
288
|
},
|
|
289
289
|
|
|
290
|
+
/// Generate addon scaffolding for Devalang.
|
|
291
|
+
///
|
|
292
|
+
/// ### Subcommands
|
|
293
|
+
/// - `bank` - Generates a bank scaffold.
|
|
294
|
+
/// - `plugin` - Generates a plugin scaffold.
|
|
295
|
+
/// - `preset` - Generates a preset scaffold.
|
|
296
|
+
///
|
|
297
|
+
// Scaffold {
|
|
298
|
+
// #[command(subcommand)]
|
|
299
|
+
// command: ScaffoldCommand,
|
|
300
|
+
// },
|
|
301
|
+
|
|
290
302
|
/// Log in to your Devaloop account.
|
|
291
303
|
///
|
|
292
304
|
Login {},
|
package/rust/cli/mod.rs
CHANGED
package/rust/cli/telemetry.rs
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
use crate::config::settings::set_user_config_bool;
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
use crate::config::settings::set_user_config_bool;
|
|
2
|
+
use crate::utils::logger::{LogLevel, Logger};
|
|
3
|
+
|
|
4
|
+
#[cfg(feature = "cli")]
|
|
5
|
+
pub async fn handle_telemetry_enable_command() -> Result<(), String> {
|
|
6
|
+
set_user_config_bool("telemetry", true);
|
|
7
|
+
|
|
8
|
+
let logger = Logger::new();
|
|
9
|
+
logger.log_message(LogLevel::Info, "Telemetry has been enabled.");
|
|
10
|
+
|
|
11
|
+
Ok(())
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[cfg(feature = "cli")]
|
|
15
|
+
pub async fn handle_telemetry_disable_command() -> Result<(), String> {
|
|
16
|
+
set_user_config_bool("telemetry", false);
|
|
17
|
+
|
|
18
|
+
let logger = Logger::new();
|
|
19
|
+
logger.log_message(LogLevel::Info, "Telemetry has been disabled.");
|
|
20
|
+
|
|
21
|
+
Ok(())
|
|
22
|
+
}
|
package/rust/config/settings.rs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use serde::{Deserialize, Serialize};
|
|
2
|
-
use std::
|
|
2
|
+
use std::io::Write;
|
|
3
3
|
|
|
4
4
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
|
5
5
|
pub struct UserSettings {
|
|
@@ -15,12 +15,16 @@ pub struct TelemetrySettings {
|
|
|
15
15
|
pub enabled: bool,
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
pub fn get_home_dir() -> std::path::PathBuf {
|
|
19
|
-
dirs::home_dir()
|
|
18
|
+
pub fn get_home_dir() -> Option<std::path::PathBuf> {
|
|
19
|
+
dirs::home_dir()
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
pub fn get_devalang_homedir() -> std::path::PathBuf {
|
|
23
|
-
|
|
23
|
+
if let Some(home_dir) = get_home_dir() {
|
|
24
|
+
home_dir.join(".devalang")
|
|
25
|
+
} else {
|
|
26
|
+
std::path::PathBuf::from("~/.devalang")
|
|
27
|
+
}
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
pub fn get_default_user_config() -> UserSettings {
|
|
@@ -36,8 +40,7 @@ pub fn get_default_user_config() -> UserSettings {
|
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
pub fn get_user_config() -> Option<UserSettings> {
|
|
39
|
-
let config_path = get_devalang_homedir().join("config.json")
|
|
40
|
-
if config_path.try_exists().is_ok() {
|
|
43
|
+
if let Some(config_path) = get_devalang_homedir().join("config.json").into() {
|
|
41
44
|
let file = std::fs::File::open(config_path).ok()?;
|
|
42
45
|
let settings = serde_json::from_reader(file).ok()?;
|
|
43
46
|
Some(settings)
|
|
@@ -47,13 +50,16 @@ pub fn get_user_config() -> Option<UserSettings> {
|
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
pub fn write_user_config_file() {
|
|
50
|
-
let
|
|
53
|
+
if let Some(config_path) = get_devalang_homedir().join("config.json").into() {
|
|
54
|
+
let settings = get_user_config().unwrap_or_else(get_default_user_config);
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
let config_json = serde_json::to_string(&settings).unwrap();
|
|
56
|
+
let mut file = std::fs::File::create(config_path).unwrap();
|
|
57
|
+
let config_json = serde_json::to_string(&settings).unwrap();
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
file.write_all(config_json.as_bytes()).unwrap();
|
|
60
|
+
} else {
|
|
61
|
+
println!("Could not create config file");
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
pub fn set_user_config_bool(key: &str, value: bool) {
|
|
@@ -66,11 +72,14 @@ pub fn set_user_config_bool(key: &str, value: bool) {
|
|
|
66
72
|
_ => {}
|
|
67
73
|
}
|
|
68
74
|
|
|
69
|
-
let config_path = get_devalang_homedir().join("config.json")
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
if let Some(config_path) = get_devalang_homedir().join("config.json").into() {
|
|
76
|
+
let config_json = serde_json::to_string(&settings).unwrap();
|
|
77
|
+
let mut file = std::fs::File::create(config_path).unwrap();
|
|
72
78
|
|
|
73
|
-
|
|
79
|
+
file.write_all(config_json.as_bytes()).unwrap();
|
|
80
|
+
} else {
|
|
81
|
+
println!("Could not create config file");
|
|
82
|
+
}
|
|
74
83
|
}
|
|
75
84
|
|
|
76
85
|
pub fn set_user_config_string(key: &str, value: String) {
|
|
@@ -83,9 +92,12 @@ pub fn set_user_config_string(key: &str, value: String) {
|
|
|
83
92
|
_ => {}
|
|
84
93
|
}
|
|
85
94
|
|
|
86
|
-
let config_path = get_devalang_homedir().join("config.json")
|
|
87
|
-
|
|
88
|
-
|
|
95
|
+
if let Some(config_path) = get_devalang_homedir().join("config.json").into() {
|
|
96
|
+
let config_json = serde_json::to_string(&settings).unwrap();
|
|
97
|
+
let mut file = std::fs::File::create(config_path).unwrap();
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
file.write_all(config_json.as_bytes()).unwrap();
|
|
100
|
+
} else {
|
|
101
|
+
println!("Could not create config file");
|
|
102
|
+
}
|
|
91
103
|
}
|
|
@@ -3,15 +3,14 @@ use std::fmt::Write;
|
|
|
3
3
|
|
|
4
4
|
use crate::{
|
|
5
5
|
config::settings::{get_devalang_homedir, set_user_config_bool, write_user_config_file},
|
|
6
|
-
utils::
|
|
6
|
+
utils::{
|
|
7
|
+
logger::{LogLevel, Logger},
|
|
8
|
+
signature::get_signature,
|
|
9
|
+
},
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
pub fn check_is_first_usage() {
|
|
10
|
-
if get_devalang_homedir()
|
|
11
|
-
.join("config.json")
|
|
12
|
-
.try_exists()
|
|
13
|
-
.is_ok()
|
|
14
|
-
{
|
|
13
|
+
if get_devalang_homedir().exists() == true {
|
|
15
14
|
// Do nothing
|
|
16
15
|
} else {
|
|
17
16
|
first_usage_welcome();
|
|
@@ -20,18 +19,22 @@ pub fn check_is_first_usage() {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
pub fn first_usage_welcome() {
|
|
22
|
+
std::fs::create_dir_all(get_devalang_homedir()).ok();
|
|
23
|
+
|
|
23
24
|
let version = env!("CARGO_PKG_VERSION");
|
|
24
25
|
print!("{}", get_signature(version));
|
|
25
26
|
|
|
26
|
-
let
|
|
27
|
+
let homedir = get_devalang_homedir().display().to_string();
|
|
28
|
+
|
|
27
29
|
let welcome_msg = format!(
|
|
28
30
|
"Welcome to Devalang ! \n\
|
|
29
31
|
It looks like this is your first time using the tool.\n\
|
|
30
32
|
A configuration file will be created in your home directory.\n\
|
|
31
|
-
({})",
|
|
32
|
-
|
|
33
|
+
(location: '{}')",
|
|
34
|
+
homedir
|
|
33
35
|
);
|
|
34
36
|
|
|
37
|
+
let mut s = String::new();
|
|
35
38
|
write!(&mut s, "{}", SetAttribute(Attribute::Bold)).unwrap();
|
|
36
39
|
write!(&mut s, "{}", welcome_msg).unwrap();
|
|
37
40
|
write!(&mut s, "{}", SetAttribute(Attribute::Reset)).unwrap();
|
|
@@ -56,17 +59,21 @@ pub fn first_usage_ask_for_telemetry() {
|
|
|
56
59
|
|
|
57
60
|
write_user_config_file();
|
|
58
61
|
|
|
62
|
+
let logger = Logger::new();
|
|
63
|
+
|
|
59
64
|
if telemetry_response == true {
|
|
60
65
|
println!("");
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
logger.log_message(
|
|
67
|
+
LogLevel::Info,
|
|
68
|
+
"Telemetry enabled. You can opt-out at any time by using 'devalang telemetry disable'",
|
|
63
69
|
);
|
|
64
70
|
println!("");
|
|
65
71
|
|
|
66
72
|
set_user_config_bool("telemetry", true);
|
|
67
73
|
} else {
|
|
68
74
|
println!("");
|
|
69
|
-
|
|
75
|
+
logger.log_message(
|
|
76
|
+
LogLevel::Info,
|
|
70
77
|
"Telemetry disabled. You can enable it at any time by using 'devalang telemetry enable'"
|
|
71
78
|
);
|
|
72
79
|
println!("");
|
|
@@ -4,17 +4,15 @@ import { https } from "follow-redirects";
|
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import path from "path";
|
|
6
6
|
|
|
7
|
-
const projectVersionPath = path.join(
|
|
8
|
-
__dirname,
|
|
9
|
-
"../../project-version.json"
|
|
10
|
-
);
|
|
7
|
+
const projectVersionPath = path.join(__dirname, "../../project-version.json");
|
|
11
8
|
|
|
12
9
|
const version = fs.readFileSync(projectVersionPath, "utf-8").trim();
|
|
13
10
|
const versionString = JSON.parse(version).version;
|
|
14
11
|
|
|
15
12
|
const platform = process.platform;
|
|
16
13
|
|
|
17
|
-
let binaryName: string;
|
|
14
|
+
let binaryName: string = "";
|
|
15
|
+
|
|
18
16
|
switch (platform) {
|
|
19
17
|
case "win32":
|
|
20
18
|
binaryName = "devalang-x86_64-pc-windows-msvc.exe";
|
|
@@ -25,32 +23,47 @@ switch (platform) {
|
|
|
25
23
|
case "linux":
|
|
26
24
|
binaryName = "devalang-x86_64-unknown-linux-gnu";
|
|
27
25
|
break;
|
|
28
|
-
default:
|
|
29
|
-
console.error(`❌ Unsupported platform: ${platform}`);
|
|
30
|
-
process.exit(1);
|
|
31
26
|
}
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
28
|
+
if (binaryName !== "") {
|
|
29
|
+
const destDir = join(__dirname, "..", "..", "out-tsc", "bin");
|
|
30
|
+
const dest = join(destDir, binaryName);
|
|
31
|
+
|
|
32
|
+
const url = `https://github.com/devaloop-labs/devalang/releases/download/v${versionString}/${binaryName}`;
|
|
33
|
+
|
|
34
|
+
mkdirSync(destDir, { recursive: true });
|
|
35
|
+
|
|
36
|
+
console.log(`⬇️ Downloading ${binaryName} from ${url}`);
|
|
37
|
+
|
|
38
|
+
https
|
|
39
|
+
.get(url, (res: any) => {
|
|
40
|
+
if (res.statusCode === 404) {
|
|
41
|
+
console.warn(
|
|
42
|
+
`⚠️ Asset not found (HTTP 404). Skipping binary download.`
|
|
43
|
+
);
|
|
44
|
+
res.resume();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (res.statusCode !== 200) {
|
|
49
|
+
console.error(
|
|
50
|
+
`❌ Failed (HTTP ${res.statusCode}). Skipping binary download.`
|
|
51
|
+
);
|
|
52
|
+
res.resume();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const file = createWriteStream(dest, { mode: 0o755 });
|
|
57
|
+
res.pipe(file);
|
|
58
|
+
file.on("finish", () => {
|
|
59
|
+
file.close();
|
|
60
|
+
console.log(`✅ Downloaded ${binaryName} to ${dest}`);
|
|
61
|
+
});
|
|
62
|
+
})
|
|
63
|
+
.on("error", (err) => {
|
|
64
|
+
// Network or other errors should not fail CI; log and continue
|
|
65
|
+
console.error(`❌ Error: ${err.message}. Skipping binary download.`);
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
console.error(`❌ Unsupported platform: ${platform}`);
|
|
69
|
+
}
|
package/rust/cli/generator.rs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// TODO: Plugin generator
|