diff --git a/crates/model/src/deployment_audit_log/types.rs b/crates/model/src/deployment_audit_log/types.rs index e1eb2825..e707243a 100644 --- a/crates/model/src/deployment_audit_log/types.rs +++ b/crates/model/src/deployment_audit_log/types.rs @@ -35,7 +35,9 @@ use value::{ codegen_convex_serialization, obj, remove_int64, + remove_nullable_int64, remove_nullable_object, + remove_nullable_vec_of_strings, remove_object, remove_string, remove_vec, @@ -401,7 +403,8 @@ impl TryFrom for DeploymentAuditLogEvent { .map(|s| TableName::from_str(s)) .try_collect()?; let table_names_deleted = - remove_vec_of_strings(&mut fields, "table_names_deleted")? + remove_nullable_vec_of_strings(&mut fields, "table_names_deleted")? + .unwrap_or_default() .iter() .map(|s| TableName::from_str(s)) .try_collect()?; @@ -413,7 +416,8 @@ impl TryFrom for DeploymentAuditLogEvent { requestor: remove_nullable_object(&mut fields, "requestor")? .unwrap_or(ImportRequestor::SnapshotImport), table_names_deleted, - table_count_deleted: remove_int64(&mut fields, "table_count_deleted")? as u64, + table_count_deleted: remove_nullable_int64(&mut fields, "table_count_deleted")? + .unwrap_or(0) as u64, } }, _ => anyhow::bail!("action {action} unrecognized"), diff --git a/crates/value/src/lib.rs b/crates/value/src/lib.rs index 251a0f74..c3c4fdd0 100644 --- a/crates/value/src/lib.rs +++ b/crates/value/src/lib.rs @@ -90,8 +90,11 @@ pub use crate::{ object::{ remove_boolean, remove_int64, + remove_nullable_int64, remove_nullable_object, remove_nullable_string, + remove_nullable_vec, + remove_nullable_vec_of_strings, remove_object, remove_string, remove_vec, diff --git a/crates/value/src/object.rs b/crates/value/src/object.rs index d89a48d8..f4e8944f 100644 --- a/crates/value/src/object.rs +++ b/crates/value/src/object.rs @@ -239,6 +239,17 @@ pub fn remove_int64( } } +pub fn remove_nullable_int64( + fields: &mut BTreeMap, + field: &str, +) -> anyhow::Result> { + match fields.remove(field) { + Some(ConvexValue::Int64(i)) => Ok(Some(i)), + None => Ok(None), + v => anyhow::bail!("expected int for {field}, got {v:?}"), + } +} + pub fn remove_object>( fields: &mut BTreeMap, field: &str, @@ -288,6 +299,34 @@ pub fn remove_vec_of_strings( .try_collect() } +pub fn remove_nullable_vec( + fields: &mut BTreeMap, + field: &str, +) -> anyhow::Result>> { + match fields.remove(field) { + Some(ConvexValue::Array(a)) => Ok(Some(a.into())), + None => Ok(None), + v => anyhow::bail!("expected array for {field}, got {v:?}"), + } +} +pub fn remove_nullable_vec_of_strings( + fields: &mut BTreeMap, + field: &str, +) -> anyhow::Result>> { + let Some(values) = remove_nullable_vec(fields, field)? else { + return Ok(None); + }; + Ok(Some( + values + .into_iter() + .map(|value| match value { + ConvexValue::String(s) => anyhow::Ok(s.into()), + v => anyhow::bail!("expected string in array at {field}, got {v:?}"), + }) + .try_collect()?, + )) +} + impl Size for ConvexObject { fn size(&self) -> usize { self.size