Skip to content

Commit

Permalink
add wasi modules for jsonnet with external vars
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul007-bit committed Jan 18, 2024
1 parent 400ce2a commit d2e2465
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 108 deletions.
4 changes: 3 additions & 1 deletion JS/wasm/assets/wasmjs/wit/http.wit
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use * from http-types
send-http-request: func(request: http-request) -> expected<http-response, http-request-error>
parse-jsonnet: func(file: string) -> expected<string, file-error>
jsonnet: func(file: string) -> expected<string, file-error>
jsonnet-ext-var: func(name: string, value: string) -> expected<string, file-error>

read-bytes: func(file: string) -> expected<string, file-error>
6 changes: 3 additions & 3 deletions JS/wasm/crates/wasmjs-engine/shims/src/arakoo-jsonnet.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const parseJsonnet = globalThis.parseJsonnet;

export { parseJsonnet };
const jsonnet = globalThis.jsonnet;
const jsonnetExtVars = globalThis.jsonnetExtVars;
export { jsonnet, jsonnetExtVars };
50 changes: 40 additions & 10 deletions JS/wasm/crates/wasmjs-engine/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,11 @@ pub fn load_bindings(context: &JSContextRef, global: JSValueRef) -> Result<(), R

global
.set_property(
"parseJsonnet",
"jsonnet",
context
.wrap_callback(|_ctx, _this_arg, args| {
let path = args[0].to_string();
match parse_jsonnet(path.as_str()) {
match jsonnet(path.as_str()) {
Ok(result) => Ok(JSValue::String(result)),
Err(err) => {
let kind = match err {
Expand All @@ -188,6 +188,36 @@ pub fn load_bindings(context: &JSContextRef, global: JSValueRef) -> Result<(), R
.map_err(|_| RuntimeError::InvalidBinding {
invalid_export: "parseJsonnet".to_string(),
})?;

global
.set_property(
"jsonnetExtVars",
context
.wrap_callback(|_ctx, _this_arg, args| {
let path = args[0].to_string();
let ext_var = args[1].to_string();
match jsonnet_ext_var(path.as_str(), ext_var.as_str()) {
Ok(result) => Ok(JSValue::String(result)),
Err(err) => {
let kind = match err {
FileError::NotFound => "File not found".to_string(),
FileError::InvalidPath => "Not allowed".to_string(),
};
Ok(JSValue::from_hashmap(HashMap::from([
("error", JSValue::Bool(true)),
("type", JSValue::String(kind)),
])))
}
}
})
.map_err(|_| RuntimeError::InvalidBinding {
invalid_export: "parseJsonnet".to_string(),
})?,
)
.map_err(|_| RuntimeError::InvalidBinding {
invalid_export: "parseJsonnet".to_string(),
})?;

Ok(())
}

Expand Down Expand Up @@ -227,19 +257,19 @@ fn main() {
let global = context.global_object().unwrap();
match load_bindings(context, global) {
Ok(_) => {}
Err(e) => {
match e {
RuntimeError::InvalidBinding { invalid_export } => {
eprintln!("There was an error adding the '{invalid_export}' binding");
}
Err(e) => match e {
RuntimeError::InvalidBinding { invalid_export } => {
eprintln!("There was an error adding the '{invalid_export}' binding");
}
}
},
}

context.eval_module("buffer", &buffer).unwrap();
context.eval_module("crypto", &crypto).unwrap();
context.eval_module("arakoo-jsonnet", &ARAKOOJSONNET).unwrap();

context
.eval_module("arakoo-jsonnet", &ARAKOOJSONNET)
.unwrap();

match context.eval_module("path", &path) {
Ok(_) => {}
Err(err) => eprintln!("Error loading the path shim: {err}"),
Expand Down
Binary file modified JS/wasm/crates/wasmjs-engine/wasmjs-engine.wasm
Binary file not shown.
66 changes: 51 additions & 15 deletions JS/wasm/crates/wasmjs-runtime/src/bindings.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::collections::HashMap;

use crate::error::Error;
use actix_web::http::Uri;
use jsonnet::JsonnetVm;
use reqwest::Method;
use serde::Deserialize;
use serde_json::Value;
use tokio::runtime::Builder;
use wiggle::GuestErrorType;
use crate::error::Error;

wit_bindgen_wasmtime::export!({paths: ["../../assets/wasmjs/wit/http.wit",],
async:[]
Expand All @@ -16,13 +19,16 @@ wiggle::from_witx!({
errors: { arakoo_status => Error },
});

impl GuestErrorType for ArakooStatus {
impl GuestErrorType for ArakooStatus {
fn success() -> Self {
ArakooStatus::Ok
}
}

use self::{http::{Http, HttpRequest, HttpRequestError, HttpResponse, HttpError, HttpMethod, FileError}, types::ArakooStatus};
use self::{
http::{FileError, Http, HttpError, HttpMethod, HttpRequest, HttpRequestError, HttpResponse},
types::ArakooStatus,
};

#[derive(Deserialize, Clone)]
#[serde(default)]
Expand Down Expand Up @@ -205,15 +211,12 @@ impl Http for HttpBindings {
.block_on(async {
let bytes = tokio::fs::read(path).await;
match bytes {
Ok(bytes) =>
Ok(std::str::from_utf8(&bytes).unwrap().to_string()),
Err(_) => {
Err(FileError::NotFound)
}
Ok(bytes) => Ok(std::str::from_utf8(&bytes).unwrap().to_string()),
Err(_) => Err(FileError::NotFound),
}
})
})
.join();
.join();

match thread_result {
Ok(res) => match res {
Expand All @@ -224,14 +227,47 @@ impl Http for HttpBindings {
}
}

fn jsonnet(&mut self, file: &str) -> Result<String, FileError> {
jsonnet(file)
}

fn parse_jsonnet(&mut self, file: &str) -> Result<String, FileError> {
parse_jsonnet(file)
fn jsonnet_ext_var(&mut self, file: &str, ext_var: &str) -> Result<String, FileError> {
let file = file.to_owned();
let ext_var = ext_var.to_owned();
let thread_result = std::thread::spawn(move || {
Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(async {
let mut vm = JsonnetVm::new();
let ext_var_str = ext_var.as_str();
let ext_vars: HashMap<&str, Value> = serde_json::from_str(ext_var_str).unwrap();
for (key, value) in ext_vars {
vm.ext_var(key, value.as_str().unwrap());
}
let json = vm.evaluate_file(&file);
match json {
Ok(json) => Ok(json.to_string()),
Err(e) => {
println!("Error: {}", e);
Err(FileError::NotFound)
}
}
})
})
.join();
match thread_result {
Ok(res) => match res {
Ok(res) => Ok(res),
Err(err) => Err(err),
},
Err(_) => Err(FileError::NotFound),
}
}
}


pub fn parse_jsonnet(file: &str) -> Result<String, FileError> {
pub fn jsonnet(file: &str) -> Result<String, FileError> {
let file = file.to_owned();
let thread_result = std::thread::spawn(move || {
Builder::new_current_thread()
Expand All @@ -247,11 +283,11 @@ pub fn parse_jsonnet(file: &str) -> Result<String, FileError> {
Err(e) => {
println!("Error: {}", e);
Err(FileError::NotFound)
},
}
}
})
})
.join();
.join();

match thread_result {
Ok(res) => match res {
Expand Down
6 changes: 6 additions & 0 deletions JS/wasm/crates/wasmjs-runtime/test-vars.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
local var1 = std.extVar("var1");

{
var: var1,
}

48 changes: 33 additions & 15 deletions JS/wasm/examples/ec-wasmjs-hono/src/index.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,62 @@
import { Hono } from "hono";
import { connect } from "@planetscale/database";
import { parseJsonnet } from "arakoo-jsonnet"
import { jsonnet, jsonnetExtVars } from "arakoo-jsonnet";

const app = new Hono();

app.get("/", (c) => {
const geo = c.req.raw.geo;
return c.text(`Your from ${geo.city}, ${geo.country_name}!`);
const geo = c.req.raw.geo;
return c.text(`Your from ${geo.city}, ${geo.country_name}!`);
});

app.get("/jsonnet", async (c) => {
const jsonnet = await parseJsonnet('test.jsonnet')
return c.json(JSON.parse(jsonnet));
try {
const result = await jsonnet("test.jsonnet");
return c.json(JSON.parse(result));
} catch (error) {
console.log(JSON.stringify(error));
c.text(error);
}
});

app.get("/vars", async (c) => {
try {
const extVars = JSON.stringify({
var1: "value1",
});
const result = await jsonnetExtVars("test-vars.jsonnet", extVars);
return c.json(JSON.parse(result));
} catch (error) {
console.log(JSON.stringify(error));
c.text(error);
}
});

app.get("/hello/:name", async (c) => {
const name = c.req.param("name");
return c.text(`Async Hello ${name}!`);
const name = c.req.param("name");
return c.text(`Async Hello ${name}!`);
});

app.get("/env/:key", async (c) => {
const key = c.req.param("key");
return c.text(env[key]);
const key = c.req.param("key");
return c.text(env[key]);
});

const config = {
host: env["PLANETSCALE_HOST"],
username: env["PLANETSCALE_USERNAME"],
password: env["PLANETSCALE_PASSWORD"],
host: env["PLANETSCALE_HOST"],
username: env["PLANETSCALE_USERNAME"],
password: env["PLANETSCALE_PASSWORD"],
};
const conn = connect(config);

app.get("/db", async (c) => {
const result = await conn.execute("SHOW TABLES");
const result = await conn.execute("SHOW TABLES");

return c.json(result);
return c.json(result);
});

app.notFound((c) => {
return c.text("404 not found", 404);
return c.text("404 not found", 404);
});

export default app;
1 change: 0 additions & 1 deletion JS/wasm/types/jsonnet/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
target
index.node
**/node_modules
**/.DS_Store
npm-debug.log*
Expand Down
Loading

0 comments on commit d2e2465

Please sign in to comment.