@@ -28,82 +28,62 @@ export const repo = new Repo({
2828 network : [ ] ,
2929} ) ;
3030
31- // Function to create schema functions
32- export function createFunctions <
33- Attributes extends { [ attrName : string ] : S . Schema < any > } ,
34- Types extends { [ typeName : string ] : ReadonlyArray < keyof Attributes > } ,
35- > ( { attributes, types } : { attributes : Attributes ; types : Types } ) {
36- // Build attribute schemas
37- const attributeSchemas : {
38- [ K in keyof Attributes ] : Attributes [ K ] ;
39- } = attributes ;
40-
41- // Build type schemas
42- const typeSchemas : {
43- [ K in keyof Types ] : S . Schema < {
44- [ AttrName in Types [ K ] [ number ] ] : S . Schema . Type <
45- ( typeof attributeSchemas ) [ AttrName ]
46- > ;
47- } > ;
48- } = { } as any ;
49-
50- for ( const typeName in types ) {
51- const attrNames = types [ typeName as keyof Types ] ;
52- const attrSchemaEntries : any = { } ;
53- for ( const attrName of attrNames ) {
54- const attrSchema = attributeSchemas [ attrName ] ;
55- if ( ! attrSchema ) {
56- throw new Error ( `Attribute ${ String ( attrName ) } is not defined` ) ;
57- }
58- attrSchemaEntries [ attrName as string ] = attrSchema ;
59- }
60- typeSchemas [ typeName as keyof Types ] = S . Struct ( attrSchemaEntries ) as any ;
61- }
31+ // Helper type to extract schema type
32+ type SchemaType < T > = T extends S . Schema < any , infer A > ? A : never ;
6233
63- // Type for merged types
64- type TypeSchemasMap = typeof typeSchemas ;
65-
66- type TypeSchemaTypes < T extends keyof TypeSchemasMap > = S . Schema . Type <
67- TypeSchemasMap [ T ]
68- > ;
69-
70- type UnionToIntersection < U > = (
71- U extends any ? ( k : U ) => void : never
72- ) extends ( k : infer I ) => void
73- ? I
74- : never ;
75-
76- type MergedType < T extends ( keyof TypeSchemasMap ) [ ] > = UnionToIntersection <
77- TypeSchemaTypes < T [ number ] >
78- > ;
79-
80- // Helper function to build merged schema
81- function buildMergedSchema < TypeNames extends ( keyof TypeSchemasMap ) [ ] > (
82- typesToCombine : [ ...TypeNames ]
83- ) : S . Schema < any > {
84- const mergedFields : Record < string , S . Schema < any > > = { } ;
85-
86- for ( const typeName of typesToCombine ) {
87- const schema = typeSchemas [ typeName ] ;
88- const structSchema = schema as S . Schema < any > & {
89- fields : Record < string , S . Schema < any > > ;
90- } ;
34+ // Type for the schema structure
35+ export type SchemaDefinition = {
36+ types : Record < string , Record < string , S . Schema < any , any > > > ;
37+ } ;
9138
92- if ( "fields" in structSchema ) {
93- Object . assign ( mergedFields , structSchema . fields ) ;
94- } else {
95- throw new Error ( `Schema for type ${ String ( typeName ) } is not a struct` ) ;
96- }
97- }
39+ // Extract all possible keys from schema types
40+ type EntityKeys < T extends SchemaDefinition > = keyof T [ "types" ] & string ;
41+
42+ // Get merged type from array of keys
43+ type MergedEntityType <
44+ T extends SchemaDefinition ,
45+ Keys extends readonly EntityKeys < T > [ ] ,
46+ > = UnionToIntersection <
47+ {
48+ [ K in Keys [ number ] ] : {
49+ [ P in keyof T [ "types" ] [ K ] ] : SchemaType < T [ "types" ] [ K ] [ P ] > ;
50+ } ;
51+ } [ Keys [ number ] ]
52+ > ;
9853
99- return S . Struct ( mergedFields ) ;
100- }
54+ // Helper type to convert union to intersection
55+ type UnionToIntersection < U > = ( U extends any ? ( k : U ) => void : never ) extends (
56+ k : infer I
57+ ) => void
58+ ? I
59+ : never ;
10160
61+ // Function to create schema functions
62+ export function createFunctions < T extends SchemaDefinition > ( schema : T ) {
10263 // Create a React Context to provide the schema
10364 type SpaceContextProps = {
10465 id : string ;
10566 } ;
10667
68+ function buildMergedSchema < K extends readonly EntityKeys < T > [ ] > (
69+ types : [ ...K ]
70+ ) : S . Schema < any , MergedEntityType < T , K > > {
71+ // Create a record of all properties and their schemas
72+ const propertySchemas = types . reduce (
73+ ( acc , type ) => {
74+ const typeSchema = schema . types [ type ] ;
75+ return { ...acc , ...typeSchema } ;
76+ } ,
77+ { } as Record < string , S . Schema < any , any > >
78+ ) ;
79+
80+ // Convert the record to a struct schema
81+ return S . Struct ( propertySchemas ) as unknown as S . Schema <
82+ any ,
83+ MergedEntityType < T , K >
84+ > ;
85+ }
86+
10787 const SpaceContext = createContext < SpaceContextProps | undefined > ( undefined ) ;
10888
10989 function SpaceProvider ( { children, id } : SpaceProviderProps ) {
@@ -137,10 +117,10 @@ export function createFunctions<
137117 const id = useSpaceId ( ) ;
138118 const [ , changeDoc ] = useDocument < DocumentContent > ( id as AnyDocumentId ) ;
139119
140- function createEntity < TypeNames extends ( keyof TypeSchemasMap ) [ ] > (
141- types : [ ...TypeNames ] ,
142- data : MergedType < TypeNames >
143- ) : MergedType < TypeNames > {
120+ function createEntity < K extends readonly EntityKeys < T > [ ] > (
121+ types : [ ...K ] ,
122+ data : MergedEntityType < T , K >
123+ ) : MergedEntityType < T , K > {
144124 if ( types . length === 0 ) {
145125 throw new Error ( "Entity must have at least one type" ) ;
146126 }
@@ -156,7 +136,7 @@ export function createFunctions<
156136 doc . entities [ entityId ] = { ...result , types } ;
157137 } ) ;
158138
159- return result as MergedType < TypeNames > ;
139+ return result as MergedEntityType < T , K > ;
160140 }
161141
162142 return createEntity ;
@@ -194,17 +174,10 @@ export function createFunctions<
194174 return deleteEntity ;
195175 }
196176
197- function useQuery < TypeNames extends ( keyof TypeSchemasMap ) [ ] > ( {
177+ function useQuery < K extends readonly EntityKeys < T > [ ] > ( {
198178 types,
199- where,
200179 } : {
201- types : [ ...TypeNames ] ;
202- where ?: {
203- [ AttrName in keyof Attributes ] ?: {
204- equals ?: S . Schema . Type < Attributes [ AttrName ] > ;
205- contains ?: S . Schema . Type < Attributes [ AttrName ] > ;
206- } ;
207- } ;
180+ types : [ ...K ] ;
208181 } ) {
209182 const prevEntitiesRef = useRef < any > ( { } ) ;
210183 const id = useSpaceId ( ) ;
@@ -234,7 +207,7 @@ export function createFunctions<
234207
235208 const entities = useSyncExternalStore (
236209 subscribe ,
237- ( ) : Record < string , MergedType < TypeNames > > => {
210+ ( ) : Record < string , MergedEntityType < T , K > > => {
238211 const doc = handle ?. docSync ( ) ;
239212 if ( ! doc ) {
240213 if ( fastDeepEqual ( prevEntitiesRef . current , { } ) ) {
@@ -246,11 +219,11 @@ export function createFunctions<
246219 }
247220
248221 // create filteredEntities object with only entities that include all the types
249- const filteredEntities : Record < string , MergedType < TypeNames > > = { } ;
222+ const filteredEntities : Record < string , MergedEntityType < T , K > > = { } ;
250223 for ( const entityId in doc . entities ) {
251224 const entity = doc . entities [ entityId ] ;
252225 if ( types . every ( ( type ) => entity . types . includes ( type as string ) ) ) {
253- filteredEntities [ entityId ] = entity as MergedType < TypeNames > ;
226+ filteredEntities [ entityId ] = entity as MergedEntityType < T , K > ;
254227 }
255228 }
256229
0 commit comments