@executor-js/plugin-openapi 1.4.29 → 1.4.30
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.
- package/dist/{AddOpenApiSource-FLMNI742.js → AddOpenApiSource-KSOMPQ2R.js} +4 -4
- package/dist/{EditOpenApiSource-I4NIGIIJ.js → EditOpenApiSource-AOA7APR2.js} +301 -192
- package/dist/EditOpenApiSource-AOA7APR2.js.map +1 -0
- package/dist/{OpenApiSourceSummary-CM46DB4L.js → OpenApiSourceSummary-Y3S6ZBOZ.js} +4 -4
- package/dist/OpenApiSourceSummary-Y3S6ZBOZ.js.map +1 -0
- package/dist/api/group.d.ts +124 -118
- package/dist/api/index.d.ts +148 -369
- package/dist/chunk-BB5IAKRG.js +136 -0
- package/dist/chunk-BB5IAKRG.js.map +1 -0
- package/dist/{chunk-E7PZ2QGD.js → chunk-EOXXE5DG.js} +17 -455
- package/dist/chunk-EOXXE5DG.js.map +1 -0
- package/dist/{chunk-OZ67JNID.js → chunk-NIKLYJ3X.js} +830 -319
- package/dist/chunk-NIKLYJ3X.js.map +1 -0
- package/dist/{chunk-TGDT6QCH.js → chunk-YJMXYKYX.js} +178 -117
- package/dist/chunk-YJMXYKYX.js.map +1 -0
- package/dist/{chunk-GFQUEZUW.js → chunk-ZZBTLFTA.js} +78 -93
- package/dist/chunk-ZZBTLFTA.js.map +1 -0
- package/dist/client.js +7 -137
- package/dist/client.js.map +1 -1
- package/dist/core.js +5 -10
- package/dist/index.js +3 -2
- package/dist/react/atoms.d.ts +83 -223
- package/dist/react/client.d.ts +123 -117
- package/dist/sdk/credential-status.d.ts +3 -3
- package/dist/sdk/extract.d.ts +19 -19
- package/dist/sdk/index.d.ts +2 -2
- package/dist/sdk/invoke.d.ts +7 -7
- package/dist/sdk/parse.d.ts +2 -3
- package/dist/sdk/plugin.d.ts +181 -275
- package/dist/sdk/preview.d.ts +12 -12
- package/dist/sdk/source-contracts.d.ts +55 -0
- package/dist/sdk/store.d.ts +6 -269
- package/dist/sdk/types.d.ts +16 -65
- package/dist/testing/index.d.ts +149 -11
- package/dist/testing.js +419 -33
- package/dist/testing.js.map +1 -1
- package/dist/testing.test.d.ts +1 -0
- package/package.json +3 -4
- package/dist/EditOpenApiSource-I4NIGIIJ.js.map +0 -1
- package/dist/OpenApiSourceSummary-CM46DB4L.js.map +0 -1
- package/dist/chunk-E7PZ2QGD.js.map +0 -1
- package/dist/chunk-GFQUEZUW.js.map +0 -1
- package/dist/chunk-OZ67JNID.js.map +0 -1
- package/dist/chunk-TGDT6QCH.js.map +0 -1
- /package/dist/{AddOpenApiSource-FLMNI742.js.map → AddOpenApiSource-KSOMPQ2R.js.map} +0 -0
|
@@ -4,19 +4,15 @@ import {
|
|
|
4
4
|
OpenApiSourceDetailsFields,
|
|
5
5
|
inferOAuthIssuerUrl,
|
|
6
6
|
resolveOAuthUrl
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YJMXYKYX.js";
|
|
8
8
|
import {
|
|
9
9
|
openApiSourceAtom,
|
|
10
|
-
openApiSourceBindingsAtom
|
|
11
|
-
|
|
12
|
-
setOpenApiSourceBinding,
|
|
13
|
-
updateOpenApiSource
|
|
14
|
-
} from "./chunk-GFQUEZUW.js";
|
|
10
|
+
openApiSourceBindingsAtom
|
|
11
|
+
} from "./chunk-ZZBTLFTA.js";
|
|
15
12
|
import {
|
|
16
13
|
OAuth2SourceConfig,
|
|
17
|
-
OpenApiSourceBindingInput,
|
|
18
14
|
oauth2ClientSecretSlot
|
|
19
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-EOXXE5DG.js";
|
|
20
16
|
|
|
21
17
|
// src/react/EditOpenApiSource.tsx
|
|
22
18
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -25,8 +21,14 @@ import * as Exit from "effect/Exit";
|
|
|
25
21
|
import * as Option from "effect/Option";
|
|
26
22
|
import * as Schema from "effect/Schema";
|
|
27
23
|
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
|
|
28
|
-
import {
|
|
29
|
-
|
|
24
|
+
import {
|
|
25
|
+
connectionsAtom,
|
|
26
|
+
configureSource,
|
|
27
|
+
setSourceCredentialBinding,
|
|
28
|
+
sourceAtom,
|
|
29
|
+
startOAuth
|
|
30
|
+
} from "@executor-js/react/api/atoms";
|
|
31
|
+
import { useScope, useUserScope } from "@executor-js/react/api/scope-context";
|
|
30
32
|
import { connectionWriteKeys, sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
|
|
31
33
|
import { Button } from "@executor-js/react/components/button";
|
|
32
34
|
import { CopyButton } from "@executor-js/react/components/copy-button";
|
|
@@ -36,18 +38,28 @@ import {
|
|
|
36
38
|
CardStackEntry,
|
|
37
39
|
CardStackEntryContent,
|
|
38
40
|
CardStackEntryDescription,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
CardStackEntryTitle,
|
|
42
|
+
CardStackEntryField
|
|
41
43
|
} from "@executor-js/react/components/card-stack";
|
|
42
|
-
import {
|
|
44
|
+
import { FieldLabel } from "@executor-js/react/components/field";
|
|
45
|
+
import { HelpTooltip } from "@executor-js/react/components/help-tooltip";
|
|
43
46
|
import { Input } from "@executor-js/react/components/input";
|
|
44
47
|
import { sourceWriteKeys as openApiWriteKeys } from "@executor-js/react/api/reactivity-keys";
|
|
45
|
-
import {
|
|
48
|
+
import {
|
|
49
|
+
ConnectionId,
|
|
50
|
+
ScopeId,
|
|
51
|
+
SetSourceCredentialBindingInput
|
|
52
|
+
} from "@executor-js/sdk/shared";
|
|
46
53
|
import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets";
|
|
47
54
|
import {
|
|
48
55
|
oauthCallbackUrl,
|
|
49
56
|
useOAuthPopupFlow
|
|
50
57
|
} from "@executor-js/react/plugins/oauth-sign-in";
|
|
58
|
+
import {
|
|
59
|
+
CredentialControlField,
|
|
60
|
+
CredentialScopeDropdown,
|
|
61
|
+
CredentialUsageRow
|
|
62
|
+
} from "@executor-js/react/plugins/credential-target-scope";
|
|
51
63
|
import {
|
|
52
64
|
effectiveCredentialBindingForScope,
|
|
53
65
|
exactCredentialBindingForScope,
|
|
@@ -55,6 +67,11 @@ import {
|
|
|
55
67
|
isSecretCredentialBindingValue
|
|
56
68
|
} from "@executor-js/react/plugins/credential-bindings";
|
|
57
69
|
import { SecretCredentialSlotBindings } from "@executor-js/react/plugins/credential-slot-bindings";
|
|
70
|
+
import {
|
|
71
|
+
useSourceCredentialBindingScopes,
|
|
72
|
+
useSourceCredentialBindingWriter
|
|
73
|
+
} from "@executor-js/react/plugins/source-credential-bindings";
|
|
74
|
+
import { CreatableSecretPicker } from "@executor-js/react/plugins/secret-header-auth";
|
|
58
75
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
59
76
|
var ErrorMessage = Schema.Struct({ message: Schema.String });
|
|
60
77
|
var decodeErrorMessage = Schema.decodeUnknownOption(ErrorMessage);
|
|
@@ -77,27 +94,26 @@ var openApiOAuthConnectionId = (sourceId, securitySchemeName, targetScope) => Co
|
|
|
77
94
|
var effectiveClientSecretSlot = (oauth2) => oauth2.clientSecretSlot ?? oauth2ClientSecretSlot(oauth2.securitySchemeName);
|
|
78
95
|
function EditOpenApiSource(props) {
|
|
79
96
|
const displayScope = useScope();
|
|
80
|
-
const scopeStack = useScopeStack();
|
|
81
97
|
const userScope = useUserScope();
|
|
82
98
|
const sourceSummaryResult = useAtomValue(sourceAtom(props.sourceId, displayScope));
|
|
83
99
|
const sourceSummary = AsyncResult.isSuccess(sourceSummaryResult) && sourceSummaryResult.value ? sourceSummaryResult.value : null;
|
|
84
100
|
const sourceScopeId = sourceSummary?.scopeId ?? displayScope;
|
|
85
101
|
const sourceScope = ScopeId.make(sourceScopeId);
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
const {
|
|
103
|
+
credentialScopes,
|
|
104
|
+
credentialScopeOptions,
|
|
105
|
+
organizationCredentialScope,
|
|
106
|
+
secretBindingScopes,
|
|
107
|
+
scopeRanks
|
|
108
|
+
} = useSourceCredentialBindingScopes({ sourceScope });
|
|
90
109
|
const sourceResult = useAtomValue(openApiSourceAtom(sourceScope, props.sourceId));
|
|
91
110
|
const bindingsResult = useAtomValue(
|
|
92
111
|
openApiSourceBindingsAtom(displayScope, props.sourceId, sourceScope)
|
|
93
112
|
);
|
|
94
113
|
const connectionsResult = useAtomValue(connectionsAtom(displayScope));
|
|
95
114
|
const secretList = useSecretPickerSecrets();
|
|
96
|
-
const
|
|
97
|
-
const doSetBinding = useAtomSet(
|
|
98
|
-
mode: "promiseExit"
|
|
99
|
-
});
|
|
100
|
-
const doRemoveBinding = useAtomSet(removeOpenApiSourceBinding, {
|
|
115
|
+
const doConfigure = useAtomSet(configureSource, { mode: "promiseExit" });
|
|
116
|
+
const doSetBinding = useAtomSet(setSourceCredentialBinding, {
|
|
101
117
|
mode: "promiseExit"
|
|
102
118
|
});
|
|
103
119
|
const doStartOAuth = useAtomSet(startOAuth, { mode: "promiseExit" });
|
|
@@ -115,11 +131,20 @@ function EditOpenApiSource(props) {
|
|
|
115
131
|
const [sourceSaveState, setSourceSaveState] = useState("idle");
|
|
116
132
|
const [error, setError] = useState(null);
|
|
117
133
|
const [busyKey, setBusyKey] = useState(null);
|
|
134
|
+
const sourceBindingWriter = useSourceCredentialBindingWriter({
|
|
135
|
+
displayScope,
|
|
136
|
+
source: { id: props.sourceId, scope: sourceScope },
|
|
137
|
+
onError: setError,
|
|
138
|
+
errorMessageFromExit
|
|
139
|
+
});
|
|
118
140
|
const [pendingOAuthConnection, setPendingOAuthConnection] = useState(null);
|
|
119
141
|
const [loadedSourceKey, setLoadedSourceKey] = useState(null);
|
|
120
142
|
const [selectedOAuthTokenScope, setSelectedOAuthTokenScope] = useState(
|
|
121
143
|
userScope !== sourceScopeId ? userScope : sourceScopeId
|
|
122
144
|
);
|
|
145
|
+
const [selectedOAuthClientIdScope, setSelectedOAuthClientIdScope] = useState(sourceScopeId);
|
|
146
|
+
const [selectedOAuthClientSecretScope, setSelectedOAuthClientSecretScope] = useState(sourceScopeId);
|
|
147
|
+
const [oauthEndpointsOpen, setOAuthEndpointsOpen] = useState(false);
|
|
123
148
|
const [oauth2AuthorizationUrl, setOAuth2AuthorizationUrl] = useState(
|
|
124
149
|
source?.config.oauth2?.authorizationUrl ?? ""
|
|
125
150
|
);
|
|
@@ -141,6 +166,8 @@ function EditOpenApiSource(props) {
|
|
|
141
166
|
const oauth2EndpointsSaveSeq = useRef(0);
|
|
142
167
|
useEffect(() => {
|
|
143
168
|
setSelectedOAuthTokenScope(userScope !== sourceScopeId ? userScope : sourceScopeId);
|
|
169
|
+
setSelectedOAuthClientIdScope(sourceScopeId);
|
|
170
|
+
setSelectedOAuthClientSecretScope(sourceScopeId);
|
|
144
171
|
}, [sourceScopeId, userScope]);
|
|
145
172
|
useEffect(() => {
|
|
146
173
|
if (!source) return;
|
|
@@ -151,6 +178,7 @@ function EditOpenApiSource(props) {
|
|
|
151
178
|
setOAuth2AuthorizationUrl(source.config.oauth2?.authorizationUrl ?? "");
|
|
152
179
|
setOAuth2TokenUrl(source.config.oauth2?.tokenUrl ?? "");
|
|
153
180
|
setOAuth2EndpointsSaveState("idle");
|
|
181
|
+
setOAuthEndpointsOpen(false);
|
|
154
182
|
setSourceSaveState("idle");
|
|
155
183
|
setLoadedSourceKey(sourceKey);
|
|
156
184
|
}, [loadedSourceKey, source, sourceScopeId]);
|
|
@@ -170,12 +198,17 @@ function EditOpenApiSource(props) {
|
|
|
170
198
|
setSourceSaveState("saving");
|
|
171
199
|
setError(null);
|
|
172
200
|
void (async () => {
|
|
173
|
-
const exit = await
|
|
174
|
-
params: { scopeId: displayScope
|
|
201
|
+
const exit = await doConfigure({
|
|
202
|
+
params: { scopeId: displayScope },
|
|
175
203
|
payload: {
|
|
176
|
-
sourceScope,
|
|
177
|
-
|
|
178
|
-
|
|
204
|
+
source: { id: props.sourceId, scope: sourceScope },
|
|
205
|
+
scope: sourceScope,
|
|
206
|
+
type: "openapi",
|
|
207
|
+
config: {
|
|
208
|
+
scope: sourceScope,
|
|
209
|
+
name: nextName || void 0,
|
|
210
|
+
baseUrl: nextBaseUrl || void 0
|
|
211
|
+
}
|
|
179
212
|
},
|
|
180
213
|
reactivityKeys: openApiWriteKeys
|
|
181
214
|
});
|
|
@@ -195,7 +228,7 @@ function EditOpenApiSource(props) {
|
|
|
195
228
|
}, [
|
|
196
229
|
baseUrl,
|
|
197
230
|
displayScope,
|
|
198
|
-
|
|
231
|
+
doConfigure,
|
|
199
232
|
loadedSourceKey,
|
|
200
233
|
name,
|
|
201
234
|
props.sourceId,
|
|
@@ -236,29 +269,6 @@ function EditOpenApiSource(props) {
|
|
|
236
269
|
}
|
|
237
270
|
return slots;
|
|
238
271
|
}, [source]);
|
|
239
|
-
const credentialScopes = useMemo(() => {
|
|
240
|
-
const entries = [{ scopeId: ScopeId.make(sourceScopeId), label: "Organization" }];
|
|
241
|
-
if (userScope !== sourceScopeId) {
|
|
242
|
-
entries.unshift({ scopeId: ScopeId.make(userScope), label: "Personal" });
|
|
243
|
-
} else {
|
|
244
|
-
entries[0] = {
|
|
245
|
-
scopeId: ScopeId.make(sourceScopeId),
|
|
246
|
-
label: "Credentials"
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
return entries;
|
|
250
|
-
}, [sourceScopeId, userScope]);
|
|
251
|
-
const credentialScopeOptions = useMemo(
|
|
252
|
-
() => credentialScopes.map((entry) => ({
|
|
253
|
-
scopeId: entry.scopeId,
|
|
254
|
-
label: entry.label,
|
|
255
|
-
description: entry.label === "Personal" ? "Saved only for your account." : "Shared with everyone who can use this source."
|
|
256
|
-
})),
|
|
257
|
-
[credentialScopes]
|
|
258
|
-
);
|
|
259
|
-
const organizationCredentialScope = credentialScopes.find((entry) => entry.label === "Organization") ?? credentialScopes[0];
|
|
260
|
-
const personalCredentialScope = credentialScopes.find((entry) => entry.label === "Personal") ?? null;
|
|
261
|
-
const secretBindingScopes = personalCredentialScope && personalCredentialScope.scopeId !== organizationCredentialScope.scopeId ? [organizationCredentialScope, personalCredentialScope] : [organizationCredentialScope];
|
|
262
272
|
const activeOAuthTokenScope = credentialScopes.find((entry) => entry.scopeId === selectedOAuthTokenScope) ?? credentialScopes[0];
|
|
263
273
|
const activeOAuthTokenScopeId = activeOAuthTokenScope.scopeId;
|
|
264
274
|
const activeOAuthTokenScopeLabel = activeOAuthTokenScope.label;
|
|
@@ -268,50 +278,10 @@ function EditOpenApiSource(props) {
|
|
|
268
278
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Loading configuration\u2026" })
|
|
269
279
|
] });
|
|
270
280
|
}
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
setBusyKey(inputKey);
|
|
276
|
-
setError(null);
|
|
277
|
-
const exit = await doSetBinding({
|
|
278
|
-
params: { scopeId: displayScope },
|
|
279
|
-
payload: OpenApiSourceBindingInput.make({
|
|
280
|
-
sourceId: props.sourceId,
|
|
281
|
-
sourceScope,
|
|
282
|
-
scope: targetScope,
|
|
283
|
-
slot,
|
|
284
|
-
value: {
|
|
285
|
-
kind: "secret",
|
|
286
|
-
secretId: SecretId.make(trimmed),
|
|
287
|
-
secretScopeId: secretScope
|
|
288
|
-
}
|
|
289
|
-
}),
|
|
290
|
-
reactivityKeys: sourceWriteKeys
|
|
291
|
-
});
|
|
292
|
-
if (Exit.isFailure(exit)) {
|
|
293
|
-
setError(errorMessageFromExit(exit, "Failed to save credential binding"));
|
|
294
|
-
}
|
|
295
|
-
setBusyKey(null);
|
|
296
|
-
};
|
|
297
|
-
const clearBinding = async (targetScope, slot) => {
|
|
298
|
-
setBusyKey(`${targetScope}:${slot}:clear`);
|
|
299
|
-
setError(null);
|
|
300
|
-
const exit = await doRemoveBinding({
|
|
301
|
-
params: { scopeId: displayScope },
|
|
302
|
-
payload: {
|
|
303
|
-
sourceId: props.sourceId,
|
|
304
|
-
sourceScope,
|
|
305
|
-
slot,
|
|
306
|
-
scope: targetScope
|
|
307
|
-
},
|
|
308
|
-
reactivityKeys: sourceWriteKeys
|
|
309
|
-
});
|
|
310
|
-
if (Exit.isFailure(exit)) {
|
|
311
|
-
setError(errorMessageFromExit(exit, "Failed to clear credential binding"));
|
|
312
|
-
}
|
|
313
|
-
setBusyKey(null);
|
|
314
|
-
};
|
|
281
|
+
const oauthClientSecretSlot = source.config.oauth2 ? effectiveClientSecretSlot(source.config.oauth2) : null;
|
|
282
|
+
const nonOAuthSecretSlots = secretSlots.filter(
|
|
283
|
+
(slot) => slot.kind === "secret" && (!source.config.oauth2 || slot.slot !== source.config.oauth2.clientIdSlot && slot.slot !== oauthClientSecretSlot)
|
|
284
|
+
);
|
|
315
285
|
const connectOAuth = async (targetScope) => {
|
|
316
286
|
const oauth2 = source.config.oauth2;
|
|
317
287
|
if (!oauth2) return;
|
|
@@ -333,11 +303,13 @@ function EditOpenApiSource(props) {
|
|
|
333
303
|
return;
|
|
334
304
|
}
|
|
335
305
|
const clientIdSecretId = clientIdBinding.value.secretId;
|
|
306
|
+
const clientIdSecretScopeId = clientIdBinding.value.secretScopeId ?? clientIdBinding.scopeId;
|
|
336
307
|
if (oauth2.flow === "clientCredentials" && (!clientSecretBinding || !isSecretCredentialBindingValue(clientSecretBinding.value))) {
|
|
337
308
|
setError("Client secret must be bound before connecting");
|
|
338
309
|
return;
|
|
339
310
|
}
|
|
340
311
|
const clientSecretValue = oauth2.flow === "clientCredentials" && clientSecretBinding && isSecretCredentialBindingValue(clientSecretBinding.value) ? clientSecretBinding.value : null;
|
|
312
|
+
const clientSecretSecretScopeId = clientSecretBinding && isSecretCredentialBindingValue(clientSecretBinding.value) ? clientSecretBinding.value.secretScopeId ?? clientSecretBinding.scopeId : null;
|
|
341
313
|
const existingConnection = exactCredentialBindingForScope(
|
|
342
314
|
bindingRows,
|
|
343
315
|
oauth2.connectionSlot,
|
|
@@ -370,7 +342,9 @@ function EditOpenApiSource(props) {
|
|
|
370
342
|
kind: "client-credentials",
|
|
371
343
|
tokenEndpoint: tokenUrl,
|
|
372
344
|
clientIdSecretId,
|
|
345
|
+
clientIdSecretScopeId: String(clientIdSecretScopeId),
|
|
373
346
|
clientSecretSecretId: clientSecretValue.secretId,
|
|
347
|
+
clientSecretSecretScopeId: clientSecretSecretScopeId ? String(clientSecretSecretScopeId) : null,
|
|
374
348
|
scopes: [...oauth2.scopes]
|
|
375
349
|
},
|
|
376
350
|
pluginId: "openapi",
|
|
@@ -388,11 +362,10 @@ function EditOpenApiSource(props) {
|
|
|
388
362
|
}
|
|
389
363
|
const setBindingExit = await doSetBinding({
|
|
390
364
|
params: { scopeId: displayScope },
|
|
391
|
-
payload:
|
|
392
|
-
|
|
393
|
-
sourceScope,
|
|
365
|
+
payload: SetSourceCredentialBindingInput.make({
|
|
366
|
+
source: { id: props.sourceId, scope: sourceScope },
|
|
394
367
|
scope: targetScope,
|
|
395
|
-
|
|
368
|
+
slotKey: oauth2.connectionSlot,
|
|
396
369
|
value: {
|
|
397
370
|
kind: "connection",
|
|
398
371
|
connectionId: ConnectionId.make(response2.completedConnection.connectionId)
|
|
@@ -426,7 +399,9 @@ function EditOpenApiSource(props) {
|
|
|
426
399
|
tokenEndpoint: tokenUrl,
|
|
427
400
|
issuerUrl,
|
|
428
401
|
clientIdSecretId,
|
|
402
|
+
clientIdSecretScopeId: String(clientIdSecretScopeId),
|
|
429
403
|
clientSecretSecretId: clientSecretBinding && isSecretCredentialBindingValue(clientSecretBinding.value) ? clientSecretBinding.value.secretId : null,
|
|
404
|
+
clientSecretSecretScopeId: clientSecretSecretScopeId ? String(clientSecretSecretScopeId) : null,
|
|
430
405
|
scopes: [...oauth2.scopes]
|
|
431
406
|
},
|
|
432
407
|
pluginId: "openapi",
|
|
@@ -451,11 +426,10 @@ function EditOpenApiSource(props) {
|
|
|
451
426
|
onSuccess: async (result) => {
|
|
452
427
|
const setBindingExit = await doSetBinding({
|
|
453
428
|
params: { scopeId: displayScope },
|
|
454
|
-
payload:
|
|
455
|
-
|
|
456
|
-
sourceScope,
|
|
429
|
+
payload: SetSourceCredentialBindingInput.make({
|
|
430
|
+
source: { id: props.sourceId, scope: sourceScope },
|
|
457
431
|
scope: targetScope,
|
|
458
|
-
|
|
432
|
+
slotKey: oauth2.connectionSlot,
|
|
459
433
|
value: {
|
|
460
434
|
kind: "connection",
|
|
461
435
|
connectionId: ConnectionId.make(result.connectionId)
|
|
@@ -497,23 +471,28 @@ function EditOpenApiSource(props) {
|
|
|
497
471
|
}
|
|
498
472
|
),
|
|
499
473
|
/* @__PURE__ */ jsx(CardStack, { children: /* @__PURE__ */ jsxs(CardStackContent, { className: "border-t-0", children: [
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
474
|
+
nonOAuthSecretSlots.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
475
|
+
/* @__PURE__ */ jsx(CardStackEntry, { children: /* @__PURE__ */ jsxs(CardStackEntryContent, { children: [
|
|
476
|
+
/* @__PURE__ */ jsx(CardStackEntryTitle, { children: "Request credentials" }),
|
|
477
|
+
/* @__PURE__ */ jsx(CardStackEntryDescription, { children: "Headers and query parameters sent with every API request." })
|
|
478
|
+
] }) }),
|
|
479
|
+
/* @__PURE__ */ jsx(
|
|
480
|
+
SecretCredentialSlotBindings,
|
|
481
|
+
{
|
|
482
|
+
slots: nonOAuthSecretSlots,
|
|
483
|
+
bindingScopes: secretBindingScopes,
|
|
484
|
+
bindingRows,
|
|
485
|
+
scopeRanks,
|
|
486
|
+
secrets: secretList,
|
|
487
|
+
sourceId: props.sourceId,
|
|
488
|
+
sourceName: source.name,
|
|
489
|
+
credentialScopeOptions,
|
|
490
|
+
busyKey: sourceBindingWriter.busyKey,
|
|
491
|
+
onSetSecretBinding: sourceBindingWriter.setSecretBinding,
|
|
492
|
+
onClearBinding: sourceBindingWriter.clearBinding
|
|
493
|
+
}
|
|
494
|
+
)
|
|
495
|
+
] }),
|
|
517
496
|
source.config.oauth2 && (() => {
|
|
518
497
|
const oauth2 = source.config.oauth2;
|
|
519
498
|
const trimmedAuthUrl = oauth2AuthorizationUrl.trim();
|
|
@@ -529,22 +508,27 @@ function EditOpenApiSource(props) {
|
|
|
529
508
|
const seq = ++oauth2EndpointsSaveSeq.current;
|
|
530
509
|
setOAuth2EndpointsSaveState("saving");
|
|
531
510
|
setError(null);
|
|
532
|
-
const exit = await
|
|
533
|
-
params: { scopeId: displayScope
|
|
511
|
+
const exit = await doConfigure({
|
|
512
|
+
params: { scopeId: displayScope },
|
|
534
513
|
payload: {
|
|
535
|
-
sourceScope,
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
514
|
+
source: { id: props.sourceId, scope: sourceScope },
|
|
515
|
+
scope: sourceScope,
|
|
516
|
+
type: "openapi",
|
|
517
|
+
config: {
|
|
518
|
+
scope: sourceScope,
|
|
519
|
+
oauth2Source: OAuth2SourceConfig.make({
|
|
520
|
+
kind: "oauth2",
|
|
521
|
+
securitySchemeName: oauth2.securitySchemeName,
|
|
522
|
+
flow: oauth2.flow,
|
|
523
|
+
tokenUrl: trimmedTokenUrl,
|
|
524
|
+
authorizationUrl: isAuthCode ? trimmedAuthUrl || null : null,
|
|
525
|
+
issuerUrl: oauth2.issuerUrl ?? null,
|
|
526
|
+
clientIdSlot: oauth2.clientIdSlot,
|
|
527
|
+
clientSecretSlot: oauth2.clientSecretSlot,
|
|
528
|
+
connectionSlot: oauth2.connectionSlot,
|
|
529
|
+
scopes: [...oauth2.scopes]
|
|
530
|
+
})
|
|
531
|
+
}
|
|
548
532
|
},
|
|
549
533
|
reactivityKeys: openApiWriteKeys
|
|
550
534
|
});
|
|
@@ -580,78 +564,203 @@ function EditOpenApiSource(props) {
|
|
|
580
564
|
const isConnected = connection !== null && connection !== void 0;
|
|
581
565
|
const statusText = isConnecting || isPendingOAuthConnection ? "Saving OAuth connection..." : connectionBinding && bindingScopeId ? connection ? bindingScopeId === activeOAuthTokenScopeId ? `Connected in ${activeOAuthTokenScopeLabel.toLowerCase()} as ${connection.identityLabel ?? connection.id}` : `Using organization connection ${connection.identityLabel ?? connection.id}` : bindingScopeId === activeOAuthTokenScopeId ? `Saved connection is missing in ${activeOAuthTokenScopeLabel.toLowerCase()}` : "Organization connection is missing" : `No ${activeOAuthTokenScopeLabel.toLowerCase()} connection`;
|
|
582
566
|
const connectDisabled = isConnecting || endpointsDirty || saving;
|
|
567
|
+
const clientSecretSlot = effectiveClientSecretSlot(oauth2);
|
|
568
|
+
const renderAppSecret = (input) => {
|
|
569
|
+
const activeScope = credentialScopes.find((entry) => entry.scopeId === input.scopeId) ?? organizationCredentialScope;
|
|
570
|
+
const exactSecret = exactCredentialBindingForScope(
|
|
571
|
+
bindingRows,
|
|
572
|
+
input.slot,
|
|
573
|
+
activeScope.scopeId
|
|
574
|
+
);
|
|
575
|
+
const effectiveSecret = effectiveCredentialBindingForScope(
|
|
576
|
+
bindingRows,
|
|
577
|
+
input.slot,
|
|
578
|
+
activeScope.scopeId,
|
|
579
|
+
scopeRanks
|
|
580
|
+
);
|
|
581
|
+
const exactSecretId = exactSecret && isSecretCredentialBindingValue(exactSecret.value) ? exactSecret.value.secretId : null;
|
|
582
|
+
const inheritedSecret = !exactSecretId && effectiveSecret && effectiveSecret.scopeId !== activeScope.scopeId && isSecretCredentialBindingValue(effectiveSecret.value) ? effectiveSecret : null;
|
|
583
|
+
const status = exactSecretId ? `${activeScope.label} credential set` : inheritedSecret ? "Using organization credential" : "Not set";
|
|
584
|
+
const inputKey = `${activeScope.scopeId}:${input.slot}`;
|
|
585
|
+
const clearKey = `${activeScope.scopeId}:${input.slot}:clear`;
|
|
586
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
587
|
+
/* @__PURE__ */ jsxs(FieldLabel, { className: "text-[11px]", children: [
|
|
588
|
+
input.label,
|
|
589
|
+
" ",
|
|
590
|
+
input.hint && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
591
|
+
"\xB7 ",
|
|
592
|
+
input.hint
|
|
593
|
+
] })
|
|
594
|
+
] }),
|
|
595
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
|
|
596
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
597
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
598
|
+
/* @__PURE__ */ jsx(FieldLabel, { className: "text-[11px]", children: "Secret" }),
|
|
599
|
+
/* @__PURE__ */ jsxs(HelpTooltip, { label: `${input.label} secret`, children: [
|
|
600
|
+
"Select or create the OAuth ",
|
|
601
|
+
input.label.toLowerCase(),
|
|
602
|
+
" secret."
|
|
603
|
+
] }),
|
|
604
|
+
/* @__PURE__ */ jsx("span", { className: "ml-auto truncate text-xs text-muted-foreground", children: status })
|
|
605
|
+
] }),
|
|
606
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
607
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
|
|
608
|
+
CreatableSecretPicker,
|
|
609
|
+
{
|
|
610
|
+
value: exactSecretId,
|
|
611
|
+
onSelect: (secretId, secretScopeId) => void sourceBindingWriter.setSecretBinding(
|
|
612
|
+
activeScope.scopeId,
|
|
613
|
+
input.slot,
|
|
614
|
+
secretId,
|
|
615
|
+
secretScopeId ?? activeScope.scopeId
|
|
616
|
+
),
|
|
617
|
+
secrets: secretList,
|
|
618
|
+
placeholder: "Select or create a secret",
|
|
619
|
+
targetScope: activeScope.scopeId,
|
|
620
|
+
credentialScopeOptions,
|
|
621
|
+
suggestedId: `source-binding-${slugify(props.sourceId)}-${slugify(
|
|
622
|
+
input.slot
|
|
623
|
+
)}-${slugify(activeScope.scopeId)}`,
|
|
624
|
+
sourceName: source.name,
|
|
625
|
+
secretLabel: input.label
|
|
626
|
+
}
|
|
627
|
+
) }),
|
|
628
|
+
exactSecretId && /* @__PURE__ */ jsx(
|
|
629
|
+
Button,
|
|
630
|
+
{
|
|
631
|
+
variant: "outline",
|
|
632
|
+
size: "sm",
|
|
633
|
+
onClick: () => void sourceBindingWriter.clearBinding(
|
|
634
|
+
activeScope.scopeId,
|
|
635
|
+
input.slot
|
|
636
|
+
),
|
|
637
|
+
disabled: sourceBindingWriter.busyKey === clearKey,
|
|
638
|
+
children: "Clear"
|
|
639
|
+
}
|
|
640
|
+
),
|
|
641
|
+
sourceBindingWriter.busyKey === inputKey && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Saving\u2026" })
|
|
642
|
+
] })
|
|
643
|
+
] }),
|
|
644
|
+
/* @__PURE__ */ jsx(
|
|
645
|
+
CredentialScopeDropdown,
|
|
646
|
+
{
|
|
647
|
+
value: activeScope.scopeId,
|
|
648
|
+
options: credentialScopeOptions,
|
|
649
|
+
onChange: input.onScopeChange,
|
|
650
|
+
label: "Used by",
|
|
651
|
+
help: `Choose where this OAuth ${input.label.toLowerCase()} credential lives.`
|
|
652
|
+
}
|
|
653
|
+
)
|
|
654
|
+
] })
|
|
655
|
+
] });
|
|
656
|
+
};
|
|
583
657
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
658
|
+
/* @__PURE__ */ jsx(CardStackEntry, { children: /* @__PURE__ */ jsxs(CardStackEntryContent, { children: [
|
|
659
|
+
/* @__PURE__ */ jsx(CardStackEntryTitle, { children: "OAuth" }),
|
|
660
|
+
/* @__PURE__ */ jsx(CardStackEntryDescription, { children: "Configure app credentials and connect accounts for this source." })
|
|
661
|
+
] }) }),
|
|
662
|
+
/* @__PURE__ */ jsx(CardStackEntryField, { label: "OAuth app credentials", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4 rounded-lg border border-border/60 bg-muted/10 p-3", children: [
|
|
663
|
+
renderAppSecret({
|
|
664
|
+
slot: oauth2.clientIdSlot,
|
|
665
|
+
label: "Client ID",
|
|
666
|
+
scopeId: ScopeId.make(selectedOAuthClientIdScope),
|
|
667
|
+
onScopeChange: setSelectedOAuthClientIdScope
|
|
668
|
+
}),
|
|
669
|
+
renderAppSecret({
|
|
670
|
+
slot: clientSecretSlot,
|
|
671
|
+
label: "Client secret",
|
|
672
|
+
hint: oauth2.flow === "authorizationCode" ? "Optional for public clients with PKCE" : void 0,
|
|
673
|
+
scopeId: ScopeId.make(selectedOAuthClientSecretScope),
|
|
674
|
+
onScopeChange: setSelectedOAuthClientSecretScope
|
|
675
|
+
})
|
|
676
|
+
] }) }),
|
|
677
|
+
/* @__PURE__ */ jsx(CardStackEntryField, { label: "Account connection", children: /* @__PURE__ */ jsx(
|
|
678
|
+
CredentialUsageRow,
|
|
679
|
+
{
|
|
680
|
+
value: activeOAuthTokenScopeId,
|
|
681
|
+
options: credentialScopeOptions,
|
|
682
|
+
onChange: setSelectedOAuthTokenScope,
|
|
683
|
+
label: "Connection saved to",
|
|
684
|
+
help: "Choose where the signed-in OAuth token is saved.",
|
|
685
|
+
children: /* @__PURE__ */ jsxs(
|
|
686
|
+
CredentialControlField,
|
|
687
|
+
{
|
|
688
|
+
label: "OAuth connection",
|
|
689
|
+
help: "Start the provider OAuth flow.",
|
|
690
|
+
children: [
|
|
691
|
+
/* @__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: [
|
|
692
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-xs text-muted-foreground", children: statusText }),
|
|
693
|
+
/* @__PURE__ */ jsx(
|
|
694
|
+
Button,
|
|
695
|
+
{
|
|
696
|
+
size: "sm",
|
|
697
|
+
onClick: () => void connectOAuth(activeOAuthTokenScopeId),
|
|
698
|
+
disabled: connectDisabled,
|
|
699
|
+
children: isConnecting ? "Connecting\u2026" : isConnected ? "Reconnect" : "Connect"
|
|
700
|
+
}
|
|
701
|
+
)
|
|
702
|
+
] }),
|
|
703
|
+
endpointsDirty && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Save endpoint changes before reconnecting." })
|
|
704
|
+
]
|
|
705
|
+
}
|
|
706
|
+
)
|
|
707
|
+
}
|
|
708
|
+
) }),
|
|
584
709
|
/* @__PURE__ */ jsxs(CardStackEntry, { children: [
|
|
585
710
|
/* @__PURE__ */ jsxs(CardStackEntryContent, { children: [
|
|
586
|
-
/* @__PURE__ */ jsx(CardStackEntryTitle, { children: "
|
|
587
|
-
/* @__PURE__ */ jsx(CardStackEntryDescription, { children: "Override
|
|
711
|
+
/* @__PURE__ */ jsx(CardStackEntryTitle, { children: "Advanced endpoints" }),
|
|
712
|
+
/* @__PURE__ */ jsx(CardStackEntryDescription, { children: "Override provider URLs only when the OpenAPI spec is wrong." })
|
|
588
713
|
] }),
|
|
589
714
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
590
715
|
oauth2EndpointsSaveState !== "idle" && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: saving ? "Saving\u2026" : "Saved" }),
|
|
591
716
|
/* @__PURE__ */ jsx(
|
|
592
717
|
Button,
|
|
593
718
|
{
|
|
719
|
+
variant: "outline",
|
|
594
720
|
size: "sm",
|
|
595
|
-
onClick: () =>
|
|
596
|
-
|
|
597
|
-
children: "Save"
|
|
721
|
+
onClick: () => setOAuthEndpointsOpen((open) => !open),
|
|
722
|
+
children: oauthEndpointsOpen ? "Hide" : endpointsDirty ? "Review" : "Show"
|
|
598
723
|
}
|
|
599
724
|
)
|
|
600
725
|
] })
|
|
601
726
|
] }),
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
value: oauth2AuthorizationUrl,
|
|
606
|
-
onChange: (e) => setOAuth2AuthorizationUrl(e.target.value),
|
|
607
|
-
className: "font-mono text-sm"
|
|
608
|
-
}
|
|
609
|
-
) }),
|
|
610
|
-
/* @__PURE__ */ jsx(CardStackEntryField, { label: "Token URL", children: /* @__PURE__ */ jsx(
|
|
611
|
-
Input,
|
|
612
|
-
{
|
|
613
|
-
value: oauth2TokenUrl,
|
|
614
|
-
onChange: (e) => setOAuth2TokenUrl(e.target.value),
|
|
615
|
-
className: "font-mono text-sm"
|
|
616
|
-
}
|
|
617
|
-
) }),
|
|
618
|
-
/* @__PURE__ */ jsx(CardStackEntryField, { label: "Redirect URL", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
619
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 rounded-md border border-border bg-background/50 px-2.5 py-1.5 font-mono text-[11px]", children: [
|
|
620
|
-
/* @__PURE__ */ jsx("span", { className: "truncate flex-1 text-foreground", children: oauth2RedirectUrl }),
|
|
621
|
-
/* @__PURE__ */ jsx(CopyButton, { value: oauth2RedirectUrl })
|
|
622
|
-
] }),
|
|
623
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Add this to your OAuth app's allowed redirects." })
|
|
624
|
-
] }) }),
|
|
625
|
-
credentialScopes.length > 1 && /* @__PURE__ */ jsxs(CardStackEntry, { children: [
|
|
626
|
-
/* @__PURE__ */ jsxs(CardStackEntryContent, { children: [
|
|
627
|
-
/* @__PURE__ */ jsx(CardStackEntryTitle, { children: "OAuth token" }),
|
|
628
|
-
/* @__PURE__ */ jsx(CardStackEntryDescription, { children: "Choose where the signed-in OAuth token is saved." })
|
|
629
|
-
] }),
|
|
630
|
-
/* @__PURE__ */ jsx(
|
|
631
|
-
FilterTabs,
|
|
727
|
+
oauthEndpointsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
728
|
+
isAuthCode && /* @__PURE__ */ jsx(CardStackEntryField, { label: "Authorization URL", children: /* @__PURE__ */ jsx(
|
|
729
|
+
Input,
|
|
632
730
|
{
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
})),
|
|
637
|
-
value: activeOAuthTokenScopeId,
|
|
638
|
-
onChange: setSelectedOAuthTokenScope
|
|
731
|
+
value: oauth2AuthorizationUrl,
|
|
732
|
+
onChange: (e) => setOAuth2AuthorizationUrl(e.target.value),
|
|
733
|
+
className: "font-mono text-sm"
|
|
639
734
|
}
|
|
640
|
-
)
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: statusText }),
|
|
644
|
-
/* @__PURE__ */ jsx(
|
|
645
|
-
Button,
|
|
735
|
+
) }),
|
|
736
|
+
/* @__PURE__ */ jsx(CardStackEntryField, { label: "Token URL", children: /* @__PURE__ */ jsx(
|
|
737
|
+
Input,
|
|
646
738
|
{
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
children: isConnecting ? "Connecting\u2026" : isConnected ? "Reconnect" : "Connect"
|
|
739
|
+
value: oauth2TokenUrl,
|
|
740
|
+
onChange: (e) => setOAuth2TokenUrl(e.target.value),
|
|
741
|
+
className: "font-mono text-sm"
|
|
651
742
|
}
|
|
652
|
-
),
|
|
653
|
-
|
|
654
|
-
|
|
743
|
+
) }),
|
|
744
|
+
/* @__PURE__ */ jsx(CardStackEntryField, { label: "Redirect URL", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
745
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 rounded-md border border-border bg-background/50 px-2.5 py-1.5 font-mono text-[11px]", children: [
|
|
746
|
+
/* @__PURE__ */ jsx("span", { className: "truncate flex-1 text-foreground", children: oauth2RedirectUrl }),
|
|
747
|
+
/* @__PURE__ */ jsx(CopyButton, { value: oauth2RedirectUrl })
|
|
748
|
+
] }),
|
|
749
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Add this to your OAuth app's allowed redirects." })
|
|
750
|
+
] }) }),
|
|
751
|
+
/* @__PURE__ */ jsxs(CardStackEntry, { children: [
|
|
752
|
+
/* @__PURE__ */ jsx(CardStackEntryContent, { children: /* @__PURE__ */ jsx(CardStackEntryDescription, { children: "Save endpoint changes before reconnecting." }) }),
|
|
753
|
+
/* @__PURE__ */ jsx(
|
|
754
|
+
Button,
|
|
755
|
+
{
|
|
756
|
+
size: "sm",
|
|
757
|
+
onClick: () => void saveOAuth2Endpoints(),
|
|
758
|
+
disabled: !canSave,
|
|
759
|
+
children: "Save endpoints"
|
|
760
|
+
}
|
|
761
|
+
)
|
|
762
|
+
] })
|
|
763
|
+
] })
|
|
655
764
|
] });
|
|
656
765
|
})()
|
|
657
766
|
] }) }),
|
|
@@ -662,4 +771,4 @@ function EditOpenApiSource(props) {
|
|
|
662
771
|
export {
|
|
663
772
|
EditOpenApiSource as default
|
|
664
773
|
};
|
|
665
|
-
//# sourceMappingURL=EditOpenApiSource-
|
|
774
|
+
//# sourceMappingURL=EditOpenApiSource-AOA7APR2.js.map
|