diff --git a/app/Rest/Resources/MoleculeResource.php b/app/Rest/Resources/MoleculeResource.php index 573eb29f..c9842c48 100644 --- a/app/Rest/Resources/MoleculeResource.php +++ b/app/Rest/Resources/MoleculeResource.php @@ -6,6 +6,7 @@ use App\Rest\Resource as RestResource; use Illuminate\Database\Eloquent\Model; use Lomkit\Rest\Http\Requests\RestRequest; +use Lomkit\Rest\Relations\BelongsToMany; use Lomkit\Rest\Relations\HasOne; class MoleculeResource extends RestResource @@ -37,6 +38,7 @@ public function fields(RestRequest $request): array 'name_trust_level', 'annotation_level', 'variants_count', + 'organism_count', 'status', 'active', @@ -55,6 +57,7 @@ public function relations(RestRequest $request): array { return [ HasOne::make('properties', PropertiesResource::class), + BelongsToMany::make('organisms', OrganismResource::class), ]; } diff --git a/docs/api-documentation.md b/docs/api-documentation.md index 12507dc1..b661c5ad 100644 --- a/docs/api-documentation.md +++ b/docs/api-documentation.md @@ -93,7 +93,7 @@ Search Molecules using various attributes. There are two tables invovled in this #### Searchable fields ::: info molecules -'standard_inchi', 'standard_inchi_key', 'canonical_smiles', 'sugar_free_smiles', 'identifier', 'name', 'cas', 'iupac_name', 'murko_framework', 'structural_comments', 'name_trust_level', 'annotation_level', 'variants_count', 'status', 'active', 'has_variants', 'has_stereo', 'is_tautomer', 'is_parent', 'is_placeholder' +'standard_inchi', 'standard_inchi_key', 'canonical_smiles', 'sugar_free_smiles', 'identifier', 'name', 'cas', 'iupac_name', 'murko_framework', 'structural_comments', 'name_trust_level', 'annotation_level', 'variants_count', 'organism_count', 'status', 'active', 'has_variants', 'has_stereo', 'is_tautomer', 'is_parent', 'is_placeholder' ::: ::: info properties 'total_atom_count', 'heavy_atom_count', 'molecular_weight', 'exact_molecular_weight', 'molecular_formula', 'alogp', 'topological_polar_surface_area', 'rotatable_bond_count', 'hydrogen_bond_acceptors', 'hydrogen_bond_donors', 'hydrogen_bond_acceptors_lipinski', 'hydrogen_bond_donors_lipinski', 'lipinski_rule_of_five_violations', 'aromatic_rings_count', 'qed_drug_likeliness', 'formal_charge', 'fractioncsp3', 'number_of_minimal_rings', 'van_der_walls_volume', 'contains_sugar', 'contains_ring_sugars', 'contains_linear_sugars', 'murcko_framework', 'np_likeness', 'chemical_class', 'chemical_sub_class', 'chemical_super_class', 'direct_parent_classification', 'np_classifier_pathway', 'np_classifier_superclass', 'np_classifier_class', 'np_classifier_is_glycoside' @@ -103,6 +103,35 @@ Search Molecules using various attributes. There are two tables invovled in this The fields in the *molecules* table can be accessed directly with their column names. The fields in the *properties* table are to be accessed prefixing them with the table name. Ex: **properties.field-name**. ::: +#### Includable relations +::: info relations +'properties', 'organisms' +::: + +Use the `includes` array in the search request to load related records. For example, to include organisms reported for a molecule: + +**Request Body Example with organisms (application/json):** +```json +{ + "search": { + "filters": [ + { + "field": "identifier", + "operator": "=", + "value": "CNP0228556.0" + } + ], + "includes": [ + { + "relation": "organisms" + } + ] + } +} +``` + +Each included organism exposes: `name`, `iri`, `rank`, `molecule_count`. + **Request Body Example (application/json):** ```json diff --git a/public/vendor/rest/openapi.json b/public/vendor/rest/openapi.json index 118bc128..9a302122 100644 --- a/public/vendor/rest/openapi.json +++ b/public/vendor/rest/openapi.json @@ -47,6 +47,7 @@ "name_trust_level", "annotation_level", "variants_count", + "organism_count", "status", "active", "has_variants", @@ -73,6 +74,17 @@ "prohibited_on_update": false }, "name": "HasOne" + }, + { + "resource": "App\\Rest\\Resources\\OrganismResource", + "relation": "organisms", + "constraints": { + "required_on_creation": false, + "prohibited_on_creation": false, + "required_on_update": false, + "prohibited_on_update": false + }, + "name": "BelongsToMany" } ], "rules": { @@ -224,6 +236,11 @@ "operator": "=", "value": "" }, + { + "field": "organism_count", + "operator": "=", + "value": "" + }, { "field": "status", "operator": "=", @@ -313,6 +330,10 @@ "field": "variants_count", "direction": "desc" }, + { + "field": "organism_count", + "direction": "desc" + }, { "field": "status", "direction": "desc" @@ -382,6 +403,9 @@ { "field": "variants_count" }, + { + "field": "organism_count" + }, { "field": "status" }, @@ -407,6 +431,9 @@ "includes": [ { "relation": "properties" + }, + { + "relation": "organisms" } ], "aggregates": [], @@ -476,6 +503,7 @@ "name_trust_level": "", "annotation_level": "", "variants_count": "", + "organism_count": "", "status": "", "active": "", "has_variants": "", @@ -488,6 +516,10 @@ "properties": { "operation": "update", "key": 1 + }, + "organisms": { + "operation": "update", + "key": 1 } } } @@ -629,9 +661,9 @@ "application\/json": { "example": { "data": { - "title": "Est consectetur labore ut.", - "description": "Distinctio assumenda eum itaque veritatis in aut. Rem aut exercitationem occaecati rerum quo. Illo veritatis aut non non. Quia ipsum doloribus fugiat vel corrupti fugit quasi.", - "url": "http:\/\/crooks.com\/", + "title": "Vero velit sint aut voluptatum.", + "description": "Saepe omnis ut corrupti placeat iure provident. Accusamus dolorem tenetur consequuntur sed. Aut sunt voluptates incidunt qui omnis.", + "url": "http:\/\/tillman.info\/dolorem-assumenda-dolores-ad-odio.html", "identifier": null }, "meta": [] @@ -674,10 +706,10 @@ "application\/json": { "example": { "data": { - "title": "Et alias rerum incidunt et.", - "description": "Libero nesciunt placeat magnam sint. Ut in voluptas consequatur. Laborum aspernatur sint ut optio. Voluptatem illo distinctio culpa laborum.", - "url": "http:\/\/kutch.com\/ab-voluptatem-consequatur-minus-voluptas-repudiandae-perferendis", - "identifier": null + "title": "Enim ratione enim accusantium quia.", + "description": "Temporibus sit eum qui sint sequi ratione dolorem. Esse eum cupiditate quis quasi cum et. Qui eius voluptas amet autem accusamus.", + "url": "https:\/\/www.grady.net\/id-commodi-ratione-aut-iste-ducimus-mollitia-aut-eos", + "identifier": "Sint et repudiandae et earum et itaque ratione." }, "meta": [] } @@ -946,9 +978,9 @@ "application\/json": { "example": { "data": { - "doi": "10.1016\/j.bbrep.2025.102032~58", - "title": "RNA signaling in medicinal plants: An overlooked mechanism for phytochemical regulation.", - "authors": "Alum EU, Udechukwu CD, Obasi DC.", + "doi": "10.1038\/s41598-026-45889-0~78", + "title": "The impact of herbal medicine development on the population health in China.", + "authors": "Wang Y, Zheng X, Masron TA.", "citation_text": "" }, "meta": [] @@ -991,9 +1023,9 @@ "application\/json": { "example": { "data": { - "doi": "10.1039\/b700306b~29", - "title": "Natural product isolation.", - "authors": "Sticher O.", + "doi": "10.1016\/j.jaim.2026.101328~60", + "title": "The Delhi Declaration on Traditional Medicine: Outcome of the Second WHO Global Summit on Traditional Medicine (2025).", + "authors": null, "citation_text": "" }, "meta": [] @@ -1568,8 +1600,8 @@ "application\/json": { "example": { "data": { - "name": "Annabel Medhurst", - "email": "veum.adolphus@example.com" + "name": "Grayce Bauch", + "email": "pabernathy@example.org" }, "meta": [] } @@ -1611,8 +1643,8 @@ "application\/json": { "example": { "data": { - "name": "Dr. Gonzalo Simonis II", - "email": "ssimonis@example.net" + "name": "Cathy Boyer", + "email": "hand.octavia@example.com" }, "meta": [] } @@ -2535,7 +2567,8 @@ "title", "evidence", "comment", - "suggested_changes" + "suggested_changes", + "mol_ids" ], "scout_fields": [], "limits": [ @@ -2654,6 +2687,11 @@ "field": "suggested_changes", "operator": "=", "value": "" + }, + { + "field": "mol_ids", + "operator": "=", + "value": "" } ], "sorts": [ @@ -2668,6 +2706,10 @@ { "field": "comment", "direction": "desc" + }, + { + "field": "mol_ids", + "direction": "desc" } ], "selects": [ @@ -2682,6 +2724,9 @@ }, { "field": "suggested_changes" + }, + { + "field": "mol_ids" } ], "includes": [], @@ -2742,7 +2787,8 @@ "title": "", "evidence": "", "comment": "", - "suggested_changes": "" + "suggested_changes": "", + "mol_ids": "" }, "relations": [] } @@ -3063,6 +3109,75 @@ } } } + }, + "\/api\/auth\/verify\/{user_id}": { + "get": { + "tags": [ + "Authentication" + ], + "summary": "Email verification endpoint", + "responses": { + "default": { + "description": "Email verification successful and redirected", + "headers": { + "Location": { + "description": "URL to redirect to", + "schema": { + "type": "string" + } + }, + "Http-Response-Code": { + "description": "HTTP Response Code", + "schema": { + "type": "integer" + } + } + } + }, + "\"401\"": { + "description": "Invalid\/Expired URL provided" + } + }, + "requestBody": { + "content": { + "application\/json": { + "example": { + "user": { + "id": "example_user_id", + "name": "example_name", + "email": "example_email", + "password": "example_password" + }, + "signature": "example_signature" + } + } + }, + "description": "User object and Request Signature" + }, + "security": [ + { + "sanctum": [] + } + ] + } + }, + "\/api\/auth\/email\/resend": { + "get": { + "tags": [ + "Authentication" + ], + "summary": "Resend email verification endpoint", + "responses": { + "default": { + "description": "Email verification link sent to your email address" + } + }, + "security": [ + { + "sanctum": [] + } + ] + } } }, "servers": [