From b5489425c17b1f7cc9454e670fa2a45f0f84937d Mon Sep 17 00:00:00 2001 From: Manuel Holtgrewe Date: Wed, 20 Nov 2024 14:00:37 +0100 Subject: [PATCH] feat: proper OpenAPI-documented and versioned endpoints (#227) (#228) --- openapi.yaml | 509 ++++++++++++++---- src/query/mod.rs | 30 +- src/server/run/hpo_genes.rs | 83 +-- src/server/run/hpo_omims.rs | 87 ++- src/server/run/hpo_sim/term_gene.rs | 29 +- src/server/run/hpo_sim/term_term.rs | 51 +- src/server/run/hpo_terms.rs | 67 ++- src/server/run/mod.rs | 41 +- ..._hpo_omims_name_contains_no_hpo_terms.snap | 4 +- ...po_omims_name_contains_with_hpo_terms.snap | 4 +- ...st__hpo_omims_name_exact_no_hpo_terms.snap | 4 +- ...__hpo_omims_name_exact_with_hpo_terms.snap | 4 +- ...t__hpo_omims_name_prefix_no_hpo_terms.snap | 4 +- ..._hpo_omims_name_prefix_with_hpo_terms.snap | 4 +- ...t__hpo_omims_name_suffix_no_hpo_terms.snap | 4 +- ..._hpo_omims_name_suffix_with_hpo_terms.snap | 4 +- ..._hpo_omims_omim_id_exact_no_hpo_terms.snap | 4 +- ...po_omims_omim_id_exact_with_hpo_terms.snap | 4 +- 18 files changed, 621 insertions(+), 316 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index dabc1c5..041476d 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -9,12 +9,16 @@ info: name: Apache-2.0 version: 0.3.2 paths: - /hpo/genes: + /api/v1/hpo/genes: get: tags: - hpo_genes summary: Query for genes in the HPO database. - operationId: hpo_genes + description: |- + # Errors + + In the case that there is an error running the server. + operationId: hpoGenes parameters: - name: gene_id in: query @@ -59,13 +63,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Result' - /hpo/omims: + $ref: '#/components/schemas/HpoGenesResult' + '500': + description: The server encountered an error. + content: + application/json: + schema: + $ref: '#/components/schemas/CustomError' + /api/v1/hpo/omims: get: tags: - hpo_omims summary: Query for OMIM diseases in the HPO database. - operationId: hpo_omims + operationId: hpoOmims parameters: - name: omim_id in: query @@ -83,7 +93,7 @@ paths: type: - string - 'null' - - name: match_ + - name: match in: query description: The match mode, default is `Match::Exact`. required: false @@ -118,15 +128,21 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Result' - /hpo/sim/term-gene: + $ref: '#/components/schemas/HpoOmimsResult' + '500': + description: The server encountered an error. + content: + application/json: + schema: + $ref: '#/components/schemas/CustomError' + /api/v1/hpo/sim/term-gene: get: tags: - hpo_sim::term_gene summary: |- Query for similarity between a set of terms to each entry in a list of genes. - operationId: hpo_sim_term_gene + operationId: hpoSimTermGene parameters: - name: terms in: query @@ -162,8 +178,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Result' - /hpo/sim/term-term: + $ref: '#/components/schemas/HpoSimTermGeneResult' + '500': + description: The server encountered an error. + content: + application/json: + schema: + $ref: '#/components/schemas/CustomError' + /api/v1/hpo/sim/term-term: get: tags: - hpo_sim::term_term @@ -174,7 +196,7 @@ paths: # Errors In the case that there is an error running the server. - operationId: hpo_sim_term_term + operationId: hpoSimTermTerm parameters: - name: lhs in: query @@ -216,8 +238,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Result' - /hpo/terms: + $ref: '#/components/schemas/HpoSimTermTermResult' + '500': + description: The server encountered an error. + content: + application/json: + schema: + $ref: '#/components/schemas/CustomError' + /api/v1/hpo/terms: get: tags: - hpo_terms @@ -226,7 +254,7 @@ paths: # Errors In the case that there is an error running the server. - operationId: hpo_terms + operationId: hpoTerms parameters: - name: term_id in: query @@ -263,9 +291,22 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Result_' + $ref: '#/components/schemas/HpoTermsResult' + '500': + description: The server encountered an error. + content: + application/json: + schema: + $ref: '#/components/schemas/CustomError' components: schemas: + CustomError: + type: object + required: + - err + properties: + err: + type: string Gene: type: object description: Struct for storing gene information in the result. @@ -286,41 +327,176 @@ components: - string - 'null' description: The HGNC ID. - HpoTerm: + HpoGenesQuery: type: object - description: Struct for loading an HPO term from JSON. + description: |- + Parameters for `fetch_hpo_genes`. + + This allows to query for genes. The first given of the following is + interpreted. + + - `gene_id` -- specify gene ID (either NCBI or HGNC gene ID) + - `gene_symbol` -- specify the gene symbol + - `max_results` -- the maximnum number of records to return + - `hpo_terms` -- whether to include `"hpo_terms"` in result + + The following propery defines how matches are performed: + + - `match` -- how to match + properties: + gene_id: + type: + - string + - 'null' + description: The gene ID to search for. + gene_symbol: + type: + - string + - 'null' + description: The gene symbol to search for. + match_: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Match' + description: The match mode. + max_results: + type: integer + description: Maximal number of results to return. + minimum: 0 + hpo_terms: + type: boolean + description: Whether to include HPO terms. + HpoGenesResult: + type: object + description: Container for the result. required: - - term_id + - version + - query + - result properties: - term_id: + version: + $ref: '#/components/schemas/Version' + description: Version information. + query: + $ref: '#/components/schemas/HpoGenesQuery' + description: The original query records. + result: + type: array + items: + $ref: '#/components/schemas/HpoGenesResultEntry' + description: The resulting records for the scored genes. + HpoGenesResultEntry: + type: object + description: Result entry for `handle`. + required: + - gene_ncbi_id + - gene_symbol + properties: + gene_ncbi_id: + type: integer + format: int32 + description: The gene's NCBI ID. + minimum: 0 + gene_symbol: type: string - description: The term ID. - term_name: + description: The gene's HGNC symbol. + hgnc_id: type: - string - 'null' - description: The term name (optional). - IcBasedOn: - type: string + description: The gene's HGNC ID. + hpo_terms: + type: + - array + - 'null' + items: + $ref: '#/components/schemas/ResultHpoTerm' + description: The gene's associated HPO terms. + HpoOmimsQuery: + type: object description: |- - Enum for representing the information content kind. + Parameters for `handle`. - We replicate what is in the `hpo` create so we can put them on the command line and use - them in HTTP queries more easily. - enum: - - gene - - omim - Match: - type: string - description: Specify how to perform query matches in the API calls. - enum: - - exact - - prefix - - suffix - - contains - Query: + This allows to query for diseases. The first given of the following + is interpreted. + + - `omim_id` -- specify disease ID + - `name` -- specify the name to query for + - `max_results` -- the maximum number of records to return + - `hpo_terms` -- whether to include `"hpo_terms"` in result + + The following propery defines how matches are performed: + + - `match` -- how to match + properties: + omim_id: + type: + - string + - 'null' + description: The OMIM ID to search for. + name: + type: + - string + - 'null' + description: The disease name to search for. + match: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/Match' + description: The match mode, default is `Match::Exact`. + ignore_case: + type: + - boolean + - 'null' + description: Whether case is insentivie, default is `false`. + max_results: + type: integer + description: Maximal number of results to return. + minimum: 0 + hpo_terms: + type: boolean + description: Whether to include HPO terms. + HpoOmimsResult: + type: object + description: Container for the result. + required: + - version + - query + - result + properties: + version: + $ref: '#/components/schemas/Version' + description: Version information. + query: + $ref: '#/components/schemas/HpoOmimsQuery' + description: The original query records. + result: + type: array + items: + $ref: '#/components/schemas/HpoOmimsResultEntry' + description: The resulting records for the scored genes. + HpoOmimsResultEntry: + type: object + description: Result entry for `handle`. + required: + - omim_id + - name + properties: + omim_id: + type: string + description: The OMIM ID. + name: + type: string + description: The OMIM disease name. + hpo_terms: + type: + - array + - 'null' + items: + $ref: '#/components/schemas/ResultHpoTerm' + description: The gene's associated HPO terms. + HpoSimTermGeneQuery: type: object - title: HpoSimTermGeneQuery description: The performed query. required: - terms @@ -336,9 +512,67 @@ components: items: $ref: '#/components/schemas/Gene' description: The gene list to score. - ResponseQuery: + HpoSimTermGeneResult: + type: object + description: Result container data structure. + required: + - version + - query + - result + properties: + version: + $ref: '#/components/schemas/Version' + description: Version information. + query: + $ref: '#/components/schemas/HpoSimTermGeneQuery' + description: The original query records. + result: + type: array + items: + $ref: '#/components/schemas/HpoSimTermGeneResultEntry' + description: The resulting records for the scored genes. + HpoSimTermGeneResultEntry: + type: object + description: Store score for a record with information on individual terms. + required: + - gene_symbol + - raw_score + properties: + gene_symbol: + type: string + description: The gene symbol. + raw_score: + type: number + format: float + description: The raw Phenomizer score. + terms: + type: + - array + - 'null' + items: + $ref: '#/components/schemas/HpoSimTermGeneTermDetails' + description: Details on individual terms. + HpoSimTermGeneTermDetails: + type: object + description: Detailed term scores. + required: + - term_gene + - score + properties: + term_query: + oneOf: + - type: 'null' + - $ref: '#/components/schemas/HpoTerm' + description: The query HPO term. + term_gene: + $ref: '#/components/schemas/HpoTerm' + description: The gene's HPO term. + score: + type: number + format: float + description: The similarity score. + HpoSimTermTermQuery: type: object - title: HpoSimTermTermQuery description: |- Request as sent together with the response. @@ -366,10 +600,9 @@ components: combiner: $ref: '#/components/schemas/ScoreCombiner' description: The score combiner. - Result: + HpoSimTermTermResult: type: object - title: HpoSimTermGeneResult - description: Result container data structure. + description: Result container. required: - version - query @@ -379,35 +612,151 @@ components: $ref: '#/components/schemas/Version' description: Version information. query: - $ref: '#/components/schemas/Query' + $ref: '#/components/schemas/HpoSimTermTermQuery' description: The original query records. result: type: array items: - $ref: '#/components/schemas/ResultEntry' + $ref: '#/components/schemas/HpoSimTermTermResultEntry' description: The resulting records for the scored genes. - ResultEntry: + HpoSimTermTermResultEntry: type: object - title: HpoSimTermGeneResultEntry - description: Store score for a record with information on individual terms. + description: Result entry for `handle`. required: - - gene_symbol - - raw_score + - lhs + - rhs + - score properties: - gene_symbol: + lhs: type: string - description: The gene symbol. - raw_score: + description: The lhs entry. + rhs: + type: string + description: The rhs entry. + score: type: number format: float - description: The raw Phenomizer score. - terms: + description: The similarity score. + HpoTerm: + type: object + description: Struct for loading an HPO term from JSON. + required: + - term_id + properties: + term_id: + type: string + description: The term ID. + term_name: + type: + - string + - 'null' + description: The term name (optional). + HpoTermsQuery: + type: object + description: |- + Parameters for `handle`. + + This allows to query for terms. The first given of the following is + interpreted. + + - `term_id` -- specify term ID + - `gene_symbol` -- specify the gene symbol + - `max_results` -- the maximum number of records to return + - `genes` -- whether to include `"genes"` in result + properties: + term_id: + type: + - string + - 'null' + description: The term ID to search for. + name: + type: + - string + - 'null' + description: The term name to search for. + max_results: + type: integer + description: Maximal number of results to return. + minimum: 0 + genes: + type: boolean + description: Whether to include genes. + HpoTermsResult: + type: object + description: Container for the result. + required: + - version + - query + - result + properties: + version: + $ref: '#/components/schemas/Version' + description: Version information. + query: + $ref: '#/components/schemas/HpoTermsQuery' + description: The original query records. + result: + type: array + items: + $ref: '#/components/schemas/HpoTermsResultEntry' + description: The resulting records for the scored genes. + HpoTermsResultEntry: + type: object + description: Result entry for `fetch_hpo_genes`. + required: + - term_id + - name + properties: + term_id: + type: string + description: The HPO term's ID. + name: + type: string + description: The HPO term's name. + definition: + type: + - string + - 'null' + description: Any matching description. + synonyms: type: - array - 'null' items: - $ref: '#/components/schemas/TermDetails' - description: Details on individual terms. + type: string + description: Any matching synonyms. + xrefs: + type: + - array + - 'null' + items: + type: string + description: Any matching xref. + genes: + type: + - array + - 'null' + items: + $ref: '#/components/schemas/ResultGene' + description: The gene's associated HPO terms. + IcBasedOn: + type: string + description: |- + Enum for representing the information content kind. + + We replicate what is in the `hpo` create so we can put them on the command line and use + them in HTTP queries more easily. + enum: + - gene + - omim + Match: + type: string + description: Specify how to perform query matches in the API calls. + enum: + - exact + - prefix + - suffix + - contains ResultGene: type: object description: Representation of a gene. @@ -441,26 +790,6 @@ components: name: type: string description: The term name. - Result_: - type: object - title: HpoTermsResult - description: Container for the result. - required: - - version - - query - - result - properties: - version: - $ref: '#/components/schemas/Version' - description: Version information. - query: - $ref: '#/components/schemas/Query' - description: The original query records. - result: - type: array - items: - $ref: '#/components/schemas/ResultEntry' - description: The resulting records for the scored genes. ScoreCombiner: type: string description: |- @@ -488,26 +817,6 @@ components: - mutation - relevance - resnik - TermDetails: - type: object - title: HpoSimTermGeneTermDetails - description: Detailed term scores. - required: - - term_gene - - score - properties: - term_query: - oneOf: - - type: 'null' - - $ref: '#/components/schemas/HpoTerm' - description: The query HPO term. - term_gene: - $ref: '#/components/schemas/HpoTerm' - description: The gene's HPO term. - score: - type: number - format: float - description: The similarity score. Version: type: object description: Version information that is returned by the HTTP server. diff --git a/src/query/mod.rs b/src/query/mod.rs index c83e0d3..8bcfdf7 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -9,7 +9,7 @@ use clap::Parser; use hpo::{annotations::AnnotationId, term::HpoGroup, HpoTermId, Ontology}; use crate::algos::phenomizer; -use crate::query::query_result::TermDetails; +use crate::query::query_result::HpoSimTermGeneTermDetails; /// Command line arguments for `query` command. #[derive(Parser, Debug)] @@ -74,8 +74,7 @@ pub mod query_result { /// The performed query. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] - #[schema(title = "HpoSimTermGeneQuery")] - pub struct Query { + pub struct HpoSimTermGeneQuery { /// The query HPO terms. pub terms: Vec, /// The gene list to score. @@ -84,33 +83,30 @@ pub mod query_result { /// Result container data structure. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] - #[schema(title = "HpoSimTermGeneResult")] - pub struct Result { + pub struct HpoSimTermGeneResult { /// Version information. pub version: Version, /// The original query records. - pub query: Query, + pub query: HpoSimTermGeneQuery, /// The resulting records for the scored genes. - pub result: Vec, + pub result: Vec, } /// Store score for a record with information on individual terms. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] - #[schema(title = "HpoSimTermGeneResultEntry")] - pub struct ResultEntry { + pub struct HpoSimTermGeneResultEntry { /// The gene symbol. pub gene_symbol: String, /// The raw Phenomizer score. pub raw_score: f32, /// Details on individual terms. #[serde(default = "Option::default")] - pub terms: Option>, + pub terms: Option>, } /// Detailed term scores. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] - #[schema(title = "HpoSimTermGeneTermDetails")] - pub struct TermDetails { + pub struct HpoSimTermGeneTermDetails { /// The query HPO term. pub term_query: Option, /// The gene's HPO term. @@ -149,11 +145,11 @@ pub fn run_query( genes: &Vec<&hpo::annotations::Gene>, hpo: &Ontology, ncbi_to_hgnc: &HashMap, -) -> Result +) -> Result where S: std::hash::BuildHasher, { - let query = query_result::Query { + let query = query_result::HpoSimTermGeneQuery { terms: patient .iter() .map(|t| { @@ -166,7 +162,7 @@ where .collect(), genes: Vec::new(), }; - let mut result = query_result::Result { + let mut result = query_result::HpoSimTermGeneResult { version: crate::common::Version::new(&hpo.hpo_version()), query, result: Vec::new(), @@ -217,7 +213,7 @@ where None }; - TermDetails { + HpoSimTermGeneTermDetails { term_query, term_gene: HpoTerm { term_id: gene_term.id().to_string(), @@ -235,7 +231,7 @@ where hgnc_id: ncbi_to_hgnc.get(&ncbi_gene_id).cloned(), }); - result.result.push(query_result::ResultEntry { + result.result.push(query_result::HpoSimTermGeneResultEntry { gene_symbol: gene.name().to_string(), raw_score, terms: Some(terms), diff --git a/src/server/run/hpo_genes.rs b/src/server/run/hpo_genes.rs index a8bbdf5..96a897b 100644 --- a/src/server/run/hpo_genes.rs +++ b/src/server/run/hpo_genes.rs @@ -29,10 +29,9 @@ use super::{CustomError, Match, ResultHpoTerm}; /// /// - `match` -- how to match #[derive( - serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, Debug, Clone, + Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, )] -#[schema(title = "HpoGenesQuery")] -pub struct Query { +pub struct HpoGenesQuery { /// The gene ID to search for. pub gene_id: Option, /// The gene symbol to search for. @@ -60,19 +59,17 @@ fn _default_hpo_terms() -> bool { /// Result entry for `handle`. #[derive( - serde::Serialize, - serde::Deserialize, - utoipa::ToSchema, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, + serde::Serialize, + serde::Deserialize, + utoipa::ToSchema, )] -#[serde_with::skip_serializing_none] -#[schema(title = "HpoGenesResultEntry")] -pub struct ResultEntry { +pub struct HpoGenesResultEntry { /// The gene's NCBI ID. pub gene_ncbi_id: u32, /// The gene's HGNC symbol. @@ -84,7 +81,7 @@ pub struct ResultEntry { pub hpo_terms: Option>, } -impl ResultEntry { +impl HpoGenesResultEntry { /// Create a `ResultEntry` from a `Gene` with an `Ontology`. pub fn from_gene_with_ontology( gene: &Gene, @@ -107,7 +104,7 @@ impl ResultEntry { } else { None }; - ResultEntry { + HpoGenesResultEntry { gene_ncbi_id: gene.id().as_u32(), gene_symbol: gene.name().to_string(), hgnc_id: ncbi_to_hgnc.get(&gene.id().as_u32()).cloned(), @@ -117,35 +114,39 @@ impl ResultEntry { } /// Container for the result. -#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] -#[schema(title = "HpoGenesResult")] -pub struct Result { +#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::ToResponse)] +pub struct HpoGenesResult { /// Version information. pub version: Version, /// The original query records. - pub query: Query, + pub query: HpoGenesQuery, /// The resulting records for the scored genes. - pub result: Vec, + pub result: Vec, } /// Query for genes in the HPO database. -#[allow(clippy::unused_async)] +/// +/// # Errors +/// +/// In the case that there is an error running the server. #[utoipa::path( - operation_id = "hpo_genes", - params(Query), + get, + operation_id = "hpoGenes", + params(HpoGenesQuery), responses( - (status = 200, description = "The query was successful.", body = Result), + (status = 200, description = "The query was successful.", body = HpoGenesResult), + (status = 500, description = "The server encountered an error.", body = CustomError) ) )] -#[get("/hpo/genes")] +#[get("/api/v1/hpo/genes")] async fn handle( data: Data>, _path: Path<()>, - query: web::Query, -) -> actix_web::Result, CustomError> { + query: web::Query, +) -> actix_web::Result, CustomError> { let ontology = &data.ontology; let match_ = query.match_.unwrap_or_default(); - let mut result: Vec = Vec::new(); + let mut result: Vec = Vec::new(); if match_ == Match::Exact { let gene = if let Some(gene_id) = &query.gene_id { @@ -163,7 +164,7 @@ async fn handle( None }; if let Some(gene) = gene { - result.push(ResultEntry::from_gene_with_ontology( + result.push(HpoGenesResultEntry::from_gene_with_ontology( gene, ontology, query.hpo_terms, @@ -182,7 +183,7 @@ async fn handle( Match::Exact => panic!("cannot happen here"), }; if is_match { - result.push(ResultEntry::from_gene_with_ontology( + result.push(HpoGenesResultEntry::from_gene_with_ontology( gene.expect("checked above"), ontology, query.hpo_terms, @@ -196,7 +197,7 @@ async fn handle( result.sort(); - let result = Result { + let result = HpoGenesResult { version: Version::new(&data.ontology.hpo_version()), query: query.into_inner(), result, @@ -234,7 +235,7 @@ pub(crate) mod test { pub async fn run_query( web_server_data: Arc, uri: &str, - ) -> Result { + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() .app_data(actix_web::web::Data::new(web_server_data)) @@ -242,7 +243,7 @@ pub(crate) mod test { ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::HpoGenesResult = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } @@ -253,7 +254,7 @@ pub(crate) mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/genes?gene_id=2348").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/genes?gene_id=2348").await? )) } @@ -265,7 +266,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_id=2348&hpo_terms=true" + "/api/v1/hpo/genes?gene_id=2348&hpo_terms=true" ) .await? )) @@ -277,7 +278,7 @@ pub(crate) mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/genes?gene_id=HGNC:3791").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/genes?gene_id=HGNC:3791").await? )) } @@ -289,7 +290,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_id=HGNC:3791&hpo_terms=true" + "/api/v1/hpo/genes?gene_id=HGNC:3791&hpo_terms=true" ) .await? )) @@ -301,7 +302,7 @@ pub(crate) mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/genes?gene_symbol=TGDS").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/genes?gene_symbol=TGDS").await? )) } @@ -313,7 +314,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=TGDS&hpo_terms=true" + "/api/v1/hpo/genes?gene_symbol=TGDS&hpo_terms=true" ) .await? )) @@ -327,7 +328,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=TGD&match=prefix" + "/api/v1/hpo/genes?gene_symbol=TGD&match=prefix" ) .await? )) @@ -341,7 +342,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=TGD&match=prefix&hpo_terms=true" + "/api/v1/hpo/genes?gene_symbol=TGD&match=prefix&hpo_terms=true" ) .await? )) @@ -355,7 +356,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=GDS&match=suffix" + "/api/v1/hpo/genes?gene_symbol=GDS&match=suffix" ) .await? )) @@ -369,7 +370,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=GDS&match=suffix&hpo_terms=true" + "/api/v1/hpo/genes?gene_symbol=GDS&match=suffix&hpo_terms=true" ) .await? )) @@ -383,7 +384,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=GD&match=contains" + "/api/v1/hpo/genes?gene_symbol=GD&match=contains" ) .await? )) @@ -397,7 +398,7 @@ pub(crate) mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/genes?gene_symbol=GD&match=contains&hpo_terms=true" + "/api/v1/hpo/genes?gene_symbol=GD&match=contains&hpo_terms=true" ) .await? )) diff --git a/src/server/run/hpo_omims.rs b/src/server/run/hpo_omims.rs index f2c35cf..ffab502 100644 --- a/src/server/run/hpo_omims.rs +++ b/src/server/run/hpo_omims.rs @@ -30,17 +30,15 @@ use super::{CustomError, Match, ResultHpoTerm}; /// /// - `match` -- how to match #[derive( - serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, Debug, Clone, + Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, )] -#[schema(title = "HpoOmimsQuery")] -pub struct Query { +pub struct HpoOmimsQuery { /// The OMIM ID to search for. pub omim_id: Option, /// The disease name to search for. pub name: Option, /// The match mode, default is `Match::Exact`. - #[serde(alias = "match")] - pub match_: Option, + pub r#match: Option, /// Whether case is insentivie, default is `false`. pub ignore_case: Option, /// Maximal number of results to return. @@ -51,7 +49,7 @@ pub struct Query { pub hpo_terms: bool, } -impl Query { +impl HpoOmimsQuery { /// Strip "OMIM:" prefix from `omim_id`, if any. fn with_stripped_prefix(self) -> Self { Self { @@ -81,9 +79,8 @@ fn _default_hpo_terms() -> bool { } /// Result entry for `handle`. -#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] -#[schema(title = "HpoOmimsResultEntry")] -pub struct ResultEntry { +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +pub struct HpoOmimsResultEntry { /// The OMIM ID. pub omim_id: String, /// The OMIM disease name. @@ -93,21 +90,21 @@ pub struct ResultEntry { pub hpo_terms: Option>, } -impl PartialEq for ResultEntry { +impl PartialEq for HpoOmimsResultEntry { fn eq(&self, other: &Self) -> bool { (self.omim_id == other.omim_id) && (self.name == other.name) } } -impl Eq for ResultEntry {} +impl Eq for HpoOmimsResultEntry {} -impl PartialOrd for ResultEntry { +impl PartialOrd for HpoOmimsResultEntry { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for ResultEntry { +impl Ord for HpoOmimsResultEntry { fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self.omim_id.cmp(&other.omim_id) { core::cmp::Ordering::Equal => {} @@ -117,7 +114,7 @@ impl Ord for ResultEntry { } } -impl ResultEntry { +impl HpoOmimsResultEntry { /// Create a `ResultEntry` from an `OmimDisease`. pub fn from_omim_disease_with_ontology( omim_disease: &OmimDisease, @@ -142,7 +139,7 @@ impl ResultEntry { } else { None }; - ResultEntry { + HpoOmimsResultEntry { omim_id: omim_disease.id().to_string(), name: omim_disease.name().to_string(), hpo_terms, @@ -151,36 +148,36 @@ impl ResultEntry { } /// Container for the result. -#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug)] -#[schema(title = "HpoOmimsResult")] -pub struct Result { +#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +pub struct HpoOmimsResult { /// Version information. pub version: Version, /// The original query records. - pub query: Query, + pub query: HpoOmimsQuery, /// The resulting records for the scored genes. - pub result: Vec, + pub result: Vec, } /// Query for OMIM diseases in the HPO database. -#[allow(clippy::unused_async)] #[allow(clippy::too_many_lines)] #[utoipa::path( - operation_id = "hpo_omims", - params(Query), + get, + operation_id = "hpoOmims", + params(HpoOmimsQuery), responses( - (status = 200, description = "The query was successful.", body = Result), + (status = 200, description = "The query was successful.", body = HpoOmimsResult), + (status = 500, description = "The server encountered an error.", body = CustomError) ) )] -#[get("/hpo/omims")] +#[get("/api/v1/hpo/omims")] async fn handle( data: Data>, _path: Path<()>, - query: web::Query, -) -> actix_web::Result, CustomError> { + query: web::Query, +) -> actix_web::Result, CustomError> { let ontology = &data.ontology; - let match_ = query.match_.unwrap_or_default(); - let mut result: Vec = Vec::new(); + let match_ = query.r#match.unwrap_or_default(); + let mut result: Vec = Vec::new(); // Strip "OMIM:" and "MIM:" prefix from `query.omim_id` if given. let query = query.into_inner().with_stripped_prefix(); @@ -216,7 +213,7 @@ async fn handle( None }; if let Some(omim_disease) = &omim_disease { - result.push(ResultEntry::from_omim_disease_with_ontology( + result.push(HpoOmimsResultEntry::from_omim_disease_with_ontology( omim_disease, ontology, query.hpo_terms, @@ -237,14 +234,14 @@ async fn handle( } else { omim_name.to_string() }; - let is_match = match query.match_.unwrap_or_default() { + let is_match = match query.r#match.unwrap_or_default() { Match::Prefix => omim_name.starts_with(&name), Match::Suffix => omim_name.ends_with(&name), Match::Contains => omim_name.contains(&name), Match::Exact => panic!("cannot happen here"), }; if is_match { - result.push(ResultEntry::from_omim_disease_with_ontology( + result.push(HpoOmimsResultEntry::from_omim_disease_with_ontology( omim_disease.as_ref().expect("checked above"), ontology, query.hpo_terms, @@ -257,7 +254,7 @@ async fn handle( result.sort(); - let result = Result { + let result = HpoOmimsResult { version: Version::new(&data.ontology.hpo_version()), query, result, @@ -277,7 +274,7 @@ mod test { pub async fn run_query( web_server_data: Arc, uri: &str, - ) -> Result { + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() .app_data(actix_web::web::Data::new(web_server_data)) @@ -285,7 +282,7 @@ mod test { ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::HpoOmimsResult = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } @@ -296,7 +293,7 @@ mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/omims?omim_id=616145").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/omims?omim_id=616145").await? )) } @@ -308,7 +305,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?omim_id=616145&hpo_terms=true" + "/api/v1/hpo/omims?omim_id=616145&hpo_terms=true" ) .await? )) @@ -322,7 +319,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=Catel-Manzke+syndrome" + "/api/v1/hpo/omims?name=Catel-Manzke+syndrome" ) .await? )) @@ -336,7 +333,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true" + "/api/v1/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true" ) .await? )) @@ -350,7 +347,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=Catel-Manzke+syndro&match=prefix" + "/api/v1/hpo/omims?name=Catel-Manzke+syndro&match=prefix" ) .await? )) @@ -364,7 +361,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true" + "/api/v1/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true" ) .await? )) @@ -378,7 +375,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=tel-Manzke+syndrome&match=suffix" + "/api/v1/hpo/omims?name=tel-Manzke+syndrome&match=suffix" ) .await? )) @@ -392,7 +389,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true" + "/api/v1/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true" ) .await? )) @@ -406,7 +403,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=tel-Manzke+syndro&match=contains" + "/api/v1/hpo/omims?name=tel-Manzke+syndro&match=contains" ) .await? )) @@ -420,7 +417,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true" + "/api/v1/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true" ) .await? )) diff --git a/src/server/run/hpo_sim/term_gene.rs b/src/server/run/hpo_sim/term_gene.rs index ccdf78e..30d4ccb 100644 --- a/src/server/run/hpo_sim/term_gene.rs +++ b/src/server/run/hpo_sim/term_gene.rs @@ -12,7 +12,7 @@ use hpo::{annotations::GeneId, term::HpoGroup, HpoTermId, Ontology}; use super::super::CustomError; use crate::{ - query::{self, query_result}, + query::{self, query_result::HpoSimTermGeneResult}, server::run::WebServerData, }; @@ -26,8 +26,7 @@ use crate::{ /// - `gene_symbols` -- set of symbols for genes to use as /// "database" #[derive(serde::Deserialize, Debug, Clone, utoipa::ToSchema, utoipa::IntoParams)] -#[schema(title = "HpoSimTermGeneQuery")] -pub struct Query { +pub struct HpoSimTermGeneQuery { /// Set of terms to use as query. #[serde(deserialize_with = "super::super::vec_str_deserialize")] pub terms: Vec, @@ -51,18 +50,20 @@ pub struct Query { /// list of genes. #[allow(clippy::unused_async)] #[utoipa::path( - operation_id = "hpo_sim_term_gene", - params(Query), + get, + operation_id = "hpoSimTermGene", + params(HpoSimTermGeneQuery), responses( - (status = 200, description = "The query was successful.", body = query_result::Result), + (status = 200, description = "The query was successful.", body = HpoSimTermGeneResult), + (status = 500, description = "The server encountered an error.", body = CustomError) ) )] -#[get("/hpo/sim/term-gene")] +#[get("/api/v1/hpo/sim/term-gene")] async fn handle( data: Data>, _path: Path<()>, - query: web::Query, -) -> actix_web::Result, CustomError> { + query: web::Query, +) -> actix_web::Result, CustomError> { let hpo: &Ontology = &data.ontology; // Translate strings from the query into an `HpoGroup`. @@ -119,7 +120,7 @@ mod test { pub async fn run_query( web_server_data: Arc, uri: &str, - ) -> Result { + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() .app_data(actix_web::web::Data::new(web_server_data)) @@ -127,7 +128,7 @@ mod test { ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: crate::query::query_result::Result = + let resp: crate::query::query_result::HpoSimTermGeneResult = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) @@ -141,7 +142,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=23483,7273" + "/api/v1/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=23483,7273" ) .await? )) @@ -155,7 +156,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=HGNC:20324,HGNC:12403" + "/api/v1/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=HGNC:20324,HGNC:12403" ) .await? )) @@ -169,7 +170,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_symbols=TGDS,TTN" + "/api/v1/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_symbols=TGDS,TTN" ) .await? )) diff --git a/src/server/run/hpo_sim/term_term.rs b/src/server/run/hpo_sim/term_term.rs index 1f572a1..d85d0af 100644 --- a/src/server/run/hpo_sim/term_term.rs +++ b/src/server/run/hpo_sim/term_term.rs @@ -22,7 +22,7 @@ use crate::server::{run::CustomError, run::WebServerData}; /// /// - `lhs` -- first set of terms to compute similarity for /// - `rhs` -- econd set of terms to compute similarity for -#[derive(serde::Serialize, serde::Deserialize, utoipa::IntoParams, Default, Debug, Clone)] +#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::IntoParams)] pub struct RequestQuery { /// The one set of HPO terms to compute similarity for. #[serde(deserialize_with = "super::super::vec_str_deserialize")] @@ -44,9 +44,8 @@ pub struct RequestQuery { /// Request as sent together with the response. /// /// The difference is that the `lhs` and `rhs` fields are replaced by vecs. -#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Default, Debug, Clone)] -#[schema(title = "HpoSimTermTermQuery")] -pub struct ResponseQuery { +#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +pub struct HpoSimTermTermQuery { /// The one set of HPO terms to compute similarity for. pub lhs: Vec, /// The second set of HPO terms to compute similarity for. @@ -63,30 +62,28 @@ pub struct ResponseQuery { } /// Result container. -#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Default, Debug, Clone)] -#[schema(title = "HpoSimTermTermResult")] -pub struct Result { +#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +pub struct HpoSimTermTermResult { /// Version information. pub version: Version, /// The original query records. - pub query: ResponseQuery, + pub query: HpoSimTermTermQuery, /// The resulting records for the scored genes. - pub result: Vec, + pub result: Vec, } /// Result entry for `handle`. #[derive( - serde::Serialize, - serde::Deserialize, - utoipa::ToSchema, Default, Debug, Clone, PartialEq, PartialOrd, + serde::Serialize, + serde::Deserialize, + utoipa::ToSchema, )] -#[schema(title = "HpoSimTermTermResultEntry")] -pub struct ResultEntry { +pub struct HpoSimTermTermResultEntry { /// The lhs entry. pub lhs: String, /// The rhs entry. @@ -102,20 +99,21 @@ pub struct ResultEntry { /// # Errors /// /// In the case that there is an error running the server. -#[allow(clippy::unused_async)] #[utoipa::path( - operation_id = "hpo_sim_term_term", + get, + operation_id = "hpoSimTermTerm", params(RequestQuery), responses( - (status = 200, description = "The query was successful.", body = Result), + (status = 200, description = "The query was successful.", body = HpoSimTermTermResult), + (status = 500, description = "The server encountered an error.", body = CustomError) ) )] -#[get("/hpo/sim/term-term")] +#[get("/api/v1/hpo/sim/term-term")] async fn handle( data: Data>, _path: Path<()>, query: web::Query, -) -> actix_web::Result, CustomError> { +) -> actix_web::Result, CustomError> { let ontology: &Ontology = &data.ontology; let mut result = Vec::new(); @@ -136,7 +134,7 @@ async fn handle( // Compute the similarity for each pair. for (lhs, rhs) in lhs.iter().cartesian_product(rhs.iter()) { let similarity = ic.calculate(lhs, rhs); - let elem = ResultEntry { + let elem = HpoSimTermTermResultEntry { lhs: lhs.id().to_string(), rhs: rhs.id().to_string(), score: similarity, @@ -160,9 +158,9 @@ async fn handle( combiner, } = query.into_inner(); - let result = Result { + let result = HpoSimTermTermResult { version: Version::new(&data.ontology.hpo_version()), - query: ResponseQuery { + query: HpoSimTermTermQuery { lhs, rhs, ic_base, @@ -188,7 +186,7 @@ mod test { pub async fn run_query( web_server_data: Arc, uri: &str, - ) -> Result { + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() .app_data(actix_web::web::Data::new(web_server_data)) @@ -196,7 +194,8 @@ mod test { ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::HpoSimTermTermResult = + actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } @@ -209,7 +208,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/sim/term-term?lhs=HP:0010442&rhs=HP:0001780" + "/api/v1/hpo/sim/term-term?lhs=HP:0010442&rhs=HP:0001780" ) .await? )) @@ -223,7 +222,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/sim/term-term?lhs=HP:0010442,HP:0000347&rhs=HP:0001780,HP:0000252" + "/api/v1/hpo/sim/term-term?lhs=HP:0010442,HP:0000347&rhs=HP:0001780,HP:0000252" ) .await? )) diff --git a/src/server/run/hpo_terms.rs b/src/server/run/hpo_terms.rs index 0b92750..ba8e607 100644 --- a/src/server/run/hpo_terms.rs +++ b/src/server/run/hpo_terms.rs @@ -23,10 +23,9 @@ use super::{CustomError, ResultGene}; /// - `max_results` -- the maximum number of records to return /// - `genes` -- whether to include `"genes"` in result #[derive( - serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, Debug, Clone, + Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, )] -#[schema(title = "HpoTermsQuery")] -pub struct Query { +pub struct HpoTermsQuery { /// The term ID to search for. pub term_id: Option, /// The term name to search for. @@ -50,9 +49,8 @@ fn _default_genes() -> bool { } /// Result entry for `fetch_hpo_genes`. -#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] -#[schema(title = "HpoTermsResultEntry")] -pub struct ResultEntry { +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +pub struct HpoTermsResultEntry { /// The HPO term's ID. pub term_id: String, /// The HPO term's name. @@ -68,21 +66,21 @@ pub struct ResultEntry { pub genes: Option>, } -impl PartialEq for ResultEntry { +impl PartialEq for HpoTermsResultEntry { fn eq(&self, other: &Self) -> bool { (self.term_id == other.term_id) && (self.name == other.name) } } -impl Eq for ResultEntry {} +impl Eq for HpoTermsResultEntry {} -impl PartialOrd for ResultEntry { +impl PartialOrd for HpoTermsResultEntry { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for ResultEntry { +impl Ord for HpoTermsResultEntry { fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self.term_id.cmp(&other.term_id) { core::cmp::Ordering::Equal => {} @@ -92,7 +90,7 @@ impl Ord for ResultEntry { } } -impl ResultEntry { +impl HpoTermsResultEntry { /// Create a `ResultEntry` from an `HpoTerm`. /// /// # Errors @@ -181,7 +179,7 @@ impl ResultEntry { } else { None }; - Ok(ResultEntry { + Ok(HpoTermsResultEntry { term_id: term.id().to_string(), name: term.name().to_string(), genes, @@ -194,14 +192,13 @@ impl ResultEntry { /// Container for the result. #[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] -#[schema(title = "HpoTermsResult")] -pub struct Result_ { +pub struct HpoTermsResult { /// Version information. pub version: Version, /// The original query records. - pub query: Query, + pub query: HpoTermsQuery, /// The resulting records for the scored genes. - pub result: Vec, + pub result: Vec, } /// Query for terms in the HPO database. @@ -212,20 +209,22 @@ pub struct Result_ { #[allow(clippy::unused_async)] #[allow(clippy::too_many_lines)] #[utoipa::path( - operation_id = "hpo_terms", - params(Query), + get, + operation_id = "hpoTerms", + params(HpoTermsQuery), responses( - (status = 200, description = "The query was successful.", body = Result_), + (status = 200, description = "The query was successful.", body = HpoTermsResult), + (status = 500, description = "The server encountered an error.", body = CustomError) ) )] -#[get("/hpo/terms")] +#[get("/api/v1/hpo/terms")] async fn handle( data: Data>, _path: Path<()>, - query: web::Query, -) -> actix_web::Result, CustomError> { + query: web::Query, +) -> actix_web::Result, CustomError> { let ontology = &data.ontology; - let mut result: Vec = Vec::new(); + let mut result: Vec = Vec::new(); let field_term_id = data .full_text_index @@ -277,7 +276,7 @@ async fn handle( CustomError::new(anyhow::anyhow!("Term ID {} not found in HPO", term_id)) })?; result.push( - ResultEntry::from_term_with_ontology( + HpoTermsResultEntry::from_term_with_ontology( &term, ontology, query.genes, @@ -345,7 +344,7 @@ async fn handle( })?; result.push( - ResultEntry::from_term_with_ontology( + HpoTermsResultEntry::from_term_with_ontology( &term, ontology, query.genes, @@ -358,7 +357,7 @@ async fn handle( } }; - let result = Result_ { + let result = HpoTermsResult { version: Version::new(&data.ontology.hpo_version()), query: query.into_inner(), result, @@ -378,7 +377,7 @@ mod test { pub async fn run_query( web_server_data: Arc, uri: &str, - ) -> Result { + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() .app_data(actix_web::web::Data::new(web_server_data)) @@ -386,7 +385,7 @@ mod test { ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Result_ = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::HpoTermsResult = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } @@ -397,7 +396,7 @@ mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/terms?term_id=HP:0000023").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/terms?term_id=HP:0000023").await? )) } @@ -409,7 +408,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/terms?term_id=HP:0000023&genes=true" + "/api/v1/hpo/terms?term_id=HP:0000023&genes=true" ) .await? )) @@ -421,7 +420,7 @@ mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/terms?name=Inguinal+hernia").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/terms?name=Inguinal+hernia").await? )) } @@ -433,7 +432,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/terms?name=Inguinal+hernia&genes=true" + "/api/v1/hpo/terms?name=Inguinal+hernia&genes=true" ) .await? )) @@ -445,7 +444,7 @@ mod test { web_server_data: &Arc, ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query(web_server_data.clone(), "/hpo/terms?name=Inguinal+hern").await? + &run_query(web_server_data.clone(), "/api/v1/hpo/terms?name=Inguinal+hern").await? )) } @@ -457,7 +456,7 @@ mod test { Ok(insta::assert_yaml_snapshot!( &run_query( web_server_data.clone(), - "/hpo/terms?name=Inguinal+hern&genes=true" + "/api/v1/hpo/terms?name=Inguinal+hern&genes=true" ) .await? )) diff --git a/src/server/run/mod.rs b/src/server/run/mod.rs index 2885121..cf54365 100644 --- a/src/server/run/mod.rs +++ b/src/server/run/mod.rs @@ -45,9 +45,9 @@ pub struct Args { pub listen_port: u16, } -#[derive(Debug)] +#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] struct CustomError { - err: anyhow::Error, + err: String, } impl std::fmt::Display for CustomError { @@ -57,8 +57,11 @@ impl std::fmt::Display for CustomError { } impl CustomError { + #[allow(clippy::needless_pass_by_value)] fn new(err: anyhow::Error) -> Self { - CustomError { err } + CustomError { + err: err.to_string(), + } } } @@ -163,23 +166,23 @@ where hpo_sim::term_gene::handle, ), components(schemas( - hpo_genes::Query, - hpo_genes::Result, - hpo_genes::ResultEntry, - hpo_omims::Query, - hpo_omims::Result, - hpo_omims::ResultEntry, - hpo_terms::Query, - hpo_terms::Result_, - hpo_terms::ResultEntry, - hpo_sim::term_gene::Query, - crate::query::query_result::Result, - crate::query::query_result::ResultEntry, - crate::query::query_result::TermDetails, + hpo_genes::HpoGenesQuery, + hpo_genes::HpoGenesResult, + hpo_genes::HpoGenesResultEntry, + hpo_omims::HpoOmimsQuery, + hpo_omims::HpoOmimsResult, + hpo_omims::HpoOmimsResultEntry, + hpo_terms::HpoTermsQuery, + hpo_terms::HpoTermsResult, + hpo_terms::HpoTermsResultEntry, + hpo_sim::term_gene::HpoSimTermGeneQuery, + crate::query::query_result::HpoSimTermGeneResult, + crate::query::query_result::HpoSimTermGeneResultEntry, + crate::query::query_result::HpoSimTermGeneTermDetails, crate::query::HpoTerm, - hpo_sim::term_term::ResponseQuery, - hpo_sim::term_term::Result, - hpo_sim::term_term::ResultEntry, + hpo_sim::term_term::HpoSimTermTermQuery, + hpo_sim::term_term::HpoSimTermTermResult, + hpo_sim::term_term::HpoSimTermTermResultEntry, ResultGene, ResultHpoTerm, Match, diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap index cfe4f6c..2be261f 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=tel-Manzke+syndro&match=contains\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=tel-Manzke+syndro&match=contains\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: tel-Manzke syndro - match_: contains + match: contains ignore_case: ~ max_results: 100 hpo_terms: false diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap index 48ecb3d..bb30ed0 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: tel-Manzke syndro - match_: contains + match: contains ignore_case: ~ max_results: 100 hpo_terms: true diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap index 21e40b4..c9f0c40 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=Catel-Manzke+syndrome\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=Catel-Manzke+syndrome\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: Catel-Manzke syndrome - match_: ~ + match: ~ ignore_case: ~ max_results: 100 hpo_terms: false diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap index c06ceb6..3a4fbef 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: Catel-Manzke syndrome - match_: ~ + match: ~ ignore_case: ~ max_results: 100 hpo_terms: true diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap index 7abe192..d8f3fac 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=Catel-Manzke+syndro&match=prefix\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=Catel-Manzke+syndro&match=prefix\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: Catel-Manzke syndro - match_: prefix + match: prefix ignore_case: ~ max_results: 100 hpo_terms: false diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap index d06e83a..54eed5b 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: Catel-Manzke syndro - match_: prefix + match: prefix ignore_case: ~ max_results: 100 hpo_terms: true diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap index 2d4f4df..2cb0de4 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=tel-Manzke+syndrome&match=suffix\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=tel-Manzke+syndrome&match=suffix\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: tel-Manzke syndrome - match_: suffix + match: suffix ignore_case: ~ max_results: 100 hpo_terms: false diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap index 41196eb..3d64fdc 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: ~ name: tel-Manzke syndrome - match_: suffix + match: suffix ignore_case: ~ max_results: 100 hpo_terms: true diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap index 484b0b3..9f9ede1 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(), \"/hpo/omims?omim_id=616145\").await?" +expression: "&run_query(web_server_data.clone(), \"/api/v1/hpo/omims?omim_id=616145\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: "616145" name: ~ - match_: ~ + match: ~ ignore_case: ~ max_results: 100 hpo_terms: false diff --git a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap index 83a2d7f..5a92d76 100644 --- a/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap @@ -1,6 +1,6 @@ --- source: src/server/run/hpo_omims.rs -expression: "&run_query(web_server_data.clone(),\n \"/hpo/omims?omim_id=616145&hpo_terms=true\").await?" +expression: "&run_query(web_server_data.clone(),\n\"/api/v1/hpo/omims?omim_id=616145&hpo_terms=true\").await?" --- version: hpo: 2024-07-01 @@ -8,7 +8,7 @@ version: query: omim_id: "616145" name: ~ - match_: ~ + match: ~ ignore_case: ~ max_results: 100 hpo_terms: true