Defining the Application Adapter

The first step in setting up data access is to generate an Application adapter. This establishes a default adapter for the Store to use, which can be supplemented later by additional model-specific adapters.

Let's generate a REST-based Application adapter:

$ auric generate adapter application --target rest
created src/adapters/application.rs
updated src/adapters/mod.rs
==> make
   Compiling drr v0.1.0 (/Users/davidr/workspaces/drr)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.47s

This will create the following file:

// src/adapters/application.rs
use auric_runtime::{
    Config,
    async_trait::async_trait,
    data::{Adapter, QueryRecordOptions, adapters::RestAdapter},
};
use jsonapi_core::Resource;

#[derive(Default)]
pub struct ApplicationAdapter {
    target: RestAdapter,
}

#[async_trait(?Send)]
impl Adapter for ApplicationAdapter {
    fn init(&mut self, config: &Config) -> Result<()> {
        self.target.init(config)
    }

    async fn create_record(&self, resource: Resource) -> Result<Resource> {
        self.target.create_record(resource).await
    }

    async fn delete_record(&self, resource: &Resource) -> Result<()> {
        self.target.delete_record(resource).await
    }

    async fn find_record(&self, resource_type: &str, id: &str) -> Result<Resource> {
        self.target.find_record(resource_type, id).await
    }

    async fn query(&self, resource_type: &str, query: serde_json::Value) -> Result<Vec<Resource>> {
        self.target.query(resource_type, query).await
    }

    async fn query_record(
        &self,
        resource_type: &str,
        query: serde_json::Value,
        options: QueryRecordOptions,
    ) -> Result<Option<Resource>> {
        self.target
            .query_record(resource_type, query, options)
            .await
    }

    async fn update_record(&self, resource: Resource) -> Result<Resource> {
        self.target.update_record(resource).await
    }
}

#[cfg(test)]
mod tests {
    use super::ApplicationAdapter;
    use auric_runtime::data::Adapter;
    use serde_json::json;

    #[test]
    fn can_construct() {
        let _ = ApplicationAdapter::default();
    }

    #[test]
    fn can_init() {
        let mut adapter = ApplicationAdapter::default();
        let config = json!({"api_url": "http://localhost:3000"});
        adapter
            .init(&config)
            .expect("Expected to initialize with a valid api url");
    }

    #[test]
    fn cannot_init_with_missing_api_url() {
        let mut adapter = ApplicationAdapter::default();
        let config = json!({"someStuff": "abc"});
        assert!(
            adapter.init(&config).is_err(),
            "Expected init to fail due to missing api url",
        );
    }
}

As you can see, the implementation of each Adapter trait function simply delegates to a target RestAdapter, providing a default implementation upfront, while leaving you in a position to make future customizations.


©2026 Megalithic LLC | Website | GitLab | Contact