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 { SubscriptionProtocol , UrlLoader } from '@graphql-tools/url-loader' ;
12+ import type { LaboratorySettingsActions , LaboratorySettingsState } from './settings' ;
1113
1214export interface LaboratoryEndpointState {
1315 endpoint : string | null ;
@@ -22,20 +24,11 @@ export interface LaboratoryEndpointActions {
2224 restoreDefaultEndpoint : ( ) => void ;
2325}
2426
25- const GraphQLResponseErrorSchema = z
26- . object ( {
27- errors : z . array (
28- z . object ( {
29- message : z . string ( ) ,
30- } ) ,
31- ) ,
32- } )
33- . strict ( ) ;
34-
3527export const useEndpoint = ( props : {
3628 defaultEndpoint ?: string | null ;
3729 onEndpointChange ?: ( endpoint : string | null ) => void ;
3830 defaultSchemaIntrospection ?: IntrospectionQuery | null ;
31+ settingsApi ?: LaboratorySettingsState & LaboratorySettingsActions ;
3932} ) : LaboratoryEndpointState & LaboratoryEndpointActions => {
4033 const [ endpoint , _setEndpoint ] = useState < string | null > ( props . defaultEndpoint ?? null ) ;
4134 const [ introspection , setIntrospection ] = useState < IntrospectionQuery | null > ( null ) ;
@@ -52,6 +45,8 @@ export const useEndpoint = (props: {
5245 return introspection ? buildClientSchema ( introspection ) : null ;
5346 } , [ introspection ] ) ;
5447
48+ const loader = useMemo ( ( ) => new UrlLoader ( ) , [ ] ) ;
49+
5550 const fetchSchema = useCallback (
5651 async ( signal ?: AbortSignal ) => {
5752 if ( endpoint === props . defaultEndpoint && props . defaultSchemaIntrospection ) {
@@ -65,28 +60,37 @@ export const useEndpoint = (props: {
6560 }
6661
6762 try {
68- const response = await fetch ( endpoint , {
69- signal,
70- method : 'POST' ,
71- body : JSON . stringify ( {
72- query : getIntrospectionQuery ( ) ,
73- } ) ,
74- headers : {
75- 'Content-Type' : 'application/json' ,
76- } ,
77- } ) . then ( r => r . json ( ) ) ;
78-
79- const parsedResponse = GraphQLResponseErrorSchema . safeParse ( response ) ;
80-
81- if ( parsedResponse . success ) {
82- throw new Error ( parsedResponse . data . errors . map ( e => e . message ) . join ( '\n' ) ) ;
63+ const result = await loader . load ( endpoint , {
64+ subscriptionsEndpoint : endpoint ,
65+ subscriptionsProtocol :
66+ ( props . settingsApi ?. settings . subscriptions . protocol as SubscriptionProtocol ) ??
67+ SubscriptionProtocol . GRAPHQL_SSE ,
68+ credentials : props . settingsApi ?. settings . fetch . credentials ,
69+ specifiedByUrl : true ,
70+ directiveIsRepeatable : true ,
71+ inputValueDeprecation : true ,
72+ retry : props . settingsApi ?. settings . fetch . retry ,
73+ timeout : props . settingsApi ?. settings . fetch . timeout ,
74+ useGETForQueries : props . settingsApi ?. settings . fetch . useGETForQueries ,
75+ exposeHTTPDetailsInExtensions : true ,
76+ descriptions : props . settingsApi ?. settings . introspection . schemaDescription ?? false ,
77+ method : props . settingsApi ?. settings . introspection . method ?? 'POST' ,
78+ fetch : ( input : string | URL | Request , init ?: RequestInit ) =>
79+ fetch ( input , {
80+ ...init ,
81+ signal,
82+ } ) ,
83+ } ) ;
84+
85+ if ( result . length === 0 ) {
86+ throw new Error ( 'Failed to fetch schema' ) ;
8387 }
8488
85- if ( response . error && typeof response . error === 'string' ) {
86- throw new Error ( response . error ) ;
89+ if ( ! result [ 0 ] . schema ) {
90+ throw new Error ( 'Failed to fetch schema' ) ;
8791 }
8892
89- setIntrospection ( response . data as IntrospectionQuery ) ;
93+ setIntrospection ( introspectionFromSchema ( result [ 0 ] . schema ) ) ;
9094 } catch ( error : unknown ) {
9195 if (
9296 error &&
@@ -104,7 +108,12 @@ export const useEndpoint = (props: {
104108 throw error ;
105109 }
106110 } ,
107- [ endpoint ] ,
111+ [
112+ endpoint ,
113+ props . settingsApi ?. settings . fetch . timeout ,
114+ props . settingsApi ?. settings . introspection . method ,
115+ props . settingsApi ?. settings . introspection . schemaDescription ,
116+ ] ,
108117 ) ;
109118
110119 const shouldPollSchema = useMemo ( ( ) => {
@@ -129,6 +138,7 @@ export const useEndpoint = (props: {
129138 5000 ,
130139 intervalController . signal ,
131140 ) ;
141+
132142 return ( ) => {
133143 intervalController . abort ( ) ;
134144 } ;
0 commit comments