@@ -7,12 +7,9 @@ import * as Schema from "effect/Schema";
77import { useScope } from "@executor-js/react/api/scope-context" ;
88import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys" ;
99import {
10- HttpCredentials ,
11- httpCredentialsValid ,
12- serializeScopedHttpCredentials ,
13- serializeHttpCredentials ,
14- type HttpCredentialsState ,
15- } from "@executor-js/react/plugins/http-credentials" ;
10+ HttpCredentialEditor ,
11+ useHttpCredentialEditorController ,
12+ } from "@executor-js/react/plugins/http-credential-state" ;
1613import {
1714 sourceDisplayNameFromUrl ,
1815 slugifyNamespace ,
@@ -31,7 +28,6 @@ import {
3128} from "@executor-js/react/plugins/credential-target-scope" ;
3229import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets" ;
3330import { Button } from "@executor-js/react/components/button" ;
34- import { FilterTabs } from "@executor-js/react/components/filter-tabs" ;
3531import { FloatActions } from "@executor-js/react/components/float-actions" ;
3632import { Spinner } from "@executor-js/react/components/spinner" ;
3733import { addGraphqlSourceOptimistic } from "./atoms" ;
@@ -59,7 +55,6 @@ export default function AddGraphqlSource(props: {
5955 const identity = useSourceIdentity ( {
6056 fallbackName : sourceDisplayNameFromUrl ( endpoint , "GraphQL" ) ?? "" ,
6157 } ) ;
62- const [ credentials , setCredentials ] = useState < HttpCredentialsState > ( initialGraphqlCredentials ) ;
6358 const [ adding , setAdding ] = useState ( false ) ;
6459 const [ addError , setAddError ] = useState < string | null > ( null ) ;
6560 const [ authMode , setAuthMode ] = useState < AuthMode > ( "none" ) ;
@@ -76,14 +71,22 @@ export default function AddGraphqlSource(props: {
7671 mode : "promiseExit" ,
7772 } ) ;
7873 const secretList = useSecretPickerSecrets ( ) ;
74+ const credentialEditor = useHttpCredentialEditorController ( {
75+ initialCredentials : initialGraphqlCredentials ( ) ,
76+ targetScope : requestCredentialTargetScope ,
77+ existingSecrets : secretList ,
78+ sourceName : identity . name ,
79+ credentialScopeOptions,
80+ bindingScopeOptions : credentialScopeOptions ,
81+ } ) ;
7982 const oauth = useOAuthPopupFlow ( {
8083 popupName : "graphql-oauth" ,
8184 startErrorMessage : "Failed to start OAuth" ,
8285 } ) ;
8386
8487 const canAdd =
8588 endpoint . trim ( ) . length > 0 &&
86- httpCredentialsValid ( credentials ) &&
89+ credentialEditor . state . valid &&
8790 ( authMode === "none" || tokens !== null ) &&
8891 ! oauth . busy ;
8992
@@ -99,15 +102,13 @@ export default function AddGraphqlSource(props: {
99102 } , [ endpoint , identity . name , identity . namespace ] ) ;
100103
101104 const handleOAuth = useCallback ( async ( ) => {
102- if ( ! endpoint . trim ( ) || ! httpCredentialsValid ( credentials ) ) return ;
105+ if ( ! endpoint . trim ( ) || ! credentialEditor . state . valid ) return ;
103106 setAddError ( null ) ;
104107 const { trimmedEndpoint, namespace, displayName } = sourceIdentity ( ) ;
105- const { headers, queryParams } = serializeHttpCredentials ( credentials ) ;
106108 await oauth . start ( {
107109 payload : {
108110 endpoint : trimmedEndpoint ,
109- ...( Object . keys ( headers ) . length > 0 ? { headers } : { } ) ,
110- ...( Object . keys ( queryParams ) . length > 0 ? { queryParams } : { } ) ,
111+ ...credentialEditor . serialized . requestFields ,
111112 redirectUrl : oauthCallbackUrl ( ) ,
112113 connectionId : oauthConnectionId ( { pluginId : "graphql" , namespace } ) ,
113114 tokenScope : oauthCredentialTargetScope ,
@@ -124,15 +125,12 @@ export default function AddGraphqlSource(props: {
124125 } ,
125126 onError : setAddError ,
126127 } ) ;
127- } , [ endpoint , credentials , oauth , sourceIdentity , oauthCredentialTargetScope ] ) ;
128+ } , [ endpoint , credentialEditor , oauth , sourceIdentity , oauthCredentialTargetScope ] ) ;
128129
129130 const handleAdd = async ( ) => {
130131 setAdding ( true ) ;
131132 setAddError ( null ) ;
132- const { headers : headerMap , queryParams } = serializeScopedHttpCredentials (
133- credentials ,
134- requestCredentialTargetScope ,
135- ) ;
133+ const requestCredentials = credentialEditor . serialized . scopedFields < GraphqlCredentialInput > ( ) ;
136134
137135 const { trimmedEndpoint, namespace, displayName } = sourceIdentity ( ) ;
138136 const exit = await doAdd ( {
@@ -142,12 +140,7 @@ export default function AddGraphqlSource(props: {
142140 endpoint : trimmedEndpoint ,
143141 name : displayName ,
144142 namespace,
145- ...( Object . keys ( headerMap ) . length > 0 ? { headers : headerMap } : { } ) ,
146- ...( Object . keys ( queryParams ) . length > 0
147- ? {
148- queryParams : queryParams as Record < string , GraphqlCredentialInput > ,
149- }
150- : { } ) ,
143+ ...requestCredentials ,
151144 credentialTargetScope :
152145 authMode === "oauth2" && tokens
153146 ? oauthCredentialTargetScope
@@ -177,35 +170,24 @@ export default function AddGraphqlSource(props: {
177170
178171 < GraphqlSourceFields endpoint = { endpoint } onEndpointChange = { setEndpoint } identity = { identity } />
179172
180- < HttpCredentials . Root
181- credentials = { credentials }
182- onChange = { setCredentials }
183- existingSecrets = { secretList }
184- sourceName = { identity . name }
185- targetScope = { requestCredentialTargetScope }
186- credentialScopeOptions = { credentialScopeOptions }
187- bindingScopeOptions = { credentialScopeOptions }
188- >
189- < HttpCredentials . Headers />
190- < HttpCredentials . QueryParams />
191- </ HttpCredentials . Root >
173+ < HttpCredentialEditor . Provider controller = { credentialEditor } >
174+ < HttpCredentialEditor . Headers />
175+ < HttpCredentialEditor . QueryParams />
176+ </ HttpCredentialEditor . Provider >
192177
193178 { /* Temporarily hidden while we revisit GraphQL OAuth discovery and UX. */ }
194179 < section className = "hidden space-y-2.5" >
195- < div className = "flex items-center justify-between gap-3" >
196- < span className = "text-sm font-medium text-foreground" > Authentication</ span >
197- < FilterTabs < AuthMode >
198- tabs = { [
199- { value : "none" , label : "None" } ,
200- { value : "oauth2" , label : "OAuth" } ,
201- ] }
202- value = { authMode }
203- onChange = { ( value ) => {
204- setAuthMode ( value ) ;
205- setTokens ( null ) ;
206- } }
207- />
208- </ div >
180+ < HttpCredentialEditor . Auth . Root
181+ label = "Authentication"
182+ value = { authMode }
183+ onValueChange = { ( value ) => {
184+ setAuthMode ( value === "oauth2" ? "oauth2" : "none" ) ;
185+ setTokens ( null ) ;
186+ } }
187+ >
188+ < HttpCredentialEditor . Auth . None />
189+ < HttpCredentialEditor . Auth . OAuth value = "oauth2" label = "OAuth" />
190+ </ HttpCredentialEditor . Auth . Root >
209191
210192 { authMode === "oauth2" && (
211193 < CredentialUsageRow
@@ -233,7 +215,7 @@ export default function AddGraphqlSource(props: {
233215 size = "sm"
234216 className = "ml-auto h-7 px-2 text-xs"
235217 onClick = { ( ) => void handleOAuth ( ) }
236- disabled = { ! endpoint . trim ( ) || ! httpCredentialsValid ( credentials ) || oauth . busy }
218+ disabled = { ! endpoint . trim ( ) || ! credentialEditor . state . valid || oauth . busy }
237219 >
238220 { oauth . busy ? "Signing in..." : tokens ? "Reconnect" : "Sign in" }
239221 </ Button >
0 commit comments