Skip to content

Conversation

@nikgraf
Copy link
Collaborator

@nikgraf nikgraf commented Sep 29, 2025

  • public query filters
  • preparePublish
  • remove isRelationField
  • investigate create
  • refactor/merge parseResult from useEntityPublic and useQueryPublic
  • live updates
  • fix adding two relations during creation (2 users for one todo)

Follow up:

  • public query: relation entity
  • rename EntitySchema to Entity
  • rename useQuery to useEntities
  • relation from private to public entity
  • switch to d2ts
  • check test date mapping (dApps, assets)

@nikgraf nikgraf merged commit edf7630 into main Oct 9, 2025
6 checks passed
@nikgraf nikgraf deleted the schema-improvements branch October 9, 2025 16:43
@nikgraf nikgraf requested a review from Copilot October 9, 2025 17:19
Copy link
Contributor

Copilot AI left a 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.Class pattern with EntitySchema function requiring explicit type and property IDs
  • Removes mapping system and stores GRC-20 metadata directly in schema definitions
  • Refactors relation handling and removes isRelationField utility in favor of isRelation

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.

Comment on lines +16 to +18
export const String = (propertyId: string) => {
return Schema.String.pipe(Schema.annotations({ [PropertyIdSymbol]: propertyId, [PropertyTypeSymbol]: 'string' }));
};
Copy link

Copilot AI Oct 9, 2025

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.

Comment on lines +11 to +37
* @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 };
}> {
Copy link

Copilot AI Oct 9, 2025

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.

Suggested change
* @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.

Comment on lines +16 to +26
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];
Copy link

Copilot AI Oct 9, 2025

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);
Copy link

Copilot AI Oct 9, 2025

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.

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant