Skip to content

Commit 8e51467

Browse files
authored
Merge pull request #294 from f4z3r/feat/interface
Feat/interface
2 parents 53a69b2 + 74d2302 commit 8e51467

5 files changed

Lines changed: 186 additions & 35 deletions

File tree

lua/README.md

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,79 @@
11
# KCL Artifact Library for Lua
22

3-
This repo is under development, PRs welcome!
3+
> [!WARNING]
4+
> This repo is under development, PRs welcome!
45
5-
## Build from Source
6+
A Lua library for interacting with KCL (Kusion Configuration Language) artifacts. This library
7+
enables you to work with KCL modules, configurations, and artifacts directly from Lua scripts.
68

7-
**Prerequisites**
9+
## Installation
810

9-
+ Lua
10-
+ Cargo
11+
### From Source
1112

12-
### Lua version
13+
#### Prerequisites
1314

14-
You have to enable one of the features: lua54, lua53, lua52, lua51, luajit(52) or luau in `Cargo.toml`, according to the chosen Lua version. **Default Lua version is 5.2**.
15+
- **Rust** (with Cargo) - For building the library.
16+
- **Lua** - The target Lua version you want to use.
17+
- **LuaRocks** - The Lua package manager to manage the build and installation.
1518

16-
If you build on macos, you can set the environment to prevent link errors.
19+
#### Supported Lua Versions
1720

18-
```shell
21+
This library supports multiple Lua versions. Enable the appropriate feature in `Cargo.toml`:
22+
23+
- `lua54` - Lua 5.4
24+
- `lua53` - Lua 5.3
25+
- `lua52` - Lua 5.2 (default)
26+
- `lua51` - Lua 5.1
27+
- `luajit` - LuaJIT
28+
29+
#### Platform-Specific Setup
30+
31+
**macOS:** Set the deployment target to avoid link errors:
32+
33+
```bash
1934
# Set cargo build target on macos
2035
export MACOSX_DEPLOYMENT_TARGET='10.13'
2136
```
2237

23-
### Linux
38+
#### Build Steps
39+
40+
Use `luarocks` to build the library and install it for your current Lua version:
41+
42+
```bash
43+
luarocks --local make
44+
```
45+
46+
## Usage
47+
48+
### Basic Usage
49+
50+
The KCL Lua library provides two main functions for working with KCL configurations:
51+
52+
```lua
53+
local kcl = require("kcl_lib")
54+
55+
-- Execute a single KCL file
56+
local result = assert(kcl.run("./config/schema.k"))
57+
print("Configuration result:", result.yaml_result)
58+
59+
-- Execute multiple KCL files
60+
local result = assert(kcl.run({
61+
"./config/schema.k",
62+
"./config/data.k"
63+
}))
64+
print("Combined configuration:", result.yaml_result)
65+
66+
-- Format a KCL file
67+
local formatted_files = assert(kcl.format("./config/unordered.k"))
68+
print("Formatted files:", table.concat(formatted_files, ", "))
69+
```
70+
71+
## Development
72+
73+
### Running Tests
74+
75+
Tests are directly run in Lua using `busted`. You can run them using:
2476

25-
```shell
26-
make
27-
# copy to lua share library directory
28-
cp ./target/release/libkcl_lib_lua.so /usr/lib/lua/5.2/kcl_lib.so
77+
```bash
78+
luarocks test
2979
```

lua/spec/exec_spec.lua

Lines changed: 0 additions & 13 deletions
This file was deleted.

lua/spec/kcl_lib_spec.lua

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
local io = require("io")
2+
local os = require("os")
3+
4+
local kcl_lib = require("kcl_lib")
5+
6+
describe("kcl_lib", function()
7+
describe("run", function()
8+
it("should take a single path, run it, and return the result", function()
9+
local expected = [[app:
10+
replicas: 2]]
11+
local result = assert(kcl_lib.run("./spec/test_data/schema.k"))
12+
assert.are.equal(expected, result.yaml_result)
13+
end)
14+
15+
it(
16+
"should take an array of paths, run them, and return the result",
17+
function()
18+
local expected = [[app:
19+
replicas: 2
20+
app2:
21+
replicas: 4]]
22+
local result = assert(kcl_lib.run({
23+
"./spec/test_data/schema.k",
24+
"./spec/test_data/data.k",
25+
}))
26+
assert.are.equal(expected, result.yaml_result)
27+
end
28+
)
29+
end)
30+
31+
describe("format", function()
32+
local unformated_file = "/tmp/unformated.k"
33+
local unformated_content = [[
34+
schema AppConfig:
35+
replicas: int
36+
37+
app: AppConfig {
38+
replicas: 2
39+
}]]
40+
local expected_content = [[schema AppConfig:
41+
replicas: int
42+
43+
app: AppConfig {
44+
replicas: 2
45+
}
46+
]]
47+
48+
it(
49+
"should take a single path to unformated code, properly format it, and the path",
50+
function()
51+
local file = assert(
52+
io.open(unformated_file, "w"),
53+
"failed to open test file for formatting"
54+
)
55+
file:write(unformated_content)
56+
file:close()
57+
local result = assert(kcl_lib.format(unformated_file))
58+
assert.are.same({ unformated_file }, result)
59+
file = assert(
60+
io.open(unformated_file, "r"),
61+
"failed to open formatted file for reading"
62+
)
63+
local data = file:read("*a")
64+
file:close()
65+
assert.are.equal(expected_content, data)
66+
os.execute("rm " .. unformated_file)
67+
end
68+
)
69+
70+
it(
71+
"should take a single path to formated code, do nothing, and return an empty table",
72+
function()
73+
local file = assert(
74+
io.open(unformated_file, "w"),
75+
"failed to open test file for formatting"
76+
)
77+
file:write(expected_content)
78+
file:close()
79+
local result = assert(kcl_lib.format(unformated_file))
80+
assert.are.same({}, result)
81+
os.execute("rm " .. unformated_file)
82+
end
83+
)
84+
end)
85+
end)

lua/spec/test_data/data.k

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
app2: AppConfig {
2+
replicas: 4
3+
}

lua/src/lib.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@ extern crate kcl_api;
22

33
use mlua::prelude::*;
44

5-
/// Execute KCL file with arguments and return the JSON/YAML result.
6-
fn exec_program<'a>(lua: &'a Lua, args: LuaTable<'a>) -> LuaResult<LuaTable<'a>> {
5+
/// Execute KCL code and return the JSON/YAML result.
6+
fn run<'a>(lua: &'a Lua, path: LuaValue) -> LuaResult<LuaTable<'a>> {
77
let api = kcl_api::API::default();
8-
let work_dir: String = args.get("work_dir").unwrap_or_default();
9-
let k_filename_list: Vec<String> = args.get("k_filename_list").unwrap_or_default();
10-
let k_code_list: Vec<String> = args.get("k_code_list").unwrap_or_default();
8+
let k_filename_list = match path {
9+
LuaValue::String(s) => Ok(vec![s.to_str()?.to_owned()]),
10+
LuaValue::Table(t) => t
11+
.sequence_values::<String>()
12+
.collect::<Result<Vec<String>, LuaError>>(),
13+
_ => {
14+
return Err(LuaError::runtime(
15+
"invalid argument type for function `run`, expecting string or table",
16+
));
17+
}
18+
}?;
1119

1220
let result = match api.exec_program(&kcl_api::ExecProgramArgs {
13-
work_dir,
1421
k_filename_list,
15-
k_code_list,
1622
..Default::default()
1723
}) {
1824
Ok(r) => r,
@@ -27,9 +33,29 @@ fn exec_program<'a>(lua: &'a Lua, args: LuaTable<'a>) -> LuaResult<LuaTable<'a>>
2733
Ok(t)
2834
}
2935

36+
/// Format KCL code from a file.
37+
fn format<'a>(lua: &'a Lua, path: String) -> LuaResult<LuaTable<'a>> {
38+
let api = kcl_api::API::default();
39+
40+
let result = match api.format_path(&kcl_api::FormatPathArgs {
41+
path,
42+
..Default::default()
43+
}) {
44+
Ok(r) => r,
45+
Err(e) => return Err(LuaError::external(e)),
46+
};
47+
48+
let t = lua.create_table()?;
49+
for changed_path in result.changed_paths.iter() {
50+
t.push(lua.create_string(changed_path)?)?;
51+
}
52+
Ok(t)
53+
}
54+
3055
#[mlua::lua_module]
3156
fn kcl_lib(lua: &Lua) -> LuaResult<LuaTable<'_>> {
3257
let module = lua.create_table()?;
33-
module.set("exec_program", lua.create_function(exec_program)?)?;
58+
module.set("run", lua.create_function(run)?)?;
59+
module.set("format", lua.create_function(format)?)?;
3460
Ok(module)
3561
}

0 commit comments

Comments
 (0)