@executor-js/plugin-openapi 1.5.20 → 1.5.21
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-IBZQRCTW.js → AddOpenApiSource-SSXZBQEK.js} +3 -3
- package/dist/{AddOpenApiSource-IBZQRCTW.js.map → AddOpenApiSource-SSXZBQEK.js.map} +1 -1
- package/dist/{chunk-ELCKZJE4.js → chunk-3O3PGRRG.js} +2 -2
- package/dist/{chunk-5IDND4UF.js → chunk-MWF55JPY.js} +34 -11
- package/dist/chunk-MWF55JPY.js.map +1 -0
- package/dist/client.js +1 -1
- package/dist/core.js +2 -2
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-5IDND4UF.js.map +0 -1
- /package/dist/{chunk-ELCKZJE4.js.map → chunk-3O3PGRRG.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectedAuthenticationTemplates
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MWF55JPY.js";
|
|
4
4
|
import {
|
|
5
5
|
openApiPresets
|
|
6
6
|
} from "./chunk-QQFCICLX.js";
|
|
@@ -117,7 +117,7 @@ function OpenApiSourceDetailsFields(props) {
|
|
|
117
117
|
className: "font-mono text-sm"
|
|
118
118
|
}
|
|
119
119
|
),
|
|
120
|
-
props.baseUrlMissingMessage && !props.baseUrl && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-
|
|
120
|
+
props.baseUrlMissingMessage && !props.baseUrl && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: props.baseUrlMissingMessage }),
|
|
121
121
|
props.baseUrlHint && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: props.baseUrlHint })
|
|
122
122
|
] }),
|
|
123
123
|
specIsUrl && props.onSpecUrlChange && /* @__PURE__ */ jsx(CardStackEntryField, { label: "Spec URL", children: /* @__PURE__ */ jsx(
|
|
@@ -366,4 +366,4 @@ function AddOpenApiSource(props) {
|
|
|
366
366
|
export {
|
|
367
367
|
AddOpenApiSource as default
|
|
368
368
|
};
|
|
369
|
-
//# sourceMappingURL=AddOpenApiSource-
|
|
369
|
+
//# sourceMappingURL=AddOpenApiSource-SSXZBQEK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/AddOpenApiSource.tsx","../src/react/OpenApiSourceDetailsFields.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAtomSet } from \"@effect/atom-react\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Option from \"effect/Option\";\n\nimport { IntegrationSlug } from \"@executor-js/sdk/shared\";\nimport { integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport {\n slugifyNamespace,\n useIntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n AuthMethodListEditor,\n useAuthMethodList,\n type AuthMethodRow,\n type AuthMethodSeed,\n} from \"@executor-js/react/components/auth-method-list-editor\";\nimport { CardStack, CardStackContent } from \"@executor-js/react/components/card-stack\";\nimport { FieldLabel } from \"@executor-js/react/components/field\";\nimport { FloatActions } from \"@executor-js/react/components/float-actions\";\nimport { Textarea } from \"@executor-js/react/components/textarea\";\nimport { IOSSpinner, Spinner } from \"@executor-js/react/components/spinner\";\nimport {\n addIntegrationErrorMessage,\n errorMessageFromExit,\n FormErrorAlert,\n SlugCollisionAlert,\n useSlugAlreadyExists,\n} from \"@executor-js/react/lib/integration-add\";\n\nimport {\n authenticationFromEditorValue,\n editorValueFromAuthentication,\n openApiWireAuthInput,\n} from \"./auth-method-config\";\nimport { addOpenApiSpec, previewOpenApiSpec } from \"./atoms\";\nimport { OpenApiSourceDetailsFields } from \"./OpenApiSourceDetailsFields\";\nimport { openApiPresets } from \"../sdk/presets\";\nimport type { SpecPreviewSummary } from \"../sdk/preview\";\nimport { type Authentication } from \"../sdk/types\";\nimport { resolveServerUrl } from \"../sdk/openapi-utils\";\nimport { detectedAuthenticationTemplates } from \"../sdk/derive-auth\";\n\nconst normalizePresetUrl = (url: string): string => {\n const trimmed = url.trim();\n if (!URL.canParse(trimmed)) return trimmed.replace(/\\/$/, \"\");\n const parsed = new URL(trimmed);\n parsed.hash = \"\";\n parsed.searchParams.sort();\n return parsed.toString().replace(/\\/$/, \"\");\n};\n\nconst specInputForAdd = (input: string) => {\n const value = input.trim();\n const parsed = Effect.runSyncExit(\n Effect.try({\n try: () => new URL(value),\n catch: () => null,\n }),\n );\n return Exit.isSuccess(parsed)\n ? { kind: \"url\" as const, url: value }\n : { kind: \"blob\" as const, value };\n};\n\n// ---------------------------------------------------------------------------\n// Component: single progressive form. Post-redesign: preview -> addSpec\n// (register the integration catalog entry with ALL detected auth methods) →\n// route to the integration's detail hub, where the user adds accounts. The add\n// flow no longer creates a connection.\n// ---------------------------------------------------------------------------\n\nexport default function AddOpenApiSource(props: {\n onComplete: (slug?: string) => void;\n onCancel: () => void;\n initialUrl?: string;\n initialPreset?: string;\n initialNamespace?: string;\n}) {\n const [specUrl, setSpecUrl] = useState(props.initialUrl ?? \"\");\n const [analyzing, setAnalyzing] = useState(false);\n const [analyzeError, setAnalyzeError] = useState<string | null>(null);\n\n // After analysis\n const [preview, setPreview] = useState<SpecPreviewSummary | null>(null);\n const [baseUrl, setBaseUrl] = useState(\"\");\n // Agent-visible description: prefilled from the spec's `info.description`\n // until the user types (null = untouched, keep deriving from the preview).\n const [descriptionDraft, setDescriptionDraft] = useState<string | null>(null);\n const identityFallbackName = preview ? Option.getOrElse(preview.title, () => \"\") : \"\";\n const identity = useIntegrationIdentity({\n fallbackName: identityFallbackName,\n fallbackNamespace: props.initialNamespace,\n });\n\n // Submit\n const [adding, setAdding] = useState(false);\n const [addError, setAddError] = useState<string | null>(null);\n\n const doPreview = useAtomSet(previewOpenApiSpec, { mode: \"promiseExit\" });\n const doAdd = useAtomSet(addOpenApiSpec, { mode: \"promiseExit\" });\n\n // Keep the latest handleAnalyze in a ref so the debounced effect doesn't need\n // it as a dependency (it closes over fresh state).\n const handleAnalyzeRef = useRef<() => void>(() => {});\n\n useEffect(() => {\n const trimmed = specUrl.trim();\n if (!trimmed) return;\n if (preview) return;\n const handle = setTimeout(() => {\n handleAnalyzeRef.current();\n }, 400);\n return () => clearTimeout(handle);\n }, [specUrl, preview]);\n\n // ---- Derived state ----\n\n const previewHasNoServers = preview !== null && preview.servers.length === 0;\n // Offer the spec's servers (resolved with defaults) as base-URL choices when\n // there's more than one; a single/no server uses a plain input.\n const baseUrlOptions =\n preview && preview.servers.length > 1\n ? preview.servers.map((server) => {\n const url = resolveServerUrl(server.url, Option.getOrUndefined(server.variables), {});\n return { value: url, label: url };\n })\n : undefined;\n const firstServer = preview?.servers[0];\n const firstServerUrl = firstServer\n ? resolveServerUrl(firstServer.url, Option.getOrUndefined(firstServer.variables), {})\n : \"\";\n const previewPresetIcon =\n openApiPresets.find(\n (preset) => preset.url && normalizePresetUrl(preset.url) === normalizePresetUrl(specUrl),\n )?.icon ?? null;\n\n const resolvedBaseUrl = baseUrl.trim();\n const resolvedSourceId =\n slugifyNamespace(identity.namespace) ||\n (preview ? Option.getOrElse(preview.title, () => \"openapi\") : \"openapi\");\n const resolvedDisplayName =\n identity.name.trim() ||\n (preview ? Option.getOrElse(preview.title, () => resolvedSourceId) : resolvedSourceId);\n const resolvedDescription =\n descriptionDraft ?? (preview ? Option.getOrElse(preview.description, () => \"\") : \"\");\n\n // Register EVERY spec-detected auth method, not just a single selected one.\n // Keyed off `preview` (stable per analysis) so the memo doesn't re-run on the\n // freshly-allocated `?? []` fallback arrays.\n const authenticationTemplate: readonly Authentication[] = useMemo(\n () =>\n detectedAuthenticationTemplates(\n preview?.headerPresets ?? [],\n preview?.oauth2Presets ?? [],\n resolvedBaseUrl,\n ),\n [preview, resolvedBaseUrl],\n );\n\n // Editable auth methods, seeded from the spec-detected templates. The add flow\n // registers EVERY method (P6), so this is a LIST, preserving multi-method\n // specs (e.g. apiKey + OAuth). Each seed carries the detected template's\n // original slug, so an unedited detected method submits with its EXACT\n // original slug (preserving behavior); added methods (no seed) get a\n // deterministic fresh slug. Re-seeded whenever a fresh detection arrives\n // (keyed on the detected templates, stable per analysis + base URL).\n const authMethodSeeds: readonly AuthMethodSeed[] = useMemo(() => {\n const labels = [\n ...(preview?.headerPresets ?? []).map((preset) => preset.label),\n ...(preview?.oauth2Presets ?? []).map((preset) => preset.label),\n ];\n return authenticationTemplate.map(\n (template: Authentication, index: number): AuthMethodSeed => ({\n value: editorValueFromAuthentication(template),\n slug: String(template.slug),\n ...(labels[index] !== undefined ? { label: labels[index] } : {}),\n }),\n );\n }, [preview, authenticationTemplate]);\n const authMethodList = useAuthMethodList(authMethodSeeds);\n\n // The methods to register, mapped back to stored `Authentication[]`. Drops\n // `none` rows (nothing to register). An unedited detected method keeps its\n // original `seedSlug`; an added method gets a deterministic fresh slug.\n const editedAuthenticationTemplate: readonly Authentication[] = useMemo(() => {\n const templates: Authentication[] = [];\n authMethodList.rows.forEach((row: AuthMethodRow, index: number) => {\n const slug =\n row.seedSlug ?? (row.value.kind === \"oauth\" ? `oauth-${index}` : `apikey-${index}`);\n const template = authenticationFromEditorValue(row.value, slug);\n if (template !== null) templates.push(template);\n });\n return templates;\n }, [authMethodList.rows]);\n\n // Pre-empt the API's `IntegrationAlreadyExistsError`: adding an integration\n // whose slug already exists clobbers the existing one's connections/policies,\n // so the API blocks it. Surface that here from the tenant-scoped catalog list.\n const slugAlreadyExists = useSlugAlreadyExists(resolvedSourceId);\n\n // The base URL is optional when the spec declares servers (resolved per call);\n // required only when it doesn't.\n const canAdd =\n preview !== null && !slugAlreadyExists && (!previewHasNoServers || resolvedBaseUrl.length > 0);\n\n // ---- Handlers ----\n\n const handleAnalyze = async () => {\n setAnalyzing(true);\n setAnalyzeError(null);\n setAddError(null);\n const exit = await doPreview({ payload: { spec: specUrl } });\n if (Exit.isFailure(exit)) {\n setAnalyzeError(errorMessageFromExit(exit, \"Failed to parse spec\"));\n setAnalyzing(false);\n return;\n }\n const result = exit.value;\n setPreview(result);\n setBaseUrl(\"\");\n setAnalyzing(false);\n };\n\n handleAnalyzeRef.current = handleAnalyze;\n\n // Persist the integration and return its slug. Registers the catalog entry\n // with every detected auth method. Adding a slug that already exists is\n // rejected by the API (`IntegrationAlreadyExistsError`), surfaced inline.\n const ensureIntegration = useCallback(async (): Promise<IntegrationSlug | null> => {\n const exit = await doAdd({\n payload: {\n spec: specInputForAdd(specUrl),\n slug: resolvedSourceId,\n name: resolvedDisplayName,\n ...(resolvedDescription.trim().length > 0\n ? { description: resolvedDescription.trim() }\n : {}),\n baseUrl: resolvedBaseUrl,\n // Always send the edited method list (even empty) when the user has\n // inspected a preview: an explicit [] means \"no auth methods\", while\n // OMITTING the field tells the server to derive defaults from the\n // spec, which would silently resurrect methods the user deleted.\n // Serialize to the wire input dialect (apikey -> request-shaped).\n authenticationTemplate: editedAuthenticationTemplate.map(openApiWireAuthInput),\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setAddError(addIntegrationErrorMessage(exit, resolvedSourceId, \"Failed to add integration\"));\n return null;\n }\n return exit.value.slug;\n }, [\n specUrl,\n doAdd,\n resolvedSourceId,\n resolvedDisplayName,\n resolvedDescription,\n resolvedBaseUrl,\n editedAuthenticationTemplate,\n ]);\n\n const handleAdd = async () => {\n setAdding(true);\n setAddError(null);\n\n const integration = await ensureIntegration();\n if (!integration) {\n setAdding(false);\n return;\n }\n\n props.onComplete(String(integration));\n };\n\n // ---- Render ----\n\n return (\n <div className=\"flex flex-1 flex-col gap-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Add OpenAPI Integration</h1>\n </div>\n\n {!preview ? (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <div className=\"space-y-2 p-3\">\n <FieldLabel>OpenAPI Spec</FieldLabel>\n <div className=\"relative\">\n <Textarea\n value={specUrl}\n onChange={(e) => setSpecUrl((e.target as HTMLTextAreaElement).value)}\n placeholder=\"https://api.example.com/openapi.json\"\n rows={3}\n maxRows={10}\n className=\"font-mono text-sm\"\n />\n {analyzing && (\n <div className=\"pointer-events-none absolute right-2 top-2\">\n <IOSSpinner className=\"size-4\" />\n </div>\n )}\n </div>\n <p className=\"text-[11px] text-muted-foreground\">\n Paste a URL or raw JSON/YAML content.\n </p>\n </div>\n </CardStackContent>\n </CardStack>\n ) : null}\n\n {preview ? (\n <OpenApiSourceDetailsFields\n title={Option.getOrElse(preview.title, () => \"API\")}\n subtitle={`${Option.getOrElse(preview.version, () => \"\")}${\n Option.isSome(preview.version) ? \" · \" : \"\"\n }${preview.operationCount} operation${preview.operationCount !== 1 ? \"s\" : \"\"}${\n preview.tags.length > 0\n ? ` · ${preview.tags.length} tag${preview.tags.length !== 1 ? \"s\" : \"\"}`\n : \"\"\n }`}\n identity={identity}\n description={resolvedDescription}\n onDescriptionChange={setDescriptionDraft}\n baseUrl={resolvedBaseUrl}\n onBaseUrlChange={setBaseUrl}\n baseUrlOptions={baseUrlOptions}\n baseUrlLabel={previewHasNoServers ? \"Base URL\" : \"Base URL override (optional)\"}\n baseUrlPlaceholder={firstServerUrl || \"https://api.example.com\"}\n baseUrlHint={\n previewHasNoServers\n ? undefined\n : \"Overrides the spec's servers; leave empty to choose the server (and variables) per tool call.\"\n }\n baseUrlMissingMessage={\n previewHasNoServers ? \"This spec declares no servers, enter a base URL.\" : undefined\n }\n specUrl={specUrl}\n onSpecUrlChange={(value) => {\n setSpecUrl(value);\n setPreview(null);\n setBaseUrl(\"\");\n }}\n faviconIcon={previewPresetIcon}\n faviconUrl={resolvedBaseUrl || firstServerUrl}\n />\n ) : null}\n\n {analyzeError && <FormErrorAlert message={analyzeError} />}\n\n {preview && (\n <AuthMethodListEditor\n list={authMethodList}\n emptyHint=\"No authentication detected. Add a method, or add the integration without auth and connect an account from the integration page later.\"\n footerHint=\"Every method here is registered with the integration. Connect an account from the integration page after adding.\"\n />\n )}\n\n {preview && slugAlreadyExists && !adding && <SlugCollisionAlert slug={resolvedSourceId} />}\n\n {addError && <FormErrorAlert message={addError} />}\n\n <FloatActions>\n <Button variant=\"ghost\" onClick={() => props.onCancel()} disabled={adding}>\n Cancel\n </Button>\n {preview && (\n <Button onClick={() => void handleAdd()} disabled={!canAdd || adding}>\n {adding && <Spinner className=\"size-3.5\" />}\n {adding ? \"Adding...\" : \"Add integration\"}\n </Button>\n )}\n </FloatActions>\n </div>\n );\n}\n","import {\n CardStack,\n CardStackContent,\n CardStackEntry,\n CardStackEntryContent,\n CardStackEntryDescription,\n CardStackEntryField,\n CardStackEntryTitle,\n} from \"@executor-js/react/components/card-stack\";\nimport {\n FreeformCombobox,\n type FreeformComboboxOption,\n} from \"@executor-js/react/components/combobox\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Textarea } from \"@executor-js/react/components/textarea\";\nimport { IntegrationFavicon } from \"@executor-js/react/components/integration-favicon\";\nimport {\n IntegrationIdentityFieldRows,\n type IntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\n\n/** The spec input is shown as a one-line \"Spec URL\" field only when it IS a\n * URL; pasted document content gets a multi-line editor instead. */\nconst isUrlInput = (value: string): boolean => URL.canParse(value.trim());\n\nexport function OpenApiSourceDetailsFields(props: {\n readonly title: string;\n readonly subtitle?: string;\n readonly identity: IntegrationIdentity;\n /** The integration's agent-visible description (prefilled from the spec). */\n readonly description?: string;\n readonly onDescriptionChange?: (value: string) => void;\n readonly baseUrl: string;\n readonly onBaseUrlChange: (value: string) => void;\n readonly baseUrlOptions?: readonly FreeformComboboxOption[];\n readonly baseUrlLabel?: string;\n readonly baseUrlPlaceholder?: string;\n readonly baseUrlHint?: string;\n readonly specUrl?: string;\n readonly onSpecUrlChange?: (value: string) => void;\n readonly faviconIcon?: string | null;\n readonly faviconUrl?: string;\n readonly namespaceReadOnly?: boolean;\n readonly specUrlDisabled?: boolean;\n readonly saveState?: \"idle\" | \"saving\" | \"saved\";\n readonly baseUrlMissingMessage?: string;\n readonly footer?: string;\n}) {\n const specIsUrl = props.specUrl !== undefined && isUrlInput(props.specUrl);\n\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n {(props.faviconIcon || props.faviconUrl) && (\n <IntegrationFavicon icon={props.faviconIcon} url={props.faviconUrl} size={16} />\n )}\n <CardStackEntryContent>\n <CardStackEntryTitle>{props.title}</CardStackEntryTitle>\n {props.subtitle && (\n <CardStackEntryDescription>{props.subtitle}</CardStackEntryDescription>\n )}\n </CardStackEntryContent>\n {props.saveState && props.saveState !== \"idle\" && (\n <span className=\"text-xs text-muted-foreground\">\n {props.saveState === \"saving\" ? \"Saving…\" : \"Saved\"}\n </span>\n )}\n </CardStackEntry>\n <IntegrationIdentityFieldRows\n identity={props.identity}\n namespaceReadOnly={props.namespaceReadOnly}\n />\n {props.onDescriptionChange && (\n <CardStackEntryField label=\"Description\">\n <Textarea\n value={props.description ?? \"\"}\n onChange={(e) => props.onDescriptionChange?.((e.target as HTMLTextAreaElement).value)}\n placeholder=\"What this API is and when to reach for it\"\n rows={2}\n maxRows={6}\n className=\"text-sm\"\n />\n </CardStackEntryField>\n )}\n <div className=\"grid grid-cols-1 md:grid-cols-2\">\n <CardStackEntryField label={props.baseUrlLabel ?? \"Base URL\"}>\n {props.baseUrlOptions && props.baseUrlOptions.length > 0 ? (\n <FreeformCombobox\n value={props.baseUrl}\n onValueChange={props.onBaseUrlChange}\n options={props.baseUrlOptions}\n placeholder={props.baseUrlPlaceholder ?? \"https://api.example.com\"}\n className=\"w-full\"\n inputClassName=\"font-mono text-sm\"\n />\n ) : (\n <Input\n value={props.baseUrl}\n onChange={(e) => props.onBaseUrlChange((e.target as HTMLInputElement).value)}\n placeholder={props.baseUrlPlaceholder ?? \"https://api.example.com\"}\n className=\"font-mono text-sm\"\n />\n )}\n\n {props.baseUrlMissingMessage && !props.baseUrl && (\n <p className=\"text-[11px] text-amber-600 dark:text-amber-400\">\n {props.baseUrlMissingMessage}\n </p>\n )}\n {props.baseUrlHint && (\n <p className=\"text-[11px] text-muted-foreground\">{props.baseUrlHint}</p>\n )}\n </CardStackEntryField>\n {specIsUrl && props.onSpecUrlChange && (\n <CardStackEntryField label=\"Spec URL\">\n <Input\n value={props.specUrl}\n onChange={(e) => props.onSpecUrlChange?.((e.target as HTMLInputElement).value)}\n placeholder=\"https://api.example.com/openapi.json\"\n className=\"font-mono text-sm\"\n disabled={props.specUrlDisabled}\n />\n </CardStackEntryField>\n )}\n </div>\n {props.specUrl !== undefined && !specIsUrl && props.onSpecUrlChange && (\n <CardStackEntryField label=\"Spec\">\n <Textarea\n value={props.specUrl}\n onChange={(e) => props.onSpecUrlChange?.((e.target as HTMLTextAreaElement).value)}\n placeholder=\"Pasted OpenAPI JSON/YAML\"\n rows={4}\n maxRows={12}\n className=\"font-mono text-xs\"\n disabled={props.specUrlDisabled}\n />\n </CardStackEntryField>\n )}\n {props.footer && (\n <CardStackEntry>\n <CardStackEntryContent>\n <CardStackEntryTitle>{props.footer}</CardStackEntryTitle>\n </CardStackEntryContent>\n </CardStackEntry>\n )}\n </CardStackContent>\n </CardStack>\n );\n}\n"],"mappings":"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","names":["CardStack","CardStackContent","Textarea","jsx","jsxs","CardStack","CardStackContent","Textarea"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/AddOpenApiSource.tsx","../src/react/OpenApiSourceDetailsFields.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAtomSet } from \"@effect/atom-react\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Option from \"effect/Option\";\n\nimport { IntegrationSlug } from \"@executor-js/sdk/shared\";\nimport { integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport {\n slugifyNamespace,\n useIntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n AuthMethodListEditor,\n useAuthMethodList,\n type AuthMethodRow,\n type AuthMethodSeed,\n} from \"@executor-js/react/components/auth-method-list-editor\";\nimport { CardStack, CardStackContent } from \"@executor-js/react/components/card-stack\";\nimport { FieldLabel } from \"@executor-js/react/components/field\";\nimport { FloatActions } from \"@executor-js/react/components/float-actions\";\nimport { Textarea } from \"@executor-js/react/components/textarea\";\nimport { IOSSpinner, Spinner } from \"@executor-js/react/components/spinner\";\nimport {\n addIntegrationErrorMessage,\n errorMessageFromExit,\n FormErrorAlert,\n SlugCollisionAlert,\n useSlugAlreadyExists,\n} from \"@executor-js/react/lib/integration-add\";\n\nimport {\n authenticationFromEditorValue,\n editorValueFromAuthentication,\n openApiWireAuthInput,\n} from \"./auth-method-config\";\nimport { addOpenApiSpec, previewOpenApiSpec } from \"./atoms\";\nimport { OpenApiSourceDetailsFields } from \"./OpenApiSourceDetailsFields\";\nimport { openApiPresets } from \"../sdk/presets\";\nimport type { SpecPreviewSummary } from \"../sdk/preview\";\nimport { type Authentication } from \"../sdk/types\";\nimport { resolveServerUrl } from \"../sdk/openapi-utils\";\nimport { detectedAuthenticationTemplates } from \"../sdk/derive-auth\";\n\nconst normalizePresetUrl = (url: string): string => {\n const trimmed = url.trim();\n if (!URL.canParse(trimmed)) return trimmed.replace(/\\/$/, \"\");\n const parsed = new URL(trimmed);\n parsed.hash = \"\";\n parsed.searchParams.sort();\n return parsed.toString().replace(/\\/$/, \"\");\n};\n\nconst specInputForAdd = (input: string) => {\n const value = input.trim();\n const parsed = Effect.runSyncExit(\n Effect.try({\n try: () => new URL(value),\n catch: () => null,\n }),\n );\n return Exit.isSuccess(parsed)\n ? { kind: \"url\" as const, url: value }\n : { kind: \"blob\" as const, value };\n};\n\n// ---------------------------------------------------------------------------\n// Component: single progressive form. Post-redesign: preview -> addSpec\n// (register the integration catalog entry with ALL detected auth methods) →\n// route to the integration's detail hub, where the user adds accounts. The add\n// flow no longer creates a connection.\n// ---------------------------------------------------------------------------\n\nexport default function AddOpenApiSource(props: {\n onComplete: (slug?: string) => void;\n onCancel: () => void;\n initialUrl?: string;\n initialPreset?: string;\n initialNamespace?: string;\n}) {\n const [specUrl, setSpecUrl] = useState(props.initialUrl ?? \"\");\n const [analyzing, setAnalyzing] = useState(false);\n const [analyzeError, setAnalyzeError] = useState<string | null>(null);\n\n // After analysis\n const [preview, setPreview] = useState<SpecPreviewSummary | null>(null);\n const [baseUrl, setBaseUrl] = useState(\"\");\n // Agent-visible description: prefilled from the spec's `info.description`\n // until the user types (null = untouched, keep deriving from the preview).\n const [descriptionDraft, setDescriptionDraft] = useState<string | null>(null);\n const identityFallbackName = preview ? Option.getOrElse(preview.title, () => \"\") : \"\";\n const identity = useIntegrationIdentity({\n fallbackName: identityFallbackName,\n fallbackNamespace: props.initialNamespace,\n });\n\n // Submit\n const [adding, setAdding] = useState(false);\n const [addError, setAddError] = useState<string | null>(null);\n\n const doPreview = useAtomSet(previewOpenApiSpec, { mode: \"promiseExit\" });\n const doAdd = useAtomSet(addOpenApiSpec, { mode: \"promiseExit\" });\n\n // Keep the latest handleAnalyze in a ref so the debounced effect doesn't need\n // it as a dependency (it closes over fresh state).\n const handleAnalyzeRef = useRef<() => void>(() => {});\n\n useEffect(() => {\n const trimmed = specUrl.trim();\n if (!trimmed) return;\n if (preview) return;\n const handle = setTimeout(() => {\n handleAnalyzeRef.current();\n }, 400);\n return () => clearTimeout(handle);\n }, [specUrl, preview]);\n\n // ---- Derived state ----\n\n const previewHasNoServers = preview !== null && preview.servers.length === 0;\n // Offer the spec's servers (resolved with defaults) as base-URL choices when\n // there's more than one; a single/no server uses a plain input.\n const baseUrlOptions =\n preview && preview.servers.length > 1\n ? preview.servers.map((server) => {\n const url = resolveServerUrl(server.url, Option.getOrUndefined(server.variables), {});\n return { value: url, label: url };\n })\n : undefined;\n const firstServer = preview?.servers[0];\n const firstServerUrl = firstServer\n ? resolveServerUrl(firstServer.url, Option.getOrUndefined(firstServer.variables), {})\n : \"\";\n const previewPresetIcon =\n openApiPresets.find(\n (preset) => preset.url && normalizePresetUrl(preset.url) === normalizePresetUrl(specUrl),\n )?.icon ?? null;\n\n const resolvedBaseUrl = baseUrl.trim();\n const resolvedSourceId =\n slugifyNamespace(identity.namespace) ||\n (preview ? Option.getOrElse(preview.title, () => \"openapi\") : \"openapi\");\n const resolvedDisplayName =\n identity.name.trim() ||\n (preview ? Option.getOrElse(preview.title, () => resolvedSourceId) : resolvedSourceId);\n const resolvedDescription =\n descriptionDraft ?? (preview ? Option.getOrElse(preview.description, () => \"\") : \"\");\n\n // Register EVERY spec-detected auth method, not just a single selected one.\n // Keyed off `preview` (stable per analysis) so the memo doesn't re-run on the\n // freshly-allocated `?? []` fallback arrays.\n const authenticationTemplate: readonly Authentication[] = useMemo(\n () =>\n detectedAuthenticationTemplates(\n preview?.headerPresets ?? [],\n preview?.oauth2Presets ?? [],\n resolvedBaseUrl,\n ),\n [preview, resolvedBaseUrl],\n );\n\n // Editable auth methods, seeded from the spec-detected templates. The add flow\n // registers EVERY method (P6), so this is a LIST, preserving multi-method\n // specs (e.g. apiKey + OAuth). Each seed carries the detected template's\n // original slug, so an unedited detected method submits with its EXACT\n // original slug (preserving behavior); added methods (no seed) get a\n // deterministic fresh slug. Re-seeded whenever a fresh detection arrives\n // (keyed on the detected templates, stable per analysis + base URL).\n const authMethodSeeds: readonly AuthMethodSeed[] = useMemo(() => {\n const labels = [\n ...(preview?.headerPresets ?? []).map((preset) => preset.label),\n ...(preview?.oauth2Presets ?? []).map((preset) => preset.label),\n ];\n return authenticationTemplate.map(\n (template: Authentication, index: number): AuthMethodSeed => ({\n value: editorValueFromAuthentication(template),\n slug: String(template.slug),\n ...(labels[index] !== undefined ? { label: labels[index] } : {}),\n }),\n );\n }, [preview, authenticationTemplate]);\n const authMethodList = useAuthMethodList(authMethodSeeds);\n\n // The methods to register, mapped back to stored `Authentication[]`. Drops\n // `none` rows (nothing to register). An unedited detected method keeps its\n // original `seedSlug`; an added method gets a deterministic fresh slug.\n const editedAuthenticationTemplate: readonly Authentication[] = useMemo(() => {\n const templates: Authentication[] = [];\n authMethodList.rows.forEach((row: AuthMethodRow, index: number) => {\n const slug =\n row.seedSlug ?? (row.value.kind === \"oauth\" ? `oauth-${index}` : `apikey-${index}`);\n const template = authenticationFromEditorValue(row.value, slug);\n if (template !== null) templates.push(template);\n });\n return templates;\n }, [authMethodList.rows]);\n\n // Pre-empt the API's `IntegrationAlreadyExistsError`: adding an integration\n // whose slug already exists clobbers the existing one's connections/policies,\n // so the API blocks it. Surface that here from the tenant-scoped catalog list.\n const slugAlreadyExists = useSlugAlreadyExists(resolvedSourceId);\n\n // The base URL is optional when the spec declares servers (resolved per call);\n // required only when it doesn't.\n const canAdd =\n preview !== null && !slugAlreadyExists && (!previewHasNoServers || resolvedBaseUrl.length > 0);\n\n // ---- Handlers ----\n\n const handleAnalyze = async () => {\n setAnalyzing(true);\n setAnalyzeError(null);\n setAddError(null);\n const exit = await doPreview({ payload: { spec: specUrl } });\n if (Exit.isFailure(exit)) {\n setAnalyzeError(errorMessageFromExit(exit, \"Failed to parse spec\"));\n setAnalyzing(false);\n return;\n }\n const result = exit.value;\n setPreview(result);\n setBaseUrl(\"\");\n setAnalyzing(false);\n };\n\n handleAnalyzeRef.current = handleAnalyze;\n\n // Persist the integration and return its slug. Registers the catalog entry\n // with every detected auth method. Adding a slug that already exists is\n // rejected by the API (`IntegrationAlreadyExistsError`), surfaced inline.\n const ensureIntegration = useCallback(async (): Promise<IntegrationSlug | null> => {\n const exit = await doAdd({\n payload: {\n spec: specInputForAdd(specUrl),\n slug: resolvedSourceId,\n name: resolvedDisplayName,\n ...(resolvedDescription.trim().length > 0\n ? { description: resolvedDescription.trim() }\n : {}),\n baseUrl: resolvedBaseUrl,\n // Always send the edited method list (even empty) when the user has\n // inspected a preview: an explicit [] means \"no auth methods\", while\n // OMITTING the field tells the server to derive defaults from the\n // spec, which would silently resurrect methods the user deleted.\n // Serialize to the wire input dialect (apikey -> request-shaped).\n authenticationTemplate: editedAuthenticationTemplate.map(openApiWireAuthInput),\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setAddError(addIntegrationErrorMessage(exit, resolvedSourceId, \"Failed to add integration\"));\n return null;\n }\n return exit.value.slug;\n }, [\n specUrl,\n doAdd,\n resolvedSourceId,\n resolvedDisplayName,\n resolvedDescription,\n resolvedBaseUrl,\n editedAuthenticationTemplate,\n ]);\n\n const handleAdd = async () => {\n setAdding(true);\n setAddError(null);\n\n const integration = await ensureIntegration();\n if (!integration) {\n setAdding(false);\n return;\n }\n\n props.onComplete(String(integration));\n };\n\n // ---- Render ----\n\n return (\n <div className=\"flex flex-1 flex-col gap-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Add OpenAPI Integration</h1>\n </div>\n\n {!preview ? (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <div className=\"space-y-2 p-3\">\n <FieldLabel>OpenAPI Spec</FieldLabel>\n <div className=\"relative\">\n <Textarea\n value={specUrl}\n onChange={(e) => setSpecUrl((e.target as HTMLTextAreaElement).value)}\n placeholder=\"https://api.example.com/openapi.json\"\n rows={3}\n maxRows={10}\n className=\"font-mono text-sm\"\n />\n {analyzing && (\n <div className=\"pointer-events-none absolute right-2 top-2\">\n <IOSSpinner className=\"size-4\" />\n </div>\n )}\n </div>\n <p className=\"text-[11px] text-muted-foreground\">\n Paste a URL or raw JSON/YAML content.\n </p>\n </div>\n </CardStackContent>\n </CardStack>\n ) : null}\n\n {preview ? (\n <OpenApiSourceDetailsFields\n title={Option.getOrElse(preview.title, () => \"API\")}\n subtitle={`${Option.getOrElse(preview.version, () => \"\")}${\n Option.isSome(preview.version) ? \" · \" : \"\"\n }${preview.operationCount} operation${preview.operationCount !== 1 ? \"s\" : \"\"}${\n preview.tags.length > 0\n ? ` · ${preview.tags.length} tag${preview.tags.length !== 1 ? \"s\" : \"\"}`\n : \"\"\n }`}\n identity={identity}\n description={resolvedDescription}\n onDescriptionChange={setDescriptionDraft}\n baseUrl={resolvedBaseUrl}\n onBaseUrlChange={setBaseUrl}\n baseUrlOptions={baseUrlOptions}\n baseUrlLabel={previewHasNoServers ? \"Base URL\" : \"Base URL override (optional)\"}\n baseUrlPlaceholder={firstServerUrl || \"https://api.example.com\"}\n baseUrlHint={\n previewHasNoServers\n ? undefined\n : \"Overrides the spec's servers; leave empty to choose the server (and variables) per tool call.\"\n }\n baseUrlMissingMessage={\n previewHasNoServers ? \"This spec declares no servers, enter a base URL.\" : undefined\n }\n specUrl={specUrl}\n onSpecUrlChange={(value) => {\n setSpecUrl(value);\n setPreview(null);\n setBaseUrl(\"\");\n }}\n faviconIcon={previewPresetIcon}\n faviconUrl={resolvedBaseUrl || firstServerUrl}\n />\n ) : null}\n\n {analyzeError && <FormErrorAlert message={analyzeError} />}\n\n {preview && (\n <AuthMethodListEditor\n list={authMethodList}\n emptyHint=\"No authentication detected. Add a method, or add the integration without auth and connect an account from the integration page later.\"\n footerHint=\"Every method here is registered with the integration. Connect an account from the integration page after adding.\"\n />\n )}\n\n {preview && slugAlreadyExists && !adding && <SlugCollisionAlert slug={resolvedSourceId} />}\n\n {addError && <FormErrorAlert message={addError} />}\n\n <FloatActions>\n <Button variant=\"ghost\" onClick={() => props.onCancel()} disabled={adding}>\n Cancel\n </Button>\n {preview && (\n <Button onClick={() => void handleAdd()} disabled={!canAdd || adding}>\n {adding && <Spinner className=\"size-3.5\" />}\n {adding ? \"Adding...\" : \"Add integration\"}\n </Button>\n )}\n </FloatActions>\n </div>\n );\n}\n","import {\n CardStack,\n CardStackContent,\n CardStackEntry,\n CardStackEntryContent,\n CardStackEntryDescription,\n CardStackEntryField,\n CardStackEntryTitle,\n} from \"@executor-js/react/components/card-stack\";\nimport {\n FreeformCombobox,\n type FreeformComboboxOption,\n} from \"@executor-js/react/components/combobox\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Textarea } from \"@executor-js/react/components/textarea\";\nimport { IntegrationFavicon } from \"@executor-js/react/components/integration-favicon\";\nimport {\n IntegrationIdentityFieldRows,\n type IntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\n\n/** The spec input is shown as a one-line \"Spec URL\" field only when it IS a\n * URL; pasted document content gets a multi-line editor instead. */\nconst isUrlInput = (value: string): boolean => URL.canParse(value.trim());\n\nexport function OpenApiSourceDetailsFields(props: {\n readonly title: string;\n readonly subtitle?: string;\n readonly identity: IntegrationIdentity;\n /** The integration's agent-visible description (prefilled from the spec). */\n readonly description?: string;\n readonly onDescriptionChange?: (value: string) => void;\n readonly baseUrl: string;\n readonly onBaseUrlChange: (value: string) => void;\n readonly baseUrlOptions?: readonly FreeformComboboxOption[];\n readonly baseUrlLabel?: string;\n readonly baseUrlPlaceholder?: string;\n readonly baseUrlHint?: string;\n readonly specUrl?: string;\n readonly onSpecUrlChange?: (value: string) => void;\n readonly faviconIcon?: string | null;\n readonly faviconUrl?: string;\n readonly namespaceReadOnly?: boolean;\n readonly specUrlDisabled?: boolean;\n readonly saveState?: \"idle\" | \"saving\" | \"saved\";\n readonly baseUrlMissingMessage?: string;\n readonly footer?: string;\n}) {\n const specIsUrl = props.specUrl !== undefined && isUrlInput(props.specUrl);\n\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n {(props.faviconIcon || props.faviconUrl) && (\n <IntegrationFavicon icon={props.faviconIcon} url={props.faviconUrl} size={16} />\n )}\n <CardStackEntryContent>\n <CardStackEntryTitle>{props.title}</CardStackEntryTitle>\n {props.subtitle && (\n <CardStackEntryDescription>{props.subtitle}</CardStackEntryDescription>\n )}\n </CardStackEntryContent>\n {props.saveState && props.saveState !== \"idle\" && (\n <span className=\"text-xs text-muted-foreground\">\n {props.saveState === \"saving\" ? \"Saving…\" : \"Saved\"}\n </span>\n )}\n </CardStackEntry>\n <IntegrationIdentityFieldRows\n identity={props.identity}\n namespaceReadOnly={props.namespaceReadOnly}\n />\n {props.onDescriptionChange && (\n <CardStackEntryField label=\"Description\">\n <Textarea\n value={props.description ?? \"\"}\n onChange={(e) => props.onDescriptionChange?.((e.target as HTMLTextAreaElement).value)}\n placeholder=\"What this API is and when to reach for it\"\n rows={2}\n maxRows={6}\n className=\"text-sm\"\n />\n </CardStackEntryField>\n )}\n <div className=\"grid grid-cols-1 md:grid-cols-2\">\n <CardStackEntryField label={props.baseUrlLabel ?? \"Base URL\"}>\n {props.baseUrlOptions && props.baseUrlOptions.length > 0 ? (\n <FreeformCombobox\n value={props.baseUrl}\n onValueChange={props.onBaseUrlChange}\n options={props.baseUrlOptions}\n placeholder={props.baseUrlPlaceholder ?? \"https://api.example.com\"}\n className=\"w-full\"\n inputClassName=\"font-mono text-sm\"\n />\n ) : (\n <Input\n value={props.baseUrl}\n onChange={(e) => props.onBaseUrlChange((e.target as HTMLInputElement).value)}\n placeholder={props.baseUrlPlaceholder ?? \"https://api.example.com\"}\n className=\"font-mono text-sm\"\n />\n )}\n\n {props.baseUrlMissingMessage && !props.baseUrl && (\n <p className=\"text-[11px] text-muted-foreground\">{props.baseUrlMissingMessage}</p>\n )}\n {props.baseUrlHint && (\n <p className=\"text-[11px] text-muted-foreground\">{props.baseUrlHint}</p>\n )}\n </CardStackEntryField>\n {specIsUrl && props.onSpecUrlChange && (\n <CardStackEntryField label=\"Spec URL\">\n <Input\n value={props.specUrl}\n onChange={(e) => props.onSpecUrlChange?.((e.target as HTMLInputElement).value)}\n placeholder=\"https://api.example.com/openapi.json\"\n className=\"font-mono text-sm\"\n disabled={props.specUrlDisabled}\n />\n </CardStackEntryField>\n )}\n </div>\n {props.specUrl !== undefined && !specIsUrl && props.onSpecUrlChange && (\n <CardStackEntryField label=\"Spec\">\n <Textarea\n value={props.specUrl}\n onChange={(e) => props.onSpecUrlChange?.((e.target as HTMLTextAreaElement).value)}\n placeholder=\"Pasted OpenAPI JSON/YAML\"\n rows={4}\n maxRows={12}\n className=\"font-mono text-xs\"\n disabled={props.specUrlDisabled}\n />\n </CardStackEntryField>\n )}\n {props.footer && (\n <CardStackEntry>\n <CardStackEntryContent>\n <CardStackEntryTitle>{props.footer}</CardStackEntryTitle>\n </CardStackEntryContent>\n </CardStackEntry>\n )}\n </CardStackContent>\n </CardStack>\n );\n}\n"],"mappings":"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","names":["CardStack","CardStackContent","Textarea","jsx","jsxs","CardStack","CardStackContent","Textarea"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deriveAuthenticationTemplateFromPreview,
|
|
3
3
|
firstBaseUrlForPreview
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MWF55JPY.js";
|
|
5
5
|
import {
|
|
6
6
|
openApiPresets
|
|
7
7
|
} from "./chunk-QQFCICLX.js";
|
|
@@ -1639,4 +1639,4 @@ export {
|
|
|
1639
1639
|
resolveOpenApiBackedAnnotations,
|
|
1640
1640
|
openApiPlugin
|
|
1641
1641
|
};
|
|
1642
|
-
//# sourceMappingURL=chunk-
|
|
1642
|
+
//# sourceMappingURL=chunk-3O3PGRRG.js.map
|
|
@@ -37,16 +37,39 @@ var headerPrefix = (preset, headerName) => {
|
|
|
37
37
|
}
|
|
38
38
|
return void 0;
|
|
39
39
|
};
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
40
|
+
var slugifyVariable = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
41
|
+
var variablesForHeaders = (headerNames) => {
|
|
42
|
+
const variables = /* @__PURE__ */ new Map();
|
|
43
|
+
if (headerNames.length <= 1) return variables;
|
|
44
|
+
const taken = /* @__PURE__ */ new Set();
|
|
45
|
+
for (const headerName of headerNames) {
|
|
46
|
+
const base = slugifyVariable(headerName) || "input";
|
|
47
|
+
let variable = base;
|
|
48
|
+
for (let suffix = 2; taken.has(variable); suffix += 1) {
|
|
49
|
+
variable = `${base}_${suffix}`;
|
|
50
|
+
}
|
|
51
|
+
taken.add(variable);
|
|
52
|
+
variables.set(headerName, variable);
|
|
53
|
+
}
|
|
54
|
+
return variables;
|
|
55
|
+
};
|
|
56
|
+
var apiKeyTemplateFromHeaderPreset = (preset, slug) => {
|
|
57
|
+
const variables = variablesForHeaders(preset.secretHeaders);
|
|
58
|
+
return {
|
|
59
|
+
slug,
|
|
60
|
+
kind: "apikey",
|
|
61
|
+
placements: preset.secretHeaders.map((headerName) => {
|
|
62
|
+
const prefix = headerPrefix(preset, headerName);
|
|
63
|
+
const variable = variables.get(headerName);
|
|
64
|
+
return {
|
|
65
|
+
carrier: "header",
|
|
66
|
+
name: headerName,
|
|
67
|
+
...prefix ? { prefix } : {},
|
|
68
|
+
...variable ? { variable } : {}
|
|
69
|
+
};
|
|
70
|
+
})
|
|
71
|
+
};
|
|
72
|
+
};
|
|
50
73
|
var oauthTemplateFromPreset = (preset, baseUrl, slug, scopes) => ({
|
|
51
74
|
slug,
|
|
52
75
|
kind: "oauth2",
|
|
@@ -92,4 +115,4 @@ export {
|
|
|
92
115
|
firstBaseUrlForPreview,
|
|
93
116
|
deriveAuthenticationTemplateFromPreview
|
|
94
117
|
};
|
|
95
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-MWF55JPY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sdk/derive-auth.ts"],"sourcesContent":["// Spec-detected auth → stored `Authentication` templates, shared by every add\n// path. The React add flow derives templates from the preview before calling\n// `addSpec`; `addSpec` itself falls back to the same derivation when the\n// caller omits `authenticationTemplate` (the agentic/API path has no client\n// to do it). One implementation so the web UI and headless callers cannot\n// drift: an integration added over MCP gets the same auth methods the add\n// page would have produced.\nimport * as Option from \"effect/Option\";\n\nimport { AuthTemplateSlug, type OAuthAuthentication } from \"@executor-js/sdk/shared\";\n\nimport type { HeaderPreset, OAuth2Preset, SpecPreview, SpecPreviewSummary } from \"./preview\";\nimport type { APIKeyAuthentication, Authentication } from \"./types\";\nimport { resolveServerUrl } from \"./openapi-utils\";\n\ntype PreviewAuthMetadata = SpecPreview | SpecPreviewSummary;\n\n// ---------------------------------------------------------------------------\n// OpenAPI url helpers — specs sometimes ship relative OAuth endpoints; resolve\n// them against the chosen base URL so the stored auth template is absolute.\n// ---------------------------------------------------------------------------\n\nexport function resolveOAuthUrl(url: string, baseUrl: string): string {\n if (!url) return url;\n // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: URL constructor normalizes provider metadata URLs\n try {\n new URL(url);\n return url;\n } catch {\n if (!baseUrl) return url;\n // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: URL constructor resolves relative provider metadata URLs\n try {\n return new URL(url, baseUrl).toString();\n } catch {\n return url;\n }\n }\n}\n\nconst standardOidcIdentityScopes = [\"openid\", \"email\", \"profile\"] as const;\n\nconst identityScopesForPreset = (\n identityScopes: OAuth2Preset[\"identityScopes\"],\n): readonly string[] => {\n if (identityScopes === false) return [];\n return identityScopes === \"auto\" ? standardOidcIdentityScopes : identityScopes;\n};\n\nexport const resolvedOAuthScopes = (\n apiScopes: Iterable<string>,\n identityScopes: OAuth2Preset[\"identityScopes\"],\n): string[] => {\n const merged = new Set(apiScopes);\n for (const scope of identityScopesForPreset(identityScopes)) merged.add(scope);\n return [...merged];\n};\n\n// ---------------------------------------------------------------------------\n// Auth-template builders — turn a preview preset into the integration's stored\n// `Authentication` template (v2). A single-header preset becomes an `apiKey`\n// template whose secret header value renders from the conventional `token`\n// input. A multi-header preset gets one input per header, matching OpenAPI's\n// security-strategy semantics where multiple schemes in one object are required\n// together. The oauth2 preset becomes an `oauth` template carrying the provider\n// endpoints.\n// ---------------------------------------------------------------------------\n\nconst headerPrefix = (preset: HeaderPreset, headerName: string): string | undefined => {\n const label = preset.label.toLowerCase();\n if (headerName.toLowerCase() === \"authorization\") {\n if (label.includes(\"bearer\")) return \"Bearer \";\n if (label.includes(\"basic\")) return \"Basic \";\n }\n return undefined;\n};\n\nconst slugifyVariable = (name: string): string =>\n name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst variablesForHeaders = (headerNames: readonly string[]): ReadonlyMap<string, string> => {\n const variables = new Map<string, string>();\n if (headerNames.length <= 1) return variables;\n\n const taken = new Set<string>();\n for (const headerName of headerNames) {\n const base = slugifyVariable(headerName) || \"input\";\n let variable = base;\n for (let suffix = 2; taken.has(variable); suffix += 1) {\n variable = `${base}_${suffix}`;\n }\n taken.add(variable);\n variables.set(headerName, variable);\n }\n return variables;\n};\n\nconst apiKeyTemplateFromHeaderPreset = (\n preset: HeaderPreset,\n slug: AuthTemplateSlug,\n): APIKeyAuthentication => {\n const variables = variablesForHeaders(preset.secretHeaders);\n return {\n slug,\n kind: \"apikey\",\n placements: preset.secretHeaders.map((headerName) => {\n const prefix = headerPrefix(preset, headerName);\n const variable = variables.get(headerName);\n return {\n carrier: \"header\" as const,\n name: headerName,\n ...(prefix ? { prefix } : {}),\n ...(variable ? { variable } : {}),\n };\n }),\n };\n};\n\nconst oauthTemplateFromPreset = (\n preset: OAuth2Preset,\n baseUrl: string,\n slug: AuthTemplateSlug,\n scopes: readonly string[],\n): OAuthAuthentication => ({\n slug,\n kind: \"oauth2\",\n authorizationUrl: resolveOAuthUrl(\n Option.getOrElse(preset.authorizationUrl, () => \"\"),\n baseUrl,\n ),\n tokenUrl: resolveOAuthUrl(preset.tokenUrl, baseUrl),\n scopes: [...scopes],\n});\n\n// ---------------------------------------------------------------------------\n// All spec-detected auth methods → the union of stored `Authentication`\n// templates. Header presets become apiKey templates; each oauth2 preset becomes\n// an oauth template (with its declared API scopes plus, for auth-code flows,\n// the standard identity scopes). Slugs stay deterministic per method so the\n// stored template is stable across previews of the same spec.\n// ---------------------------------------------------------------------------\n\nexport const detectedAuthenticationTemplates = (\n headerPresets: readonly HeaderPreset[],\n oauth2Presets: readonly OAuth2Preset[],\n baseUrl: string,\n): readonly Authentication[] => {\n const templates: Authentication[] = [];\n headerPresets.forEach((preset, index) => {\n templates.push(\n apiKeyTemplateFromHeaderPreset(preset, AuthTemplateSlug.make(`apikey-${index}`)),\n );\n });\n for (const preset of oauth2Presets) {\n const scopes = resolvedOAuthScopes(Object.keys(preset.scopes), preset.identityScopes);\n templates.push(\n oauthTemplateFromPreset(\n preset,\n baseUrl,\n AuthTemplateSlug.make(`oauth-${preset.securitySchemeName}`),\n scopes,\n ),\n );\n }\n return templates;\n};\n\nexport const firstBaseUrlForPreview = (preview: PreviewAuthMetadata): string => {\n const firstServer = preview.servers[0];\n return firstServer\n ? resolveServerUrl(firstServer.url, Option.getOrUndefined(firstServer.variables), {})\n : \"\";\n};\n\n/** The fallback `addSpec` uses when no explicit template was passed: every\n * spec-detected method, resolved against the integration's base URL. */\nexport const deriveAuthenticationTemplateFromPreview = (\n preview: PreviewAuthMetadata,\n baseUrl: string | undefined,\n): readonly Authentication[] =>\n detectedAuthenticationTemplates(\n preview.headerPresets,\n preview.oauth2Presets,\n baseUrl ?? firstBaseUrlForPreview(preview),\n );\n"],"mappings":"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","names":[]}
|
package/dist/client.js
CHANGED
|
@@ -7,7 +7,7 @@ import { defineClientPlugin } from "@executor-js/sdk/client";
|
|
|
7
7
|
|
|
8
8
|
// src/react/source-plugin.ts
|
|
9
9
|
import { lazy } from "react";
|
|
10
|
-
var importAdd = () => import("./AddOpenApiSource-
|
|
10
|
+
var importAdd = () => import("./AddOpenApiSource-SSXZBQEK.js");
|
|
11
11
|
var importEditSheet = () => import("./UpdateSpecSection-FFYVB3VH.js");
|
|
12
12
|
var importAccounts = () => import("./OpenApiAccountsPanel-U47OVLYG.js");
|
|
13
13
|
var openApiIntegrationPlugin = {
|
package/dist/core.js
CHANGED
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
renderAuthTemplate,
|
|
23
23
|
resolveOpenApiBackedAnnotations,
|
|
24
24
|
resolveOpenApiBackedTools
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
25
|
+
} from "./chunk-3O3PGRRG.js";
|
|
26
|
+
import "./chunk-MWF55JPY.js";
|
|
27
27
|
import "./chunk-QQFCICLX.js";
|
|
28
28
|
import {
|
|
29
29
|
AuthStrategy,
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@executor-js/plugin-openapi",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.21",
|
|
4
4
|
"homepage": "https://github.com/RhysSullivan/executor/tree/main/packages/plugins/openapi",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/RhysSullivan/executor/issues"
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@effect/platform-node": "4.0.0-beta.59",
|
|
56
|
-
"@executor-js/config": "1.5.
|
|
57
|
-
"@executor-js/sdk": "1.5.
|
|
56
|
+
"@executor-js/config": "1.5.21",
|
|
57
|
+
"@executor-js/sdk": "1.5.21",
|
|
58
58
|
"js-yaml": "4.1.1",
|
|
59
59
|
"lucide-react": "^1.7.0",
|
|
60
60
|
"openapi-types": "^12.1.3"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sdk/derive-auth.ts"],"sourcesContent":["// Spec-detected auth → stored `Authentication` templates, shared by every add\n// path. The React add flow derives templates from the preview before calling\n// `addSpec`; `addSpec` itself falls back to the same derivation when the\n// caller omits `authenticationTemplate` (the agentic/API path has no client\n// to do it). One implementation so the web UI and headless callers cannot\n// drift: an integration added over MCP gets the same auth methods the add\n// page would have produced.\nimport * as Option from \"effect/Option\";\n\nimport { AuthTemplateSlug, type OAuthAuthentication } from \"@executor-js/sdk/shared\";\n\nimport type { HeaderPreset, OAuth2Preset, SpecPreview, SpecPreviewSummary } from \"./preview\";\nimport type { APIKeyAuthentication, Authentication } from \"./types\";\nimport { resolveServerUrl } from \"./openapi-utils\";\n\ntype PreviewAuthMetadata = SpecPreview | SpecPreviewSummary;\n\n// ---------------------------------------------------------------------------\n// OpenAPI url helpers — specs sometimes ship relative OAuth endpoints; resolve\n// them against the chosen base URL so the stored auth template is absolute.\n// ---------------------------------------------------------------------------\n\nexport function resolveOAuthUrl(url: string, baseUrl: string): string {\n if (!url) return url;\n // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: URL constructor normalizes provider metadata URLs\n try {\n new URL(url);\n return url;\n } catch {\n if (!baseUrl) return url;\n // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: URL constructor resolves relative provider metadata URLs\n try {\n return new URL(url, baseUrl).toString();\n } catch {\n return url;\n }\n }\n}\n\nconst standardOidcIdentityScopes = [\"openid\", \"email\", \"profile\"] as const;\n\nconst identityScopesForPreset = (\n identityScopes: OAuth2Preset[\"identityScopes\"],\n): readonly string[] => {\n if (identityScopes === false) return [];\n return identityScopes === \"auto\" ? standardOidcIdentityScopes : identityScopes;\n};\n\nexport const resolvedOAuthScopes = (\n apiScopes: Iterable<string>,\n identityScopes: OAuth2Preset[\"identityScopes\"],\n): string[] => {\n const merged = new Set(apiScopes);\n for (const scope of identityScopesForPreset(identityScopes)) merged.add(scope);\n return [...merged];\n};\n\n// ---------------------------------------------------------------------------\n// Auth-template builders — turn a preview preset into the integration's stored\n// `Authentication` template (v2). The header preset becomes an `apiKey` template\n// whose secret header value renders the resolved credential via `variable(token)`;\n// the oauth2 preset becomes an `oauth` template carrying the provider endpoints.\n// ---------------------------------------------------------------------------\n\nconst headerPrefix = (preset: HeaderPreset, headerName: string): string | undefined => {\n const label = preset.label.toLowerCase();\n if (headerName.toLowerCase() === \"authorization\") {\n if (label.includes(\"bearer\")) return \"Bearer \";\n if (label.includes(\"basic\")) return \"Basic \";\n }\n return undefined;\n};\n\nconst apiKeyTemplateFromHeaderPreset = (\n preset: HeaderPreset,\n slug: AuthTemplateSlug,\n): APIKeyAuthentication => ({\n slug,\n kind: \"apikey\",\n // Every secret header shares the one credential input (the canonical\n // `token`, stored as an absent placement variable).\n placements: preset.secretHeaders.map((headerName) => {\n const prefix = headerPrefix(preset, headerName);\n return { carrier: \"header\" as const, name: headerName, ...(prefix ? { prefix } : {}) };\n }),\n});\n\nconst oauthTemplateFromPreset = (\n preset: OAuth2Preset,\n baseUrl: string,\n slug: AuthTemplateSlug,\n scopes: readonly string[],\n): OAuthAuthentication => ({\n slug,\n kind: \"oauth2\",\n authorizationUrl: resolveOAuthUrl(\n Option.getOrElse(preset.authorizationUrl, () => \"\"),\n baseUrl,\n ),\n tokenUrl: resolveOAuthUrl(preset.tokenUrl, baseUrl),\n scopes: [...scopes],\n});\n\n// ---------------------------------------------------------------------------\n// All spec-detected auth methods → the union of stored `Authentication`\n// templates. Header presets become apiKey templates; each oauth2 preset becomes\n// an oauth template (with its declared API scopes plus, for auth-code flows,\n// the standard identity scopes). Slugs stay deterministic per method so the\n// stored template is stable across previews of the same spec.\n// ---------------------------------------------------------------------------\n\nexport const detectedAuthenticationTemplates = (\n headerPresets: readonly HeaderPreset[],\n oauth2Presets: readonly OAuth2Preset[],\n baseUrl: string,\n): readonly Authentication[] => {\n const templates: Authentication[] = [];\n headerPresets.forEach((preset, index) => {\n templates.push(\n apiKeyTemplateFromHeaderPreset(preset, AuthTemplateSlug.make(`apikey-${index}`)),\n );\n });\n for (const preset of oauth2Presets) {\n const scopes = resolvedOAuthScopes(Object.keys(preset.scopes), preset.identityScopes);\n templates.push(\n oauthTemplateFromPreset(\n preset,\n baseUrl,\n AuthTemplateSlug.make(`oauth-${preset.securitySchemeName}`),\n scopes,\n ),\n );\n }\n return templates;\n};\n\nexport const firstBaseUrlForPreview = (preview: PreviewAuthMetadata): string => {\n const firstServer = preview.servers[0];\n return firstServer\n ? resolveServerUrl(firstServer.url, Option.getOrUndefined(firstServer.variables), {})\n : \"\";\n};\n\n/** The fallback `addSpec` uses when no explicit template was passed: every\n * spec-detected method, resolved against the integration's base URL. */\nexport const deriveAuthenticationTemplateFromPreview = (\n preview: PreviewAuthMetadata,\n baseUrl: string | undefined,\n): readonly Authentication[] =>\n detectedAuthenticationTemplates(\n preview.headerPresets,\n preview.oauth2Presets,\n baseUrl ?? firstBaseUrlForPreview(preview),\n );\n"],"mappings":";;;;;AAOA,YAAY,YAAY;AAExB,SAAS,wBAAkD;AAapD,SAAS,gBAAgB,KAAa,SAAyB;AACpE,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI;AACF,QAAI,IAAI,GAAG;AACX,WAAO;AAAA,EACT,QAAQ;AACN,QAAI,CAAC,QAAS,QAAO;AAErB,QAAI;AACF,aAAO,IAAI,IAAI,KAAK,OAAO,EAAE,SAAS;AAAA,IACxC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,IAAM,6BAA6B,CAAC,UAAU,SAAS,SAAS;AAEhE,IAAM,0BAA0B,CAC9B,mBACsB;AACtB,MAAI,mBAAmB,MAAO,QAAO,CAAC;AACtC,SAAO,mBAAmB,SAAS,6BAA6B;AAClE;AAEO,IAAM,sBAAsB,CACjC,WACA,mBACa;AACb,QAAM,SAAS,IAAI,IAAI,SAAS;AAChC,aAAW,SAAS,wBAAwB,cAAc,EAAG,QAAO,IAAI,KAAK;AAC7E,SAAO,CAAC,GAAG,MAAM;AACnB;AASA,IAAM,eAAe,CAAC,QAAsB,eAA2C;AACrF,QAAM,QAAQ,OAAO,MAAM,YAAY;AACvC,MAAI,WAAW,YAAY,MAAM,iBAAiB;AAChD,QAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,QAAI,MAAM,SAAS,OAAO,EAAG,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAEA,IAAM,iCAAiC,CACrC,QACA,UAC0B;AAAA,EAC1B;AAAA,EACA,MAAM;AAAA;AAAA;AAAA,EAGN,YAAY,OAAO,cAAc,IAAI,CAAC,eAAe;AACnD,UAAM,SAAS,aAAa,QAAQ,UAAU;AAC9C,WAAO,EAAE,SAAS,UAAmB,MAAM,YAAY,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG;AAAA,EACvF,CAAC;AACH;AAEA,IAAM,0BAA0B,CAC9B,QACA,SACA,MACA,YACyB;AAAA,EACzB;AAAA,EACA,MAAM;AAAA,EACN,kBAAkB;AAAA,IACT,iBAAU,OAAO,kBAAkB,MAAM,EAAE;AAAA,IAClD;AAAA,EACF;AAAA,EACA,UAAU,gBAAgB,OAAO,UAAU,OAAO;AAAA,EAClD,QAAQ,CAAC,GAAG,MAAM;AACpB;AAUO,IAAM,kCAAkC,CAC7C,eACA,eACA,YAC8B;AAC9B,QAAM,YAA8B,CAAC;AACrC,gBAAc,QAAQ,CAAC,QAAQ,UAAU;AACvC,cAAU;AAAA,MACR,+BAA+B,QAAQ,iBAAiB,KAAK,UAAU,KAAK,EAAE,CAAC;AAAA,IACjF;AAAA,EACF,CAAC;AACD,aAAW,UAAU,eAAe;AAClC,UAAM,SAAS,oBAAoB,OAAO,KAAK,OAAO,MAAM,GAAG,OAAO,cAAc;AACpF,cAAU;AAAA,MACR;AAAA,QACE;AAAA,QACA;AAAA,QACA,iBAAiB,KAAK,SAAS,OAAO,kBAAkB,EAAE;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,yBAAyB,CAAC,YAAyC;AAC9E,QAAM,cAAc,QAAQ,QAAQ,CAAC;AACrC,SAAO,cACH,iBAAiB,YAAY,KAAY,sBAAe,YAAY,SAAS,GAAG,CAAC,CAAC,IAClF;AACN;AAIO,IAAM,0CAA0C,CACrD,SACA,YAEA;AAAA,EACE,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW,uBAAuB,OAAO;AAC3C;","names":[]}
|
|
File without changes
|