@@ -7,72 +7,74 @@ import { SchemaDrivenDataMap } from '../../types/SchemaDrivenDataMap/__.js'
7
7
import type { GeneratedExtensions } from './global.js'
8
8
import { injectTypenameOnRootResultFields } from './injectTypenameOnRootResultFields.js'
9
9
10
- export const SchemaErrors = ( ) => {
11
- return createExtension ( {
12
- name : `SchemaErrors` ,
13
- onRequest : async ( { pack } ) => {
14
- const state = pack . input . state
15
- const sddm = state . schemaMap
16
-
17
- if ( ! sddm ) return pack ( )
18
-
19
- const request = normalizeRequestToNode ( pack . input . request )
20
-
21
- // We will mutate query. Assign it back to input for it to be carried forward.
22
- pack . input . request . query = request . query
23
-
24
- injectTypenameOnRootResultFields ( { sddm, request } )
25
-
26
- const { exchange } = await pack ( )
27
- const { unpack } = await exchange ( )
28
- const { decode } = await unpack ( )
29
- const result = await decode ( )
30
-
31
- if ( result instanceof Error || ! result . data ) return result
32
-
33
- const schemaErrors : Error [ ] = [ ]
34
- for ( const [ rootFieldName , rootFieldValue ] of Object . entries ( result . data ) ) {
35
- // todo this check would be nice but it doesn't account for aliases right now. To achieve this we would
36
- // need to have the selection set available to use and then do a costly analysis for all fields that were aliases.
37
- // So costly that we would probably instead want to create an index of them on the initial encoding step and
38
- // then make available down stream.
39
- // const sddmNodeField = sddm.roots[rootTypeName]?.f[rootFieldName]
40
- // if (!sddmNodeField) return null
41
- // if (!isPlainObject(rootFieldValue)) return new Error(`Expected result field to be an object.`)
42
- if ( ! isRecordLikeObject ( rootFieldValue ) ) continue
43
-
44
- // If __typename is not selected we assume that this is not a result field.
45
- // The extension makes sure that the __typename would have been selected if it were a result field.
46
- const __typename = rootFieldValue [ `__typename` ]
47
- if ( ! isString ( __typename ) ) continue
48
-
49
- const sddmNode = sddm . types [ __typename ]
50
- const isErrorObject = SchemaDrivenDataMap . isOutputObject ( sddmNode ) && Boolean ( sddmNode . e )
51
- if ( ! isErrorObject ) continue
52
-
53
- // todo extract message
54
- // todo allow mapping error instances to schema errors
55
- schemaErrors . push ( new Error ( `Failure on field ${ rootFieldName } : ${ __typename } ` ) )
56
- }
57
-
58
- const error = ( schemaErrors . length === 1 )
59
- ? schemaErrors [ 0 ] !
60
- : schemaErrors . length > 0
61
- ? new Errors . ContextualAggregateError ( `Two or more schema errors in the execution result.` , { } , schemaErrors )
62
- : null
63
-
64
- if ( error ) {
65
- result . errors = [ ...result . errors ?? [ ] , error as any ]
66
- }
67
-
68
- return result
69
- } ,
70
- typeHooks : createTypeHooks < {
71
- onRequestDocumentRootType : OnRequestDocumentRootType_
72
- onRequestResult : OnRequestResult_
73
- } > ,
74
- } )
75
- }
10
+ export const SchemaErrors = createExtension ( {
11
+ name : `SchemaErrors` ,
12
+ create : ( ) => {
13
+ return {
14
+ onRequest : async ( { pack } ) => {
15
+ const state = pack . input . state
16
+ const sddm = state . schemaMap
17
+
18
+ if ( ! sddm ) return pack ( )
19
+
20
+ const request = normalizeRequestToNode ( pack . input . request )
21
+
22
+ // We will mutate query. Assign it back to input for it to be carried forward.
23
+ pack . input . request . query = request . query
24
+
25
+ injectTypenameOnRootResultFields ( { sddm, request } )
26
+
27
+ const { exchange } = await pack ( )
28
+ const { unpack } = await exchange ( )
29
+ const { decode } = await unpack ( )
30
+ const result = await decode ( )
31
+
32
+ if ( result instanceof Error || ! result . data ) return result
33
+
34
+ const schemaErrors : Error [ ] = [ ]
35
+ for ( const [ rootFieldName , rootFieldValue ] of Object . entries ( result . data ) ) {
36
+ // todo this check would be nice but it doesn't account for aliases right now. To achieve this we would
37
+ // need to have the selection set available to use and then do a costly analysis for all fields that were aliases.
38
+ // So costly that we would probably instead want to create an index of them on the initial encoding step and
39
+ // then make available down stream.
40
+ // const sddmNodeField = sddm.roots[rootTypeName]?.f[rootFieldName]
41
+ // if (!sddmNodeField) return null
42
+ // if (!isPlainObject(rootFieldValue)) return new Error(`Expected result field to be an object.`)
43
+ if ( ! isRecordLikeObject ( rootFieldValue ) ) continue
44
+
45
+ // If __typename is not selected we assume that this is not a result field.
46
+ // The extension makes sure that the __typename would have been selected if it were a result field.
47
+ const __typename = rootFieldValue [ `__typename` ]
48
+ if ( ! isString ( __typename ) ) continue
49
+
50
+ const sddmNode = sddm . types [ __typename ]
51
+ const isErrorObject = SchemaDrivenDataMap . isOutputObject ( sddmNode ) && Boolean ( sddmNode . e )
52
+ if ( ! isErrorObject ) continue
53
+
54
+ // todo extract message
55
+ // todo allow mapping error instances to schema errors
56
+ schemaErrors . push ( new Error ( `Failure on field ${ rootFieldName } : ${ __typename } ` ) )
57
+ }
58
+
59
+ const error = ( schemaErrors . length === 1 )
60
+ ? schemaErrors [ 0 ] !
61
+ : schemaErrors . length > 0
62
+ ? new Errors . ContextualAggregateError ( `Two or more schema errors in the execution result.` , { } , schemaErrors )
63
+ : null
64
+
65
+ if ( error ) {
66
+ result . errors = [ ...result . errors ?? [ ] , error as any ]
67
+ }
68
+
69
+ return result
70
+ } ,
71
+ typeHooks : createTypeHooks < {
72
+ onRequestDocumentRootType : OnRequestDocumentRootType_
73
+ onRequestResult : OnRequestResult_
74
+ } > ,
75
+ }
76
+ } ,
77
+ } )
76
78
77
79
type OnRequestDocumentRootType < $Params extends Extension . Hooks . OnRequestDocumentRootType . Params > =
78
80
$Params [ 'selectionRootType' ]
0 commit comments