use crate::{
ids::CanisterRole,
support::{self, WasmStoreGcExecutionStats},
};
use canic_core::{cdk::types::Principal, dto::error::Error};
use canic_template_types::dto::template::{
TemplateChunkInput, TemplateChunkResponse, TemplateChunkSetInfoResponse,
TemplateChunkSetPrepareInput, TemplateManifestInput, WasmStoreAdminCommand,
WasmStoreAdminResponse, WasmStoreBootstrapDebugResponse, WasmStoreCatalogEntryResponse,
WasmStoreOverviewResponse, WasmStoreStatusResponse,
};
use canic_template_types::{TemplateId, TemplateVersion, WasmStoreBinding, WasmStoreGcStatus};
const ROOT_WASM_STORE_BOOTSTRAP_TEMPLATE_ID: TemplateId = TemplateId::new("embedded:wasm_store");
const ROOT_WASM_STORE_BOOTSTRAP_BINDING: WasmStoreBinding = WasmStoreBinding::new("bootstrap");
pub struct WasmStoreBootstrapApi;
impl WasmStoreBootstrapApi {
fn ensure_root_wasm_store_bootstrap_template(template_id: &TemplateId) -> Result<(), Error> {
if template_id == &ROOT_WASM_STORE_BOOTSTRAP_TEMPLATE_ID {
Ok(())
} else {
Err(Error::invalid(format!(
"bootstrap only accepts template '{ROOT_WASM_STORE_BOOTSTRAP_TEMPLATE_ID}'"
)))
}
}
fn normalize_root_wasm_store_bootstrap_manifest(
request: TemplateManifestInput,
) -> Result<TemplateManifestInput, Error> {
if request.role != CanisterRole::WASM_STORE {
return Err(Error::invalid(format!(
"bootstrap only accepts role '{}'",
CanisterRole::WASM_STORE
)));
}
Self::ensure_root_wasm_store_bootstrap_template(&request.template_id)?;
let now_secs = support::now_secs();
Ok(TemplateManifestInput {
template_id: ROOT_WASM_STORE_BOOTSTRAP_TEMPLATE_ID,
role: CanisterRole::WASM_STORE,
version: request.version,
payload_hash: request.payload_hash,
payload_size_bytes: request.payload_size_bytes,
store_binding: ROOT_WASM_STORE_BOOTSTRAP_BINDING,
chunking_mode: crate::ids::TemplateChunkingMode::Chunked,
manifest_state: crate::ids::TemplateManifestState::Approved,
approved_at: Some(now_secs),
created_at: now_secs,
})
}
pub fn stage_root_wasm_store_manifest(request: TemplateManifestInput) -> Result<(), Error> {
Self::stage_manifest(Self::normalize_root_wasm_store_bootstrap_manifest(request)?);
Ok(())
}
pub fn prepare_root_wasm_store_chunk_set(
request: TemplateChunkSetPrepareInput,
) -> Result<TemplateChunkSetInfoResponse, Error> {
Self::ensure_root_wasm_store_bootstrap_template(&request.template_id)?;
Self::prepare_chunk_set(request)
}
pub fn publish_root_wasm_store_chunk(request: TemplateChunkInput) -> Result<(), Error> {
Self::ensure_root_wasm_store_bootstrap_template(&request.template_id)?;
Self::publish_chunk(request)
}
pub fn stage_manifest(input: TemplateManifestInput) {
support::stage_manifest(input);
}
pub fn prepare_chunk_set(
request: TemplateChunkSetPrepareInput,
) -> Result<TemplateChunkSetInfoResponse, Error> {
support::prepare_chunk_set(request)
}
pub fn publish_chunk(request: TemplateChunkInput) -> Result<(), Error> {
support::publish_chunk(request)
}
pub async fn publish_staged_release_set_to_current_store() -> Result<(), Error> {
support::publish_staged_release_set_to_current_store().await
}
pub fn debug_bootstrap() -> Result<WasmStoreBootstrapDebugResponse, Error> {
support::bootstrap_debug(&CanisterRole::WASM_STORE)
}
}
pub struct WasmStorePublicationApi;
impl WasmStorePublicationApi {
pub async fn admin(cmd: WasmStoreAdminCommand) -> Result<WasmStoreAdminResponse, Error> {
support::publication_admin(cmd).await
}
pub async fn publish_current_release_set_to_store(store_pid: Principal) -> Result<(), Error> {
support::publish_current_release_set_to_store(store_pid).await
}
pub async fn publish_current_release_set_to_current_store() -> Result<(), Error> {
support::publish_current_release_set_to_current_store().await
}
pub fn set_current_publication_store_binding(binding: WasmStoreBinding) -> Result<(), Error> {
support::set_current_publication_store_binding(binding)
}
pub fn clear_current_publication_store_binding() {
support::clear_current_publication_store_binding();
}
#[must_use]
pub fn retire_detached_publication_store_binding() -> Option<WasmStoreBinding> {
support::retire_detached_publication_store_binding()
}
pub fn overview() -> Result<WasmStoreOverviewResponse, Error> {
Ok(support::publication_overview())
}
pub async fn prepare_retired_publication_store_for_gc()
-> Result<Option<WasmStoreBinding>, Error> {
support::prepare_retired_publication_store_for_gc().await
}
pub async fn begin_retired_publication_store_gc() -> Result<Option<WasmStoreBinding>, Error> {
support::begin_retired_publication_store_gc().await
}
pub async fn complete_retired_publication_store_gc() -> Result<Option<WasmStoreBinding>, Error>
{
support::complete_retired_publication_store_gc().await
}
pub async fn finalize_retired_publication_store_binding()
-> Result<Option<WasmStoreBinding>, Error> {
support::finalize_retired_publication_store_binding().await
}
pub async fn delete_finalized_publication_store(
binding: WasmStoreBinding,
store_pid: Principal,
) -> Result<(), Error> {
support::delete_finalized_publication_store(binding, store_pid).await
}
}
pub struct WasmStoreApi;
impl WasmStoreApi {
pub fn template_catalog() -> Result<Vec<WasmStoreCatalogEntryResponse>, Error> {
Ok(support::local_template_catalog())
}
pub fn template_status(gc: WasmStoreGcStatus) -> Result<WasmStoreStatusResponse, Error> {
support::local_template_status(gc)
}
pub fn prepare_chunk_set(
request: TemplateChunkSetPrepareInput,
) -> Result<TemplateChunkSetInfoResponse, Error> {
support::local_prepare_chunk_set(request)
}
pub fn publish_chunk(request: TemplateChunkInput) -> Result<(), Error> {
support::local_publish_chunk(request)
}
pub async fn execute_local_store_gc() -> Result<WasmStoreGcExecutionStats, Error> {
support::execute_local_store_gc().await
}
pub fn template_info(
template_id: TemplateId,
version: TemplateVersion,
) -> Result<TemplateChunkSetInfoResponse, Error> {
support::local_template_info(template_id, version)
}
pub fn template_chunk(
template_id: TemplateId,
version: TemplateVersion,
chunk_index: u32,
) -> Result<TemplateChunkResponse, Error> {
support::local_template_chunk(template_id, version, chunk_index)
}
}