Update bindings to include newer APIs (#250)

- c, cpp
- csharp
- ffi
- go
- Java
- Python
- WASM

`arc` feature is turned on for all bindings
Use pretty string instead of colored string.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2024-05-25 13:24:06 -04:00
committed by GitHub
parent 33fe9d5039
commit d09c445add
41 changed files with 1175 additions and 565 deletions
+4 -1
View File
@@ -10,8 +10,11 @@ keywords = ["interpreter", "opa", "policy-as-code", "rego"]
[lib]
crate-type = ["cdylib"]
[features]
default = ["regorus/std", "regorus/full-opa"]
[dependencies]
regorus = { path = "../.." }
regorus = { path = "../..", default-features = false, features = ["arc"] }
serde_json = "1.0.111"
wasm-bindgen = "0.2.90"
+2 -64
View File
@@ -10,72 +10,10 @@
See [Repository](https://github.com/microsoft/regorus).
To build this binding, see [building](https://github.com/microsoft/regorus/bindings/wasm/building.md)
To build this binding, see [building.md](https://github.com/microsoft/regorus/blob/main/bindings/wasm/building.md)
## Usage
```javascript
var regorus = require('regorusjs')
// Create an engine.
var engine = new regorus.Engine();
// Add Rego policy.
engine.add_policy(
// Associate this file name with policy
'hello.rego',
// Rego policy
`
package test
# Join messages
message = concat(", ", [input.message, data.message])
`)
// Set policy data
engine.add_data_json(`
{
"message" : "World!"
}
`)
// Set policy input
engine.set_input_json(`
{
"message" : "Hello"
}
`)
// Eval query
results = engine.eval_query('data.test.message')
// Display
console.log(results)
// {
// "result": [
// {
// "expressions": [
// {
// "value": "Hello, World!",
// "text": "data.test.message",
// "location": {
// "row": 1,
// "col": 1
// }
// }
// ]
// }
// ]
// }
// Convert results to object
results = JSON.parse(results)
// Process result
console.log(results.result[0].expressions[0].value)
// Hello, World!
```
See [test.js](https://github.com/microsoft/regorus/blob/main/bindings/wasm/test.js) for example usage.
+114 -9
View File
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#![allow(non_snake_case)]
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
@@ -50,7 +52,7 @@ impl Engine {
///
/// * `path`: A filename to be associated with the policy.
/// * `rego`: Rego policy.
pub fn add_policy(&mut self, path: String, rego: String) -> Result<String, JsValue> {
pub fn addPolicy(&mut self, path: String, rego: String) -> Result<String, JsValue> {
self.engine.add_policy(path, rego).map_err(error_to_jsvalue)
}
@@ -58,15 +60,22 @@ impl Engine {
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data
/// * `data`: JSON encoded value to be used as policy data.
pub fn add_data_json(&mut self, data: String) -> Result<(), JsValue> {
pub fn addDataJson(&mut self, data: String) -> Result<(), JsValue> {
let data = regorus::Value::from_json_str(&data).map_err(error_to_jsvalue)?;
self.engine.add_data(data).map_err(error_to_jsvalue)
}
/// Get the list of packages defined by loaded policies.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_packages
pub fn getPackages(&self) -> Result<Vec<String>, JsValue> {
self.engine.get_packages().map_err(error_to_jsvalue)
}
/// Clear policy data.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data
pub fn clear_data(&mut self) -> Result<(), JsValue> {
pub fn clearData(&mut self) -> Result<(), JsValue> {
self.engine.clear_data();
Ok(())
}
@@ -75,7 +84,7 @@ impl Engine {
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_input
/// * `input`: JSON encoded value to be used as input to query.
pub fn set_input_json(&mut self, input: String) -> Result<(), JsValue> {
pub fn setInputJson(&mut self, input: String) -> Result<(), JsValue> {
let input = regorus::Value::from_json_str(&input).map_err(error_to_jsvalue)?;
self.engine.set_input(input);
Ok(())
@@ -85,13 +94,75 @@ impl Engine {
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_query
/// * `query`: Rego expression to be evaluate.
pub fn eval_query(&mut self, query: String) -> Result<String, JsValue> {
pub fn evalQuery(&mut self, query: String) -> Result<String, JsValue> {
let results = self
.engine
.eval_query(query, false)
.map_err(error_to_jsvalue)?;
serde_json::to_string_pretty(&results).map_err(error_to_jsvalue)
}
/// Evaluate rule(s) at given path.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_rule
///
/// * `path`: The full path to the rule(s).
pub fn evalRule(&mut self, path: String) -> Result<String, JsValue> {
let v = self.engine.eval_rule(path).map_err(error_to_jsvalue)?;
v.to_json_str().map_err(error_to_jsvalue)
}
/// Gather output from print statements instead of emiting to stderr.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_gather_prints
/// * `b`: Whether to enable gathering prints or not.
pub fn setGatherPrints(&mut self, b: bool) {
self.engine.set_gather_prints(b)
}
/// Take the gathered output of print statements.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.take_prints
pub fn takePrints(&mut self) -> Result<Vec<String>, JsValue> {
self.engine.take_prints().map_err(error_to_jsvalue)
}
/// Enable/disable policy coverage.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_enable_coverage
/// * `b`: Whether to enable gathering coverage or not.
pub fn setEnableCoverage(&mut self, enable: bool) {
self.engine.set_enable_coverage(enable)
}
/// Get the coverage report as json.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_coverage_report
pub fn getCoverageReport(&self) -> Result<String, JsValue> {
let report = self
.engine
.get_coverage_report()
.map_err(error_to_jsvalue)?;
serde_json::to_string_pretty(&report).map_err(error_to_jsvalue)
}
/// Clear gathered coverage data.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_coverage_data
pub fn clearCoverageData(&mut self) {
self.engine.clear_coverage_data()
}
/// Get ANSI color coded coverage report.
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Report.html#method.to_string_pretty
pub fn getCoverageReportPretty(&self) -> Result<String, JsValue> {
let report = self
.engine
.get_coverage_report()
.map_err(error_to_jsvalue)?;
report.to_string_pretty().map_err(error_to_jsvalue)
}
}
#[cfg(test)]
@@ -102,9 +173,10 @@ mod tests {
#[wasm_bindgen_test]
pub fn basic() -> Result<(), JsValue> {
let mut engine = crate::Engine::new();
engine.setEnableCoverage(true);
// Exercise all APIs.
engine.add_data_json(
engine.addDataJson(
r#"
{
"foo" : "bar"
@@ -113,7 +185,7 @@ mod tests {
.to_string(),
)?;
engine.set_input_json(
engine.setInputJson(
r#"
{
"message" : "Hello"
@@ -122,15 +194,16 @@ mod tests {
.to_string(),
)?;
engine.add_policy(
let pkg = engine.addPolicy(
"hello.rego".to_string(),
r#"
package test
message = input.message"#
.to_string(),
)?;
assert_eq!(pkg, "data.test");
let results = engine.eval_query("data".to_string())?;
let results = engine.evalQuery("data".to_string())?;
let r = regorus::Value::from_json_str(&results).map_err(crate::error_to_jsvalue)?;
let v = &r["result"][0]["expressions"][0]["value"];
@@ -141,6 +214,38 @@ mod tests {
// Test that data was set.
assert_eq!(v["foo"], regorus::Value::from("bar"));
// Use eval_rule to perform same query.
let v = engine.evalRule("data.test.message".to_owned())?;
let v = regorus::Value::from_json_str(&v).map_err(crate::error_to_jsvalue)?;
// Ensure that input and policy were evaluated.
assert_eq!(v, regorus::Value::from("Hello"));
let pkgs = engine.getPackages()?;
assert_eq!(pkgs, vec!["data.test"]);
engine.setGatherPrints(true);
let _ = engine.evalQuery("print(\"Hello\")".to_owned());
let prints = engine.takePrints()?;
assert_eq!(prints, vec!["<query.rego>:1: Hello"]);
// Test clone.
let mut engine1 = engine.clone();
// Test code coverage.
let report = engine1.getCoverageReport()?;
let r = regorus::Value::from_json_str(&report).map_err(crate::error_to_jsvalue)?;
assert_eq!(
r["files"][0]["covered"]
.as_array()
.map_err(crate::error_to_jsvalue)?,
&vec![regorus::Value::from(3)]
);
println!("{}", engine1.getCoverageReportPretty()?);
engine1.clearCoverageData();
Ok(())
}
}
+52 -13
View File
@@ -1,48 +1,87 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var regorus = require('./pkg/regorusjs')
var regorus = require('./pkg/regorusjs');
// Create an engine.
var engine = new regorus.Engine();
// Enable code coverage
engine.setEnableCoverage(true);
// Add Rego policy.
var pkg = engine.add_policy(
var pkg = engine.addPolicy(
// Associate this file name with policy
'hello.rego',
// Rego policy
`
package test
x = 10
# Join messages
message = concat(", ", [input.message, data.message])
`)
console.log("Loaded policy " + pkg)
`);
console.log(pkg);
// data.test
// Set policy data
engine.add_data_json(`
engine.addDataJson(`
{
"message" : "World!"
}
`)
`);
// Set policy input
engine.set_input_json(`
engine.setInputJson(`
{
"message" : "Hello"
}
`)
`);
// Eval rule as json
var value = engine.evalRule('data.test.message');
value = JSON.parse(value);
// Display value
console.log(value);
// Hello, World!
// Eval query
var results = engine.eval_query('data.test.message')
results = engine.evalQuery('data.test.message');
// Display
console.log(results)
console.log(results);
// {
// "result": [
// {
// "expressions": [
// {
// "value": "Hello, World!",
// "text": "data.test.message",
// "location": {
// "row": 1,
// "col": 1
// }
// }
// ]
// }
// ]
// }
// Convert results to object
results = JSON.parse(results)
results = JSON.parse(results);
// Process result
console.log(results.result[0].expressions[0].value)
console.log(results.result[0].expressions[0].value);
// Hello, World!
// Print coverage report
report = engine.getCoverageReport();
console.log(report);
// Print pretty report.
report = engine.getCoverageReportPretty();
console.log(report);