diff --git a/src-tauri/.sqlx/query-fe0652396bc30d926cf99083651c1cbd668bcf00ebe1a5f36616700c84972b39.json b/src-tauri/.sqlx/query-fe0652396bc30d926cf99083651c1cbd668bcf00ebe1a5f36616700c84972b39.json new file mode 100644 index 00000000..a009d61a --- /dev/null +++ b/src-tauri/.sqlx/query-fe0652396bc30d926cf99083651c1cbd668bcf00ebe1a5f36616700c84972b39.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n DELETE FROM grpc_requests\n WHERE id = ?\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "fe0652396bc30d926cf99083651c1cbd668bcf00ebe1a5f36616700c84972b39" +} diff --git a/src-tauri/grpc/src/json_schema.rs b/src-tauri/grpc/src/json_schema.rs index 4a6bb643..b915c6c0 100644 --- a/src-tauri/grpc/src/json_schema.rs +++ b/src-tauri/grpc/src/json_schema.rs @@ -143,12 +143,14 @@ pub fn message_to_json_schema( schema.properties = Some(properties); - schema.required = Some( - message - .fields() - .map(|f| f.name().to_string()) - .collect::>(), - ); + // All proto 3 fields are optional, so maybe we could + // make this a setting? + // schema.required = Some( + // message + // .fields() + // .map(|f| f.name().to_string()) + // .collect::>(), + // ); schema } diff --git a/src-tauri/grpc/src/lib.rs b/src-tauri/grpc/src/lib.rs index c2edc20e..8bb10da9 100644 --- a/src-tauri/grpc/src/lib.rs +++ b/src-tauri/grpc/src/lib.rs @@ -1,4 +1,4 @@ -use prost_reflect::SerializeOptions; +use prost_reflect::{DynamicMessage, SerializeOptions}; use serde::{Deserialize, Serialize}; mod codec; @@ -25,3 +25,16 @@ pub struct MethodDefinition { pub client_streaming: bool, pub server_streaming: bool, } + +static SERIALIZE_OPTIONS: &'static SerializeOptions = &SerializeOptions::new() + .skip_default_fields(false) + .stringify_64_bit_integers(false); + +pub fn serialize_message(msg: &DynamicMessage) -> Result { + let mut buf = Vec::new(); + let mut se = serde_json::Serializer::pretty(&mut buf); + msg.serialize_with_options(&mut se, SERIALIZE_OPTIONS) + .map_err(|e| e.to_string())?; + let s = String::from_utf8(buf).expect("serde_json to emit valid utf8"); + Ok(s) +} diff --git a/src-tauri/grpc/src/manager.rs b/src-tauri/grpc/src/manager.rs index 614cff3c..e6c8fce6 100644 --- a/src-tauri/grpc/src/manager.rs +++ b/src-tauri/grpc/src/manager.rs @@ -30,7 +30,7 @@ impl GrpcConnection { service: &str, method: &str, message: &str, - ) -> Result { + ) -> Result { let service = self.pool.get_service_by_name(service).unwrap(); let method = &service.methods().find(|m| m.name() == method).unwrap(); let input_message = method.input(); @@ -47,11 +47,11 @@ impl GrpcConnection { let codec = DynamicCodec::new(method.clone()); client.ready().await.unwrap(); - let resp = client.unary(req, path, codec).await.unwrap(); - let msg = resp.into_inner(); - let response_json = serde_json::to_string_pretty(&msg).expect("json to string"); - - Ok(response_json) + Ok(client + .unary(req, path, codec) + .await + .map_err(|e| e.to_string())? + .into_inner()) } pub async fn streaming( diff --git a/src-tauri/grpc/src/proto.rs b/src-tauri/grpc/src/proto.rs index 5fde08d4..7219c93e 100644 --- a/src-tauri/grpc/src/proto.rs +++ b/src-tauri/grpc/src/proto.rs @@ -45,6 +45,7 @@ pub async fn fill_pool_from_files(paths: Vec) -> Result { - let item = serde_json::to_string_pretty(&item).unwrap(); + let item = serialize_message(&item).unwrap(); let req = req.clone(); let conn = conn.clone(); upsert_grpc_message( @@ -591,7 +591,6 @@ async fn cmd_grpc_streaming( }, ) .await - .map_err(|e| e.to_string()) .unwrap(); } Some(Err(e)) => { @@ -727,7 +726,7 @@ async fn cmd_grpc_server_streaming( .await? .server_streaming(&service, &method, &req.message) .await - .unwrap(); + .expect("FAILED"); #[derive(serde::Deserialize)] enum IncomingMsg { @@ -768,7 +767,7 @@ async fn cmd_grpc_server_streaming( let app_handle = app_handle.clone(); match stream.next().await { Some(Ok(item)) => { - let item = serde_json::to_string_pretty(&item).unwrap(); + let item = serialize_message(&item).unwrap(); upsert_grpc_message( &app_handle, &GrpcMessage { diff --git a/src-web/components/core/JsonAttributeTree.tsx b/src-web/components/core/JsonAttributeTree.tsx index e0deacfa..08ef46c8 100644 --- a/src-web/components/core/JsonAttributeTree.tsx +++ b/src-web/components/core/JsonAttributeTree.tsx @@ -13,7 +13,7 @@ interface Props { export const JsonAttributeTree = ({ depth = 0, attrKey, attrValue, attrKeyJsonPath }: Props) => { attrKeyJsonPath = attrKeyJsonPath ?? `${attrKey}`; - const [isExpanded, setIsExpanded] = useState(depth === 0); + const [isExpanded, setIsExpanded] = useState(true); const toggleExpanded = () => setIsExpanded((v) => !v); const { isExpandable, children, label, labelClassName } = useMemo<{ @@ -78,7 +78,7 @@ export const JsonAttributeTree = ({ depth = 0, attrKey, attrValue, attrKeyJsonPa ); return ( -
+
{isExpandable ? (