11import { useCallback , useEffect , useMemo , useState } from 'react' ;
22import {
33 buildClientSchema ,
4- getIntrospectionQuery ,
54 GraphQLSchema ,
5+ introspectionFromSchema ,
66 type IntrospectionQuery ,
77} from 'graphql' ;
88import { toast } from 'sonner' ;
9- import z from 'zod' ;
9+ // import z from 'zod';
1010import { asyncInterval } from '@/lib/utils' ;
11- import { createRequestSignal } from './request ' ;
11+ import { SubscriptionProtocol , UrlLoader } from '@graphql-tools/url-loader ' ;
1212import type { LaboratorySettingsActions , LaboratorySettingsState } from './settings' ;
1313
1414export interface LaboratoryEndpointState {
@@ -24,31 +24,6 @@ export interface LaboratoryEndpointActions {
2424 restoreDefaultEndpoint : ( ) => void ;
2525}
2626
27- function buildIntrospectionRequest (
28- queryName ?: string ,
29- method ?: 'GET' | 'POST' ,
30- schemaDescription ?: boolean ,
31- ) {
32- const query = getIntrospectionQuery ( {
33- schemaDescription,
34- } ) . replace ( 'query IntrospectionQuery' , `query ${ queryName ?? 'IntrospectionQuery' } ` ) ;
35-
36- return {
37- method,
38- query,
39- } as const ;
40- }
41-
42- const GraphQLResponseErrorSchema = z
43- . object ( {
44- errors : z . array (
45- z . object ( {
46- message : z . string ( ) ,
47- } ) ,
48- ) ,
49- } )
50- . strict ( ) ;
51-
5227export const useEndpoint = ( props : {
5328 defaultEndpoint ?: string | null ;
5429 onEndpointChange ?: ( endpoint : string | null ) => void ;
@@ -70,6 +45,8 @@ export const useEndpoint = (props: {
7045 return introspection ? buildClientSchema ( introspection ) : null ;
7146 } , [ introspection ] ) ;
7247
48+ const loader = useMemo ( ( ) => new UrlLoader ( ) , [ ] ) ;
49+
7350 const fetchSchema = useCallback (
7451 async ( signal ?: AbortSignal ) => {
7552 if ( endpoint === props . defaultEndpoint && props . defaultSchemaIntrospection ) {
@@ -83,53 +60,39 @@ export const useEndpoint = (props: {
8360 }
8461
8562 try {
86- const introspectionRequest = buildIntrospectionRequest (
87- props . settingsApi ?. settings . introspection . queryName ,
88- props . settingsApi ?. settings . introspection . method ,
89- props . settingsApi ?. settings . introspection . schemaDescription ,
90- ) ;
91-
92- const requestSignal = createRequestSignal (
93- signal ,
94- props . settingsApi ?. settings . fetch . timeout ,
95- ) ;
96- const requestUrl =
97- introspectionRequest . method === 'GET'
98- ? ( ( ) => {
99- const url = new URL ( endpoint ) ;
100- url . searchParams . set ( 'query' , introspectionRequest . query ) ;
101- return url . toString ( ) ;
102- } ) ( )
103- : endpoint ;
104-
105- const response = await fetch ( requestUrl , {
106- signal : requestSignal ,
107- method : introspectionRequest . method ,
108- body :
109- introspectionRequest . method === 'POST'
110- ? JSON . stringify ( {
111- query : introspectionRequest . query ,
112- } )
113- : undefined ,
114- headers :
115- introspectionRequest . method === 'POST'
116- ? {
117- 'Content-Type' : 'application/json' ,
118- }
119- : undefined ,
120- } ) . then ( r => r . json ( ) ) ;
121-
122- const parsedResponse = GraphQLResponseErrorSchema . safeParse ( response ) ;
123-
124- if ( parsedResponse . success ) {
125- throw new Error ( parsedResponse . data . errors . map ( e => e . message ) . join ( '\n' ) ) ;
63+ console . log ( 'fetching schema' ) ;
64+
65+ const result = await loader . load ( endpoint , {
66+ subscriptionsEndpoint : endpoint ,
67+ subscriptionsProtocol :
68+ ( props . settingsApi ?. settings . subscriptions . protocol as SubscriptionProtocol ) ??
69+ SubscriptionProtocol . GRAPHQL_SSE ,
70+ credentials : props . settingsApi ?. settings . fetch . credentials ,
71+ specifiedByUrl : true ,
72+ directiveIsRepeatable : true ,
73+ inputValueDeprecation : true ,
74+ retry : props . settingsApi ?. settings . fetch . retry ,
75+ timeout : props . settingsApi ?. settings . fetch . timeout ,
76+ useGETForQueries : props . settingsApi ?. settings . fetch . useGETForQueries ,
77+ exposeHTTPDetailsInExtensions : true ,
78+ descriptions : props . settingsApi ?. settings . introspection . schemaDescription ?? false ,
79+ method : props . settingsApi ?. settings . introspection . method ?? 'POST' ,
80+ fetch : ( input : string | URL | Request , init ?: RequestInit ) =>
81+ fetch ( input , {
82+ ...init ,
83+ signal,
84+ } ) ,
85+ } ) ;
86+
87+ if ( result . length === 0 ) {
88+ throw new Error ( 'Failed to fetch schema' ) ;
12689 }
12790
128- if ( response . error && typeof response . error === 'string' ) {
129- throw new Error ( response . error ) ;
91+ if ( ! result [ 0 ] . schema ) {
92+ throw new Error ( 'Failed to fetch schema' ) ;
13093 }
13194
132- setIntrospection ( response . data as IntrospectionQuery ) ;
95+ setIntrospection ( introspectionFromSchema ( result [ 0 ] . schema ) ) ;
13396 } catch ( error : unknown ) {
13497 if (
13598 error &&
@@ -150,7 +113,6 @@ export const useEndpoint = (props: {
150113 [
151114 endpoint ,
152115 props . settingsApi ?. settings . fetch . timeout ,
153- props . settingsApi ?. settings . introspection . queryName ,
154116 props . settingsApi ?. settings . introspection . method ,
155117 props . settingsApi ?. settings . introspection . schemaDescription ,
156118 ] ,
0 commit comments