Files
crank/apps/admin-api/src/storage.rs
T
github-ops ba29ac7b94
Deploy / deploy (push) Successful in 2m44s
CI / Rust Checks (push) Successful in 5m31s
CI / UI Checks (push) Successful in 5s
CI / Deployment Manifests (push) Successful in 2s
CI / Frontend E2E (push) Successful in 4m24s
chore: publish clean community baseline
2026-06-19 16:45:51 +00:00

85 lines
2.2 KiB
Rust

use std::path::{Path, PathBuf};
use crank_core::{OperationId, SampleId};
use crank_registry::SampleKind;
use serde_json::Value;
use thiserror::Error;
use tokio::fs;
#[derive(Clone)]
pub struct LocalArtifactStorage {
root: PathBuf,
}
#[derive(Debug, Error)]
pub enum StorageError {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Serialization(#[from] serde_json::Error),
#[error("invalid storage reference: {details}")]
InvalidStorageRef { details: String },
}
impl LocalArtifactStorage {
pub fn new(root: PathBuf) -> Self {
Self { root }
}
pub async fn write_json_sample(
&self,
operation_id: &OperationId,
version: u32,
sample_kind: SampleKind,
sample_id: &SampleId,
payload: &Value,
) -> Result<String, StorageError> {
let file_name = match sample_kind {
SampleKind::InputJson => "input.json",
SampleKind::OutputJson => "output.json",
SampleKind::YamlImportSource => "source.json",
};
let path = self
.root
.join("samples")
.join(operation_id.as_str())
.join(format!("v{version}"))
.join(format!("{}_{}", sample_id.as_str(), file_name));
write_json_file(&path, payload).await?;
Ok(to_storage_ref(&path))
}
pub async fn read_json(&self, storage_ref: &str) -> Result<Value, StorageError> {
let path = from_storage_ref(storage_ref)?;
let bytes = fs::read(path).await?;
Ok(serde_json::from_slice(&bytes)?)
}
}
async fn write_json_file(path: &Path, payload: &Value) -> Result<(), StorageError> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).await?;
}
let bytes = serde_json::to_vec_pretty(payload)?;
fs::write(path, bytes).await?;
Ok(())
}
fn to_storage_ref(path: &Path) -> String {
format!("file://{}", path.display())
}
fn from_storage_ref(storage_ref: &str) -> Result<PathBuf, StorageError> {
let Some(path) = storage_ref.strip_prefix("file://") else {
return Err(StorageError::InvalidStorageRef {
details: storage_ref.to_owned(),
});
};
Ok(PathBuf::from(path))
}