179 lines
4.4 KiB
Rust
179 lines
4.4 KiB
Rust
mod directory;
|
|
|
|
use std::fmt::Debug;
|
|
use std::sync::Arc;
|
|
|
|
use anyhow::{anyhow, Context as _};
|
|
use async_trait::async_trait;
|
|
use serde::{Deserialize, Serialize};
|
|
use tera::{Context, Tera};
|
|
use thiserror::Error;
|
|
|
|
use crate::document::{Document, MetaError};
|
|
use crate::domains::common::*;
|
|
|
|
pub use self::directory::DirectoryRegistry;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum RegistryError {
|
|
#[error("config error: {0}")]
|
|
Config(anyhow::Error),
|
|
#[error("failed to parse document {0}: {1}")]
|
|
Document(DomainId, MetaError),
|
|
#[error("domain id {0} not found")]
|
|
NotFound(DomainId),
|
|
#[error("{0}")]
|
|
Other(#[from] anyhow::Error),
|
|
}
|
|
|
|
impl From<std::io::Error> for RegistryError {
|
|
fn from(err: std::io::Error) -> Self {
|
|
Self::Other(err.into())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
pub struct RegistryConfig {
|
|
edit_link: Option<String>,
|
|
}
|
|
|
|
impl RegistryConfig {
|
|
pub fn edit_link(&self, domain_id: DomainId) -> Result<String, RegistryError> {
|
|
let edit_link = self
|
|
.edit_link
|
|
.as_deref()
|
|
.ok_or_else(|| RegistryError::Config(anyhow!("edit-link option not set")))?;
|
|
let (domain, model) = domain_id.kind.parts();
|
|
let mut context = Context::new();
|
|
context.insert("id", &domain_id);
|
|
context.insert("domain", domain);
|
|
context.insert("model", model);
|
|
context.insert("model_id", &domain_id.model_id);
|
|
|
|
Tera::one_off(edit_link, &context, false)
|
|
.context("error rendering edit link")
|
|
.map_err(RegistryError::Config)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
pub trait Registry: Send + Sync {
|
|
async fn get_config(&self) -> Result<Arc<RegistryConfig>, RegistryError>;
|
|
|
|
async fn get_document<M>(&self, model_id: ModelId) -> Result<Document<M>, RegistryError>
|
|
where
|
|
M: DomainModel;
|
|
|
|
async fn get_documents<M>(&self) -> Result<Vec<(DomainId, Document<M>)>, RegistryError>
|
|
where
|
|
M: DomainModel;
|
|
|
|
async fn get_document_ids(&self, kind: DomainModelKind)
|
|
-> Result<Vec<DomainId>, RegistryError>;
|
|
|
|
async fn put_document<M>(
|
|
&self,
|
|
model_id: ModelId,
|
|
document: Document<M>,
|
|
) -> Result<(), RegistryError>
|
|
where
|
|
M: DomainModel;
|
|
}
|
|
|
|
#[async_trait]
|
|
impl<T> Registry for &T
|
|
where
|
|
T: Registry,
|
|
{
|
|
async fn get_config(&self) -> Result<Arc<RegistryConfig>, RegistryError> {
|
|
(**self).get_config().await
|
|
}
|
|
|
|
async fn get_document<M>(&self, model_id: ModelId) -> Result<Document<M>, RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
(**self).get_document(model_id).await
|
|
}
|
|
|
|
async fn get_documents<M>(&self) -> Result<Vec<(DomainId, Document<M>)>, RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
(**self).get_documents().await
|
|
}
|
|
|
|
async fn get_document_ids(
|
|
&self,
|
|
kind: DomainModelKind,
|
|
) -> Result<Vec<DomainId>, RegistryError> {
|
|
(**self).get_document_ids(kind).await
|
|
}
|
|
|
|
async fn put_document<M>(
|
|
&self,
|
|
model_id: ModelId,
|
|
document: Document<M>,
|
|
) -> Result<(), RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
(**self).put_document(model_id, document).await
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum SupportedRegistry {
|
|
Directory(DirectoryRegistry),
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Registry for SupportedRegistry {
|
|
async fn get_config(&self) -> Result<Arc<RegistryConfig>, RegistryError> {
|
|
match self {
|
|
Self::Directory(r) => r.get_config().await,
|
|
}
|
|
}
|
|
|
|
async fn get_document<M>(&self, model_id: ModelId) -> Result<Document<M>, RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
match self {
|
|
Self::Directory(r) => r.get_document(model_id).await,
|
|
}
|
|
}
|
|
|
|
async fn get_documents<M>(&self) -> Result<Vec<(DomainId, Document<M>)>, RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
match self {
|
|
Self::Directory(r) => r.get_documents().await,
|
|
}
|
|
}
|
|
|
|
async fn get_document_ids(
|
|
&self,
|
|
kind: DomainModelKind,
|
|
) -> Result<Vec<DomainId>, RegistryError> {
|
|
match self {
|
|
Self::Directory(r) => r.get_document_ids(kind).await,
|
|
}
|
|
}
|
|
|
|
async fn put_document<M>(
|
|
&self,
|
|
model_id: ModelId,
|
|
document: Document<M>,
|
|
) -> Result<(), RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
match self {
|
|
Self::Directory(r) => r.put_document(model_id, document).await,
|
|
}
|
|
}
|
|
}
|