openehr-its 0.0.78

openEHR ITS (Implementation Technology Specifications): canonical JSON + canonical XML serialization of the RM, the generated ITS-REST 1.1.0 API contract, and the OPT 1.4 and AOM2 archetype XML codecs
Documentation
// @generated by openehr-codegen (emit-rest) — DO NOT EDIT.
// SPDX-FileCopyrightText: Vernum Projecten B.V.
// SPDX-FileCopyrightText: openEHR Foundation
// SPDX-License-Identifier: Apache-2.0
//! ITS-REST contract for the `admin` API group: DTOs, per-operation
//! param structs, per-response headers structs, the `server` and
//! `client` halves, and the route table.

#![allow(
    clippy::all,
    clippy::pedantic,
    clippy::nursery,
    dead_code,
    unused_imports,
    unused_variables,
    reason = "mechanically generated contract text: the OAS is emitted in full (every DTO, param struct and route, whether or not this workspace consumes it yet), so style and dead-code lints do not apply — the hand-written runtime and the implementing adapter carry the lint bar"
)]
use serde::{Deserialize, Serialize};

/// Parameters for `admin_ehr_delete` (path/query/header).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminEhrDeleteParams {
    /// `ehr_id` (path)
    pub ehr_id: String,
}

impl AdminEhrDeleteParams {
    /// The parameters of `admin_ehr_delete`, one per field, in field order.
    pub const PARAMS: &'static [crate::rest::routes::Param] = &[crate::rest::routes::Param {
        name: "ehr_id",
        location: crate::rest::routes::ParamLocation::Path,
        required: true,
        explode: false,
        kind: crate::rest::routes::ParamKind::Uuid,
    }];
}

/// Parameters for `admin_ehr_delete_all` (path/query/header).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminEhrDeleteAllParams {
    #[serde(skip_serializing_if = "Option::is_none")]
    /// `ehr_id` (query)
    pub ehr_id: Option<String>,
}

impl AdminEhrDeleteAllParams {
    /// The parameters of `admin_ehr_delete_all`, one per field, in field order.
    pub const PARAMS: &'static [crate::rest::routes::Param] = &[crate::rest::routes::Param {
        name: "ehr_id",
        location: crate::rest::routes::ParamLocation::Query,
        required: false,
        explode: true,
        kind: crate::rest::routes::ParamKind::Uuid,
    }];
}

/// The server half of the `admin` API group (ITS-REST): the `AdminApi`
/// trait an implementation provides, one success-answer enum per operation,
/// and `router`, which binds every operation of the route table to its
/// trait method over axum.
#[cfg(feature = "rest-server")]
pub mod server {
    use super::*;

    /// The answers `DELETE /admin/ehr/{ehr_id}` succeeds with: one variant per `2xx`/`3xx` status
    /// the OAS documents (an error is a [`crate::rest::runtime::Refusal`]).
    #[derive(Debug, Clone)]
    pub enum AdminEhrDeleteResponse {
        /// The `202` answer.
        Accepted,
        /// The `204` answer.
        NoContent,
    }

    /// The answers `DELETE /admin/ehr/all{?ehr_id*}` succeeds with: one variant per `2xx`/`3xx` status
    /// the OAS documents (an error is a [`crate::rest::runtime::Refusal`]).
    #[derive(Debug, Clone)]
    pub enum AdminEhrDeleteAllResponse {
        /// The `202` answer.
        Accepted,
        /// The `204` answer.
        NoContent,
    }

    /// Server contract for the `admin` API group (ITS-REST).
    ///
    /// Every method defaults to refusing with `ApiError::NotImplemented` (`501`),
    /// so an implementor overrides only the operations it supports; `router`
    /// serves an implementation over axum. A method refuses with a
    /// [`crate::rest::runtime::Refusal`]: `?` turns an `ApiError` into one,
    /// and `Refusal::with_headers` adds the headers the OAS declares for the
    /// answer (the `ETag` of a `412`, for one).
    #[async_trait::async_trait]
    pub trait AdminApi {
        /// `DELETE /admin/ehr/{ehr_id}`
        async fn admin_ehr_delete(
            &self,
            params: AdminEhrDeleteParams,
        ) -> Result<AdminEhrDeleteResponse, crate::rest::runtime::Refusal> {
            Err(crate::rest::runtime::ApiError::NotImplemented.into())
        }
        /// `DELETE /admin/ehr/all{?ehr_id*}`
        async fn admin_ehr_delete_all(
            &self,
            params: AdminEhrDeleteAllParams,
        ) -> Result<AdminEhrDeleteAllResponse, crate::rest::runtime::Refusal> {
            Err(crate::rest::runtime::ApiError::NotImplemented.into())
        }
    }

    /// The axum router serving every operation of the `admin` group over `api`.
    ///
    /// Each route is bound at its OAS path relative to the API base (an RFC 6570
    /// query expansion dropped, path captures named by segment position). A
    /// handler decodes the request into the operation's params struct and body
    /// — a missing or unparseable parameter answers `400` naming it, a
    /// canonical-JSON body sent as another `Content-Type` answers `415` — and
    /// encodes the trait method's answer, or its `Refusal` as the ITS-REST
    /// `Error` body with the refusal's headers. Mount it under the base path
    /// with `axum::Router::nest`.
    ///
    /// The router carries no fallback, so group routers merge freely (axum
    /// refuses to merge two routers that both carry one); finish the merged
    /// router with `crate::rest::server::with_fallbacks` for the `404` and `405`
    /// answers, or take `crate::rest::server::router`, which does both.
    ///
    /// The typed bodies are canonical JSON only: a server that also serves
    /// canonical XML or a Simplified Format routes those requests itself, and
    /// the `accept` parameter reaches the trait method, which answers
    /// `ApiError::NotAcceptable` for a representation it does not serve.
    pub fn router<S>(api: std::sync::Arc<S>) -> axum::Router
    where
        S: AdminApi + Send + Sync + 'static,
    {
        axum::Router::new()
            .route(
                "/admin/ehr/{p3}",
                axum::routing::on(
                    axum::routing::MethodFilter::DELETE,
                    handle_admin_ehr_delete::<S>,
                ),
            )
            .route(
                "/admin/ehr/all",
                axum::routing::on(
                    axum::routing::MethodFilter::DELETE,
                    handle_admin_ehr_delete_all::<S>,
                ),
            )
            .with_state(api)
    }

    /// Serves `DELETE /admin/ehr/{ehr_id}` through [`AdminApi::admin_ehr_delete`].
    async fn handle_admin_ehr_delete<S>(
        axum::extract::State(api): axum::extract::State<std::sync::Arc<S>>,
        path: Result<
            axum::extract::RawPathParams,
            axum::extract::rejection::RawPathParamsRejection,
        >,
    ) -> axum::response::Response
    where
        S: AdminApi + Send + Sync + 'static,
    {
        let served: Result<axum::response::Response, crate::rest::runtime::Refusal> = async {
            let path = crate::rest::server::PathCaptures::new(path)?;
            let params = AdminEhrDeleteParams {
                ehr_id: path.value("p3", "ehr_id")?,
            };
            let reply: crate::rest::server::Reply = match api.admin_ehr_delete(params).await? {
                AdminEhrDeleteResponse::Accepted => {
                    crate::rest::server::Reply::new(http::StatusCode::ACCEPTED)
                }
                AdminEhrDeleteResponse::NoContent => {
                    crate::rest::server::Reply::new(http::StatusCode::NO_CONTENT)
                }
            };
            Ok(reply.finish())
        }
        .await;
        crate::rest::server::respond(served)
    }

    /// Serves `DELETE /admin/ehr/all{?ehr_id*}` through [`AdminApi::admin_ehr_delete_all`].
    async fn handle_admin_ehr_delete_all<S>(
        axum::extract::State(api): axum::extract::State<std::sync::Arc<S>>,
        axum::extract::RawQuery(query): axum::extract::RawQuery,
    ) -> axum::response::Response
    where
        S: AdminApi + Send + Sync + 'static,
    {
        let served: Result<axum::response::Response, crate::rest::runtime::Refusal> = async {
            let query = crate::rest::server::QueryPairs::parse(query.as_deref())?;
            let params = AdminEhrDeleteAllParams {
                ehr_id: query.optional("ehr_id")?,
            };
            let reply: crate::rest::server::Reply = match api.admin_ehr_delete_all(params).await? {
                AdminEhrDeleteAllResponse::Accepted => {
                    crate::rest::server::Reply::new(http::StatusCode::ACCEPTED)
                }
                AdminEhrDeleteAllResponse::NoContent => {
                    crate::rest::server::Reply::new(http::StatusCode::NO_CONTENT)
                }
            };
            Ok(reply.finish())
        }
        .await;
        crate::rest::server::respond(served)
    }
}

/// The client half of the `admin` API group (ITS-REST): one method per
/// operation over a [`crate::rest::client::Client`], answering an outcome
/// enum with one variant per status the OAS documents for it.
#[cfg(feature = "rest-client")]
pub mod client {
    use super::*;

    /// The outcome of `DELETE /admin/ehr/{ehr_id}`: one variant per status the OAS documents.
    /// A status outside this set is a [`crate::rest::client::ClientError`].
    #[derive(Debug, Clone)]
    pub enum AdminEhrDeleteOutcome {
        /// The `202` answer.
        Accepted,
        /// The `204` answer.
        NoContent,
        /// The `404` answer.
        NotFound {
            /// The error body as received, decoded as the ITS-REST `Error` when it is one.
            body: crate::rest::client::ErrorBody,
        },
    }

    /// The outcome of `DELETE /admin/ehr/all{?ehr_id*}`: one variant per status the OAS documents.
    /// A status outside this set is a [`crate::rest::client::ClientError`].
    #[derive(Debug, Clone)]
    pub enum AdminEhrDeleteAllOutcome {
        /// The `202` answer.
        Accepted,
        /// The `204` answer.
        NoContent,
        /// The `404` answer.
        NotFound {
            /// The error body as received, decoded as the ITS-REST `Error` when it is one.
            body: crate::rest::client::ErrorBody,
        },
        /// The `405` answer.
        MethodNotAllowed {
            /// The error body as received, decoded as the ITS-REST `Error` when it is one.
            body: crate::rest::client::ErrorBody,
        },
    }

    /// The `admin` API group over one configured CDR.
    #[derive(Debug, Clone)]
    pub struct AdminClient<'c, T> {
        client: &'c crate::rest::client::Client<T>,
        options: crate::rest::client::CallOptions,
    }

    impl<'c, T: crate::rest::client::Transport> AdminClient<'c, T> {
        /// The `admin` API group over `client`.
        #[must_use]
        pub fn new(client: &'c crate::rest::client::Client<T>) -> Self {
            Self {
                client,
                options: crate::rest::client::CallOptions::default(),
            }
        }

        /// This group client applying `options` (a deadline, extra headers) to
        /// every call it makes.
        #[must_use]
        pub fn with_options(mut self, options: crate::rest::client::CallOptions) -> Self {
            self.options = options;
            self
        }

        /// `DELETE /admin/ehr/{ehr_id}`
        ///
        /// # Errors
        /// A status the OAS does not document for this operation, a refused
        /// credential, a service failure, an undecodable body, or a request
        /// that could not be sent — see [`crate::rest::client::ClientError`].
        pub async fn admin_ehr_delete(
            &self,
            params: &AdminEhrDeleteParams,
        ) -> Result<AdminEhrDeleteOutcome, crate::rest::client::ClientError> {
            let mut request = crate::rest::client::Request::new(
                http::Method::DELETE,
                format!(
                    "/admin/ehr/{}",
                    crate::rest::client::path_segment(&params.ehr_id)
                ),
            );
            request.apply_options(&self.options);
            let answer = self.client.execute(request).await?;
            match answer.status() {
                http::StatusCode::ACCEPTED => Ok(AdminEhrDeleteOutcome::Accepted),
                http::StatusCode::NO_CONTENT => Ok(AdminEhrDeleteOutcome::NoContent),
                http::StatusCode::NOT_FOUND => Ok(AdminEhrDeleteOutcome::NotFound {
                    body: answer.error_body(),
                }),
                _ => Err(answer.into_undocumented()),
            }
        }

        /// `DELETE /admin/ehr/all{?ehr_id*}`
        ///
        /// # Errors
        /// A status the OAS does not document for this operation, a refused
        /// credential, a service failure, an undecodable body, or a request
        /// that could not be sent — see [`crate::rest::client::ClientError`].
        pub async fn admin_ehr_delete_all(
            &self,
            params: &AdminEhrDeleteAllParams,
        ) -> Result<AdminEhrDeleteAllOutcome, crate::rest::client::ClientError> {
            let mut request = crate::rest::client::Request::new(
                http::Method::DELETE,
                String::from("/admin/ehr/all"),
            );
            if let Some(value) = params.ehr_id.as_ref() {
                request.query("ehr_id", value);
            }
            request.apply_options(&self.options);
            let answer = self.client.execute(request).await?;
            match answer.status() {
                http::StatusCode::ACCEPTED => Ok(AdminEhrDeleteAllOutcome::Accepted),
                http::StatusCode::NO_CONTENT => Ok(AdminEhrDeleteAllOutcome::NoContent),
                http::StatusCode::NOT_FOUND => Ok(AdminEhrDeleteAllOutcome::NotFound {
                    body: answer.error_body(),
                }),
                http::StatusCode::METHOD_NOT_ALLOWED => {
                    Ok(AdminEhrDeleteAllOutcome::MethodNotAllowed {
                        body: answer.error_body(),
                    })
                }
                _ => Err(answer.into_undocumented()),
            }
        }
    }
}
/// The operations of this group as `(method, path, operation_id)`, in OAS
/// document order: `server::router` binds each to its trait method, and
/// `crate::rest::routes::lookup` matches a request path against them.
pub const ROUTES: &[(&str, &str, &str)] = &[
    ("DELETE", "/admin/ehr/{ehr_id}", "admin_ehr_delete"),
    ("DELETE", "/admin/ehr/all{?ehr_id*}", "admin_ehr_delete_all"),
];

/// The declared parameters of each operation, index-aligned with [`ROUTES`]:
/// the operation's `*Params::PARAMS`, empty when it declares none.
pub const ROUTE_PARAMS: &[&[crate::rest::routes::Param]] = &[
    AdminEhrDeleteParams::PARAMS,
    AdminEhrDeleteAllParams::PARAMS,
];

const _: () = assert!(
    ROUTE_PARAMS.len() == ROUTES.len(),
    "ROUTE_PARAMS carries one row per ROUTES entry"
);