diff --git a/crates/api/src/admin.rs b/crates/api/src/admin.rs index 07587c7..bf02cbe 100644 --- a/crates/api/src/admin.rs +++ b/crates/api/src/admin.rs @@ -32,7 +32,6 @@ pub(crate) struct UserView { /// Desired visibility for a publish/unpublish request. #[derive(Deserialize, ToSchema)] pub(crate) struct VisibilityRequest { - #[schema(value_type = String)] pub visibility: Visibility, } diff --git a/crates/api/src/admin_authorities.rs b/crates/api/src/admin_authorities.rs index 87d3fba..58fc79d 100644 --- a/crates/api/src/admin_authorities.rs +++ b/crates/api/src/admin_authorities.rs @@ -20,6 +20,7 @@ use crate::{ #[derive(Serialize, ToSchema)] pub(crate) struct AuthorityView { pub id: String, + #[schema(value_type = domain::AuthorityKind)] pub kind: String, pub external_uri: Option, pub labels: Vec, diff --git a/crates/api/src/admin_objects.rs b/crates/api/src/admin_objects.rs index 1b2d1b6..72ea003 100644 --- a/crates/api/src/admin_objects.rs +++ b/crates/api/src/admin_objects.rs @@ -40,9 +40,10 @@ pub(crate) struct AdminObjectView { /// `YYYY-MM-DD` or null. pub recording_date: Option, /// "draft" | "internal" | "public". + #[schema(value_type = domain::Visibility)] pub visibility: String, /// Flexible field values (key -> value). - #[schema(value_type = Object)] + #[schema(value_type = std::collections::HashMap)] pub fields: serde_json::Value, } @@ -162,7 +163,6 @@ pub(crate) struct ObjectCreateRequest { pub recorder: Option, pub recording_date: Option, /// "draft" | "internal" (public is rejected — publish via the visibility endpoint). - #[schema(value_type = String)] pub visibility: Visibility, } @@ -360,8 +360,10 @@ pub(crate) async fn delete_object( pub(crate) struct FieldDefinitionView { pub key: String, /// "text" | "localized_text" | "integer" | "date" | "boolean" | "term" | "authority". + #[schema(value_type = domain::DataType)] pub data_type: String, pub vocabulary_id: Option, + #[schema(value_type = Option)] pub authority_kind: Option, pub required: bool, pub group: Option, diff --git a/crates/api/src/openapi.rs b/crates/api/src/openapi.rs index e40d9ba..ea75cbc 100644 --- a/crates/api/src/openapi.rs +++ b/crates/api/src/openapi.rs @@ -59,7 +59,10 @@ use crate::{ admin_search::SearchHitView, admin_search::SearchResultsView, admin_authorities::AuthorityView, - admin_authorities::NewAuthorityRequest + admin_authorities::NewAuthorityRequest, + domain::Visibility, + domain::AuthorityKind, + domain::DataType )), info(title = "Collection Management System", version = "0.0.0") )] diff --git a/web/src/api/schema.d.ts b/web/src/api/schema.d.ts index e372e04..e0095dc 100644 --- a/web/src/api/schema.d.ts +++ b/web/src/api/schema.d.ts @@ -326,7 +326,9 @@ export interface components { current_location?: string | null; current_owner?: string | null; /** @description Flexible field values (key -> value). */ - fields: Record; + fields: { + [key: string]: unknown; + }; id: string; /** Format: int32 */ number_of_objects: number; @@ -336,12 +338,21 @@ export interface components { /** @description `YYYY-MM-DD` or null. */ recording_date?: string | null; /** @description "draft" | "internal" | "public". */ - visibility: string; + visibility: components["schemas"]["Visibility"]; }; + /** + * @description The kind of authority record. + * + * 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. + * @enum {string} + */ + AuthorityKind: "person" | "organisation" | "place"; AuthorityView: { external_uri?: string | null; id: string; - kind: string; + kind: components["schemas"]["AuthorityKind"]; labels: components["schemas"]["LabelView"][]; }; CreatedField: { @@ -354,11 +365,18 @@ export interface components { CreatedObject: { id: string; }; + /** + * @description 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`. + * @enum {string} + */ + DataType: "text" | "localized_text" | "integer" | "date" | "boolean" | "term" | "authority"; /** @description Field-definition descriptor for the UI to render forms. */ FieldDefinitionView: { - authority_kind?: string | null; + authority_kind?: null | components["schemas"]["AuthorityKind"]; /** @description "text" | "localized_text" | "integer" | "date" | "boolean" | "term" | "authority". */ - data_type: string; + data_type: components["schemas"]["DataType"]; group?: string | null; key: string; labels: components["schemas"]["LabelView"][]; @@ -419,7 +437,7 @@ export interface components { recorder?: string | null; recording_date?: string | null; /** @description "draft" | "internal" (public is rejected — publish via the visibility endpoint). */ - visibility: string; + visibility: components["schemas"]["Visibility"]; }; /** * @description Inventory-minimum fields for update. Visibility is intentionally absent — it changes @@ -488,9 +506,14 @@ export interface components { id: string; role: string; }; + /** + * @description Publication state of a catalogue record. + * @enum {string} + */ + Visibility: "draft" | "internal" | "public"; /** @description Desired visibility for a publish/unpublish request. */ VisibilityRequest: { - visibility: string; + visibility: components["schemas"]["Visibility"]; }; VocabularyView: { id: string;