// src/services/grpc_client.rs use common::proto::multieko2::common::Empty; use common::proto::multieko2::table_structure::table_structure_service_client::TableStructureServiceClient; use common::proto::multieko2::table_structure::{GetTableStructureRequest, TableStructureResponse}; use common::proto::multieko2::table_definition::{ table_definition_client::TableDefinitionClient, PostTableDefinitionRequest, ProfileTreeResponse, TableDefinitionResponse, }; use common::proto::multieko2::table_script::{ table_script_client::TableScriptClient, PostTableScriptRequest, TableScriptResponse, }; use common::proto::multieko2::tables_data::{ tables_data_client::TablesDataClient, GetTableDataByPositionRequest, GetTableDataResponse, GetTableDataCountRequest, PostTableDataRequest, PostTableDataResponse, PutTableDataRequest, PutTableDataResponse, }; use common::proto::multieko2::search::{ searcher_client::SearcherClient, SearchRequest, SearchResponse, }; use anyhow::{Context, Result}; use std::collections::HashMap; use tonic::transport::Channel; use prost_types::Value; #[derive(Clone)] pub struct GrpcClient { table_structure_client: TableStructureServiceClient, table_definition_client: TableDefinitionClient, table_script_client: TableScriptClient, tables_data_client: TablesDataClient, search_client: SearcherClient, } impl GrpcClient { pub async fn new() -> Result { let channel = Channel::from_static("http://[::1]:50051") .connect() .await .context("Failed to create gRPC channel")?; let table_structure_client = TableStructureServiceClient::new(channel.clone()); let table_definition_client = TableDefinitionClient::new(channel.clone()); let table_script_client = TableScriptClient::new(channel.clone()); let tables_data_client = TablesDataClient::new(channel.clone()); let search_client = SearcherClient::new(channel.clone()); Ok(Self { table_structure_client, table_definition_client, table_script_client, tables_data_client, search_client, }) } pub async fn get_table_structure( &mut self, profile_name: String, table_name: String, ) -> Result { let grpc_request = GetTableStructureRequest { profile_name, table_name, }; let request = tonic::Request::new(grpc_request); let response = self .table_structure_client .get_table_structure(request) .await .context("gRPC GetTableStructure call failed")?; Ok(response.into_inner()) } pub async fn get_profile_tree( &mut self, ) -> Result { let request = tonic::Request::new(Empty::default()); let response = self .table_definition_client .get_profile_tree(request) .await .context("gRPC GetProfileTree call failed")?; Ok(response.into_inner()) } pub async fn post_table_definition( &mut self, request: PostTableDefinitionRequest, ) -> Result { let tonic_request = tonic::Request::new(request); let response = self .table_definition_client .post_table_definition(tonic_request) .await .context("gRPC PostTableDefinition call failed")?; Ok(response.into_inner()) } pub async fn post_table_script( &mut self, request: PostTableScriptRequest, ) -> Result { let tonic_request = tonic::Request::new(request); let response = self .table_script_client .post_table_script(tonic_request) .await .context("gRPC PostTableScript call failed")?; Ok(response.into_inner()) } // NEW Methods for TablesData service pub async fn get_table_data_count( &mut self, profile_name: String, table_name: String, ) -> Result { let grpc_request = GetTableDataCountRequest { profile_name, table_name, }; let request = tonic::Request::new(grpc_request); let response = self .tables_data_client .get_table_data_count(request) .await .context("gRPC GetTableDataCount call failed")?; Ok(response.into_inner().count as u64) } pub async fn get_table_data_by_position( &mut self, profile_name: String, table_name: String, position: i32, ) -> Result { let grpc_request = GetTableDataByPositionRequest { profile_name, table_name, position, }; let request = tonic::Request::new(grpc_request); let response = self .tables_data_client .get_table_data_by_position(request) .await .context("gRPC GetTableDataByPosition call failed")?; Ok(response.into_inner()) } pub async fn post_table_data( &mut self, profile_name: String, table_name: String, // CHANGE THIS: Accept the pre-converted data data: HashMap, ) -> Result { // The conversion logic is now gone from here. let grpc_request = PostTableDataRequest { profile_name, table_name, data, // This is now the correct type }; let request = tonic::Request::new(grpc_request); let response = self .tables_data_client .post_table_data(request) .await .context("gRPC PostTableData call failed")?; Ok(response.into_inner()) } pub async fn put_table_data( &mut self, profile_name: String, table_name: String, id: i64, // CHANGE THIS: Accept the pre-converted data data: HashMap, ) -> Result { // The conversion logic is now gone from here. let grpc_request = PutTableDataRequest { profile_name, table_name, id, data, // This is now the correct type }; let request = tonic::Request::new(grpc_request); let response = self .tables_data_client .put_table_data(request) .await .context("gRPC PutTableData call failed")?; Ok(response.into_inner()) } pub async fn search_table( &mut self, table_name: String, query: String, ) -> Result { let request = tonic::Request::new(SearchRequest { table_name, query }); let response = self .search_client .search_table(request) .await?; Ok(response.into_inner()) } }