Unified · Split
| @@ -1,5 +1,6 @@ | |||
| 1 | import { useCallback, useState } from "react"; | 1 | import { useCallback, useState } from "react"; |
| 2 | import { useAtomSet } from "@effect/atom-react"; | 2 | import { useAtomSet } from "@effect/atom-react"; |
| 3 | import * as Exit from "effect/Exit"; | ||
| 3 | 4 | ||
| 4 | import { useScope } from "@executor-js/react/api/scope-context"; | 5 | import { useScope } from "@executor-js/react/api/scope-context"; |
| 5 | import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys"; | 6 | import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys"; |
| @@ -55,7 +56,7 @@ export default function AddGraphqlSource(props: { · 49 unmodified lines | |||
| 55 | const [tokens, setTokens] = useState<OAuthCompletionPayload | null>(null); | 56 | const [tokens, setTokens] = useState<OAuthCompletionPayload | null>(null); |
| 56 | 57 | ||
| 57 | const scopeId = useScope(); | 58 | const scopeId = useScope(); |
| 58 | const doAdd = useAtomSet(addGraphqlSource, { mode: "promise" }); | 59 | const doAdd = useAtomSet(addGraphqlSource, { mode: "promiseExit" }); |
| 59 | const { beginAdd } = usePendingSources(); | 60 | const { beginAdd } = usePendingSources(); |
| 60 | const secretList = useSecretPickerSecrets(); | 61 | const secretList = useSecretPickerSecrets(); |
| 61 | const oauth = useOAuthPopupFlow({ | 62 | const oauth = useOAuthPopupFlow({ |
| @@ -118,35 +119,36 @@ export default function AddGraphqlSource(props: { · 56 unmodified lines | |||
| 118 | kind: "graphql", | 119 | kind: "graphql", |
| 119 | url: trimmedEndpoint || undefined, | 120 | url: trimmedEndpoint || undefined, |
| 120 | }); | 121 | }); |
| 121 | try { | 122 | const exit = await doAdd({ |
| 122 | await doAdd({ | 123 | params: { scopeId }, |
| 123 | params: { scopeId }, | 124 | payload: { |
| 124 | payload: { | 125 | endpoint: trimmedEndpoint, |
| 125 | endpoint: trimmedEndpoint, | 126 | name: identity.name.trim() || undefined, |
| 126 | name: identity.name.trim() || undefined, | 127 | namespace: slugifyNamespace(identity.namespace) || undefined, |
| 127 | namespace: slugifyNamespace(identity.namespace) || undefined, | 128 | ...(Object.keys(headerMap).length > 0 ? { headers: headerMap } : {}), |
| 128 | ...(Object.keys(headerMap).length > 0 ? { headers: headerMap } : {}), | 129 | ...(Object.keys(queryParams).length > 0 |
| 129 | ...(Object.keys(queryParams).length > 0 | 130 | ? { queryParams: queryParams as Record<string, HeaderValue> } |
| 130 | ? { queryParams: queryParams as Record<string, HeaderValue> } | 131 | : {}), |
| 131 | : {}), | 132 | ...(authMode === "oauth2" && tokens |
| 132 | ...(authMode === "oauth2" && tokens | 133 | ? { |
| 133 | ? { | 134 | auth: { |
| 134 | auth: { | 135 | kind: "oauth2" as const, |
| 135 | kind: "oauth2" as const, | 136 | connectionId: tokens.connectionId, |
| 136 | connectionId: tokens.connectionId, | 137 | }, |
| 137 | }, | 138 | } |
| 138 | } | 139 | : {}), |
| 139 | : {}), | 140 | }, |
| 140 | }, | 141 | reactivityKeys: sourceWriteKeys, |
| 141 | reactivityKeys: sourceWriteKeys, | 142 | }); |
| 142 | }); | 143 | placeholder.done(); |
| 143 | props.onComplete(); | 144 | |
| 144 | } catch (e) { | 145 | if (Exit.isFailure(exit)) { |
| 145 | setAddError(e instanceof Error ? e.message : "Failed to add source"); | 146 | setAddError("Failed to add source"); |
| 146 | setAdding(false); | 147 | setAdding(false); |
| 147 | } finally { | 148 | return; |
| 148 | placeholder.done(); | ||
| 149 | } | 149 | } |
| 150 | |||
| 151 | props.onComplete(); | ||
| 150 | }; | 152 | }; |
| 151 | 153 | ||
| 152 | return ( | 154 | return ( |
| @@ -1,5 +1,6 @@ | |||
| 1 | import { useState } from "react"; | 1 | import { useState } from "react"; |
| 2 | import { useAtomValue, useAtomSet } from "@effect/atom-react"; | 2 | import { useAtomValue, useAtomSet } from "@effect/atom-react"; |
| 3 | import * as Exit from "effect/Exit"; | ||
| 3 | import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; | 4 | import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; |
| 4 | import { graphqlSourceAtom, updateGraphqlSource } from "./atoms"; | 5 | import { graphqlSourceAtom, updateGraphqlSource } from "./atoms"; |
| 5 | import { useScope } from "@executor-js/react/api/scope-context"; | 6 | import { useScope } from "@executor-js/react/api/scope-context"; |
| @@ -41,7 +42,7 @@ const graphqlOAuthConnectionId = (namespaceSlug: string): string => · 35 unmodified lines | |||
| 41 | 42 | ||
| 42 | function EditForm(props: { sourceId: string; initial: EditableSource; onSave: () => void }) { | 43 | function EditForm(props: { sourceId: string; initial: EditableSource; onSave: () => void }) { |
| 43 | const scopeId = useScope(); | 44 | const scopeId = useScope(); |
| 44 | const doUpdate = useAtomSet(updateGraphqlSource, { mode: "promise" }); | 45 | const doUpdate = useAtomSet(updateGraphqlSource, { mode: "promiseExit" }); |
| 45 | const secretList = useSecretPickerSecrets(); | 46 | const secretList = useSecretPickerSecrets(); |
| 46 | 47 | ||
| 47 | const identity = useSourceIdentity({ | 48 | const identity = useSourceIdentity({ |
| @@ -71,34 +72,36 @@ function EditForm(props: { sourceId: string; initial: EditableSource; onSave: () · 23 unmodified lines | |||
| 71 | setSaving(true); | 72 | setSaving(true); |
| 72 | setError(null); | 73 | setError(null); |
| 73 | const { headers, queryParams } = serializeHttpCredentials(credentials); | 74 | const { headers, queryParams } = serializeHttpCredentials(credentials); |
| 74 | try { | 75 | const exit = await doUpdate({ |
| 75 | await doUpdate({ | 76 | params: { scopeId, namespace: props.sourceId }, |
| 76 | params: { scopeId, namespace: props.sourceId }, | 77 | payload: { |
| 77 | payload: { | 78 | name: identity.name.trim() || undefined, |
| 78 | name: identity.name.trim() || undefined, | 79 | endpoint: endpoint.trim() || undefined, |
| 79 | endpoint: endpoint.trim() || undefined, | 80 | headers, |
| 80 | headers, | 81 | queryParams: queryParams as Record<string, HeaderValue>, |
| 81 | queryParams: queryParams as Record<string, HeaderValue>, | 82 | auth: |
| 82 | auth: | 83 | authMode === "oauth2" |
| 83 | authMode === "oauth2" | 84 | ? { |
| 84 | ? { | 85 | kind: "oauth2", |
| 85 | kind: "oauth2", | 86 | connectionId: |
| 86 | connectionId: | 87 | props.initial.auth.kind === "oauth2" |
| 87 | props.initial.auth.kind === "oauth2" | 88 | ? props.initial.auth.connectionId |
| 88 | ? props.initial.auth.connectionId | 89 | : graphqlOAuthConnectionId(props.initial.namespace), |
| 89 | : graphqlOAuthConnectionId(props.initial.namespace), | 90 | } |
| 90 | } | 91 | : { kind: "none" }, |
| 91 | : { kind: "none" }, | 92 | }, |
| 92 | }, | 93 | reactivityKeys: sourceWriteKeys, |
| 93 | reactivityKeys: sourceWriteKeys, | 94 | }); |
| 94 | }); | 95 | |
| 95 | setDirty(false); | 96 | if (Exit.isFailure(exit)) { |
| 96 | props.onSave(); | 97 | setError("Failed to update source"); |
| 97 | } catch (e) { | ||
| 98 | setError(e instanceof Error ? e.message : "Failed to update source"); | ||
| 99 | } finally { | ||
| 100 | setSaving(false); | 98 | setSaving(false); |
| 99 | return; | ||
| 101 | } | 100 | } |
| 101 | |||
| 102 | setDirty(false); | ||
| 103 | props.onSave(); | ||
| 104 | setSaving(false); | ||
| 102 | }; | 105 | }; |
| 103 | 106 | ||
| 104 | return ( | 107 | return ( |