106 lines
3.1 KiB
Rust
106 lines
3.1 KiB
Rust
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
use anyhow::Context;
|
|
use async_trait::async_trait;
|
|
use tokio::fs;
|
|
|
|
use crate::document::Document;
|
|
use crate::domains::common::*;
|
|
use crate::registry::{Registry, RegistryConfig, RegistryError};
|
|
|
|
#[derive(Debug)]
|
|
pub struct DirectoryRegistry {
|
|
path: PathBuf,
|
|
}
|
|
|
|
impl DirectoryRegistry {
|
|
pub fn new<P: Into<PathBuf>>(path: P) -> Self {
|
|
Self { path: path.into() }
|
|
}
|
|
|
|
fn domain_model_kind_path(&self, kind: DomainModelKind) -> PathBuf {
|
|
let (domain, model) = kind.parts();
|
|
self.path.join(format!("{}/{}", domain, model))
|
|
}
|
|
|
|
fn domain_id_path(&self, id: DomainId) -> PathBuf {
|
|
let (domain, model) = id.kind.parts();
|
|
self.path
|
|
.join(format!("{}/{}/{}.md", domain, model, id.instance))
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Registry for DirectoryRegistry {
|
|
async fn get_config(&self) -> Result<Arc<RegistryConfig>, RegistryError> {
|
|
let config_str = fs::read_to_string(self.path.join("config.toml")).await?;
|
|
toml::from_str(&config_str)
|
|
.context("failed to read registry `config.toml`")
|
|
.map(Arc::new)
|
|
.map_err(Into::into)
|
|
}
|
|
|
|
async fn get_document<M>(&self, instance: Instance) -> Result<Document<M>, RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
let id = DomainId::new(M::kind(), instance);
|
|
let path = self.domain_id_path(id);
|
|
if !path.is_file() {
|
|
return Err(RegistryError::NotFound(id));
|
|
}
|
|
let s = fs::read_to_string(path).await?;
|
|
s.parse().map_err(|err| RegistryError::Document(id, err))
|
|
}
|
|
|
|
async fn get_documents<M>(&self) -> Result<Vec<(DomainId, Document<M>)>, RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
let ids = self.get_document_ids(M::kind()).await?;
|
|
let mut docs = Vec::with_capacity(ids.len());
|
|
for id in ids {
|
|
docs.push((id, self.get_document(id.instance).await?));
|
|
}
|
|
Ok(docs)
|
|
}
|
|
|
|
async fn get_document_ids(
|
|
&self,
|
|
kind: DomainModelKind,
|
|
) -> Result<Vec<DomainId>, RegistryError> {
|
|
let mut ids = Vec::new();
|
|
let path = self.domain_model_kind_path(kind);
|
|
if !path.is_dir() {
|
|
return Ok(vec![]);
|
|
}
|
|
let mut dirs = fs::read_dir(path).await?;
|
|
while let Some(entry) = dirs.next_entry().await? {
|
|
let path = entry.path();
|
|
if path.is_file() {
|
|
let filestem = path.file_stem().unwrap().to_string_lossy();
|
|
let instance: Instance = filestem.as_ref().parse().unwrap();
|
|
if !instance.is_example() {
|
|
ids.push(DomainId::new(kind, instance))
|
|
}
|
|
}
|
|
}
|
|
Ok(ids)
|
|
}
|
|
|
|
async fn put_document<M>(
|
|
&self,
|
|
instance: Instance,
|
|
document: Document<M>,
|
|
) -> Result<(), RegistryError>
|
|
where
|
|
M: DomainModel,
|
|
{
|
|
let path = self.domain_id_path(DomainId::new(M::kind(), instance));
|
|
let document = document.to_string();
|
|
fs::write(path, document.as_str()).await?;
|
|
Ok(())
|
|
}
|
|
}
|