-
Notifications
You must be signed in to change notification settings - Fork 8
Schema improvements #545
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Schema improvements #545
Conversation
8e8959a to
47a2094
Compare
46e19d0 to
fad78d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces significant schema improvements to the Hypergraph library, transitioning from a class-based entity definition API to a new EntitySchema function-based approach. The changes eliminate the mapping system by embedding GRC-20 IDs directly in schema definitions, refactor type utilities, improve relation handling, and remove unused components.
- Replaces
Entity.Classpattern withEntitySchemafunction requiring explicit type and property IDs - Removes mapping system and stores GRC-20 metadata directly in schema definitions
- Refactors relation handling and removes
isRelationFieldutility in favor ofisRelation
Reviewed Changes
Copilot reviewed 92 out of 92 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/hypergraph/src/entity/entity.ts | Implements new EntitySchema function and GRC-20 encoding/decoding utilities |
| packages/hypergraph/src/type/type.ts | Updates type definitions to require property IDs and adds relation support |
| packages/hypergraph/src/utils/isRelation.ts | New utility to identify relation fields using schema annotations |
| packages/hypergraph-react/src/prepare-publish.ts | Updates to work with new schema format and remove mapping dependency |
| packages/hypergraph-react/src/HypergraphAppContext.tsx | Removes mapping prop requirement from provider |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| export const String = (propertyId: string) => { | ||
| return Schema.String.pipe(Schema.annotations({ [PropertyIdSymbol]: propertyId, [PropertyTypeSymbol]: 'string' })); | ||
| }; |
Copilot
AI
Oct 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new Type API requires property IDs for all type definitions, which is a breaking change. Consider providing migration guidance or backwards compatibility helpers for existing schemas.
Copilot uses AI. Check for mistakes.
| * @example | ||
| * ```typescript | ||
| * const User = EntityDefinition({ | ||
| * name: Type.String, | ||
| * age: Type.Number, | ||
| * }, { | ||
| * name: "grc-20-name", | ||
| * age: "grc-20-age" | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export function EntitySchema< | ||
| T extends Record< | ||
| string, | ||
| // biome-ignore lint/suspicious/noExplicitAny: any | ||
| (propertyId: string) => Schema.Schema<any> | Schema.PropertySignature<any, any, any, any, any, any, any> | ||
| >, | ||
| P extends Record<keyof T, string>, | ||
| >( | ||
| schemaTypes: T, | ||
| mapping: { | ||
| types: Array<string>; | ||
| properties: P; | ||
| }, | ||
| ): Schema.Struct<{ | ||
| [K in keyof T]: ReturnType<T[K]> & { id: string }; | ||
| }> { |
Copilot
AI
Oct 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The complex generic type constraints make this function difficult to understand. Consider extracting type aliases or adding comprehensive JSDoc examples to improve maintainability.
| * @example | |
| * ```typescript | |
| * const User = EntityDefinition({ | |
| * name: Type.String, | |
| * age: Type.Number, | |
| * }, { | |
| * name: "grc-20-name", | |
| * age: "grc-20-age" | |
| * }); | |
| * ``` | |
| */ | |
| export function EntitySchema< | |
| T extends Record< | |
| string, | |
| // biome-ignore lint/suspicious/noExplicitAny: any | |
| (propertyId: string) => Schema.Schema<any> | Schema.PropertySignature<any, any, any, any, any, any, any> | |
| >, | |
| P extends Record<keyof T, string>, | |
| >( | |
| schemaTypes: T, | |
| mapping: { | |
| types: Array<string>; | |
| properties: P; | |
| }, | |
| ): Schema.Struct<{ | |
| [K in keyof T]: ReturnType<T[K]> & { id: string }; | |
| }> { | |
| * @template T - A mapping from property names to functions that take a property ID and return a Schema or PropertySignature. | |
| * @template P - A mapping from property names to their corresponding property IDs. | |
| * | |
| * @example | |
| * ```typescript | |
| * type UserSchemaTypes = { | |
| * name: (propertyId: string) => Schema.Schema<string> | Schema.PropertySignature<string, any, any, any, any, any, any>; | |
| * age: (propertyId: string) => Schema.Schema<number> | Schema.PropertySignature<number, any, any, any, any, any, any>; | |
| * }; | |
| * | |
| * type UserPropertyIds = { | |
| * name: "grc-20-name"; | |
| * age: "grc-20-age"; | |
| * }; | |
| * | |
| * const User = EntitySchema<UserSchemaTypes, UserPropertyIds>( | |
| * { | |
| * name: (id) => Type.String.pipe(Schema.annotations({ id })), | |
| * age: (id) => Type.Number.pipe(Schema.annotations({ id })), | |
| * }, | |
| * { | |
| * types: ["User"], | |
| * properties: { | |
| * name: "grc-20-name", | |
| * age: "grc-20-age" | |
| * } | |
| * } | |
| * ); | |
| * ``` | |
| */ | |
| // Type alias for the property function type | |
| type EntityPropertyFunction = (propertyId: string) => Schema.Schema<any> | Schema.PropertySignature<any, any, any, any, any, any, any>; | |
| // Type alias for the schema types mapping | |
| type EntitySchemaTypes = Record<string, EntityPropertyFunction>; | |
| // Type alias for the property ID mapping | |
| type EntityPropertyIdMapping<T extends EntitySchemaTypes> = Record<keyof T, string>; | |
| // Type alias for the return type | |
| type EntitySchemaReturnType<T extends EntitySchemaTypes> = Schema.Struct<{ | |
| [K in keyof T]: ReturnType<T[K]> & { id: string }; | |
| }>; | |
| export function EntitySchema< | |
| T extends EntitySchemaTypes, | |
| P extends EntityPropertyIdMapping<T>, | |
| >( | |
| schemaTypes: T, | |
| mapping: { | |
| types: Array<string>; | |
| properties: P; | |
| }, | |
| ): EntitySchemaReturnType<T> { |
Copilot uses AI. Check for mistakes.
| type RelationArrayKeys<T> = { | ||
| [K in keyof T]: T[K] extends readonly (infer U)[] | ||
| ? U extends object | ||
| ? K | ||
| : never | ||
| : T[K] extends (infer U)[] | ||
| ? U extends object | ||
| ? K | ||
| : never | ||
| : never; | ||
| }[keyof T]; |
Copilot
AI
Oct 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This complex mapped type for identifying relation array keys is difficult to understand and maintain. Consider simplifying the logic or adding detailed comments explaining the transformation.
Copilot uses AI. Check for mistakes.
| decodedEntitiesCache.set(typeName, cacheEntry); | ||
| } | ||
| if (typeIds.length > 1) { | ||
| console.error('Schema with multiple type ids is not supported', typeIds); |
Copilot
AI
Oct 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message should be more descriptive about the consequences of having multiple type IDs and suggest alternatives or workarounds.
| console.error('Schema with multiple type ids is not supported', typeIds); | |
| console.error( | |
| 'Error: Schema with multiple type IDs is not supported. ' + | |
| 'This may cause entities to be cached or queried incorrectly. ' + | |
| 'Please ensure your schema has a single type ID. ' + | |
| 'If you need to support multiple types, consider refactoring your schema or splitting it into separate schemas. ' + | |
| 'Type IDs found:', typeIds | |
| ); |
Copilot uses AI. Check for mistakes.
createFollow up:
EntitySchematoEntity