@executor-js/plugin-graphql 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/AddGraphqlSource-LGXJQEAR.js +239 -0
  2. package/dist/AddGraphqlSource-LGXJQEAR.js.map +1 -0
  3. package/dist/EditGraphqlSource-5Y47ZAZ7.js +251 -0
  4. package/dist/EditGraphqlSource-5Y47ZAZ7.js.map +1 -0
  5. package/dist/GraphqlSourceSummary-F3JWR4YN.js +70 -0
  6. package/dist/GraphqlSourceSummary-F3JWR4YN.js.map +1 -0
  7. package/dist/api/group.d.ts +169 -13
  8. package/dist/api/handlers.d.ts +15 -3
  9. package/dist/api/index.d.ts +410 -0
  10. package/dist/chunk-7QSGNR4C.js +162 -0
  11. package/dist/chunk-7QSGNR4C.js.map +1 -0
  12. package/dist/chunk-HDPYOBBG.js +1633 -0
  13. package/dist/chunk-HDPYOBBG.js.map +1 -0
  14. package/dist/chunk-M4SJY6CB.js +45 -0
  15. package/dist/chunk-M4SJY6CB.js.map +1 -0
  16. package/dist/chunk-WPRU5C6M.js +182 -0
  17. package/dist/chunk-WPRU5C6M.js.map +1 -0
  18. package/dist/client.js +75 -0
  19. package/dist/client.js.map +1 -0
  20. package/dist/core.js +32 -10
  21. package/dist/index.js +2 -1
  22. package/dist/react/GraphqlSourceFields.d.ts +8 -0
  23. package/dist/react/GraphqlSourceSummary.d.ts +3 -1
  24. package/dist/react/atoms.d.ts +170 -10
  25. package/dist/react/client.d.ts +164 -12
  26. package/dist/sdk/index.d.ts +1 -1
  27. package/dist/sdk/introspect.d.ts +437 -43
  28. package/dist/sdk/invoke.d.ts +3 -2
  29. package/dist/sdk/plugin.d.ts +120 -170
  30. package/dist/sdk/store.d.ts +84 -11
  31. package/dist/sdk/types.d.ts +107 -3
  32. package/dist/testing/index.d.ts +52 -0
  33. package/dist/testing.js +131 -0
  34. package/dist/testing.js.map +1 -0
  35. package/package.json +18 -4
  36. package/dist/chunk-EIC5WI6C.js +0 -1225
  37. package/dist/chunk-EIC5WI6C.js.map +0 -1
@@ -0,0 +1,239 @@
1
+ import {
2
+ GraphqlSourceFields
3
+ } from "./chunk-M4SJY6CB.js";
4
+ import {
5
+ addGraphqlSourceOptimistic
6
+ } from "./chunk-WPRU5C6M.js";
7
+ import "./chunk-7QSGNR4C.js";
8
+
9
+ // src/react/AddGraphqlSource.tsx
10
+ import { useCallback, useState } from "react";
11
+ import { useAtomSet } from "@effect/atom-react";
12
+ import * as Exit from "effect/Exit";
13
+ import * as Option from "effect/Option";
14
+ import * as Schema from "effect/Schema";
15
+ import { useScope } from "@executor-js/react/api/scope-context";
16
+ import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
17
+ import {
18
+ HttpCredentialsEditor,
19
+ httpCredentialsValid,
20
+ serializeScopedHttpCredentials,
21
+ serializeHttpCredentials
22
+ } from "@executor-js/react/plugins/http-credentials";
23
+ import {
24
+ sourceDisplayNameFromUrl,
25
+ slugifyNamespace,
26
+ useSourceIdentity
27
+ } from "@executor-js/react/plugins/source-identity";
28
+ import {
29
+ oauthCallbackUrl,
30
+ oauthConnectionId,
31
+ useOAuthPopupFlow
32
+ } from "@executor-js/react/plugins/oauth-sign-in";
33
+ import {
34
+ CredentialControlField,
35
+ CredentialUsageRow,
36
+ useCredentialTargetScope
37
+ } from "@executor-js/react/plugins/credential-target-scope";
38
+ import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets";
39
+ import { Button } from "@executor-js/react/components/button";
40
+ import { FilterTabs } from "@executor-js/react/components/filter-tabs";
41
+ import { FloatActions } from "@executor-js/react/components/float-actions";
42
+ import { Spinner } from "@executor-js/react/components/spinner";
43
+
44
+ // src/react/defaults.ts
45
+ import {
46
+ emptyHttpCredentials
47
+ } from "@executor-js/react/plugins/http-credentials";
48
+ var initialGraphqlCredentials = () => emptyHttpCredentials();
49
+
50
+ // src/react/AddGraphqlSource.tsx
51
+ import { jsx, jsxs } from "react/jsx-runtime";
52
+ var ErrorMessage = Schema.Struct({ message: Schema.String });
53
+ var decodeErrorMessage = Schema.decodeUnknownOption(ErrorMessage);
54
+ var errorMessageFromExit = (exit, fallback) => Option.match(Option.flatMap(Exit.findErrorOption(exit), decodeErrorMessage), {
55
+ onNone: () => fallback,
56
+ onSome: ({ message }) => message
57
+ });
58
+ function AddGraphqlSource(props) {
59
+ const [endpoint, setEndpoint] = useState(props.initialUrl ?? "");
60
+ const identity = useSourceIdentity({
61
+ fallbackName: sourceDisplayNameFromUrl(endpoint, "GraphQL") ?? ""
62
+ });
63
+ const [credentials, setCredentials] = useState(initialGraphqlCredentials);
64
+ const [adding, setAdding] = useState(false);
65
+ const [addError, setAddError] = useState(null);
66
+ const [authMode, setAuthMode] = useState("none");
67
+ const [tokens, setTokens] = useState(null);
68
+ const scopeId = useScope();
69
+ const { credentialTargetScope: requestCredentialTargetScope } = useCredentialTargetScope();
70
+ const {
71
+ credentialTargetScope: oauthCredentialTargetScope,
72
+ setCredentialTargetScope: setOAuthCredentialTargetScope,
73
+ credentialScopeOptions
74
+ } = useCredentialTargetScope();
75
+ const doAdd = useAtomSet(addGraphqlSourceOptimistic(scopeId), {
76
+ mode: "promiseExit"
77
+ });
78
+ const secretList = useSecretPickerSecrets();
79
+ const oauth = useOAuthPopupFlow({
80
+ popupName: "graphql-oauth",
81
+ startErrorMessage: "Failed to start OAuth"
82
+ });
83
+ const canAdd = endpoint.trim().length > 0 && httpCredentialsValid(credentials) && (authMode === "none" || tokens !== null) && !oauth.busy;
84
+ const sourceIdentity = useCallback(() => {
85
+ const trimmedEndpoint = endpoint.trim();
86
+ const namespace = slugifyNamespace(identity.namespace) || slugifyNamespace(sourceDisplayNameFromUrl(trimmedEndpoint, "GraphQL") ?? "") || "graphql";
87
+ const displayName = identity.name.trim() || sourceDisplayNameFromUrl(trimmedEndpoint, "GraphQL") || namespace;
88
+ return { trimmedEndpoint, namespace, displayName };
89
+ }, [endpoint, identity.name, identity.namespace]);
90
+ const handleOAuth = useCallback(async () => {
91
+ if (!endpoint.trim() || !httpCredentialsValid(credentials)) return;
92
+ setAddError(null);
93
+ const { trimmedEndpoint, namespace, displayName } = sourceIdentity();
94
+ const { headers, queryParams } = serializeHttpCredentials(credentials);
95
+ await oauth.start({
96
+ payload: {
97
+ endpoint: trimmedEndpoint,
98
+ ...Object.keys(headers).length > 0 ? { headers } : {},
99
+ ...Object.keys(queryParams).length > 0 ? { queryParams } : {},
100
+ redirectUrl: oauthCallbackUrl(),
101
+ connectionId: oauthConnectionId({ pluginId: "graphql", namespace }),
102
+ tokenScope: oauthCredentialTargetScope,
103
+ strategy: { kind: "dynamic-dcr" },
104
+ pluginId: "graphql",
105
+ identityLabel: `${displayName} OAuth`
106
+ },
107
+ onSuccess: (result) => {
108
+ setTokens({
109
+ connectionId: result.connectionId,
110
+ expiresAt: result.expiresAt,
111
+ scope: result.scope
112
+ });
113
+ },
114
+ onError: setAddError
115
+ });
116
+ }, [endpoint, credentials, oauth, sourceIdentity, oauthCredentialTargetScope]);
117
+ const handleAdd = async () => {
118
+ setAdding(true);
119
+ setAddError(null);
120
+ const { headers: headerMap, queryParams } = serializeScopedHttpCredentials(
121
+ credentials,
122
+ requestCredentialTargetScope
123
+ );
124
+ const { trimmedEndpoint, namespace, displayName } = sourceIdentity();
125
+ const exit = await doAdd({
126
+ params: { scopeId },
127
+ payload: {
128
+ targetScope: scopeId,
129
+ endpoint: trimmedEndpoint,
130
+ name: displayName,
131
+ namespace,
132
+ ...Object.keys(headerMap).length > 0 ? { headers: headerMap } : {},
133
+ ...Object.keys(queryParams).length > 0 ? {
134
+ queryParams
135
+ } : {},
136
+ credentialTargetScope: authMode === "oauth2" && tokens ? oauthCredentialTargetScope : requestCredentialTargetScope,
137
+ ...authMode === "oauth2" && tokens ? {
138
+ auth: {
139
+ kind: "oauth2",
140
+ connectionId: tokens.connectionId
141
+ }
142
+ } : {}
143
+ },
144
+ reactivityKeys: sourceWriteKeys
145
+ });
146
+ if (Exit.isFailure(exit)) {
147
+ setAddError(errorMessageFromExit(exit, "Failed to add source"));
148
+ setAdding(false);
149
+ return;
150
+ }
151
+ props.onComplete();
152
+ };
153
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-6", children: [
154
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Add GraphQL Source" }),
155
+ /* @__PURE__ */ jsx(GraphqlSourceFields, { endpoint, onEndpointChange: setEndpoint, identity }),
156
+ /* @__PURE__ */ jsx(
157
+ HttpCredentialsEditor,
158
+ {
159
+ credentials,
160
+ onChange: setCredentials,
161
+ existingSecrets: secretList,
162
+ sourceName: identity.name,
163
+ targetScope: requestCredentialTargetScope,
164
+ credentialScopeOptions,
165
+ bindingScopeOptions: credentialScopeOptions
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsxs("section", { className: "hidden space-y-2.5", children: [
169
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
170
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Authentication" }),
171
+ /* @__PURE__ */ jsx(
172
+ FilterTabs,
173
+ {
174
+ tabs: [
175
+ { value: "none", label: "None" },
176
+ { value: "oauth2", label: "OAuth" }
177
+ ],
178
+ value: authMode,
179
+ onChange: (value) => {
180
+ setAuthMode(value);
181
+ setTokens(null);
182
+ }
183
+ }
184
+ )
185
+ ] }),
186
+ authMode === "oauth2" && /* @__PURE__ */ jsx(
187
+ CredentialUsageRow,
188
+ {
189
+ value: oauthCredentialTargetScope,
190
+ options: credentialScopeOptions,
191
+ onChange: (targetScope) => {
192
+ setOAuthCredentialTargetScope(targetScope);
193
+ setTokens(null);
194
+ },
195
+ label: "Connection saved to",
196
+ help: "Choose who can use the OAuth connection.",
197
+ children: /* @__PURE__ */ jsx(CredentialControlField, { label: "Connect via OAuth", help: "Start the provider OAuth flow.", children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-9 items-center gap-2 rounded-md border border-border bg-muted/30 px-3 py-2", children: [
198
+ tokens ? /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-emerald-600 dark:text-emerald-400", children: "Authenticated" }) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Not connected" }),
199
+ /* @__PURE__ */ jsx(
200
+ Button,
201
+ {
202
+ type: "button",
203
+ variant: "outline",
204
+ size: "sm",
205
+ className: "ml-auto h-7 px-2 text-xs",
206
+ onClick: () => void handleOAuth(),
207
+ disabled: !endpoint.trim() || !httpCredentialsValid(credentials) || oauth.busy,
208
+ children: oauth.busy ? "Signing in..." : tokens ? "Reconnect" : "Sign in"
209
+ }
210
+ )
211
+ ] }) })
212
+ }
213
+ )
214
+ ] }),
215
+ addError && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-[12px] text-destructive", children: addError }) }),
216
+ /* @__PURE__ */ jsxs(FloatActions, { children: [
217
+ /* @__PURE__ */ jsx(
218
+ Button,
219
+ {
220
+ variant: "ghost",
221
+ onClick: () => {
222
+ oauth.cancel();
223
+ props.onCancel();
224
+ },
225
+ disabled: adding,
226
+ children: "Cancel"
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsxs(Button, { onClick: handleAdd, disabled: !canAdd || adding, children: [
230
+ adding && /* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }),
231
+ adding ? "Adding..." : "Add source"
232
+ ] })
233
+ ] })
234
+ ] });
235
+ }
236
+ export {
237
+ AddGraphqlSource as default
238
+ };
239
+ //# sourceMappingURL=AddGraphqlSource-LGXJQEAR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/AddGraphqlSource.tsx","../src/react/defaults.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\nimport { useAtomSet } from \"@effect/atom-react\";\nimport * as Exit from \"effect/Exit\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\n\nimport { useScope } from \"@executor-js/react/api/scope-context\";\nimport { sourceWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport {\n HttpCredentialsEditor,\n httpCredentialsValid,\n serializeScopedHttpCredentials,\n serializeHttpCredentials,\n type HttpCredentialsState,\n} from \"@executor-js/react/plugins/http-credentials\";\nimport {\n sourceDisplayNameFromUrl,\n slugifyNamespace,\n useSourceIdentity,\n} from \"@executor-js/react/plugins/source-identity\";\nimport {\n oauthCallbackUrl,\n oauthConnectionId,\n useOAuthPopupFlow,\n type OAuthCompletionPayload,\n} from \"@executor-js/react/plugins/oauth-sign-in\";\nimport {\n CredentialControlField,\n CredentialUsageRow,\n useCredentialTargetScope,\n} from \"@executor-js/react/plugins/credential-target-scope\";\nimport { useSecretPickerSecrets } from \"@executor-js/react/plugins/use-secret-picker-secrets\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport { FilterTabs } from \"@executor-js/react/components/filter-tabs\";\nimport { FloatActions } from \"@executor-js/react/components/float-actions\";\nimport { Spinner } from \"@executor-js/react/components/spinner\";\nimport { addGraphqlSourceOptimistic } from \"./atoms\";\nimport { initialGraphqlCredentials } from \"./defaults\";\nimport { GraphqlSourceFields } from \"./GraphqlSourceFields\";\nimport type { GraphqlCredentialInput } from \"../sdk/types\";\n\nconst ErrorMessage = Schema.Struct({ message: Schema.String });\nconst decodeErrorMessage = Schema.decodeUnknownOption(ErrorMessage);\n\nconst errorMessageFromExit = (exit: Exit.Exit<unknown, unknown>, fallback: string): string =>\n Option.match(Option.flatMap(Exit.findErrorOption(exit), decodeErrorMessage), {\n onNone: () => fallback,\n onSome: ({ message }) => message,\n });\n\ntype AuthMode = \"none\" | \"oauth2\";\n\nexport default function AddGraphqlSource(props: {\n onComplete: () => void;\n onCancel: () => void;\n initialUrl?: string;\n}) {\n const [endpoint, setEndpoint] = useState(props.initialUrl ?? \"\");\n const identity = useSourceIdentity({\n fallbackName: sourceDisplayNameFromUrl(endpoint, \"GraphQL\") ?? \"\",\n });\n const [credentials, setCredentials] = useState<HttpCredentialsState>(initialGraphqlCredentials);\n const [adding, setAdding] = useState(false);\n const [addError, setAddError] = useState<string | null>(null);\n const [authMode, setAuthMode] = useState<AuthMode>(\"none\");\n const [tokens, setTokens] = useState<OAuthCompletionPayload | null>(null);\n\n const scopeId = useScope();\n const { credentialTargetScope: requestCredentialTargetScope } = useCredentialTargetScope();\n const {\n credentialTargetScope: oauthCredentialTargetScope,\n setCredentialTargetScope: setOAuthCredentialTargetScope,\n credentialScopeOptions,\n } = useCredentialTargetScope();\n const doAdd = useAtomSet(addGraphqlSourceOptimistic(scopeId), {\n mode: \"promiseExit\",\n });\n const secretList = useSecretPickerSecrets();\n const oauth = useOAuthPopupFlow({\n popupName: \"graphql-oauth\",\n startErrorMessage: \"Failed to start OAuth\",\n });\n\n const canAdd =\n endpoint.trim().length > 0 &&\n httpCredentialsValid(credentials) &&\n (authMode === \"none\" || tokens !== null) &&\n !oauth.busy;\n\n const sourceIdentity = useCallback(() => {\n const trimmedEndpoint = endpoint.trim();\n const namespace =\n slugifyNamespace(identity.namespace) ||\n slugifyNamespace(sourceDisplayNameFromUrl(trimmedEndpoint, \"GraphQL\") ?? \"\") ||\n \"graphql\";\n const displayName =\n identity.name.trim() || sourceDisplayNameFromUrl(trimmedEndpoint, \"GraphQL\") || namespace;\n return { trimmedEndpoint, namespace, displayName };\n }, [endpoint, identity.name, identity.namespace]);\n\n const handleOAuth = useCallback(async () => {\n if (!endpoint.trim() || !httpCredentialsValid(credentials)) return;\n setAddError(null);\n const { trimmedEndpoint, namespace, displayName } = sourceIdentity();\n const { headers, queryParams } = serializeHttpCredentials(credentials);\n await oauth.start({\n payload: {\n endpoint: trimmedEndpoint,\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(Object.keys(queryParams).length > 0 ? { queryParams } : {}),\n redirectUrl: oauthCallbackUrl(),\n connectionId: oauthConnectionId({ pluginId: \"graphql\", namespace }),\n tokenScope: oauthCredentialTargetScope,\n strategy: { kind: \"dynamic-dcr\" },\n pluginId: \"graphql\",\n identityLabel: `${displayName} OAuth`,\n },\n onSuccess: (result) => {\n setTokens({\n connectionId: result.connectionId,\n expiresAt: result.expiresAt,\n scope: result.scope,\n });\n },\n onError: setAddError,\n });\n }, [endpoint, credentials, oauth, sourceIdentity, oauthCredentialTargetScope]);\n\n const handleAdd = async () => {\n setAdding(true);\n setAddError(null);\n const { headers: headerMap, queryParams } = serializeScopedHttpCredentials(\n credentials,\n requestCredentialTargetScope,\n );\n\n const { trimmedEndpoint, namespace, displayName } = sourceIdentity();\n const exit = await doAdd({\n params: { scopeId },\n payload: {\n targetScope: scopeId,\n endpoint: trimmedEndpoint,\n name: displayName,\n namespace,\n ...(Object.keys(headerMap).length > 0 ? { headers: headerMap } : {}),\n ...(Object.keys(queryParams).length > 0\n ? {\n queryParams: queryParams as Record<string, GraphqlCredentialInput>,\n }\n : {}),\n credentialTargetScope:\n authMode === \"oauth2\" && tokens\n ? oauthCredentialTargetScope\n : requestCredentialTargetScope,\n ...(authMode === \"oauth2\" && tokens\n ? {\n auth: {\n kind: \"oauth2\" as const,\n connectionId: tokens.connectionId,\n },\n }\n : {}),\n },\n reactivityKeys: sourceWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setAddError(errorMessageFromExit(exit, \"Failed to add source\"));\n setAdding(false);\n return;\n }\n props.onComplete();\n };\n\n return (\n <div className=\"flex flex-1 flex-col gap-6\">\n <h1 className=\"text-xl font-semibold text-foreground\">Add GraphQL Source</h1>\n\n <GraphqlSourceFields endpoint={endpoint} onEndpointChange={setEndpoint} identity={identity} />\n\n <HttpCredentialsEditor\n credentials={credentials}\n onChange={setCredentials}\n existingSecrets={secretList}\n sourceName={identity.name}\n targetScope={requestCredentialTargetScope}\n credentialScopeOptions={credentialScopeOptions}\n bindingScopeOptions={credentialScopeOptions}\n />\n\n {/* Temporarily hidden while we revisit GraphQL OAuth discovery and UX. */}\n <section className=\"hidden space-y-2.5\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm font-medium text-foreground\">Authentication</span>\n <FilterTabs<AuthMode>\n tabs={[\n { value: \"none\", label: \"None\" },\n { value: \"oauth2\", label: \"OAuth\" },\n ]}\n value={authMode}\n onChange={(value) => {\n setAuthMode(value);\n setTokens(null);\n }}\n />\n </div>\n\n {authMode === \"oauth2\" && (\n <CredentialUsageRow\n value={oauthCredentialTargetScope}\n options={credentialScopeOptions}\n onChange={(targetScope) => {\n setOAuthCredentialTargetScope(targetScope);\n setTokens(null);\n }}\n label=\"Connection saved to\"\n help=\"Choose who can use the OAuth connection.\"\n >\n <CredentialControlField label=\"Connect via OAuth\" help=\"Start the provider OAuth flow.\">\n <div className=\"flex min-h-9 items-center gap-2 rounded-md border border-border bg-muted/30 px-3 py-2\">\n {tokens ? (\n <span className=\"text-xs font-medium text-emerald-600 dark:text-emerald-400\">\n Authenticated\n </span>\n ) : (\n <span className=\"text-xs text-muted-foreground\">Not connected</span>\n )}\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"ml-auto h-7 px-2 text-xs\"\n onClick={() => void handleOAuth()}\n disabled={!endpoint.trim() || !httpCredentialsValid(credentials) || oauth.busy}\n >\n {oauth.busy ? \"Signing in...\" : tokens ? \"Reconnect\" : \"Sign in\"}\n </Button>\n </div>\n </CredentialControlField>\n </CredentialUsageRow>\n )}\n </section>\n\n {/* Error */}\n {addError && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-[12px] text-destructive\">{addError}</p>\n </div>\n )}\n\n <FloatActions>\n <Button\n variant=\"ghost\"\n onClick={() => {\n oauth.cancel();\n props.onCancel();\n }}\n disabled={adding}\n >\n Cancel\n </Button>\n <Button onClick={handleAdd} disabled={!canAdd || adding}>\n {adding && <Spinner className=\"size-3.5\" />}\n {adding ? \"Adding...\" : \"Add source\"}\n </Button>\n </FloatActions>\n </div>\n );\n}\n","import {\n emptyHttpCredentials,\n type HttpCredentialsState,\n} from \"@executor-js/react/plugins/http-credentials\";\n\nexport const initialGraphqlCredentials = (): HttpCredentialsState => emptyHttpCredentials();\n"],"mappings":";;;;;;;;;AAAA,SAAS,aAAa,gBAAgB;AACtC,SAAS,kBAAkB;AAC3B,YAAY,UAAU;AACtB,YAAY,YAAY;AACxB,YAAY,YAAY;AAExB,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,8BAA8B;AACvC,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,eAAe;;;ACnCxB;AAAA,EACE;AAAA,OAEK;AAEA,IAAM,4BAA4B,MAA4B,qBAAqB;;;AD0KpF,cAgBE,YAhBF;AAtIN,IAAM,eAAsB,cAAO,EAAE,SAAgB,cAAO,CAAC;AAC7D,IAAM,qBAA4B,2BAAoB,YAAY;AAElE,IAAM,uBAAuB,CAAC,MAAmC,aACxD,aAAa,eAAa,qBAAgB,IAAI,GAAG,kBAAkB,GAAG;AAAA,EAC3E,QAAQ,MAAM;AAAA,EACd,QAAQ,CAAC,EAAE,QAAQ,MAAM;AAC3B,CAAC;AAIY,SAAR,iBAAkC,OAItC;AACD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,MAAM,cAAc,EAAE;AAC/D,QAAM,WAAW,kBAAkB;AAAA,IACjC,cAAc,yBAAyB,UAAU,SAAS,KAAK;AAAA,EACjE,CAAC;AACD,QAAM,CAAC,aAAa,cAAc,IAAI,SAA+B,yBAAyB;AAC9F,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,IAAI;AAC5D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,MAAM;AACzD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAwC,IAAI;AAExE,QAAM,UAAU,SAAS;AACzB,QAAM,EAAE,uBAAuB,6BAA6B,IAAI,yBAAyB;AACzF,QAAM;AAAA,IACJ,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B;AAAA,EACF,IAAI,yBAAyB;AAC7B,QAAM,QAAQ,WAAW,2BAA2B,OAAO,GAAG;AAAA,IAC5D,MAAM;AAAA,EACR,CAAC;AACD,QAAM,aAAa,uBAAuB;AAC1C,QAAM,QAAQ,kBAAkB;AAAA,IAC9B,WAAW;AAAA,IACX,mBAAmB;AAAA,EACrB,CAAC;AAED,QAAM,SACJ,SAAS,KAAK,EAAE,SAAS,KACzB,qBAAqB,WAAW,MAC/B,aAAa,UAAU,WAAW,SACnC,CAAC,MAAM;AAET,QAAM,iBAAiB,YAAY,MAAM;AACvC,UAAM,kBAAkB,SAAS,KAAK;AACtC,UAAM,YACJ,iBAAiB,SAAS,SAAS,KACnC,iBAAiB,yBAAyB,iBAAiB,SAAS,KAAK,EAAE,KAC3E;AACF,UAAM,cACJ,SAAS,KAAK,KAAK,KAAK,yBAAyB,iBAAiB,SAAS,KAAK;AAClF,WAAO,EAAE,iBAAiB,WAAW,YAAY;AAAA,EACnD,GAAG,CAAC,UAAU,SAAS,MAAM,SAAS,SAAS,CAAC;AAEhD,QAAM,cAAc,YAAY,YAAY;AAC1C,QAAI,CAAC,SAAS,KAAK,KAAK,CAAC,qBAAqB,WAAW,EAAG;AAC5D,gBAAY,IAAI;AAChB,UAAM,EAAE,iBAAiB,WAAW,YAAY,IAAI,eAAe;AACnE,UAAM,EAAE,SAAS,YAAY,IAAI,yBAAyB,WAAW;AACrE,UAAM,MAAM,MAAM;AAAA,MAChB,SAAS;AAAA,QACP,UAAU;AAAA,QACV,GAAI,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,EAAE,QAAQ,IAAI,CAAC;AAAA,QACrD,GAAI,OAAO,KAAK,WAAW,EAAE,SAAS,IAAI,EAAE,YAAY,IAAI,CAAC;AAAA,QAC7D,aAAa,iBAAiB;AAAA,QAC9B,cAAc,kBAAkB,EAAE,UAAU,WAAW,UAAU,CAAC;AAAA,QAClE,YAAY;AAAA,QACZ,UAAU,EAAE,MAAM,cAAc;AAAA,QAChC,UAAU;AAAA,QACV,eAAe,GAAG,WAAW;AAAA,MAC/B;AAAA,MACA,WAAW,CAAC,WAAW;AACrB,kBAAU;AAAA,UACR,cAAc,OAAO;AAAA,UACrB,WAAW,OAAO;AAAA,UAClB,OAAO,OAAO;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH,GAAG,CAAC,UAAU,aAAa,OAAO,gBAAgB,0BAA0B,CAAC;AAE7E,QAAM,YAAY,YAAY;AAC5B,cAAU,IAAI;AACd,gBAAY,IAAI;AAChB,UAAM,EAAE,SAAS,WAAW,YAAY,IAAI;AAAA,MAC1C;AAAA,MACA;AAAA,IACF;AAEA,UAAM,EAAE,iBAAiB,WAAW,YAAY,IAAI,eAAe;AACnE,UAAM,OAAO,MAAM,MAAM;AAAA,MACvB,QAAQ,EAAE,QAAQ;AAAA,MAClB,SAAS;AAAA,QACP,aAAa;AAAA,QACb,UAAU;AAAA,QACV,MAAM;AAAA,QACN;AAAA,QACA,GAAI,OAAO,KAAK,SAAS,EAAE,SAAS,IAAI,EAAE,SAAS,UAAU,IAAI,CAAC;AAAA,QAClE,GAAI,OAAO,KAAK,WAAW,EAAE,SAAS,IAClC;AAAA,UACE;AAAA,QACF,IACA,CAAC;AAAA,QACL,uBACE,aAAa,YAAY,SACrB,6BACA;AAAA,QACN,GAAI,aAAa,YAAY,SACzB;AAAA,UACE,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,cAAc,OAAO;AAAA,UACvB;AAAA,QACF,IACA,CAAC;AAAA,MACP;AAAA,MACA,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAS,eAAU,IAAI,GAAG;AACxB,kBAAY,qBAAqB,MAAM,sBAAsB,CAAC;AAC9D,gBAAU,KAAK;AACf;AAAA,IACF;AACA,UAAM,WAAW;AAAA,EACnB;AAEA,SACE,qBAAC,SAAI,WAAU,8BACb;AAAA,wBAAC,QAAG,WAAU,yCAAwC,gCAAkB;AAAA,IAExE,oBAAC,uBAAoB,UAAoB,kBAAkB,aAAa,UAAoB;AAAA,IAE5F;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU;AAAA,QACV,iBAAiB;AAAA,QACjB,YAAY,SAAS;AAAA,QACrB,aAAa;AAAA,QACb;AAAA,QACA,qBAAqB;AAAA;AAAA,IACvB;AAAA,IAGA,qBAAC,aAAQ,WAAU,sBACjB;AAAA,2BAAC,SAAI,WAAU,2CACb;AAAA,4BAAC,UAAK,WAAU,uCAAsC,4BAAc;AAAA,QACpE;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,cACJ,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,cAC/B,EAAE,OAAO,UAAU,OAAO,QAAQ;AAAA,YACpC;AAAA,YACA,OAAO;AAAA,YACP,UAAU,CAAC,UAAU;AACnB,0BAAY,KAAK;AACjB,wBAAU,IAAI;AAAA,YAChB;AAAA;AAAA,QACF;AAAA,SACF;AAAA,MAEC,aAAa,YACZ;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,SAAS;AAAA,UACT,UAAU,CAAC,gBAAgB;AACzB,0CAA8B,WAAW;AACzC,sBAAU,IAAI;AAAA,UAChB;AAAA,UACA,OAAM;AAAA,UACN,MAAK;AAAA,UAEL,8BAAC,0BAAuB,OAAM,qBAAoB,MAAK,kCACrD,+BAAC,SAAI,WAAU,yFACZ;AAAA,qBACC,oBAAC,UAAK,WAAU,8DAA6D,2BAE7E,IAEA,oBAAC,UAAK,WAAU,iCAAgC,2BAAa;AAAA,YAE/D;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS,MAAM,KAAK,YAAY;AAAA,gBAChC,UAAU,CAAC,SAAS,KAAK,KAAK,CAAC,qBAAqB,WAAW,KAAK,MAAM;AAAA,gBAEzE,gBAAM,OAAO,kBAAkB,SAAS,cAAc;AAAA;AAAA,YACzD;AAAA,aACF,GACF;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,IAGC,YACC,oBAAC,SAAI,WAAU,sEACb,8BAAC,OAAE,WAAU,gCAAgC,oBAAS,GACxD;AAAA,IAGF,qBAAC,gBACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,MAAM;AACb,kBAAM,OAAO;AACb,kBAAM,SAAS;AAAA,UACjB;AAAA,UACA,UAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACA,qBAAC,UAAO,SAAS,WAAW,UAAU,CAAC,UAAU,QAC9C;AAAA,kBAAU,oBAAC,WAAQ,WAAU,YAAW;AAAA,QACxC,SAAS,cAAc;AAAA,SAC1B;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,251 @@
1
+ import {
2
+ GraphqlSourceFields
3
+ } from "./chunk-M4SJY6CB.js";
4
+ import {
5
+ graphqlSourceAtom,
6
+ graphqlSourceBindingsAtom,
7
+ setGraphqlSourceBinding,
8
+ updateGraphqlSource
9
+ } from "./chunk-WPRU5C6M.js";
10
+ import {
11
+ GRAPHQL_OAUTH_CONNECTION_SLOT,
12
+ GraphqlSourceBindingInput
13
+ } from "./chunk-7QSGNR4C.js";
14
+
15
+ // src/react/EditGraphqlSource.tsx
16
+ import { useState } from "react";
17
+ import { useAtomValue, useAtomSet } from "@effect/atom-react";
18
+ import * as Exit from "effect/Exit";
19
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
20
+ import { connectionsAtom } from "@executor-js/react/api/atoms";
21
+ import { useScope, useScopeStack } from "@executor-js/react/api/scope-context";
22
+ import { connectionWriteKeys, sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
23
+ import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets";
24
+ import {
25
+ HttpCredentialsEditor,
26
+ serializeHttpCredentials,
27
+ serializeScopedHttpCredentials
28
+ } from "@executor-js/react/plugins/http-credentials";
29
+ import {
30
+ effectiveCredentialBindingForScope,
31
+ httpCredentialsFromConfiguredCredentialBindings,
32
+ initialCredentialTargetScope
33
+ } from "@executor-js/react/plugins/credential-bindings";
34
+ import { slugifyNamespace, useSourceIdentity } from "@executor-js/react/plugins/source-identity";
35
+ import { useCredentialTargetScope } from "@executor-js/react/plugins/credential-target-scope";
36
+ import { Button } from "@executor-js/react/components/button";
37
+ import { FilterTabs } from "@executor-js/react/components/filter-tabs";
38
+ import { SourceOAuthConnectionControl } from "@executor-js/react/plugins/source-oauth-connection";
39
+ import { Badge } from "@executor-js/react/components/badge";
40
+ import { ScopeId } from "@executor-js/sdk/core";
41
+ import { jsx, jsxs } from "react/jsx-runtime";
42
+ function EditForm(props) {
43
+ const displayScope = useScope();
44
+ const scopeStack = useScopeStack();
45
+ const sourceScope = ScopeId.make(props.initial.scope);
46
+ const { credentialTargetScope, credentialScopeOptions } = useCredentialTargetScope({
47
+ sourceScope,
48
+ initialTargetScope: initialCredentialTargetScope(sourceScope, props.bindings)
49
+ });
50
+ const {
51
+ credentialTargetScope: oauthCredentialTargetScope,
52
+ setCredentialTargetScope: setOAuthCredentialTargetScope
53
+ } = useCredentialTargetScope({
54
+ sourceScope,
55
+ initialTargetScope: initialCredentialTargetScope(sourceScope, props.bindings)
56
+ });
57
+ const doUpdate = useAtomSet(updateGraphqlSource, { mode: "promiseExit" });
58
+ const setBinding = useAtomSet(setGraphqlSourceBinding, { mode: "promise" });
59
+ const secretList = useSecretPickerSecrets();
60
+ const connectionsResult = useAtomValue(connectionsAtom(displayScope));
61
+ const identity = useSourceIdentity({
62
+ fallbackName: props.initial.name,
63
+ fallbackNamespace: props.initial.namespace
64
+ });
65
+ const [endpoint, setEndpoint] = useState(props.initial.endpoint);
66
+ const [credentials, setCredentials] = useState(
67
+ () => httpCredentialsFromConfiguredCredentialBindings({
68
+ headers: props.initial.headers,
69
+ queryParams: props.initial.queryParams,
70
+ bindings: props.bindings
71
+ })
72
+ );
73
+ const [authMode, setAuthMode] = useState(props.initial.auth.kind);
74
+ const [saving, setSaving] = useState(false);
75
+ const [error, setError] = useState(null);
76
+ const [credentialsDirty, setCredentialsDirty] = useState(false);
77
+ const [authDirty, setAuthDirty] = useState(false);
78
+ const identityDirty = identity.name.trim() !== props.initial.name.trim();
79
+ const metadataDirty = identityDirty || endpoint.trim() !== props.initial.endpoint.trim();
80
+ const dirty = metadataDirty || credentialsDirty || authDirty;
81
+ const oauth2 = props.initial.auth.kind === "oauth2" ? props.initial.auth : null;
82
+ const connections = AsyncResult.isSuccess(connectionsResult) ? connectionsResult.value : [];
83
+ const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index]));
84
+ const connectionBinding = oauth2 ? effectiveCredentialBindingForScope(
85
+ props.bindings,
86
+ oauth2.connectionSlot,
87
+ oauthCredentialTargetScope,
88
+ scopeRanks
89
+ ) : null;
90
+ const boundConnectionId = connectionBinding?.value.kind === "connection" ? connectionBinding.value.connectionId : null;
91
+ const isConnected = boundConnectionId !== null && connections.some((connection) => connection.id === boundConnectionId);
92
+ const oauthRequestCredentials = serializeHttpCredentials(credentials);
93
+ const handleCredentialsChange = (next) => {
94
+ setCredentials(next);
95
+ setCredentialsDirty(true);
96
+ };
97
+ const handleSave = async () => {
98
+ setSaving(true);
99
+ setError(null);
100
+ const { headers, queryParams } = serializeScopedHttpCredentials(
101
+ credentials,
102
+ credentialTargetScope
103
+ );
104
+ const payload = {
105
+ sourceScope,
106
+ name: metadataDirty ? identity.name.trim() || void 0 : void 0,
107
+ endpoint: metadataDirty ? endpoint.trim() || void 0 : void 0
108
+ };
109
+ if (credentialsDirty) {
110
+ payload.headers = headers;
111
+ payload.queryParams = queryParams;
112
+ payload.credentialTargetScope = credentialTargetScope;
113
+ }
114
+ if (authDirty) {
115
+ payload.auth = authMode === "oauth2" ? {
116
+ kind: "oauth2",
117
+ connectionSlot: props.initial.auth.kind === "oauth2" ? props.initial.auth.connectionSlot : GRAPHQL_OAUTH_CONNECTION_SLOT
118
+ } : { kind: "none" };
119
+ payload.credentialTargetScope = credentialTargetScope;
120
+ }
121
+ const exit = await doUpdate({
122
+ params: { scopeId: displayScope, namespace: props.sourceId },
123
+ payload,
124
+ reactivityKeys: sourceWriteKeys
125
+ });
126
+ if (Exit.isFailure(exit)) {
127
+ setError("Failed to update source");
128
+ setSaving(false);
129
+ return;
130
+ }
131
+ setCredentialsDirty(false);
132
+ setAuthDirty(false);
133
+ props.onSave();
134
+ setSaving(false);
135
+ };
136
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
137
+ /* @__PURE__ */ jsxs("div", { children: [
138
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit GraphQL Source" }),
139
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Update the endpoint and authentication headers for this source." })
140
+ ] }),
141
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3", children: [
142
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-card-foreground", children: props.sourceId }) }),
143
+ /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "GraphQL" })
144
+ ] }),
145
+ /* @__PURE__ */ jsx(
146
+ GraphqlSourceFields,
147
+ {
148
+ endpoint,
149
+ onEndpointChange: setEndpoint,
150
+ identity,
151
+ namespaceReadOnly: true
152
+ }
153
+ ),
154
+ /* @__PURE__ */ jsx(
155
+ HttpCredentialsEditor,
156
+ {
157
+ credentials,
158
+ onChange: handleCredentialsChange,
159
+ existingSecrets: secretList,
160
+ sourceName: identity.name,
161
+ targetScope: credentialTargetScope,
162
+ credentialScopeOptions,
163
+ bindingScopeOptions: credentialScopeOptions
164
+ }
165
+ ),
166
+ /* @__PURE__ */ jsxs("section", { className: "hidden space-y-2.5", children: [
167
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
168
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Authentication" }),
169
+ /* @__PURE__ */ jsx(
170
+ FilterTabs,
171
+ {
172
+ tabs: [
173
+ { value: "none", label: "None" },
174
+ { value: "oauth2", label: "OAuth" }
175
+ ],
176
+ value: authMode,
177
+ onChange: (value) => {
178
+ setAuthMode(value);
179
+ setAuthDirty(true);
180
+ }
181
+ }
182
+ )
183
+ ] }),
184
+ authMode === "oauth2" && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "OAuth sign-in is available from the source header after saving." })
185
+ ] }),
186
+ oauth2 && /* @__PURE__ */ jsx(
187
+ SourceOAuthConnectionControl,
188
+ {
189
+ popupName: "graphql-oauth",
190
+ pluginId: "graphql",
191
+ namespace: slugifyNamespace(props.initial.namespace) || "graphql",
192
+ fallbackNamespace: "graphql",
193
+ endpoint: endpoint.trim(),
194
+ tokenScope: oauthCredentialTargetScope,
195
+ onTokenScopeChange: setOAuthCredentialTargetScope,
196
+ credentialScopeOptions,
197
+ connectionId: boundConnectionId,
198
+ sourceLabel: `${identity.name.trim() || props.initial.namespace || "GraphQL"} OAuth`,
199
+ headers: oauthRequestCredentials.headers,
200
+ queryParams: oauthRequestCredentials.queryParams,
201
+ isConnected,
202
+ onConnected: async (connectionId) => {
203
+ await setBinding({
204
+ params: { scopeId: oauthCredentialTargetScope },
205
+ payload: new GraphqlSourceBindingInput({
206
+ sourceId: props.sourceId,
207
+ sourceScope,
208
+ scope: oauthCredentialTargetScope,
209
+ slot: oauth2.connectionSlot,
210
+ value: { kind: "connection", connectionId }
211
+ }),
212
+ reactivityKeys: [...sourceWriteKeys, ...connectionWriteKeys]
213
+ });
214
+ }
215
+ }
216
+ ),
217
+ error && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }) }),
218
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-border pt-4", children: [
219
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: props.onSave, children: "Cancel" }),
220
+ /* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: !dirty || saving, children: saving ? "Saving\u2026" : "Save changes" })
221
+ ] })
222
+ ] });
223
+ }
224
+ function EditGraphqlSource(props) {
225
+ const scopeId = useScope();
226
+ const sourceResult = useAtomValue(graphqlSourceAtom(scopeId, props.sourceId));
227
+ const source = AsyncResult.isSuccess(sourceResult) && sourceResult.value ? sourceResult.value : null;
228
+ const sourceScope = source ? ScopeId.make(source.scope) : scopeId;
229
+ const bindingsResult = useAtomValue(
230
+ graphqlSourceBindingsAtom(scopeId, props.sourceId, sourceScope)
231
+ );
232
+ if (!AsyncResult.isSuccess(sourceResult) || !source || !AsyncResult.isSuccess(bindingsResult)) {
233
+ return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { children: [
234
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit GraphQL Source" }),
235
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Loading configuration\u2026" })
236
+ ] }) });
237
+ }
238
+ return /* @__PURE__ */ jsx(
239
+ EditForm,
240
+ {
241
+ sourceId: props.sourceId,
242
+ initial: source,
243
+ bindings: bindingsResult.value,
244
+ onSave: props.onSave
245
+ }
246
+ );
247
+ }
248
+ export {
249
+ EditGraphqlSource as default
250
+ };
251
+ //# sourceMappingURL=EditGraphqlSource-5Y47ZAZ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/EditGraphqlSource.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useAtomValue, useAtomSet } from \"@effect/atom-react\";\nimport * as Exit from \"effect/Exit\";\nimport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\nimport {\n graphqlSourceAtom,\n graphqlSourceBindingsAtom,\n setGraphqlSourceBinding,\n updateGraphqlSource,\n} from \"./atoms\";\nimport { connectionsAtom } from \"@executor-js/react/api/atoms\";\nimport { useScope, useScopeStack } from \"@executor-js/react/api/scope-context\";\nimport { connectionWriteKeys, sourceWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport { useSecretPickerSecrets } from \"@executor-js/react/plugins/use-secret-picker-secrets\";\nimport {\n HttpCredentialsEditor,\n serializeHttpCredentials,\n serializeScopedHttpCredentials,\n type HttpCredentialsState,\n} from \"@executor-js/react/plugins/http-credentials\";\nimport {\n effectiveCredentialBindingForScope,\n httpCredentialsFromConfiguredCredentialBindings,\n initialCredentialTargetScope,\n} from \"@executor-js/react/plugins/credential-bindings\";\nimport { slugifyNamespace, useSourceIdentity } from \"@executor-js/react/plugins/source-identity\";\nimport { useCredentialTargetScope } from \"@executor-js/react/plugins/credential-target-scope\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport { FilterTabs } from \"@executor-js/react/components/filter-tabs\";\nimport { SourceOAuthConnectionControl } from \"@executor-js/react/plugins/source-oauth-connection\";\nimport { Badge } from \"@executor-js/react/components/badge\";\nimport { ScopeId } from \"@executor-js/sdk/core\";\nimport { GraphqlSourceFields } from \"./GraphqlSourceFields\";\nimport {\n GRAPHQL_OAUTH_CONNECTION_SLOT,\n type GraphqlCredentialInput,\n GraphqlSourceBindingInput,\n type GraphqlSourceBindingRef,\n} from \"../sdk/types\";\nimport type { StoredGraphqlSource } from \"../sdk/store\";\n\ntype EditableSource = StoredGraphqlSource;\ntype AuthMode = \"none\" | \"oauth2\";\n\n// ---------------------------------------------------------------------------\n// Edit form\n// ---------------------------------------------------------------------------\n\nfunction EditForm(props: {\n sourceId: string;\n initial: EditableSource;\n bindings: readonly GraphqlSourceBindingRef[];\n onSave: () => void;\n}) {\n const displayScope = useScope();\n const scopeStack = useScopeStack();\n const sourceScope = ScopeId.make(props.initial.scope);\n const { credentialTargetScope, credentialScopeOptions } = useCredentialTargetScope({\n sourceScope,\n initialTargetScope: initialCredentialTargetScope(sourceScope, props.bindings),\n });\n const {\n credentialTargetScope: oauthCredentialTargetScope,\n setCredentialTargetScope: setOAuthCredentialTargetScope,\n } = useCredentialTargetScope({\n sourceScope,\n initialTargetScope: initialCredentialTargetScope(sourceScope, props.bindings),\n });\n const doUpdate = useAtomSet(updateGraphqlSource, { mode: \"promiseExit\" });\n const setBinding = useAtomSet(setGraphqlSourceBinding, { mode: \"promise\" });\n const secretList = useSecretPickerSecrets();\n const connectionsResult = useAtomValue(connectionsAtom(displayScope));\n\n const identity = useSourceIdentity({\n fallbackName: props.initial.name,\n fallbackNamespace: props.initial.namespace,\n });\n const [endpoint, setEndpoint] = useState(props.initial.endpoint);\n const [credentials, setCredentials] = useState<HttpCredentialsState>(() =>\n httpCredentialsFromConfiguredCredentialBindings({\n headers: props.initial.headers,\n queryParams: props.initial.queryParams,\n bindings: props.bindings,\n }),\n );\n const [authMode, setAuthMode] = useState<AuthMode>(props.initial.auth.kind);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [credentialsDirty, setCredentialsDirty] = useState(false);\n const [authDirty, setAuthDirty] = useState(false);\n\n const identityDirty = identity.name.trim() !== props.initial.name.trim();\n const metadataDirty = identityDirty || endpoint.trim() !== props.initial.endpoint.trim();\n const dirty = metadataDirty || credentialsDirty || authDirty;\n const oauth2 = props.initial.auth.kind === \"oauth2\" ? props.initial.auth : null;\n const connections = AsyncResult.isSuccess(connectionsResult) ? connectionsResult.value : [];\n const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index] as const));\n const connectionBinding = oauth2\n ? effectiveCredentialBindingForScope(\n props.bindings,\n oauth2.connectionSlot,\n oauthCredentialTargetScope,\n scopeRanks,\n )\n : null;\n const boundConnectionId =\n connectionBinding?.value.kind === \"connection\" ? connectionBinding.value.connectionId : null;\n const isConnected =\n boundConnectionId !== null &&\n connections.some((connection) => connection.id === boundConnectionId);\n const oauthRequestCredentials = serializeHttpCredentials(credentials);\n\n const handleCredentialsChange = (next: HttpCredentialsState) => {\n setCredentials(next);\n setCredentialsDirty(true);\n };\n\n const handleSave = async () => {\n setSaving(true);\n setError(null);\n const { headers, queryParams } = serializeScopedHttpCredentials(\n credentials,\n credentialTargetScope,\n );\n const payload: {\n sourceScope: ScopeId;\n name?: string;\n endpoint?: string;\n headers?: Record<string, GraphqlCredentialInput>;\n queryParams?: Record<string, GraphqlCredentialInput>;\n credentialTargetScope?: ScopeId;\n auth?: { kind: \"none\" } | { kind: \"oauth2\"; connectionSlot: string };\n } = {\n sourceScope,\n name: metadataDirty ? identity.name.trim() || undefined : undefined,\n endpoint: metadataDirty ? endpoint.trim() || undefined : undefined,\n };\n if (credentialsDirty) {\n payload.headers = headers;\n payload.queryParams = queryParams as Record<string, GraphqlCredentialInput>;\n payload.credentialTargetScope = credentialTargetScope;\n }\n if (authDirty) {\n payload.auth =\n authMode === \"oauth2\"\n ? {\n kind: \"oauth2\",\n connectionSlot:\n props.initial.auth.kind === \"oauth2\"\n ? props.initial.auth.connectionSlot\n : GRAPHQL_OAUTH_CONNECTION_SLOT,\n }\n : { kind: \"none\" };\n payload.credentialTargetScope = credentialTargetScope;\n }\n const exit = await doUpdate({\n params: { scopeId: displayScope, namespace: props.sourceId },\n payload,\n reactivityKeys: sourceWriteKeys,\n });\n\n if (Exit.isFailure(exit)) {\n setError(\"Failed to update source\");\n setSaving(false);\n return;\n }\n\n setCredentialsDirty(false);\n setAuthDirty(false);\n props.onSave();\n setSaving(false);\n };\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit GraphQL Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Update the endpoint and authentication headers for this source.\n </p>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-semibold text-card-foreground\">{props.sourceId}</p>\n </div>\n <Badge variant=\"secondary\" className=\"text-xs\">\n GraphQL\n </Badge>\n </div>\n\n <GraphqlSourceFields\n endpoint={endpoint}\n onEndpointChange={setEndpoint}\n identity={identity}\n namespaceReadOnly\n />\n\n <HttpCredentialsEditor\n credentials={credentials}\n onChange={handleCredentialsChange}\n existingSecrets={secretList}\n sourceName={identity.name}\n targetScope={credentialTargetScope}\n credentialScopeOptions={credentialScopeOptions}\n bindingScopeOptions={credentialScopeOptions}\n />\n\n {/* Temporarily hidden while we revisit GraphQL OAuth discovery and UX. */}\n <section className=\"hidden space-y-2.5\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm font-medium text-foreground\">Authentication</span>\n <FilterTabs<AuthMode>\n tabs={[\n { value: \"none\", label: \"None\" },\n { value: \"oauth2\", label: \"OAuth\" },\n ]}\n value={authMode}\n onChange={(value) => {\n setAuthMode(value);\n setAuthDirty(true);\n }}\n />\n </div>\n {authMode === \"oauth2\" && (\n <p className=\"text-xs text-muted-foreground\">\n OAuth sign-in is available from the source header after saving.\n </p>\n )}\n </section>\n\n {oauth2 && (\n <SourceOAuthConnectionControl\n popupName=\"graphql-oauth\"\n pluginId=\"graphql\"\n namespace={slugifyNamespace(props.initial.namespace) || \"graphql\"}\n fallbackNamespace=\"graphql\"\n endpoint={endpoint.trim()}\n tokenScope={oauthCredentialTargetScope}\n onTokenScopeChange={setOAuthCredentialTargetScope}\n credentialScopeOptions={credentialScopeOptions}\n connectionId={boundConnectionId}\n sourceLabel={`${identity.name.trim() || props.initial.namespace || \"GraphQL\"} OAuth`}\n headers={oauthRequestCredentials.headers}\n queryParams={oauthRequestCredentials.queryParams}\n isConnected={isConnected}\n onConnected={async (connectionId) => {\n await setBinding({\n params: { scopeId: oauthCredentialTargetScope },\n payload: new GraphqlSourceBindingInput({\n sourceId: props.sourceId,\n sourceScope,\n scope: oauthCredentialTargetScope,\n slot: oauth2.connectionSlot,\n value: { kind: \"connection\", connectionId },\n }),\n reactivityKeys: [...sourceWriteKeys, ...connectionWriteKeys],\n });\n }}\n />\n )}\n\n {error && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n )}\n\n <div className=\"flex items-center justify-between border-t border-border pt-4\">\n <Button variant=\"ghost\" onClick={props.onSave}>\n Cancel\n </Button>\n <Button onClick={handleSave} disabled={!dirty || saving}>\n {saving ? \"Saving…\" : \"Save changes\"}\n </Button>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nexport default function EditGraphqlSource(props: { sourceId: string; onSave: () => void }) {\n const scopeId = useScope();\n const sourceResult = useAtomValue(graphqlSourceAtom(scopeId, props.sourceId));\n const source =\n AsyncResult.isSuccess(sourceResult) && sourceResult.value ? sourceResult.value : null;\n const sourceScope = source ? ScopeId.make(source.scope) : scopeId;\n const bindingsResult = useAtomValue(\n graphqlSourceBindingsAtom(scopeId, props.sourceId, sourceScope),\n );\n\n if (!AsyncResult.isSuccess(sourceResult) || !source || !AsyncResult.isSuccess(bindingsResult)) {\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit GraphQL Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">Loading configuration…</p>\n </div>\n </div>\n );\n }\n\n return (\n <EditForm\n sourceId={props.sourceId}\n initial={source as EditableSource}\n bindings={bindingsResult.value}\n onSave={props.onSave}\n />\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,70 @@
1
+ import {
2
+ graphqlSourceAtom,
3
+ graphqlSourceBindingsAtom
4
+ } from "./chunk-WPRU5C6M.js";
5
+ import "./chunk-7QSGNR4C.js";
6
+
7
+ // src/react/GraphqlSourceSummary.tsx
8
+ import { useAtomValue } from "@effect/atom-react";
9
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
10
+ import { connectionsAtom } from "@executor-js/react/api/atoms";
11
+ import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context";
12
+ import {
13
+ SourceCredentialNotice,
14
+ SourceCredentialStatusBadge,
15
+ missingSourceCredentialLabels
16
+ } from "@executor-js/react/plugins/source-credential-status";
17
+ import { ScopeId } from "@executor-js/sdk/core";
18
+ import { jsx } from "react/jsx-runtime";
19
+ var sourceCredentialSlots = (source) => {
20
+ const slots = [];
21
+ for (const [name, value] of Object.entries(source.headers)) {
22
+ if (typeof value !== "string") slots.push({ kind: "secret", slot: value.slot, label: name });
23
+ }
24
+ for (const [name, value] of Object.entries(source.queryParams)) {
25
+ if (typeof value !== "string") slots.push({ kind: "secret", slot: value.slot, label: name });
26
+ }
27
+ if (source.auth.kind === "oauth2") {
28
+ slots.push({
29
+ kind: "connection",
30
+ slot: source.auth.connectionSlot,
31
+ label: "OAuth sign-in"
32
+ });
33
+ }
34
+ return slots;
35
+ };
36
+ function GraphqlSourceSummary(props) {
37
+ const displayScope = useScope();
38
+ const userScope = useUserScope();
39
+ const scopeStack = useScopeStack();
40
+ const sourceResult = useAtomValue(graphqlSourceAtom(displayScope, props.sourceId));
41
+ const source = AsyncResult.isSuccess(sourceResult) && sourceResult.value ? sourceResult.value : null;
42
+ const sourceScope = source ? ScopeId.make(source.scope) : displayScope;
43
+ const bindingsResult = useAtomValue(
44
+ graphqlSourceBindingsAtom(displayScope, props.sourceId, sourceScope)
45
+ );
46
+ const connectionsResult = useAtomValue(connectionsAtom(displayScope));
47
+ if (!source) return null;
48
+ const slots = sourceCredentialSlots(source);
49
+ if (slots.length === 0) return null;
50
+ if (!AsyncResult.isSuccess(bindingsResult) || !AsyncResult.isSuccess(connectionsResult)) {
51
+ return props.variant === "panel" ? null : /* @__PURE__ */ jsx(SourceCredentialStatusBadge, { missing: ["credentials"] });
52
+ }
53
+ const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index]));
54
+ const liveConnectionIds = new Set(connectionsResult.value.map((connection) => connection.id));
55
+ const missing = missingSourceCredentialLabels({
56
+ slots,
57
+ bindings: bindingsResult.value,
58
+ targetScope: userScope,
59
+ scopeRanks,
60
+ liveConnectionIds
61
+ });
62
+ if (props.variant === "panel") {
63
+ return /* @__PURE__ */ jsx(SourceCredentialNotice, { missing, onAction: props.onAction });
64
+ }
65
+ return /* @__PURE__ */ jsx(SourceCredentialStatusBadge, { missing });
66
+ }
67
+ export {
68
+ GraphqlSourceSummary as default
69
+ };
70
+ //# sourceMappingURL=GraphqlSourceSummary-F3JWR4YN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/GraphqlSourceSummary.tsx"],"sourcesContent":["import { useAtomValue } from \"@effect/atom-react\";\nimport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\n\nimport { connectionsAtom } from \"@executor-js/react/api/atoms\";\nimport { useScope, useScopeStack, useUserScope } from \"@executor-js/react/api/scope-context\";\nimport {\n SourceCredentialNotice,\n SourceCredentialStatusBadge,\n missingSourceCredentialLabels,\n type SourceCredentialSlot,\n} from \"@executor-js/react/plugins/source-credential-status\";\nimport { ScopeId } from \"@executor-js/sdk/core\";\n\nimport { graphqlSourceAtom, graphqlSourceBindingsAtom } from \"./atoms\";\nimport type { StoredGraphqlSource } from \"../sdk/store\";\n\nconst sourceCredentialSlots = (source: StoredGraphqlSource): readonly SourceCredentialSlot[] => {\n const slots: SourceCredentialSlot[] = [];\n for (const [name, value] of Object.entries(source.headers)) {\n if (typeof value !== \"string\") slots.push({ kind: \"secret\", slot: value.slot, label: name });\n }\n for (const [name, value] of Object.entries(source.queryParams)) {\n if (typeof value !== \"string\") slots.push({ kind: \"secret\", slot: value.slot, label: name });\n }\n if (source.auth.kind === \"oauth2\") {\n slots.push({\n kind: \"connection\",\n slot: source.auth.connectionSlot,\n label: \"OAuth sign-in\",\n });\n }\n return slots;\n};\n\nexport default function GraphqlSourceSummary(props: {\n sourceId: string;\n variant?: \"badge\" | \"panel\";\n onAction?: () => void;\n}) {\n const displayScope = useScope();\n const userScope = useUserScope();\n const scopeStack = useScopeStack();\n const sourceResult = useAtomValue(graphqlSourceAtom(displayScope, props.sourceId));\n const source =\n AsyncResult.isSuccess(sourceResult) && sourceResult.value ? sourceResult.value : null;\n const sourceScope = source ? ScopeId.make(source.scope) : displayScope;\n const bindingsResult = useAtomValue(\n graphqlSourceBindingsAtom(displayScope, props.sourceId, sourceScope),\n );\n const connectionsResult = useAtomValue(connectionsAtom(displayScope));\n\n if (!source) return null;\n const slots = sourceCredentialSlots(source as StoredGraphqlSource);\n if (slots.length === 0) return null;\n if (!AsyncResult.isSuccess(bindingsResult) || !AsyncResult.isSuccess(connectionsResult)) {\n return props.variant === \"panel\" ? null : (\n <SourceCredentialStatusBadge missing={[\"credentials\"]} />\n );\n }\n\n const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index] as const));\n const liveConnectionIds = new Set(connectionsResult.value.map((connection) => connection.id));\n const missing = missingSourceCredentialLabels({\n slots,\n bindings: bindingsResult.value,\n targetScope: userScope,\n scopeRanks,\n liveConnectionIds,\n });\n\n if (props.variant === \"panel\") {\n return <SourceCredentialNotice missing={missing} onAction={props.onAction} />;\n }\n\n return <SourceCredentialStatusBadge missing={missing} />;\n}\n"],"mappings":";;;;;;;AAAA,SAAS,oBAAoB;AAC7B,YAAY,iBAAiB;AAE7B,SAAS,uBAAuB;AAChC,SAAS,UAAU,eAAe,oBAAoB;AACtD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,eAAe;AA6ClB;AAxCN,IAAM,wBAAwB,CAAC,WAAiE;AAC9F,QAAM,QAAgC,CAAC;AACvC,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AAC1D,QAAI,OAAO,UAAU,SAAU,OAAM,KAAK,EAAE,MAAM,UAAU,MAAM,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,EAC7F;AACA,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AAC9D,QAAI,OAAO,UAAU,SAAU,OAAM,KAAK,EAAE,MAAM,UAAU,MAAM,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,EAC7F;AACA,MAAI,OAAO,KAAK,SAAS,UAAU;AACjC,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,MAAM,OAAO,KAAK;AAAA,MAClB,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEe,SAAR,qBAAsC,OAI1C;AACD,QAAM,eAAe,SAAS;AAC9B,QAAM,YAAY,aAAa;AAC/B,QAAM,aAAa,cAAc;AACjC,QAAM,eAAe,aAAa,kBAAkB,cAAc,MAAM,QAAQ,CAAC;AACjF,QAAM,SACQ,sBAAU,YAAY,KAAK,aAAa,QAAQ,aAAa,QAAQ;AACnF,QAAM,cAAc,SAAS,QAAQ,KAAK,OAAO,KAAK,IAAI;AAC1D,QAAM,iBAAiB;AAAA,IACrB,0BAA0B,cAAc,MAAM,UAAU,WAAW;AAAA,EACrE;AACA,QAAM,oBAAoB,aAAa,gBAAgB,YAAY,CAAC;AAEpE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,sBAAsB,MAA6B;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,CAAa,sBAAU,cAAc,KAAK,CAAa,sBAAU,iBAAiB,GAAG;AACvF,WAAO,MAAM,YAAY,UAAU,OACjC,oBAAC,+BAA4B,SAAS,CAAC,aAAa,GAAG;AAAA,EAE3D;AAEA,QAAM,aAAa,IAAI,IAAI,WAAW,IAAI,CAAC,OAAO,UAAU,CAAC,MAAM,IAAI,KAAK,CAAU,CAAC;AACvF,QAAM,oBAAoB,IAAI,IAAI,kBAAkB,MAAM,IAAI,CAAC,eAAe,WAAW,EAAE,CAAC;AAC5F,QAAM,UAAU,8BAA8B;AAAA,IAC5C;AAAA,IACA,UAAU,eAAe;AAAA,IACzB,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,MAAM,YAAY,SAAS;AAC7B,WAAO,oBAAC,0BAAuB,SAAkB,UAAU,MAAM,UAAU;AAAA,EAC7E;AAEA,SAAO,oBAAC,+BAA4B,SAAkB;AACxD;","names":[]}