use crate::client::{OrdinaryApiClient, compress_zstd, ops};
use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD as b64};
use fs_err::read_to_string;
use ordinary_config::OrdinaryConfig;
use std::path::Path;
pub async fn upload(
api_client: &OrdinaryApiClient<'_>,
proj_path: &str,
template_name: &str,
) -> anyhow::Result<()> {
let config = OrdinaryConfig::get(proj_path)?;
let correlation_id = api_client
.correlation_id
.unwrap_or(uuid::Uuid::new_v4())
.to_string();
if let Some(templates) = &config.templates {
let access_token = api_client
.get_access(None, Some(correlation_id.clone()))
.await?;
ops::assets::write_frontend(
api_client,
proj_path,
&config,
&access_token,
&correlation_id,
)
.await?;
if let Some(template) = templates.iter().find(|t| t.name == template_name) {
let access_token = api_client
.get_access(None, Some(correlation_id.clone()))
.await?;
let bin_path = Path::new(proj_path)
.join(".ordinary/gen/server")
.join(&template.name)
.join("target/wasm32-wasip1/release/template.wasm");
let hash_path = Path::new(proj_path)
.join(".ordinary")
.join("gen")
.join("hashes")
.join(&template.name);
let style_path = hash_path.join("style-src.json");
let script_path = hash_path.join("script-src.json");
let mut query = vec![
("d", config.domain.clone()),
("i", template.idx.to_string()),
];
if style_path.exists() {
let csp_style_hashes: Vec<String> =
serde_json::from_str(&read_to_string(style_path)?)?;
if !csp_style_hashes.is_empty() {
for hash in csp_style_hashes {
query.push(("style_csp", hash));
}
}
}
if script_path.exists() {
let csp_script_hashes: Vec<String> =
serde_json::from_str(&read_to_string(script_path)?)?;
if !csp_script_hashes.is_empty() {
for hash in csp_script_hashes {
query.push(("script_csp", hash));
}
}
}
let template_bytes = fs_err::read(bin_path)?;
tracing::info!(
"uploading template '{}' to {} with idx {}...",
template.name,
config.domain,
template.idx
);
api_client
.client
.put(format!("{}/v1/templates", api_client.addr))
.body(compress_zstd(&template_bytes[..])?)
.query(&query)
.header("x-correlation-id", correlation_id.as_str())
.header("Content-Encoding", "zstd")
.header(
"Authorization",
format!("Bearer {}", b64.encode(&access_token)),
)
.send()
.await?
.bytes()
.await?;
tracing::info!("successfully uploaded template '{}'.", template.name);
}
} else {
tracing::warn!("no \"templates\" field in ordinary.json");
}
Ok(())
}
pub async fn upload_all(api_client: &OrdinaryApiClient<'_>, proj_path: &str) -> anyhow::Result<()> {
let config = OrdinaryConfig::get(proj_path)?;
let correlation_id = api_client
.correlation_id
.unwrap_or(uuid::Uuid::new_v4())
.to_string();
if let Some(templates) = &config.templates {
let access_token = api_client
.get_access(None, Some(correlation_id.clone()))
.await?;
ops::assets::write_frontend(
api_client,
proj_path,
&config,
&access_token,
&correlation_id,
)
.await?;
for template in templates {
let access_token = api_client
.get_access(None, Some(correlation_id.clone()))
.await?;
let bin_path = Path::new(proj_path)
.join(".ordinary/gen/server")
.join(&template.name)
.join("target/wasm32-wasip1/release/template.wasm");
let hash_path = Path::new(proj_path)
.join(".ordinary")
.join("gen")
.join("hashes")
.join(&template.name);
let style_path = hash_path.join("style-src.json");
let script_path = hash_path.join("script-src.json");
let mut query = vec![
("d", config.domain.clone()),
("i", template.idx.to_string()),
];
if style_path.exists() {
let csp_style_hashes: Vec<String> =
serde_json::from_str(&read_to_string(style_path)?)?;
if !csp_style_hashes.is_empty() {
for hash in csp_style_hashes {
query.push(("style_csp", hash));
}
}
}
if script_path.exists() {
let csp_script_hashes: Vec<String> =
serde_json::from_str(&read_to_string(script_path)?)?;
if !csp_script_hashes.is_empty() {
for hash in csp_script_hashes {
query.push(("script_csp", hash));
}
}
}
let template_bytes = fs_err::read(bin_path)?;
tracing::info!(
"uploading template '{}' to {} with idx {}...",
template.name,
config.domain,
template.idx
);
api_client
.client
.put(format!("{}/v1/templates", api_client.addr))
.body(compress_zstd(&template_bytes[..])?)
.query(&query)
.header("x-correlation-id", correlation_id.as_str())
.header("Content-Encoding", "zstd")
.header(
"Authorization",
format!("Bearer {}", b64.encode(&access_token)),
)
.send()
.await?
.bytes()
.await?;
}
tracing::info!("all templates successfully uploaded.");
} else {
tracing::warn!("no \"templates\" field in ordinary.json");
}
Ok(())
}