diff --git a/crates/domain/Cargo.toml b/crates/domain/Cargo.toml index d831a62..39631df 100644 --- a/crates/domain/Cargo.toml +++ b/crates/domain/Cargo.toml @@ -9,3 +9,4 @@ uuid.workspace = true serde.workspace = true serde_json.workspace = true time.workspace = true +utoipa.workspace = true diff --git a/crates/domain/src/authority.rs b/crates/domain/src/authority.rs index 7cc550e..aa375e7 100644 --- a/crates/domain/src/authority.rs +++ b/crates/domain/src/authority.rs @@ -7,7 +7,7 @@ use crate::{AuthorityId, LocalizedLabel}; /// NOTE: kept in sync by hand with the /// `CHECK (kind IN ('person', 'organisation', 'place'))` constraint in /// `crates/db/migrations/0002_vocabularies_authorities.sql` — add a variant in both places. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)] #[serde(rename_all = "lowercase")] pub enum AuthorityKind { Person, diff --git a/crates/domain/src/field_definition.rs b/crates/domain/src/field_definition.rs index 45d83ef..66fa47f 100644 --- a/crates/domain/src/field_definition.rs +++ b/crates/domain/src/field_definition.rs @@ -74,6 +74,23 @@ impl FieldType { } } +/// The stored `data_type` discriminant of a field definition — mirrors the strings from +/// [`FieldType::kind_str`]. Exists so the OpenAPI schema can describe `data_type` as a +/// closed string enum (consumed by the typed web client). Keep in sync with `kind_str`. +#[derive( + Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, utoipa::ToSchema, +)] +#[serde(rename_all = "snake_case")] +pub enum DataType { + Text, + LocalizedText, + Integer, + Date, + Boolean, + Term, + Authority, +} + /// A registered flexible field, with its multilingual display labels. #[derive(Debug, Clone, PartialEq, Eq)] pub struct FieldDefinition { @@ -152,4 +169,18 @@ mod tests { ); assert_eq!(FieldType::from_parts("authority", Some(v), None), None); } + + #[test] + fn data_type_serde_matches_kind_str() { + use serde_json::json; + assert_eq!( + serde_json::to_value(DataType::LocalizedText).unwrap(), + json!("localized_text") + ); + assert_eq!(serde_json::to_value(DataType::Text).unwrap(), json!("text")); + assert_eq!( + serde_json::to_value(DataType::Authority).unwrap(), + json!("authority") + ); + } } diff --git a/crates/domain/src/lib.rs b/crates/domain/src/lib.rs index fa3f759..e10dc2c 100644 --- a/crates/domain/src/lib.rs +++ b/crates/domain/src/lib.rs @@ -11,7 +11,7 @@ mod vocabulary; pub use audit::{AuditAction, AuditActor, AuditEntry, FieldChange, NewAuditEvent}; pub use authority::{Authority, AuthorityKind, AuthorityRef, NewAuthority}; -pub use field_definition::{FieldDefinition, FieldType, NewFieldDefinition}; +pub use field_definition::{DataType, FieldDefinition, FieldType, NewFieldDefinition}; pub use id::{AuthorityId, FieldDefinitionId, ObjectId, OrgId, TermId, UserId, VocabularyId}; pub use label::{LocalizedLabel, pick_label}; pub use object::{CatalogueObject, IllegalTransition, ObjectInput, Visibility}; diff --git a/crates/domain/src/object.rs b/crates/domain/src/object.rs index eb3ded6..6754ef9 100644 --- a/crates/domain/src/object.rs +++ b/crates/domain/src/object.rs @@ -4,7 +4,7 @@ use time::{Date, OffsetDateTime}; use crate::ObjectId; /// Publication state of a catalogue record. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, utoipa::ToSchema)] #[serde(rename_all = "lowercase")] pub enum Visibility { /// Work in progress; not shown anywhere public.