diff --git a/apps/hash-ai-worker-ts/src/activities/infer-entities/propose-entities.ts b/apps/hash-ai-worker-ts/src/activities/infer-entities/propose-entities.ts index 89a49d61188..3841fad3348 100644 --- a/apps/hash-ai-worker-ts/src/activities/infer-entities/propose-entities.ts +++ b/apps/hash-ai-worker-ts/src/activities/infer-entities/propose-entities.ts @@ -1,5 +1,6 @@ import type { VersionedUrl } from "@blockprotocol/type-system"; import { typedEntries } from "@local/advanced-types/typed-entries"; +import { mergePropertyObjectAndMetadata } from "@local/hash-graph-sdk/entity"; import type { EntityUuid } from "@local/hash-graph-types/entity"; import type { ProposedEntity } from "@local/hash-isomorphic-utils/ai-inference-types"; import { entityIdFromComponents } from "@local/hash-subgraph"; @@ -422,12 +423,15 @@ export const proposeEntities = async (params: { const { properties: simplifiedProperties } = proposedEntityOfType; - const properties = simplifiedProperties - ? mapSimplifiedPropertiesToProperties({ - simplifiedProperties, - simplifiedPropertyTypeMappings, - }) - : {}; + const properties = mergePropertyObjectAndMetadata( + simplifiedProperties + ? mapSimplifiedPropertiesToProperties({ + simplifiedProperties, + simplifiedPropertyTypeMappings, + }) + : {}, + undefined, + ); await graphApiClient.validateEntity( userAuthentication.actorId, diff --git a/libs/@local/codec/package.json b/libs/@local/codec/package.json index 4676dd30c22..ec7d2e1cef2 100644 --- a/libs/@local/codec/package.json +++ b/libs/@local/codec/package.json @@ -5,7 +5,8 @@ "license": "AGPL-3", "scripts": { "fix:clippy": "just clippy --fix", - "lint:clippy": "just clippy" + "lint:clippy": "just clippy", + "test:unit": "cargo hack nextest run --feature-powerset --all-targets && cargo test --all-features --doc" }, "dependencies": { "@rust/error-stack": "0.5.0", diff --git a/libs/@local/codec/src/serde/string_hash_map.rs b/libs/@local/codec/src/serde/string_hash_map.rs index f3b339dc482..70e621cb4ce 100644 --- a/libs/@local/codec/src/serde/string_hash_map.rs +++ b/libs/@local/codec/src/serde/string_hash_map.rs @@ -15,7 +15,7 @@ //! //! #[derive(Debug, PartialEq, Serialize, Deserialize)] //! struct MyStruct { -//! #[serde(with = "codec::serde::string_hash_map")] +//! #[serde(with = "hash_codec::serde::string_hash_map")] //! map: HashMap, //! } //! diff --git a/libs/@local/graph/api/openapi/openapi.json b/libs/@local/graph/api/openapi/openapi.json index 70e1d7195be..ce76c622272 100644 --- a/libs/@local/graph/api/openapi/openapi.json +++ b/libs/@local/graph/api/openapi/openapi.json @@ -8180,6 +8180,9 @@ { "type": "object", "title": "PropertyMetadataArray", + "required": [ + "value" + ], "properties": { "metadata": { "$ref": "#/components/schemas/ArrayMetadata" @@ -8195,6 +8198,9 @@ { "type": "object", "title": "PropertyMetadataObject", + "required": [ + "value" + ], "properties": { "metadata": { "$ref": "#/components/schemas/ObjectMetadata" @@ -8860,6 +8866,9 @@ }, "PropertyWithMetadataArray": { "type": "object", + "required": [ + "value" + ], "properties": { "metadata": { "$ref": "#/components/schemas/ArrayMetadata" @@ -8875,6 +8884,9 @@ }, "PropertyWithMetadataObject": { "type": "object", + "required": [ + "value" + ], "properties": { "metadata": { "$ref": "#/components/schemas/ObjectMetadata" diff --git a/libs/@local/graph/types/rust/src/knowledge/property/array.rs b/libs/@local/graph/types/rust/src/knowledge/property/array.rs index 44f329034cf..38743b44c50 100644 --- a/libs/@local/graph/types/rust/src/knowledge/property/array.rs +++ b/libs/@local/graph/types/rust/src/knowledge/property/array.rs @@ -6,7 +6,8 @@ use crate::knowledge::property::{ArrayMetadata, PropertyWithMetadata}; #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct PropertyWithMetadataArray { - #[serde(default, skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(required))] pub value: Vec, #[serde(default, skip_serializing_if = "ArrayMetadata::is_empty")] pub metadata: ArrayMetadata, diff --git a/libs/@local/graph/types/rust/src/knowledge/property/metadata/mod.rs b/libs/@local/graph/types/rust/src/knowledge/property/metadata/mod.rs index e9f0a5cec31..a8aa6433888 100644 --- a/libs/@local/graph/types/rust/src/knowledge/property/metadata/mod.rs +++ b/libs/@local/graph/types/rust/src/knowledge/property/metadata/mod.rs @@ -21,14 +21,16 @@ use type_system::url::BaseUrl; pub enum PropertyMetadata { #[cfg_attr(feature = "utoipa", schema(title = "PropertyMetadataArray"))] Array { - #[serde(default, skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(required))] value: Vec, #[serde(default, skip_serializing_if = "ArrayMetadata::is_empty")] metadata: ArrayMetadata, }, #[cfg_attr(feature = "utoipa", schema(title = "PropertyMetadataObject"))] Object { - #[serde(default, skip_serializing_if = "HashMap::is_empty")] + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(required))] value: HashMap, #[serde(default, skip_serializing_if = "ObjectMetadata::is_empty")] metadata: ObjectMetadata, diff --git a/libs/@local/graph/types/rust/src/knowledge/property/object.rs b/libs/@local/graph/types/rust/src/knowledge/property/object.rs index f6fe09e0fa9..10fa2383543 100644 --- a/libs/@local/graph/types/rust/src/knowledge/property/object.rs +++ b/libs/@local/graph/types/rust/src/knowledge/property/object.rs @@ -137,7 +137,8 @@ impl<'a> FromSql<'a> for PropertyObject { #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct PropertyWithMetadataObject { - #[serde(default, skip_serializing_if = "HashMap::is_empty")] + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(required))] pub value: HashMap, #[serde(default, skip_serializing_if = "ObjectMetadata::is_empty")] pub metadata: ObjectMetadata, diff --git a/libs/@local/graph/types/typescript/src/entity.ts b/libs/@local/graph/types/typescript/src/entity.ts index c37b3cad536..c66f6ab4359 100644 --- a/libs/@local/graph/types/typescript/src/entity.ts +++ b/libs/@local/graph/types/typescript/src/entity.ts @@ -241,6 +241,21 @@ export type PropertyWithMetadata = | PropertyObjectWithMetadata | PropertyValueWithMetadata; +export const isValueWithMetadata = ( + metadata: PropertyWithMetadata, +): metadata is PropertyValueWithMetadata => + metadata.metadata !== undefined && "dataTypeId" in metadata.metadata; + +export const isArrayWithMetadata = ( + metadata: PropertyWithMetadata, +): metadata is PropertyArrayWithMetadata => + !isValueMetadata(metadata) && Array.isArray(metadata.value); + +export const isObjectWithMetadata = ( + metadata: PropertyWithMetadata, +): metadata is PropertyObjectWithMetadata => + !isValueMetadata(metadata) && !Array.isArray(metadata.value); + /** * A path to a property in a properties object *