WASM API
The KCL core is written by Rust and can be compiled to the wasm-wasi
target using toolchains such as cargo. With the help of WASM, we can also easily achieve multilingual and browser integration. Here is how we can use the KCL WASM module in Browser, Node.js, Go and Rust.
Quick Start
We can find and download KCL WASM module from here
Browser
Install the dependency
npm install buffer @wasmer/wasi @kcl-lang/wasm-lib
Note: buffer is required by @wasmer/wasi.
Write the code
import { load, invokeKCLRun } from "@kcl-lang/wasm-lib";
async function main() {
const inst = await load();
const result = invokeKCLRun(inst, {
filename: "test.k",
source: `
schema Person:
name: str
p = Person {name = "Alice"}`,
});
console.log(result);
}
main();
Here, we use webpack
to bundle the website, the webpack.config.js
config as follows.
Note: This configuration includes necessary settings for @wasmer/wasi and other required plugins.
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require("path");
const webpack = require("webpack");
const dist = path.resolve("./dist");
const isProduction = process.argv.some((x) => x === "--mode=production");
const hash = isProduction ? ".[contenthash]" : "";
module.exports = {
mode: "development",
entry: {
main: "./src/main.ts",
},
target: "web",
output: {
path: dist,
filename: `[name]${hash}.js`,
clean: true,
},
devServer: {
hot: true,
port: 9000,
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.m?js$/,
resourceQuery: { not: [/(raw|wasm)/] },
},
{
resourceQuery: /raw/,
type: "asset/source",
},
{
resourceQuery: /wasm/,
type: "asset/resource",
generator: {
filename: "wasm/[name][ext]",
},
},
],
},
plugins: [
new MiniCssExtractPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./src/index.html"),
}),
new webpack.IgnorePlugin({
resourceRegExp: /^(path|ws|crypto|fs|os|util|node-fetch)$/,
}),
// needed by @wasmer/wasi
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
}),
],
externals: {
// needed by @wasmer/wasi
"wasmer_wasi_js_bg.wasm": true,
},
resolve: {
fallback: {
// needed by @wasmer/wasi
buffer: require.resolve("buffer/"),
},
},
};
For a complete working example, refer to here.
Troubleshooting
If you encounter any issues, make sure:
- All dependencies are correctly installed.
- Your
webpack.config.js
is properly set up. - You're using a modern browser that supports WebAssembly.
- The KCL WASM module is correctly loaded and accessible.
Node.js
Install the dependency
npm install @kcl-lang/wasm-lib
Write the code
import { load, invokeKCLRun } from "@kcl-lang/wasm-lib";
async function main() {
const inst = await load();
const result = invokeKCLRun(inst, {
filename: "test.k",
source: `
schema Person:
name: str
p = Person {name = "Alice"}`,
});
console.log(result);
}
main();
The output is
p:
name: Alice
The code example can be found here.
Rust
In Rust, we use wasmtime
as an example, and of course, you can also use other runtime that supports WASI to accomplish this.
Install the dependency
cargo add kcl-wasm-lib --git https://github.com/kcl-lang/lib
cargo add anyhow
Write the code
use anyhow::Result;
use kcl_wasm_lib::{KCLModule, RunOptions};
fn main() -> Result<()> {
let opts = RunOptions {
filename: "test.k".to_string(),
source: "a = 1".to_string(),
};
// Note replace your KCL wasm module path.
let mut module = KCLModule::from_path("path/to/kcl.wasm")?;
let result = module.run(&opts)?;
println!("{}", result);
Ok(())
}
The output is
a: 1
The code example can be found here.
Go
In Go, we use wasmtime
as an example, and of course, you can also use other runtime that supports WASI to accomplish this.
Write the code, and the code of package github.com/kcl-lang/wasm-lib/pkg/module
can be found here
package main
import (
"fmt"
"github.com/kcl-lang/wasm-lib/pkg/module"
)
func main() {
m, err := module.New("path/to/kcl.wasm")
if err != nil {
panic(err)
}
result, err := m.Run(&module.RunOptions{
Filename: "test.k",
Source: "a = 1",
})
if err != nil {
panic(err)
}
fmt.Println(result)
}
The output is
a: 1
The code example can be found here.