mod build_submission;
mod complete;
mod hash_artifacts;
mod idempotency;
mod submit;
mod upload;
use wyrd_loader::DeclarationInput;
use wyrd_spec::error::WyrdError;
use wyrd_spec::registry::{CardLifecycleStatus, DeclarationReceipt, DeclareCardResponse};
use crate::cards::engine::RegistryEngine;
use crate::cards::error::RegistryEngineError;
use crate::cards::progress::{DeclarationPhase, DeclarationProgressEvent, DeclarationProgressSink};
pub(crate) async fn declare(
engine: &RegistryEngine,
input: &DeclarationInput,
progress: Option<DeclarationProgressSink>,
) -> Result<DeclarationReceipt, RegistryEngineError> {
emit_phase(progress.as_ref(), DeclarationPhase::Preparing);
let prepared = build_submission::prepare(input).await?;
let idempotency_key = idempotency::mint();
emit_phase(progress.as_ref(), DeclarationPhase::Submitting);
let mut response =
submit::submit_card_declaration(&engine.client, &prepared.request, &idempotency_key)
.await?;
emit_phase(progress.as_ref(), DeclarationPhase::Uploading);
upload::upload_artifacts(
&engine.storage,
&response,
&prepared.artifact_sources,
&idempotency_key,
progress.clone(),
)
.await?;
emit_phase(progress.as_ref(), DeclarationPhase::Completing);
match complete::complete_uploaded_cards(&engine.client, &response, &idempotency_key).await {
Ok(finalized) => response = finalized,
Err(error) => {
return Err(error);
}
}
emit_phase(progress.as_ref(), DeclarationPhase::Verifying);
ensure_active(&response)?;
Ok(response.into())
}
fn emit_phase(progress: Option<&DeclarationProgressSink>, phase: DeclarationPhase) {
if let Some(progress) = progress {
progress(DeclarationProgressEvent::Phase(phase));
}
}
fn ensure_active(response: &DeclareCardResponse) -> Result<(), RegistryEngineError> {
if let Some(pending) = response
.outcomes
.iter()
.find(|outcome| outcome.status != CardLifecycleStatus::Active)
{
return Err(WyrdError::RegistryArtifactVerifyFailed {
message: "declaration did not reach Active state".to_owned(),
details: serde_json::json!({
"card_uid": pending.card_ref.uid,
"status": pending.status,
}),
}
.into());
}
Ok(())
}