Skip to main content

haste_server/fhir_client/
mod.rs

1use crate::{
2    auth_n::middleware::jwt::User,
3    config::ServerConfig,
4    fhir_client::{
5        middleware::{
6            ServerMiddlewareContext, ServerMiddlewareNext, ServerMiddlewareOutput,
7            ServerMiddlewareState,
8        },
9        utilities::request_to_resource_type,
10    },
11};
12use derivative::Derivative;
13use haste_fhir_client::{
14    FHIRClient,
15    middleware::{Middleware, MiddlewareChain},
16    request::{
17        DeleteRequest, DeleteResponse, FHIRBatchRequest, FHIRConditionalUpdateRequest,
18        FHIRCreateRequest, FHIRDeleteInstanceRequest, FHIRDeleteSystemRequest,
19        FHIRDeleteTypeRequest, FHIRHistoryInstanceRequest, FHIRHistorySystemRequest,
20        FHIRHistoryTypeRequest, FHIRReadRequest, FHIRRequest, FHIRResponse, FHIRSearchTypeRequest,
21        FHIRTransactionRequest, FHIRUpdateInstanceRequest, FHIRVersionReadRequest, HistoryRequest,
22        HistoryResponse, SearchRequest, SearchResponse, UpdateRequest,
23    },
24    url::ParsedParameters,
25};
26use haste_fhir_model::r4::generated::resources::{
27    Bundle, CapabilityStatement, Parameters, Resource, ResourceType,
28};
29use haste_fhir_operation_error::{OperationOutcomeError, derive::OperationOutcomeError};
30use haste_fhir_search::SearchEngine;
31use haste_fhir_terminology::FHIRTerminology;
32use haste_jwt::{
33    AuthorId, AuthorKind, ProjectId, TenantId, UserRole, VersionId,
34    claims::SubscriptionTier,
35    scopes::{
36        SMARTResourceScope, Scope, Scopes, SmartResourceScopeLevel, SmartResourceScopePermission,
37        SmartResourceScopePermissions, SmartResourceScopeUser, SmartScope,
38    },
39};
40use haste_operation_executor::providers::deno_embedded::pool::DenoPool;
41use haste_repository::{Repository, types::SupportedFHIRVersions};
42use std::{
43    fmt::Debug,
44    sync::{Arc, LazyLock},
45};
46
47mod batch_transaction_processing;
48mod compartment;
49mod middleware;
50mod resolver;
51mod subscription_limits;
52mod utilities;
53
54#[derive(OperationOutcomeError, Debug)]
55pub enum StorageError {
56    #[error(
57        code = "not-supported",
58        diagnostic = "Storage not supported for fhir method."
59    )]
60    NotSupported,
61    #[error(
62        code = "exception",
63        diagnostic = "No response was returned from the request."
64    )]
65    NoResponse,
66    #[error(
67        code = "not-found",
68        diagnostic = "Resource '{arg0:?}' with id '{arg1}' not found."
69    )]
70    NotFound(ResourceType, String),
71    #[error(code = "invalid", diagnostic = "Invalid resource type.")]
72    InvalidType,
73}
74
75#[derive(Derivative)]
76#[derivative(Debug)]
77pub struct ServerCTX<Client: FHIRClient<Arc<Self>, OperationOutcomeError>> {
78    pub tenant: TenantId,
79    pub project: ProjectId,
80    pub fhir_version: SupportedFHIRVersions,
81    pub user: Arc<User>,
82    #[derivative(Debug = "ignore")]
83    pub client: Arc<Client>,
84    #[derivative(Debug = "ignore")]
85    pub rate_limit: Arc<dyn haste_rate_limit::RateLimit>,
86    pub tracing_id: Option<String>,
87}
88
89impl<Client: FHIRClient<Arc<Self>, OperationOutcomeError>> ServerCTX<Client> {
90    pub fn swap_client<NewClient: FHIRClient<Arc<ServerCTX<NewClient>>, OperationOutcomeError>>(
91        &self,
92        new_client: Arc<NewClient>,
93    ) -> ServerCTX<NewClient> {
94        ServerCTX {
95            tenant: self.tenant.clone(),
96            project: self.project.clone(),
97            fhir_version: self.fhir_version.clone(),
98            user: self.user.clone(),
99            client: new_client,
100            rate_limit: self.rate_limit.clone(),
101            tracing_id: self.tracing_id.clone(),
102        }
103    }
104
105    pub fn new(
106        tenant: TenantId,
107        project: ProjectId,
108        fhir_version: SupportedFHIRVersions,
109        user: Arc<User>,
110        client: Arc<Client>,
111        rate_limit: Arc<dyn haste_rate_limit::RateLimit>,
112    ) -> Self {
113        ServerCTX {
114            tenant,
115            project,
116            fhir_version,
117            user,
118            client,
119            rate_limit,
120            tracing_id: None,
121        }
122    }
123
124    pub fn system(
125        tenant: TenantId,
126        project: ProjectId,
127        client: Arc<Client>,
128        rate_limit: Arc<dyn haste_rate_limit::RateLimit>,
129    ) -> Self {
130        ServerCTX {
131            tenant: tenant.clone(),
132            project: project.clone(),
133            fhir_version: SupportedFHIRVersions::R4,
134            user: Arc::new(User {
135                token: None,
136                claims: haste_jwt::claims::UserTokenClaims {
137                    sub: AuthorId::System,
138                    exp: 0,
139                    aud: AuthorKind::System.to_string(),
140                    user_role: UserRole::Owner,
141                    project: Some(project),
142                    tenant,
143                    subscription_tier: SubscriptionTier::Unlimited,
144                    scope: Scopes(vec![Scope::SMART(SmartScope::Resource(
145                        SMARTResourceScope {
146                            user: SmartResourceScopeUser::System,
147                            level: SmartResourceScopeLevel::AllResources,
148                            permissions: SmartResourceScopePermissions::new(vec![
149                                SmartResourceScopePermission::Create,
150                                SmartResourceScopePermission::Read,
151                                SmartResourceScopePermission::Update,
152                                SmartResourceScopePermission::Delete,
153                                SmartResourceScopePermission::Search,
154                            ]),
155                        },
156                    ))]),
157                    fhir_user: None,
158                    user_id: AuthorId::System,
159                    resource_type: AuthorKind::System,
160                    access_policy_version_ids: vec![],
161                    membership: None,
162                },
163            }),
164            client,
165            rate_limit,
166            tracing_id: None,
167        }
168    }
169
170    pub fn with_tracing_id(mut self, tracing_id: Option<String>) -> Self {
171        self.tracing_id = tracing_id;
172        self
173    }
174}
175
176struct ClientState<
177    Repo: Repository + Send + Sync,
178    Search: SearchEngine + Send + Sync,
179    Terminology: FHIRTerminology + Send + Sync,
180> {
181    repo: Arc<Repo>,
182    search: Arc<Search>,
183    terminology: Arc<Terminology>,
184    audit_repo: Option<Arc<Repo>>,
185    config: Arc<ServerConfig>,
186    deno_pool: Arc<DenoPool>,
187}
188
189pub struct Route<State, Client: FHIRClient<Arc<ServerCTX<Client>>, OperationOutcomeError>> {
190    filter: Box<dyn Fn(&FHIRRequest) -> bool + Send + Sync>,
191    middleware: Middleware<
192        Arc<State>,
193        Arc<ServerCTX<Client>>,
194        FHIRRequest,
195        FHIRResponse,
196        OperationOutcomeError,
197    >,
198}
199
200pub struct FHIRServerClient<
201    Repo: Repository + Send + Sync + 'static,
202    Search: SearchEngine + Send + Sync + 'static,
203    Terminology: FHIRTerminology + Send + Sync + 'static,
204> {
205    state: Arc<ClientState<Repo, Search, Terminology>>,
206    middleware: Middleware<
207        Arc<ClientState<Repo, Search, Terminology>>,
208        Arc<ServerCTX<Self>>,
209        FHIRRequest,
210        FHIRResponse,
211        OperationOutcomeError,
212    >,
213}
214
215pub struct RouterMiddleware<
216    State,
217    Client: FHIRClient<Arc<ServerCTX<Client>>, OperationOutcomeError>,
218> {
219    routes: Arc<Vec<Route<State, Client>>>,
220}
221
222impl<State, Client: FHIRClient<Arc<ServerCTX<Client>>, OperationOutcomeError>>
223    RouterMiddleware<State, Client>
224{
225    pub fn new(routes: Arc<Vec<Route<State, Client>>>) -> Self {
226        RouterMiddleware { routes }
227    }
228}
229
230impl<
231    Repo: Repository + Send + Sync + 'static,
232    Search: SearchEngine + Send + Sync + 'static,
233    Terminology: FHIRTerminology + Send + Sync + 'static,
234    Client: FHIRClient<Arc<ServerCTX<Client>>, OperationOutcomeError> + 'static,
235>
236    MiddlewareChain<
237        ServerMiddlewareState<Repo, Search, Terminology>,
238        Arc<ServerCTX<Client>>,
239        FHIRRequest,
240        FHIRResponse,
241        OperationOutcomeError,
242    > for RouterMiddleware<ClientState<Repo, Search, Terminology>, Client>
243{
244    fn call(
245        &self,
246        state: ServerMiddlewareState<Repo, Search, Terminology>,
247        context: ServerMiddlewareContext<Client>,
248        next: Option<
249            Arc<ServerMiddlewareNext<Client, ServerMiddlewareState<Repo, Search, Terminology>>>,
250        >,
251    ) -> ServerMiddlewareOutput<Client> {
252        let routes = self.routes.clone();
253        Box::pin(async move {
254            let route = routes.iter().find(|r| (r.filter)(&context.request));
255
256            match route {
257                Some(route) => {
258                    let context = route
259                        .middleware
260                        .call(state.clone(), context.ctx, context.request)
261                        .await?;
262                    if let Some(next) = next {
263                        next(state, context).await
264                    } else {
265                        Ok(context)
266                    }
267                }
268                None => {
269                    if let Some(next) = next {
270                        next(state, context).await
271                    } else {
272                        Ok(context)
273                    }
274                }
275            }
276        })
277    }
278}
279
280static ARTIFACT_TYPES: &[ResourceType] = &[
281    ResourceType::ValueSet,
282    ResourceType::CodeSystem,
283    ResourceType::StructureDefinition,
284    ResourceType::SearchParameter,
285];
286
287static TENANT_AUTH_TYPES: &[ResourceType] = &[
288    ResourceType::User,
289    ResourceType::Project,
290    ResourceType::IdentityProvider,
291];
292static PROJECT_AUTH_TYPES: &[ResourceType] = &[ResourceType::Membership];
293
294static SPECIAL_TYPES: LazyLock<Vec<ResourceType>> =
295    LazyLock::new(|| [TENANT_AUTH_TYPES, PROJECT_AUTH_TYPES, ARTIFACT_TYPES].concat());
296
297pub struct ServerClientConfig<
298    Repo: Repository + Send + Sync + 'static,
299    Search: SearchEngine + Send + Sync + 'static,
300    Terminology: FHIRTerminology + Send + Sync + 'static,
301> {
302    pub repo: Arc<Repo>,
303    pub audit_repo: Option<Arc<Repo>>,
304    pub search: Arc<Search>,
305    pub terminology: Arc<Terminology>,
306    pub mutate_artifacts: bool,
307    pub config: Arc<ServerConfig>,
308    pub deno_pool: Arc<DenoPool>,
309}
310
311impl<
312    Repo: Repository + Send + Sync + 'static,
313    Search: SearchEngine + Send + Sync + 'static,
314    Terminology: FHIRTerminology + Send + Sync + 'static,
315> ServerClientConfig<Repo, Search, Terminology>
316{
317    pub fn new(
318        repo: Arc<Repo>,
319        search: Arc<Search>,
320        terminology: Arc<Terminology>,
321        config: Arc<ServerConfig>,
322        deno_pool: Arc<DenoPool>,
323    ) -> Self {
324        ServerClientConfig {
325            repo,
326            audit_repo: None,
327            search,
328            terminology,
329            mutate_artifacts: false,
330            config,
331            deno_pool,
332        }
333    }
334
335    pub fn with_mutate_artifacts(mut self, mutate_artifacts: bool) -> Self {
336        self.mutate_artifacts = mutate_artifacts;
337        self
338    }
339
340    pub fn with_audit_repo(mut self, audit_repo: Option<Arc<Repo>>) -> Self {
341        self.audit_repo = audit_repo;
342        self
343    }
344}
345
346impl<
347    Repo: Repository + Send + Sync + 'static,
348    Search: SearchEngine + Send + Sync + 'static,
349    Terminology: FHIRTerminology + Send + Sync + 'static,
350> FHIRServerClient<Repo, Search, Terminology>
351{
352    pub fn new(config: ServerClientConfig<Repo, Search, Terminology>) -> Self {
353        let route_middleware = RouterMiddleware::new(Arc::new(vec![
354            // Clinical resources.
355            Route {
356                filter: Box::new(|req: &FHIRRequest| match req {
357                    FHIRRequest::Invocation(_) | FHIRRequest::Capabilities => false,
358                    _ => {
359                        if let Some(resource_type) = request_to_resource_type(req) {
360                            !SPECIAL_TYPES.contains(resource_type)
361                        } else {
362                            true
363                        }
364                    }
365                }),
366                middleware: Middleware::new(vec![Box::new(middleware::storage::Middleware::new())]),
367            },
368            // Artifact routes.
369            Route {
370                filter: Box::new(|req: &FHIRRequest| match req {
371                    FHIRRequest::Create(_)
372                    | FHIRRequest::Update(_)
373                    | FHIRRequest::Delete(_)
374                    | FHIRRequest::Read(_)
375                    | FHIRRequest::Search(SearchRequest::Type(_)) => {
376                        if let Some(resource_type) = request_to_resource_type(req) {
377                            ARTIFACT_TYPES.contains(resource_type)
378                        } else {
379                            false
380                        }
381                    }
382                    _ => false,
383                }),
384
385                middleware: Middleware::new(vec![
386                    Box::new(middleware::set_artifact_tenant::Middleware::new()),
387                    Box::new(middleware::storage::Middleware::new()),
388                ]),
389            },
390            // Operation routes
391            Route {
392                filter: Box::new(|req: &FHIRRequest| match req {
393                    FHIRRequest::Invocation(_) => true,
394                    _ => false,
395                }),
396                middleware: Middleware::new(vec![Box::new(
397                    middleware::operations::Middleware::new(config.deno_pool.clone()),
398                )]),
399            },
400            // Authentication routes.
401            Route {
402                filter: Box::new(|req: &FHIRRequest| match req {
403                    FHIRRequest::Invocation(_) => false,
404                    _ => request_to_resource_type(req)
405                        .is_some_and(|rt| PROJECT_AUTH_TYPES.contains(rt)),
406                }),
407                middleware: Middleware::new(vec![
408                    Box::new(middleware::transaction::Middleware::new()),
409                    Box::new(middleware::custom_models::membership::Middleware::new()),
410                    Box::new(middleware::storage::Middleware::new()),
411                ]),
412            },
413            // Tenant auth routes.
414            Route {
415                filter: Box::new(|req: &FHIRRequest| match req {
416                    FHIRRequest::Invocation(_) => false,
417                    _ => request_to_resource_type(req)
418                        .is_some_and(|rt| TENANT_AUTH_TYPES.contains(rt)),
419                }),
420                middleware: Middleware::new(vec![
421                    Box::new(
422                        middleware::check_project::SetProjectReadOnlyMiddleware::new(
423                            ProjectId::System,
424                        ),
425                    ),
426                    // Confirm in system project as above will only set to system if readonly.
427                    Box::new(middleware::check_project::Middleware::new(
428                        ProjectId::System,
429                    )),
430                    Box::new(middleware::transaction::Middleware::new()),
431                    Box::new(middleware::custom_models::project::Middleware::new()),
432                    Box::new(middleware::custom_models::user::Middleware::new()),
433                    Box::new(middleware::storage::Middleware::new()),
434                ]),
435            },
436        ]));
437
438        FHIRServerClient {
439            state: Arc::new(ClientState {
440                repo: config.repo,
441                audit_repo: config.audit_repo,
442                search: config.search,
443                terminology: config.terminology,
444                config: config.config,
445                deno_pool: config.deno_pool,
446            }),
447            middleware: Middleware::new(vec![
448                Box::new(middleware::auditing::Middleware::new()),
449                Box::new(middleware::tenant_tier_limits::Middleware::new()),
450                Box::new(middleware::rate_limit::Middleware::new()),
451                Box::new(middleware::element_filtering::Middleware::new()),
452                Box::new(middleware::auth_z::scope_check::SMARTScopeAccessMiddleware::new()),
453                Box::new(middleware::auth_z::access_control::AccessControlMiddleware::new()),
454                Box::new(middleware::validation::Middleware::new()),
455                Box::new(route_middleware),
456                Box::new(middleware::capabilities::Middleware::new()),
457            ]),
458        }
459    }
460
461    /// The `DenoPool` backing this client's custom-operations middleware.
462    ///
463    /// Used to hand the same pool to derived clients (transaction-scoped,
464    /// batch-scoped, etc.) instead of each one spinning up its own set of
465    /// worker threads.
466    pub fn deno_pool(&self) -> Arc<DenoPool> {
467        self.state.deno_pool.clone()
468    }
469}
470
471impl<
472    Repo: Repository + Send + Sync + 'static,
473    Search: SearchEngine + Send + Sync + 'static,
474    Terminology: FHIRTerminology + Send + Sync + 'static,
475> FHIRClient<Arc<ServerCTX<Self>>, OperationOutcomeError>
476    for FHIRServerClient<Repo, Search, Terminology>
477{
478    #[tracing::instrument(name = "fhir_server_client", skip(self))]
479    async fn request(
480        &self,
481        _ctx: Arc<ServerCTX<Self>>,
482        request: FHIRRequest,
483    ) -> Result<FHIRResponse, OperationOutcomeError> {
484        tracing::info!("Processing request");
485        let response = self
486            .middleware
487            .call(self.state.clone(), _ctx, request)
488            .await?;
489
490        response
491            .response
492            .ok_or_else(|| StorageError::NoResponse.into())
493    }
494
495    async fn capabilities(
496        &self,
497        _ctx: Arc<ServerCTX<Self>>,
498    ) -> Result<CapabilityStatement, OperationOutcomeError> {
499        let res = self
500            .middleware
501            .call(self.state.clone(), _ctx, FHIRRequest::Capabilities)
502            .await?;
503
504        match res.response {
505            Some(FHIRResponse::Capabilities(capabilities_response)) => {
506                Ok(capabilities_response.capabilities)
507            }
508            _ => panic!("Unexpected response type"),
509        }
510    }
511
512    async fn search_system(
513        &self,
514        _ctx: Arc<ServerCTX<Self>>,
515        _parameters: ParsedParameters,
516    ) -> Result<Bundle, OperationOutcomeError> {
517        todo!()
518    }
519
520    async fn search_type(
521        &self,
522        ctx: Arc<ServerCTX<Self>>,
523        resource_type: ResourceType,
524        parameters: ParsedParameters,
525    ) -> Result<Bundle, OperationOutcomeError> {
526        let res = self
527            .middleware
528            .call(
529                self.state.clone(),
530                ctx,
531                FHIRRequest::Search(SearchRequest::Type(FHIRSearchTypeRequest {
532                    resource_type,
533                    parameters,
534                })),
535            )
536            .await?;
537
538        match res.response {
539            Some(FHIRResponse::Search(SearchResponse::Type(search_response))) => {
540                Ok(search_response.bundle)
541            }
542            _ => panic!("Unexpected response type"),
543        }
544    }
545
546    async fn create(
547        &self,
548        ctx: Arc<ServerCTX<Self>>,
549        resource_type: ResourceType,
550        resource: Resource,
551    ) -> Result<Resource, OperationOutcomeError> {
552        let res = self
553            .middleware
554            .call(
555                self.state.clone(),
556                ctx,
557                FHIRRequest::Create(FHIRCreateRequest {
558                    resource_type,
559                    resource,
560                }),
561            )
562            .await?;
563
564        match res.response {
565            Some(FHIRResponse::Create(create_response)) => Ok(create_response.resource),
566            _ => panic!("Unexpected response type"),
567        }
568    }
569
570    async fn update(
571        &self,
572        ctx: Arc<ServerCTX<Self>>,
573        resource_type: ResourceType,
574        id: String,
575        resource: Resource,
576    ) -> Result<Resource, OperationOutcomeError> {
577        let res = self
578            .middleware
579            .call(
580                self.state.clone(),
581                ctx,
582                FHIRRequest::Update(UpdateRequest::Instance(FHIRUpdateInstanceRequest {
583                    resource_type,
584                    id,
585                    resource,
586                })),
587            )
588            .await?;
589
590        match res.response {
591            Some(FHIRResponse::Create(create_response)) => Ok(create_response.resource),
592            Some(FHIRResponse::Update(update_response)) => Ok(update_response.resource),
593            _ => panic!("Unexpected response type {:?}", res.response),
594        }
595    }
596
597    async fn conditional_update(
598        &self,
599        ctx: Arc<ServerCTX<Self>>,
600        resource_type: ResourceType,
601        parameters: ParsedParameters,
602        resource: Resource,
603    ) -> Result<Resource, OperationOutcomeError> {
604        let res = self
605            .middleware
606            .call(
607                self.state.clone(),
608                ctx,
609                FHIRRequest::Update(UpdateRequest::Conditional(FHIRConditionalUpdateRequest {
610                    resource_type,
611                    parameters,
612                    resource,
613                })),
614            )
615            .await?;
616
617        match res.response {
618            Some(FHIRResponse::Create(create_response)) => Ok(create_response.resource),
619            Some(FHIRResponse::Update(update_response)) => Ok(update_response.resource),
620            _ => panic!("Unexpected response type {:?}", res.response),
621        }
622    }
623
624    async fn patch(
625        &self,
626        _ctx: Arc<ServerCTX<Self>>,
627        _resource_type: ResourceType,
628        _id: String,
629        _patches: json_patch::Patch,
630    ) -> Result<Resource, OperationOutcomeError> {
631        todo!()
632    }
633
634    async fn read(
635        &self,
636        ctx: Arc<ServerCTX<Self>>,
637        resource_type: ResourceType,
638        id: String,
639    ) -> Result<Option<Resource>, OperationOutcomeError> {
640        let res = self
641            .middleware
642            .call(
643                self.state.clone(),
644                ctx,
645                FHIRRequest::Read(FHIRReadRequest { resource_type, id }),
646            )
647            .await?;
648
649        match res.response {
650            Some(FHIRResponse::Read(read_response)) => Ok(read_response.resource),
651            _ => panic!("Unexpected response type"),
652        }
653    }
654
655    async fn vread(
656        &self,
657        ctx: Arc<ServerCTX<Self>>,
658        resource_type: ResourceType,
659        id: String,
660        version_id: String,
661    ) -> Result<Option<Resource>, OperationOutcomeError> {
662        let res = self
663            .middleware
664            .call(
665                self.state.clone(),
666                ctx,
667                FHIRRequest::VersionRead(FHIRVersionReadRequest {
668                    resource_type,
669                    id,
670                    version_id: VersionId::new(version_id),
671                }),
672            )
673            .await?;
674
675        match res.response {
676            Some(FHIRResponse::VersionRead(version_read_response)) => {
677                Ok(Some(version_read_response.resource))
678            }
679            _ => panic!("Unexpected response type"),
680        }
681    }
682
683    async fn delete_instance(
684        &self,
685        ctx: Arc<ServerCTX<Self>>,
686        resource_type: ResourceType,
687        id: String,
688    ) -> Result<(), OperationOutcomeError> {
689        let res = self
690            .middleware
691            .call(
692                self.state.clone(),
693                ctx,
694                FHIRRequest::Delete(DeleteRequest::Instance(FHIRDeleteInstanceRequest {
695                    resource_type,
696                    id,
697                })),
698            )
699            .await?;
700
701        match res.response {
702            Some(FHIRResponse::Delete(DeleteResponse::Instance(_delete_response))) => Ok(()),
703            _ => panic!("Unexpected response type"),
704        }
705    }
706
707    async fn delete_type(
708        &self,
709        ctx: Arc<ServerCTX<Self>>,
710        resource_type: ResourceType,
711        parameters: ParsedParameters,
712    ) -> Result<(), OperationOutcomeError> {
713        let res = self
714            .middleware
715            .call(
716                self.state.clone(),
717                ctx,
718                FHIRRequest::Delete(DeleteRequest::Type(FHIRDeleteTypeRequest {
719                    resource_type,
720                    parameters,
721                })),
722            )
723            .await?;
724
725        match res.response {
726            Some(FHIRResponse::Delete(DeleteResponse::Type(_delete_response))) => Ok(()),
727            _ => panic!("Unexpected response type"),
728        }
729    }
730
731    async fn delete_system(
732        &self,
733        ctx: Arc<ServerCTX<Self>>,
734        parameters: ParsedParameters,
735    ) -> Result<(), OperationOutcomeError> {
736        let res = self
737            .middleware
738            .call(
739                self.state.clone(),
740                ctx,
741                FHIRRequest::Delete(DeleteRequest::System(FHIRDeleteSystemRequest {
742                    parameters,
743                })),
744            )
745            .await?;
746
747        match res.response {
748            Some(FHIRResponse::Delete(DeleteResponse::System(_delete_response))) => Ok(()),
749            _ => panic!("Unexpected response type"),
750        }
751    }
752
753    async fn history_system(
754        &self,
755        ctx: Arc<ServerCTX<Self>>,
756        parameters: ParsedParameters,
757    ) -> Result<Bundle, OperationOutcomeError> {
758        let res = self
759            .middleware
760            .call(
761                self.state.clone(),
762                ctx,
763                FHIRRequest::History(HistoryRequest::System(FHIRHistorySystemRequest {
764                    parameters,
765                })),
766            )
767            .await?;
768        match res.response {
769            Some(FHIRResponse::History(HistoryResponse::System(history_response))) => {
770                Ok(history_response.bundle)
771            }
772            _ => panic!("Unexpected response type"),
773        }
774    }
775
776    async fn history_type(
777        &self,
778        ctx: Arc<ServerCTX<Self>>,
779        resource_type: ResourceType,
780        parameters: ParsedParameters,
781    ) -> Result<Bundle, OperationOutcomeError> {
782        let res = self
783            .middleware
784            .call(
785                self.state.clone(),
786                ctx,
787                FHIRRequest::History(HistoryRequest::Type(FHIRHistoryTypeRequest {
788                    resource_type,
789                    parameters,
790                })),
791            )
792            .await?;
793        match res.response {
794            Some(FHIRResponse::History(HistoryResponse::Type(history_response))) => {
795                Ok(history_response.bundle)
796            }
797            _ => panic!("Unexpected response type"),
798        }
799    }
800
801    async fn history_instance(
802        &self,
803        ctx: Arc<ServerCTX<Self>>,
804        resource_type: ResourceType,
805        id: String,
806        parameters: ParsedParameters,
807    ) -> Result<Bundle, OperationOutcomeError> {
808        let res = self
809            .middleware
810            .call(
811                self.state.clone(),
812                ctx,
813                FHIRRequest::History(HistoryRequest::Instance(FHIRHistoryInstanceRequest {
814                    resource_type,
815                    id,
816                    parameters,
817                })),
818            )
819            .await?;
820        match res.response {
821            Some(FHIRResponse::History(HistoryResponse::Instance(history_response))) => {
822                Ok(history_response.bundle)
823            }
824            _ => panic!("Unexpected response type"),
825        }
826    }
827
828    async fn invoke_instance(
829        &self,
830        _ctx: Arc<ServerCTX<Self>>,
831        _resource_type: ResourceType,
832        _id: String,
833        _operation: String,
834        _parameters: Parameters,
835    ) -> Result<Resource, OperationOutcomeError> {
836        todo!()
837    }
838
839    async fn invoke_type(
840        &self,
841        _ctx: Arc<ServerCTX<Self>>,
842        _resource_type: ResourceType,
843        _operation: String,
844        _parameters: Parameters,
845    ) -> Result<Resource, OperationOutcomeError> {
846        todo!()
847    }
848
849    async fn invoke_system(
850        &self,
851        _ctx: Arc<ServerCTX<Self>>,
852        _operation: String,
853        _parameters: Parameters,
854    ) -> Result<Resource, OperationOutcomeError> {
855        todo!()
856    }
857
858    async fn transaction(
859        &self,
860        ctx: Arc<ServerCTX<Self>>,
861        bundle: Bundle,
862    ) -> Result<Bundle, OperationOutcomeError> {
863        let res = self
864            .middleware
865            .call(
866                self.state.clone(),
867                ctx,
868                FHIRRequest::Transaction(FHIRTransactionRequest { resource: bundle }),
869            )
870            .await?;
871
872        match res.response {
873            Some(FHIRResponse::Transaction(transaction_response)) => {
874                Ok(transaction_response.resource)
875            }
876            _ => panic!("Unexpected response type"),
877        }
878    }
879
880    async fn batch(
881        &self,
882        ctx: Arc<ServerCTX<Self>>,
883        bundle: Bundle,
884    ) -> Result<Bundle, OperationOutcomeError> {
885        let res = self
886            .middleware
887            .call(
888                self.state.clone(),
889                ctx,
890                FHIRRequest::Batch(FHIRBatchRequest { resource: bundle }),
891            )
892            .await?;
893
894        match res.response {
895            Some(FHIRResponse::Batch(batch_response)) => Ok(batch_response.resource),
896            _ => panic!("Unexpected response type"),
897        }
898    }
899}