mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
feat: Variable args (#1667)
* feat: Variable args * chore: Make the assert error message not wrong
This commit is contained in:
@@ -45,7 +45,10 @@ impl PathForVolumeId for Volumes {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct JsProcedure {}
|
pub struct JsProcedure {
|
||||||
|
#[serde(default)]
|
||||||
|
args: Vec<serde_json::Value>,
|
||||||
|
}
|
||||||
|
|
||||||
impl JsProcedure {
|
impl JsProcedure {
|
||||||
pub fn validate(&self, _volumes: &Volumes) -> Result<(), color_eyre::eyre::Report> {
|
pub fn validate(&self, _volumes: &Volumes) -> Result<(), color_eyre::eyre::Report> {
|
||||||
@@ -71,7 +74,7 @@ impl JsProcedure {
|
|||||||
Box::new(volumes.clone()),
|
Box::new(volumes.clone()),
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.run_action(name, input);
|
.run_action(name, input, self.args.clone());
|
||||||
let output: ErrorValue = match timeout {
|
let output: ErrorValue = match timeout {
|
||||||
Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action)
|
Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action)
|
||||||
.await
|
.await
|
||||||
@@ -105,7 +108,7 @@ impl JsProcedure {
|
|||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.read_only_effects()
|
.read_only_effects()
|
||||||
.run_action(name, input);
|
.run_action(name, input, self.args.clone());
|
||||||
let output: ErrorValue = match timeout {
|
let output: ErrorValue = match timeout {
|
||||||
Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action)
|
Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action)
|
||||||
.await
|
.await
|
||||||
@@ -145,7 +148,7 @@ fn unwrap_known_error<O: for<'de> Deserialize<'de>>(
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn js_action_execute() {
|
async fn js_action_execute() {
|
||||||
let js_action = JsProcedure {};
|
let js_action = JsProcedure { args: vec![] };
|
||||||
let path: PathBuf = "test/js_action_execute/"
|
let path: PathBuf = "test/js_action_execute/"
|
||||||
.parse::<PathBuf>()
|
.parse::<PathBuf>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -200,7 +203,7 @@ async fn js_action_execute() {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn js_action_execute_error() {
|
async fn js_action_execute_error() {
|
||||||
let js_action = JsProcedure {};
|
let js_action = JsProcedure { args: vec![] };
|
||||||
let path: PathBuf = "test/js_action_execute/"
|
let path: PathBuf = "test/js_action_execute/"
|
||||||
.parse::<PathBuf>()
|
.parse::<PathBuf>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -244,7 +247,52 @@ async fn js_action_execute_error() {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn js_action_fetch() {
|
async fn js_action_fetch() {
|
||||||
let js_action = JsProcedure {};
|
let js_action = JsProcedure { args: vec![] };
|
||||||
|
let path: PathBuf = "test/js_action_execute/"
|
||||||
|
.parse::<PathBuf>()
|
||||||
|
.unwrap()
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap();
|
||||||
|
let package_id = "test-package".parse().unwrap();
|
||||||
|
let package_version: Version = "0.3.0.3".parse().unwrap();
|
||||||
|
let name = ProcedureName::Action("fetch".parse().unwrap());
|
||||||
|
let volumes: Volumes = serde_json::from_value(serde_json::json!({
|
||||||
|
"main": {
|
||||||
|
"type": "data"
|
||||||
|
},
|
||||||
|
"compat": {
|
||||||
|
"type": "assets"
|
||||||
|
},
|
||||||
|
"filebrowser" :{
|
||||||
|
"package-id": "filebrowser",
|
||||||
|
"path": "data",
|
||||||
|
"readonly": true,
|
||||||
|
"type": "pointer",
|
||||||
|
"volume-id": "main",
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let input: Option<serde_json::Value> = None;
|
||||||
|
let timeout = Some(Duration::from_secs(10));
|
||||||
|
js_action
|
||||||
|
.execute::<serde_json::Value, serde_json::Value>(
|
||||||
|
&path,
|
||||||
|
&package_id,
|
||||||
|
&package_version,
|
||||||
|
name,
|
||||||
|
&volumes,
|
||||||
|
input,
|
||||||
|
timeout,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn js_action_var_arg() {
|
||||||
|
let js_action = JsProcedure {
|
||||||
|
args: vec![42.into()],
|
||||||
|
};
|
||||||
let path: PathBuf = "test/js_action_execute/"
|
let path: PathBuf = "test/js_action_execute/"
|
||||||
.parse::<PathBuf>()
|
.parse::<PathBuf>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -758,5 +758,18 @@ export const action = {
|
|||||||
qr: false,
|
qr: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetch(_effects, _input, testInput) {
|
||||||
|
|
||||||
|
assert(testInput == 42, "Input should be passed in");
|
||||||
|
return {
|
||||||
|
result: {
|
||||||
|
copyable: false,
|
||||||
|
message: "Done",
|
||||||
|
version: "0",
|
||||||
|
qr: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,7 @@ const fetch = async (url, options = null) => {
|
|||||||
|
|
||||||
const currentFunction = Deno.core.opSync("current_function");
|
const currentFunction = Deno.core.opSync("current_function");
|
||||||
const input = Deno.core.opSync("get_input");
|
const input = Deno.core.opSync("get_input");
|
||||||
|
const variable_args = Deno.core.opSync("get_variable_args");
|
||||||
const setState = (x) => Deno.core.opSync("set_value", x);
|
const setState = (x) => Deno.core.opSync("set_value", x);
|
||||||
const effects = {
|
const effects = {
|
||||||
writeFile,
|
writeFile,
|
||||||
@@ -93,6 +94,6 @@ const runFunction = jsonPointerValue(mainModule, currentFunction);
|
|||||||
error(`Expecting ${ currentFunction } to be a function`);
|
error(`Expecting ${ currentFunction } to be a function`);
|
||||||
throw new Error(`Expecting ${ currentFunction } to be a function`);
|
throw new Error(`Expecting ${ currentFunction } to be a function`);
|
||||||
}
|
}
|
||||||
const answer = await runFunction(effects, input);
|
const answer = await runFunction(effects, input, ...variable_args);
|
||||||
setState(answer);
|
setState(answer);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ struct JsContext {
|
|||||||
package_id: PackageId,
|
package_id: PackageId,
|
||||||
volumes: Arc<dyn PathForVolumeId>,
|
volumes: Arc<dyn PathForVolumeId>,
|
||||||
input: Value,
|
input: Value,
|
||||||
|
variable_args: Vec<serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
@@ -218,6 +219,7 @@ impl JsExecutionEnvironment {
|
|||||||
self,
|
self,
|
||||||
procedure_name: ProcedureName,
|
procedure_name: ProcedureName,
|
||||||
input: Option<I>,
|
input: Option<I>,
|
||||||
|
variable_args: Vec<serde_json::Value>,
|
||||||
) -> Result<O, (JsError, String)> {
|
) -> Result<O, (JsError, String)> {
|
||||||
let input = match serde_json::to_value(input) {
|
let input = match serde_json::to_value(input) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
@@ -231,7 +233,8 @@ impl JsExecutionEnvironment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let safer_handle: NonDetachingJoinHandle<_> =
|
let safer_handle: NonDetachingJoinHandle<_> =
|
||||||
tokio::task::spawn_blocking(move || self.execute(procedure_name, input)).into();
|
tokio::task::spawn_blocking(move || self.execute(procedure_name, input, variable_args))
|
||||||
|
.into();
|
||||||
let output = safer_handle
|
let output = safer_handle
|
||||||
.await
|
.await
|
||||||
.map_err(|err| (JsError::Tokio, format!("Tokio gave us the error: {}", err)))??;
|
.map_err(|err| (JsError::Tokio, format!("Tokio gave us the error: {}", err)))??;
|
||||||
@@ -266,6 +269,7 @@ impl JsExecutionEnvironment {
|
|||||||
fns::log_debug::decl(),
|
fns::log_debug::decl(),
|
||||||
fns::log_info::decl(),
|
fns::log_info::decl(),
|
||||||
fns::get_input::decl(),
|
fns::get_input::decl(),
|
||||||
|
fns::get_variable_args::decl(),
|
||||||
fns::set_value::decl(),
|
fns::set_value::decl(),
|
||||||
fns::is_sandboxed::decl(),
|
fns::is_sandboxed::decl(),
|
||||||
]
|
]
|
||||||
@@ -275,6 +279,7 @@ impl JsExecutionEnvironment {
|
|||||||
&self,
|
&self,
|
||||||
procedure_name: ProcedureName,
|
procedure_name: ProcedureName,
|
||||||
input: Value,
|
input: Value,
|
||||||
|
variable_args: Vec<serde_json::Value>,
|
||||||
) -> Result<Value, (JsError, String)> {
|
) -> Result<Value, (JsError, String)> {
|
||||||
let base_directory = self.base_directory.clone();
|
let base_directory = self.base_directory.clone();
|
||||||
let answer_state = AnswerState::default();
|
let answer_state = AnswerState::default();
|
||||||
@@ -287,6 +292,7 @@ impl JsExecutionEnvironment {
|
|||||||
version: self.version.clone(),
|
version: self.version.clone(),
|
||||||
sandboxed: self.sandboxed,
|
sandboxed: self.sandboxed,
|
||||||
input,
|
input,
|
||||||
|
variable_args,
|
||||||
};
|
};
|
||||||
let ext = Extension::builder()
|
let ext = Extension::builder()
|
||||||
.ops(Self::declarations())
|
.ops(Self::declarations())
|
||||||
@@ -675,6 +681,11 @@ mod fns {
|
|||||||
Ok(ctx.input.clone())
|
Ok(ctx.input.clone())
|
||||||
}
|
}
|
||||||
#[op]
|
#[op]
|
||||||
|
fn get_variable_args(state: &mut OpState) -> Result<Vec<Value>, AnyError> {
|
||||||
|
let ctx = state.borrow::<JsContext>();
|
||||||
|
Ok(ctx.variable_args.clone())
|
||||||
|
}
|
||||||
|
#[op]
|
||||||
fn set_value(state: &mut OpState, value: Value) -> Result<(), AnyError> {
|
fn set_value(state: &mut OpState, value: Value) -> Result<(), AnyError> {
|
||||||
let mut answer = state.borrow::<AnswerState>().0.lock();
|
let mut answer = state.borrow::<AnswerState>().0.lock();
|
||||||
*answer = value;
|
*answer = value;
|
||||||
|
|||||||
Reference in New Issue
Block a user