allow to specify and retrieve relation entity values from the knowledge graph - #550
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR extends the Entity.Schema API to support querying properties on relation entities themselves (not just the target entities). Previously, relations only carried an id; now they can include additional properties like a website field on a project relationship.
Key changes:
- Added support for relation properties through a second optional parameter to
Type.Relation() - Updated GraphQL queries to fetch
entity.valuesListfor relation entities at all nesting levels - Modified type system to allow flexible property ID mappings (string or object with properties)
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/hypergraph/src/type/type.ts | Added function overloads for Relation with optional properties parameter and updated type system to support relation property schemas |
| packages/hypergraph/src/utils/convert-relations.ts | Extracted ValueList type, updated RecursiveQueryEntity and NestedRawEntity types, added logic to extract relation properties from entity.valuesList |
| packages/hypergraph/src/entity/types.ts | Extended EntityWithRelation._relation type to include Record<string, unknown> for arbitrary relation properties |
| packages/hypergraph/src/entity/schema.ts | Changed generic constraints to allow flexible property ID mappings (not just strings) |
| packages/hypergraph/src/constants.ts | Added RelationPropertiesSymbol for annotating relation property schemas |
| packages/hypergraph/src/entity/find-many-public.ts | Updated GraphQL queries to fetch entity.valuesList for relations at levels 1 and 2 |
| packages/hypergraph/src/entity/search-many-public.ts | Updated GraphQL queries to fetch entity.valuesList for relations at levels 1 and 2 |
| packages/hypergraph-react/src/internal/use-entity-public.tsx | Updated GraphQL queries to fetch entity.valuesList for relations at levels 1 and 2 |
| packages/hypergraph-react/src/internal/convert-relations.ts | Deleted duplicate file (functionality consolidated in hypergraph package) |
| apps/events/src/schema.ts | Added example Podcast schema demonstrating relation properties usage |
| apps/events/src/routes/podcasts.lazy.tsx | Added test route demonstrating relation properties consumption |
Comments suppressed due to low confidence (1)
packages/hypergraph/src/utils/convert-relations.ts:94
- Inconsistent undefined handling between relation entity properties (line 94 checks
if (rawValue)) and relation properties (line 116 checksif (rawValue !== undefined)). The stricter check at line 116 correctly allows falsy values likefalse,0, or empty string to be assigned. Line 94 should use the same pattern for consistency.
if (rawValue) {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| string, | ||
| // biome-ignore lint/suspicious/noExplicitAny: any | ||
| (propertyId: string) => EffectSchema.Schema<any> | EffectSchema.PropertySignature<any, any, any, any, any, any, any> | ||
| (propertyId: any) => EffectSchema.Schema<any> | EffectSchema.PropertySignature<any, any, any, any, any, any, any> |
There was a problem hiding this comment.
The generic type constraint was changed from (propertyId: string) to (propertyId: any) to support relation properties with complex mappings. This breaking API change should be documented in the changeset or in a JSDoc comment explaining why property builders now accept any instead of string.
| for (const [key, schemaType] of Object.entries(options.properties)) { | ||
| const propertyMapping = relationPropertyIds?.[key]; |
There was a problem hiding this comment.
If relationPropertyIds is undefined (when using the simple string mapping syntax), propertyMapping will be undefined, causing schema builders to be called with undefined. This will fail for property builders like Type.String that expect a string property ID. Add a guard to skip property processing when relationPropertyIds is undefined, or throw a more helpful error message.
| for (const [key, schemaType] of Object.entries(options.properties)) { | |
| const propertyMapping = relationPropertyIds?.[key]; | |
| if (relationPropertyIds === undefined) { | |
| throw new Error( | |
| "Relation: 'relationPropertyIds' is undefined. When using 'options.properties', the mapping argument must include a 'properties' field mapping property keys to property IDs." | |
| ); | |
| } | |
| for (const [key, schemaType] of Object.entries(options.properties)) { | |
| const propertyMapping = relationPropertyIds[key]; |
No description provided.