1
1
import { Graph } from '@graphprotocol/grc-20' ;
2
- import { type Entity , type Mapping , store } from '@graphprotocol/hypergraph' ;
2
+ import { Constants , type Entity } from '@graphprotocol/hypergraph' ;
3
3
import { useQuery as useQueryTanstack } from '@tanstack/react-query' ;
4
- import { useSelector } from '@xstate/store/react' ;
5
4
import * as Either from 'effect/Either' ;
5
+ import * as Option from 'effect/Option' ;
6
6
import * as Schema from 'effect/Schema' ;
7
+ import * as SchemaAST from 'effect/SchemaAST' ;
7
8
import { gql , request } from 'graphql-request' ;
8
9
import { useMemo } from 'react' ;
9
10
import { convertPropertyValue } from './convert-property-value.js' ;
10
11
import { convertRelations } from './convert-relations.js' ;
12
+ import { getRelationTypeIds } from './get-relation-type-ids.js' ;
11
13
import { useHypergraphSpaceInternal } from './use-hypergraph-space-internal.js' ;
12
14
13
15
const entityQueryDocumentLevel0 = gql `
@@ -47,6 +49,7 @@ query entity($id: UUID!, $spaceId: UUID!, $relationTypeIdsLevel1: [UUID!]!) {
47
49
relationsList(
48
50
filter: {spaceId: {is: $spaceId}, typeId:{ in: $relationTypeIdsLevel1}},
49
51
) {
52
+ id
50
53
toEntity {
51
54
id
52
55
name
@@ -83,6 +86,7 @@ query entity($id: UUID!, $spaceId: UUID!, $relationTypeIdsLevel1: [UUID!]!, $rel
83
86
relationsList(
84
87
filter: {spaceId: {is: $spaceId}, typeId:{ in: $relationTypeIdsLevel1}},
85
88
) {
89
+ id
86
90
toEntity {
87
91
id
88
92
name
@@ -97,6 +101,7 @@ query entity($id: UUID!, $spaceId: UUID!, $relationTypeIdsLevel1: [UUID!]!, $rel
97
101
relationsList(
98
102
filter: {spaceId: {is: $spaceId}, typeId:{ in: $relationTypeIdsLevel2}},
99
103
) {
104
+ id
100
105
toEntity {
101
106
id
102
107
name
@@ -131,6 +136,7 @@ type EntityQueryResult = {
131
136
point : string ;
132
137
} [ ] ;
133
138
relationsList ?: {
139
+ id : string ;
134
140
toEntity : {
135
141
id : string ;
136
142
name : string ;
@@ -143,6 +149,7 @@ type EntityQueryResult = {
143
149
point : string ;
144
150
} [ ] ;
145
151
relationsList ?: {
152
+ id : string ;
146
153
toEntity : {
147
154
id : string ;
148
155
name : string ;
@@ -163,41 +170,51 @@ type EntityQueryResult = {
163
170
} | null ;
164
171
} ;
165
172
166
- export const parseResult = < S extends Schema . Schema . AnyNoContext > (
167
- queryData : EntityQueryResult ,
168
- type : S ,
169
- mappingEntry : Mapping . MappingEntry ,
170
- mapping : Mapping . Mapping ,
171
- ) => {
173
+ export const parseResult = < S extends Schema . Schema . AnyNoContext > ( queryData : EntityQueryResult , type : S ) => {
172
174
if ( ! queryData . entity ) {
173
175
return { data : null , invalidEntity : null } ;
174
176
}
175
177
176
- const decode = Schema . decodeUnknownEither ( type ) ;
178
+ const schemaWithId = Schema . extend ( Schema . Struct ( { id : Schema . String } ) ) ( type ) ;
179
+ const decode = Schema . decodeUnknownEither ( schemaWithId ) ;
177
180
const queryEntity = queryData . entity ;
178
181
let rawEntity : Record < string , string | boolean | number | unknown [ ] | Date > = {
179
182
id : queryEntity . id ,
180
183
} ;
181
184
182
- // take the mappingEntry and assign the attributes to the rawEntity
183
- for ( const [ key , value ] of Object . entries ( mappingEntry ?. properties ?? { } ) ) {
184
- const property = queryEntity . valuesList . find ( ( a ) => a . propertyId === value ) ;
185
- if ( property ) {
186
- rawEntity [ key ] = convertPropertyValue ( property , type ) ;
185
+ const ast = type . ast as SchemaAST . TypeLiteral ;
186
+
187
+ for ( const prop of ast . propertySignatures ) {
188
+ const propType = prop . isOptional ? prop . type . types [ 0 ] : prop . type ;
189
+ const result = SchemaAST . getAnnotation < string > ( Constants . PropertyIdSymbol ) ( propType ) ;
190
+
191
+ if ( Option . isSome ( result ) ) {
192
+ const value = queryEntity . valuesList . find ( ( a ) => a . propertyId === result . value ) ;
193
+ if ( value ) {
194
+ const rawValue = convertPropertyValue ( value , propType ) ;
195
+ if ( rawValue ) {
196
+ rawEntity [ String ( prop . name ) ] = rawValue ;
197
+ }
198
+ }
187
199
}
188
200
}
189
201
190
202
rawEntity = {
191
203
...rawEntity ,
192
- ...convertRelations ( queryEntity , type , mappingEntry , mapping ) ,
204
+ ...convertRelations ( queryEntity , ast ) ,
193
205
} ;
194
206
207
+ console . log ( 'rawEntity' , rawEntity ) ;
208
+
195
209
const decodeResult = decode ( {
196
210
...rawEntity ,
197
211
__deleted : false ,
212
+ // __version: queryEntity.currentVersion.versionId,
198
213
__version : '' ,
199
214
} ) ;
200
215
216
+ console . log ( 'decodeResult' , decodeResult ) ;
217
+
201
218
if ( Either . isRight ( decodeResult ) ) {
202
219
return {
203
220
data : { ...decodeResult . right , __schema : type } as Entity . Entity < S > ,
@@ -220,61 +237,42 @@ export const useEntityPublic = <S extends Schema.Schema.AnyNoContext>(type: S, p
220
237
const { id, enabled = true , space : spaceFromParams , include } = params ;
221
238
const { space : spaceFromContext } = useHypergraphSpaceInternal ( ) ;
222
239
const space = spaceFromParams ?? spaceFromContext ;
223
- const mapping = useSelector ( store , ( state ) => state . context . mapping ) ;
224
-
225
- // @ts -expect-error TODO should use the actual type instead of the name in the mapping
226
- const typeName = type . name ;
227
- const mappingEntry = mapping ?. [ typeName ] ;
228
- if ( enabled && ! mappingEntry ) {
229
- throw new Error ( `Mapping entry for ${ typeName } not found` ) ;
230
- }
231
240
232
241
// constructing the relation type ids for the query
233
- const relationTypeIdsLevel1 : string [ ] = [ ] ;
234
- const relationTypeIdsLevel2 : string [ ] = [ ] ;
235
- for ( const key in mappingEntry ?. relations ?? { } ) {
236
- if ( include ?. [ key ] && mappingEntry ?. relations ?. [ key ] ) {
237
- relationTypeIdsLevel1 . push ( mappingEntry ?. relations ?. [ key ] ) ;
238
- const field = type . fields [ key ] ;
239
- // @ts -expect-error TODO find a better way to access the relation type name
240
- const typeName2 = field . value . name ;
241
- const mappingEntry2 = mapping [ typeName2 ] ;
242
- for ( const key2 in mappingEntry2 ?. relations ?? { } ) {
243
- if ( include ?. [ key ] [ key2 ] && mappingEntry2 ?. relations ?. [ key2 ] ) {
244
- relationTypeIdsLevel2 . push ( mappingEntry2 ?. relations ?. [ key2 ] ) ;
245
- }
246
- }
247
- }
248
- }
242
+ const relationTypeIds = getRelationTypeIds ( type , include ) ;
243
+
244
+ const typeIds = SchemaAST . getAnnotation < string [ ] > ( Constants . TypeIdsSymbol ) ( type . ast as SchemaAST . TypeLiteral ) . pipe (
245
+ Option . getOrElse ( ( ) => [ ] ) ,
246
+ ) ;
249
247
250
248
const result = useQueryTanstack ( {
251
- queryKey : [ 'hypergraph-public-entity' , typeName , id , space , relationTypeIdsLevel1 , relationTypeIdsLevel2 , include ] ,
249
+ queryKey : [ 'hypergraph-public-entity' , id , typeIds , space , relationTypeIds . level1 , relationTypeIds . level2 , include ] ,
252
250
queryFn : async ( ) => {
253
251
let queryDocument = entityQueryDocumentLevel0 ;
254
- if ( relationTypeIdsLevel1 . length > 0 ) {
252
+ if ( relationTypeIds . level1 . length > 0 ) {
255
253
queryDocument = entityQueryDocumentLevel1 ;
256
254
}
257
- if ( relationTypeIdsLevel2 . length > 0 ) {
255
+ if ( relationTypeIds . level2 . length > 0 ) {
258
256
queryDocument = entityQueryDocumentLevel2 ;
259
257
}
260
258
261
259
const result = await request < EntityQueryResult > ( `${ Graph . TESTNET_API_ORIGIN } /graphql` , queryDocument , {
262
260
id,
263
261
spaceId : space ,
264
- relationTypeIdsLevel1,
265
- relationTypeIdsLevel2,
262
+ relationTypeIdsLevel1 : relationTypeIds . level1 ,
263
+ relationTypeIdsLevel2 : relationTypeIds . level2 ,
266
264
} ) ;
267
265
return result ;
268
266
} ,
269
267
enabled : enabled && ! ! id && ! ! space ,
270
268
} ) ;
271
269
272
270
const { data, invalidEntity } = useMemo ( ( ) => {
273
- if ( result . data && mappingEntry ) {
274
- return parseResult ( result . data , type , mappingEntry , mapping ) ;
271
+ if ( result . data ) {
272
+ return parseResult ( result . data , type ) ;
275
273
}
276
274
return { data : null , invalidEntity : null } ;
277
- } , [ result . data , type , mappingEntry , mapping ] ) ;
275
+ } , [ result . data , type ] ) ;
278
276
279
277
return { ...result , data, invalidEntity } ;
280
278
} ;
0 commit comments