1919 lines · 62.5 KB · TypeScript
RawDownload
import { useEffect, useState, type ReactNode } from "react";import { Link, useNavigate } from "@tanstack/react-router";import {  type CompleteSourceOAuthResult,  type CreateSourcePayload,  type InstanceConfig,  type Loadable,  type StartSourceOAuthPayload,  type SecretListItem,  type Source,  type UpdateSourcePayload,  useCreateSecret,  useCreateSource,  useInstanceConfig,  useRefreshSecrets,  useRemoveProviderAuthGrant,  useRemoveSource,  useSecrets,  useSources,  useStartSourceOAuth,  useSource,  useUpdateSource,} from "@executor/react";import { Badge } from "../components/ui/badge";import { Button } from "../components/ui/button";import { LoadableBlock } from "../components/loadable";import { SourceNotFoundState } from "../components/source-not-found-state";import { SourceFavicon } from "../components/source-favicon";import {  IconArrowLeft,  IconPencil,  IconPlus,  IconSpinner,  IconTrash,} from "../components/icons";import { cn } from "../lib/utils";import {  asMcpRemoteTransportValue,  defaultMcpRemoteTransportFields,  defaultMcpStdioTransportFields,  setMcpTransportFieldsTransport,  type McpRemoteTransportFields,  type McpStdioTransportFields,  type McpTransportFields,  type McpTransportValue,} from "./mcp-transport-state";import { parseJsonStringArray, parseJsonStringMap } from "./json-form";import { sourceTemplates, type SourceTemplate } from "./source-templates";import { getDomain } from "tldts"; type StatusBannerState = {  tone: "info" | "success" | "error";  text: string;}; type SourceOAuthPopupMessage =  | {      type: "executor:oauth-result";      ok: true;      sessionId: string;      auth: CompleteSourceOAuthResult["auth"];    }  | {      type: "executor:oauth-result";      ok: false;      sessionId: string | null;      error: string;    }; const SOURCE_OAUTH_POPUP_RESULT_TIMEOUT_MS = 2 * 60_000;const SOURCE_OAUTH_POPUP_RESULT_STORAGE_KEY_PREFIX = "executor:oauth-result:"; const isSourceNotFoundLoadable = (loadable: Loadable<unknown>): boolean =>  loadable.status === "error" &&  loadable.error.message.toLowerCase().includes("source not found"); type SourceFormBase = {  name: string;  kind: Source["kind"];  endpoint: string;  namespace: string;  enabled: boolean;  specUrl: string;  service: string;  version: string;  defaultHeadersText: string;  authKind: Source["auth"]["kind"];  authHeaderName: string;  authPrefix: string;  bearerProviderId: string;  bearerHandle: string;  oauthAccessProviderId: string;  oauthAccessHandle: string;  oauthRefreshProviderId: string;  oauthRefreshHandle: string;  managedAuth: Extract<    Source["auth"],    { kind: "provider_grant_ref" | "mcp_oauth" }  > | null;}; type SourceFormState = SourceFormBase & McpTransportFields; const kindOptions: ReadonlyArray<Source["kind"]> = [  "mcp",  "openapi",  "graphql",  "google_discovery",  "internal",]; const transportOptions: ReadonlyArray<Exclude<McpTransportValue, "">> = [  "auto",  "streamable-http",  "sse",  "stdio",]; const authOptions: ReadonlyArray<Source["auth"]["kind"]> = [  "none",  "bearer",  "oauth2",  "provider_grant_ref",  "mcp_oauth",]; const trimToNull = (value: string): string | null => {  const trimmed = value.trim();  return trimmed.length > 0 ? trimmed : null;}; const namespaceFromUrl = (url: string): string => {  try {    const domain = getDomain(url);    if (!domain) return "";    const dot = domain.indexOf(".");    return dot > 0 ? domain.slice(0, dot) : domain;  } catch {    return "";  }}; const googleDiscoveryNamespace = (service: string): string =>  `google.${service    .trim()    .toLowerCase()    .replace(/[^a-z0-9]+/g, ".")    .replace(/^\.+|\.+$/g, "")}`; const readStoredSourceOAuthPopupResult = (  sessionId: string,): SourceOAuthPopupMessage | null => {  if (typeof window === "undefined") {    return null;  }   const raw = window.localStorage.getItem(    `${SOURCE_OAUTH_POPUP_RESULT_STORAGE_KEY_PREFIX}${sessionId}`,  );  if (!raw) {    return null;  }   try {    return JSON.parse(raw) as SourceOAuthPopupMessage;  } catch {    return null;  }}; const clearStoredSourceOAuthPopupResult = (sessionId: string): void => {  if (typeof window === "undefined") {    return;  }   window.localStorage.removeItem(    `${SOURCE_OAUTH_POPUP_RESULT_STORAGE_KEY_PREFIX}${sessionId}`,  );}; const startSourceOAuthPopup = async (input: {  authorizationUrl: string;  sessionId: string;}): Promise<CompleteSourceOAuthResult["auth"]> => {  if (typeof window === "undefined") {    throw new Error("OAuth popup is only available in a browser context");  }   clearStoredSourceOAuthPopupResult(input.sessionId);   const popup = window.open(    input.authorizationUrl,    "executor-source-oauth",    "popup=yes,width=520,height=720",  );   if (!popup) {    throw new Error("Popup blocked. Allow popups and try again.");  }   popup.focus();   return await new Promise<CompleteSourceOAuthResult["auth"]>(    (resolve, reject) => {      let settled = false;      let closedPoll = 0;      let resultTimeout = 0;       const cleanup = () => {        window.removeEventListener("message", onMessage);        if (closedPoll) {          window.clearInterval(closedPoll);        }        if (resultTimeout) {          window.clearTimeout(resultTimeout);        }        if (!popup.closed) {          popup.close();        }        clearStoredSourceOAuthPopupResult(input.sessionId);      };       const settleWithError = (message: string) => {        if (settled) {          return;        }         settled = true;        cleanup();        reject(new Error(message));      };       const settleFromPayload = (data: SourceOAuthPopupMessage) => {        if (!data.ok) {          settleWithError(data.error || "OAuth failed");          return;        }         if (settled) {          return;        }         settled = true;        cleanup();        resolve(data.auth);      };       const onMessage = (event: MessageEvent) => {        if (event.origin !== window.location.origin) {          return;        }         const data = event.data as SourceOAuthPopupMessage | undefined;        if (!data || data.type !== "executor:oauth-result") {          return;        }         if (data.ok && data.sessionId !== input.sessionId) {          return;        }         if (          !data.ok &&          data.sessionId !== null &&          data.sessionId !== input.sessionId        ) {          return;        }         settleFromPayload(data);      };       window.addEventListener("message", onMessage);       resultTimeout = window.setTimeout(() => {        settleWithError(          "OAuth popup timed out before completion. Please try again.",        );      }, SOURCE_OAUTH_POPUP_RESULT_TIMEOUT_MS);       closedPoll = window.setInterval(() => {        const stored = readStoredSourceOAuthPopupResult(input.sessionId);        if (stored) {          settleFromPayload(stored);          return;        }        if (popup.closed) {          // Stop polling — only run one final deferred check to give the          // callback page time to write localStorage before we give up.          window.clearInterval(closedPoll);          closedPoll = 0;          window.setTimeout(() => {            const delayedStored = readStoredSourceOAuthPopupResult(              input.sessionId,            );            if (delayedStored) {              settleFromPayload(delayedStored);              return;            }            settleWithError("OAuth popup was closed before completion.");          }, 1500);        }      }, 300);    },  );}; const stringMapToEditor = (value: Record<string, string> | null): string =>  value === null ? "" : JSON.stringify(value, null, 2); const stringArrayToEditor = (  value: ReadonlyArray<string> | null | undefined,): string =>  !value || value.length === 0 ? "" : JSON.stringify(value, null, 2); const readBindingStringMap = (  source: Source,  key: string,): Record<string, string> | null => {  const candidate = source.binding[key];  if (    candidate === null ||    candidate === undefined ||    typeof candidate !== "object" ||    Array.isArray(candidate)  ) {    return null;  }   const entries = Object.entries(candidate as Record<string, unknown>);  return entries.every(([, value]) => typeof value === "string")    ? Object.fromEntries(entries as ReadonlyArray<readonly [string, string]>)    : null;}; const readBindingStringArray = (  source: Source,  key: string,): Array<string> | null => {  const candidate = source.binding[key];  return Array.isArray(candidate) &&    candidate.every((value) => typeof value === "string")    ? [...candidate]    : null;}; const readBindingString = (source: Source, key: string): string =>  typeof source.binding[key] === "string" ? String(source.binding[key]) : ""; const readBindingTransport = (source: Source): McpTransportValue => {  const candidate = source.binding.transport;  return typeof candidate === "string" &&    (candidate === "auto" ||      candidate === "streamable-http" ||      candidate === "sse" ||      candidate === "stdio")    ? candidate    : "";}; const buildSyntheticMcpStdioEndpoint = (input: {  name?: string | null;  endpoint?: string | null;  command?: string | null;}): string => {  const label =    input.name?.trim() ||    input.endpoint?.trim() ||    input.command?.trim() ||    "mcp";  const slug = label    .toLowerCase()    .replace(/[^a-z0-9]+/g, "-")    .replace(/^-+|-+$/g, "");   return `stdio://local/${slug || "mcp"}`;}; const defaultFormState = (template?: SourceTemplate): SourceFormState => ({  name: template?.name ?? "",  kind: template?.kind ?? "openapi",  endpoint: template?.endpoint ?? "",  namespace: template    ? (template.namespace ??      ("service" in template        ? googleDiscoveryNamespace(template.service)        : namespaceFromUrl(template.endpoint ?? "")))    : "",  enabled: true,  specUrl: template && "specUrl" in template ? template.specUrl : "",  service: template && "service" in template ? template.service : "",  version: template && "version" in template ? template.version : "",  defaultHeadersText: "",  authKind: template?.kind === "google_discovery" ? "oauth2" : "none",  authHeaderName: "Authorization",  authPrefix: "Bearer ",  bearerProviderId: "",  bearerHandle: "",  oauthAccessProviderId: "",  oauthAccessHandle: "",  oauthRefreshProviderId: "",  oauthRefreshHandle: "",  managedAuth: null,  ...(template?.kind === "mcp" && template.connectionType === "command"    ? defaultMcpStdioTransportFields({        command: template.command ?? "",        argsText: stringArrayToEditor(template.args),        envText: stringMapToEditor(template.env ?? null),        cwd: template.cwd ?? "",      })    : defaultMcpRemoteTransportFields(        template?.kind === "mcp"          ? asMcpRemoteTransportValue(template.transport)          : "",      )),}); const formStateFromSource = (source: Source): SourceFormState => ({  name: source.name,  kind: source.kind,  endpoint: source.endpoint,  namespace: source.namespace ?? "",  enabled: source.enabled,  specUrl: readBindingString(source, "specUrl"),  service: readBindingString(source, "service"),  version: readBindingString(source, "version"),  defaultHeadersText: stringMapToEditor(    readBindingStringMap(source, "defaultHeaders"),  ),  authKind: source.auth.kind,  authHeaderName:    source.auth.kind === "none" || source.auth.kind === "mcp_oauth"      ? "Authorization"      : source.auth.headerName,  authPrefix:    source.auth.kind === "none" || source.auth.kind === "mcp_oauth"      ? "Bearer "      : source.auth.prefix,  bearerProviderId:    source.auth.kind === "bearer" ? source.auth.token.providerId : "",  bearerHandle: source.auth.kind === "bearer" ? source.auth.token.handle : "",  oauthAccessProviderId:    source.auth.kind === "oauth2" ? source.auth.accessToken.providerId : "",  oauthAccessHandle:    source.auth.kind === "oauth2" ? source.auth.accessToken.handle : "",  oauthRefreshProviderId:    source.auth.kind === "oauth2" && source.auth.refreshToken !== null      ? source.auth.refreshToken.providerId      : "",  oauthRefreshHandle:    source.auth.kind === "oauth2" && source.auth.refreshToken !== null      ? source.auth.refreshToken.handle      : "",  managedAuth:    source.auth.kind === "provider_grant_ref" ||    source.auth.kind === "mcp_oauth"      ? source.auth      : null,  ...(source.kind === "mcp" && readBindingTransport(source) === "stdio"    ? defaultMcpStdioTransportFields({        command: readBindingString(source, "command"),        argsText: stringArrayToEditor(readBindingStringArray(source, "args")),        envText: stringMapToEditor(readBindingStringMap(source, "env")),        cwd: readBindingString(source, "cwd"),      })    : defaultMcpRemoteTransportFields(        source.kind === "mcp"          ? asMcpRemoteTransportValue(readBindingTransport(source) || "auto")          : "",      )),  ...(source.kind === "mcp" && readBindingTransport(source) !== "stdio"    ? {        queryParamsText: stringMapToEditor(          readBindingStringMap(source, "queryParams"),        ),        headersText: stringMapToEditor(readBindingStringMap(source, "headers")),      }    : {}),}); const buildAuthPayload = (  state: SourceFormState,): CreateSourcePayload["auth"] => {  if (state.authKind === "none") {    return { kind: "none" };  }   if (    (state.authKind === "provider_grant_ref" ||      state.authKind === "mcp_oauth") &&    state.managedAuth !== null  ) {    return state.managedAuth;  }   const headerName = state.authHeaderName.trim() || "Authorization";  const prefix = state.authPrefix;   if (state.authKind === "bearer") {    const providerId = state.bearerProviderId.trim();

Lines 1–500 of 1919.