From bb1f86d0ecb0aa05219d4457b9085c3c25ca2781 Mon Sep 17 00:00:00 2001 From: Duy Do Date: Thu, 30 Nov 2023 14:32:14 +0700 Subject: [PATCH] Patch (#20) --- .../node-definitions/postgrest/new_rpc.json | 105 ++++++++++++++++++ crates/cmds-std/src/postgrest/mod.rs | 1 + crates/cmds-std/src/postgrest/new_rpc.rs | 48 ++++++++ crates/flow/src/command/rhai.rs | 18 ++- lib/flow-lib/src/config/client.rs | 41 ++++--- 5 files changed, 194 insertions(+), 19 deletions(-) create mode 100644 crates/cmds-std/node-definitions/postgrest/new_rpc.json create mode 100644 crates/cmds-std/src/postgrest/new_rpc.rs diff --git a/crates/cmds-std/node-definitions/postgrest/new_rpc.json b/crates/cmds-std/node-definitions/postgrest/new_rpc.json new file mode 100644 index 00000000..d33e778c --- /dev/null +++ b/crates/cmds-std/node-definitions/postgrest/new_rpc.json @@ -0,0 +1,105 @@ +{ + "type": "native", + "data": { + "node_definition_version": "0.1", + "unique_id": "", + "node_id": "postgrest_new_rpc", + "version": "0.1", + "display_name": "New RPC", + "description": "https://docs.rs/postgrest/latest/postgrest/struct.Postgrest.html#method.rpc", + "tags": ["database", "postgrest", "supabase"], + "related_to": [ + { + "id": "", + "type": "", + "relationship": "" + } + ], + "resources": { + "source_code_url": "", + "documentation_url": "" + }, + "usage": { + "license": "Apache-2.0", + "license_url": "", + "pricing": { + "currency": "USDC", + "purchase_price": 0, + "price_per_run": 0, + "custom": { + "unit": "monthly", + "value": "0" + } + } + }, + "authors": [ + { + "name": "Space Operator", + "contact": "" + } + ], + "design": { + "width": 0, + "height": 0, + "icon_url": "", + "backgroundColorDark": "#000000", + "backgroundColor": "#fff" + }, + "options": {} + }, + "targets": [ + { + "name": "url", + "type_bounds": ["string"], + "required": false, + "defaultValue": "https://base.spaceoperator.com/rest/v1/", + "tooltip": "", + "passthrough": false + }, + { + "name": "schema", + "type_bounds": ["string"], + "required": false, + "defaultValue": "public", + "tooltip": "", + "passthrough": false + }, + { + "name": "function", + "type_bounds": ["string"], + "required": true, + "defaultValue": null, + "tooltip": "", + "passthrough": false + }, + { + "name": "params", + "type_bounds": ["free"], + "required": true, + "defaultValue": null, + "tooltip": "", + "passthrough": false + } + ], + "sources": [ + { + "name": "quey", + "type": "object", + "defaultValue": "", + "tooltip": "" + } + ], + "targets_form.json_schema": { + "type": "object", + "title": "New RPC", + "properties": { + "table": { + "title": "table", + "type": "string" + } + } + }, + "targets_form.ui_schema": { + "ui:order": ["table"] + } +} diff --git a/crates/cmds-std/src/postgrest/mod.rs b/crates/cmds-std/src/postgrest/mod.rs index be140659..06ee5e90 100644 --- a/crates/cmds-std/src/postgrest/mod.rs +++ b/crates/cmds-std/src/postgrest/mod.rs @@ -6,3 +6,4 @@ pub mod builder_select; pub mod builder_update; pub mod execute_query; pub mod new_query; +pub mod new_rpc; diff --git a/crates/cmds-std/src/postgrest/new_rpc.rs b/crates/cmds-std/src/postgrest/new_rpc.rs new file mode 100644 index 00000000..8f4479a2 --- /dev/null +++ b/crates/cmds-std/src/postgrest/new_rpc.rs @@ -0,0 +1,48 @@ +use flow_lib::command::prelude::*; + +const NAME: &str = "postgrest_new_rpc"; + +#[derive(Deserialize, Debug)] +struct Input { + url: Option, + schema: Option, + function: String, + params: JsonValue, +} + +#[derive(Serialize, Debug)] +struct Output { + query: postgrest::Builder, +} + +async fn run(ctx: Context, input: Input) -> Result { + let url = input + .url + .unwrap_or_else(|| format!("{}/rest/v1", ctx.endpoints.supabase)); + let mut pg = postgrest::Postgrest::new(url); + if let Some(schema) = input.schema { + pg = pg.schema(schema); + } + let query = pg.rpc(input.function, serde_json::to_string(&input.params)?); + Ok(Output { query }) +} + +fn build() -> BuildResult { + Ok( + CmdBuilder::new(flow_lib::node_definition!("postgrest/new_rpc.json"))? + .check_name(NAME)? + .build(run), + ) +} + +flow_lib::submit!(CommandDescription::new(NAME, |_| build())); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_build() { + build().unwrap(); + } +} diff --git a/crates/flow/src/command/rhai.rs b/crates/flow/src/command/rhai.rs index 614073c1..c4edf125 100644 --- a/crates/flow/src/command/rhai.rs +++ b/crates/flow/src/command/rhai.rs @@ -23,11 +23,8 @@ impl CommandTrait for Command { } async fn run(&self, ctx: Context, input: ValueSet) -> Result { - let registry = ctx - .get::() - .ok_or_else(|| anyhow::anyhow!("FlowRegistry not found"))?; - // TODO: stop token - registry + ctx.get::() + .ok_or_else(|| anyhow::anyhow!("FlowRegistry not found"))? .run_rhai(run_rhai::Request { command: self.inner.clone(), ctx: ctx.clone(), @@ -39,7 +36,16 @@ impl CommandTrait for Command { pub fn build(nd: &NodeData) -> Result, CommandError> { let inputs: Vec = nd.targets.iter().cloned().map(Into::into).collect(); - let outputs: Vec = nd.sources.iter().cloned().map(Into::into).collect(); + let outputs: Vec = nd + .sources + .iter() + .cloned() + .map(|s| Output { + // TODO: we did not upload this field to db + optional: true, + ..Output::from(s) + }) + .collect(); let source_code_name = inputs .get(0) .ok_or_else(|| CommandError::msg("no source code input"))? diff --git a/lib/flow-lib/src/config/client.rs b/lib/flow-lib/src/config/client.rs index 79a0deda..bc061a39 100644 --- a/lib/flow-lib/src/config/client.rs +++ b/lib/flow-lib/src/config/client.rs @@ -145,12 +145,19 @@ pub struct Source { pub optional: bool, } -impl Into for Source { - fn into(self) -> CmdOutputDescription { - CmdOutputDescription { - name: self.name, - r#type: self.r#type, - optional: self.optional, +impl From for CmdOutputDescription { + fn from( + Source { + name, + r#type, + optional, + .. + }: Source, + ) -> Self { + Self { + name, + r#type, + optional, } } } @@ -164,13 +171,21 @@ pub struct Target { pub passthrough: bool, } -impl Into for Target { - fn into(self) -> CmdInputDescription { - CmdInputDescription { - name: self.name, - type_bounds: self.type_bounds, - required: self.required, - passthrough: self.passthrough, +impl From for CmdInputDescription { + fn from( + Target { + name, + type_bounds, + required, + passthrough, + .. + }: Target, + ) -> Self { + Self { + name, + type_bounds, + required, + passthrough, } } }