@rebasepro/studio 0.25.0-canary.ge06257e → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -747,6 +747,7 @@ function ApiExplorer() {
747
747
  const apiConfig = useApiConfig();
748
748
  const apiBase = useApiBase();
749
749
  const authController = useAuthController();
750
+ const { t } = useTranslation();
750
751
  const apiUrl = apiConfig?.apiUrl;
751
752
  const [spec, setSpec] = useState(null);
752
753
  const [loading, setLoading] = useState(true);
@@ -840,12 +841,12 @@ function ApiExplorer() {
840
841
  /* @__PURE__ */ jsx(Typography, {
841
842
  variant: "subtitle2",
842
843
  className: "block text-text-primary dark:text-text-primary-dark",
843
- children: isAuth ? "This session cannot read the API specification" : "Could not load the API specification"
844
+ children: isAuth ? t("studio_api_explorer_spec_refused_title") : t("studio_api_explorer_spec_failed_title")
844
845
  }),
845
846
  /* @__PURE__ */ jsx(Typography, {
846
847
  variant: "body2",
847
848
  className: "block mt-2 text-text-secondary dark:text-text-secondary-dark",
848
- children: isAuth ? "The console's access to this project's API was refused. It usually means the session expired — sign in again — or that console access has been turned off for this project in Settings." : "The project answered, but not with a specification this explorer could read. Its API is unaffected; only this page is."
849
+ children: isAuth ? t("studio_api_explorer_spec_refused_body") : t("studio_api_explorer_spec_failed_body")
849
850
  }),
850
851
  /* @__PURE__ */ jsx(Button, {
851
852
  variant: "outlined",
@@ -853,7 +854,7 @@ function ApiExplorer() {
853
854
  size: "small",
854
855
  className: "mt-4",
855
856
  onClick: () => window.location.reload(),
856
- children: "Try again"
857
+ children: t("retry")
857
858
  }),
858
859
  status && /* @__PURE__ */ jsx(Typography, {
859
860
  variant: "caption",
@@ -985,4 +986,4 @@ ApiExplorer.displayName = "ApiExplorer";
985
986
  //#endregion
986
987
  export { ApiExplorer };
987
988
 
988
- //# sourceMappingURL=ApiExplorer-Bzt7Ye49.js.map
989
+ //# sourceMappingURL=ApiExplorer-B82tFVBX.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApiExplorer-Bzt7Ye49.js","names":[],"sources":["../src/components/ApiExplorer/parseSpec.ts","../src/components/ApiExplorer/EndpointDetail.tsx","../src/components/ApiExplorer/TryItPanel.tsx","../src/components/ApiExplorer/ApiExplorer.tsx"],"sourcesContent":["import type { OpenApiSpec, ParsedEndpoint, EndpointGroup } from \"./types\";\n\n/**\n * Parse an OpenAPI 3.x spec into grouped, sorted endpoints for the sidebar.\n */\nexport function parseOpenApiSpec(spec: OpenApiSpec): {\n groups: EndpointGroup[];\n allEndpoints: ParsedEndpoint[];\n} {\n const allEndpoints: ParsedEndpoint[] = [];\n const tagMap = new Map<string, ParsedEndpoint[]>();\n\n // Build tag description lookup\n const tagDescriptions = new Map<string, string>();\n for (const t of spec.tags ?? []) {\n tagDescriptions.set(t.name, t.description ?? \"\");\n }\n\n for (const [path, methods] of Object.entries(spec.paths ?? {})) {\n for (const [method, op] of Object.entries(methods)) {\n if ([\"get\", \"post\", \"put\", \"patch\", \"delete\"].indexOf(method) === -1) continue;\n\n const tags = op.tags?.length ? op.tags : [\"Other\"];\n const shortPath = path.replace(/^\\/api\\/data/, \"\");\n\n const endpoint: ParsedEndpoint = {\n id: `${method}:${path}`,\n method,\n path,\n shortPath: shortPath || \"/\",\n summary: op.summary ?? \"\",\n description: op.description ?? \"\",\n tags,\n parameters: op.parameters ?? [],\n requestBody: op.requestBody,\n responses: op.responses ?? {},\n security: op.security,\n operationId: op.operationId\n };\n\n allEndpoints.push(endpoint);\n for (const tag of tags) {\n if (!tagMap.has(tag)) tagMap.set(tag, []);\n tagMap.get(tag)!.push(endpoint);\n }\n }\n }\n\n // Method sort order\n const ORDER: Record<string, number> = { get: 0,\npost: 1,\nput: 2,\npatch: 3,\ndelete: 4 };\n\n const groups: EndpointGroup[] = [];\n // Sort tags: use spec.tags order if available, else alphabetical\n const tagOrder = (spec.tags ?? []).map((t) => t.name);\n const sortedTags = [...tagMap.keys()].sort((a, b) => {\n const ai = tagOrder.indexOf(a);\n const bi = tagOrder.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n\n for (const tag of sortedTags) {\n const endpoints = tagMap.get(tag)!;\n endpoints.sort((a, b) => {\n const pa = a.path.localeCompare(b.path);\n if (pa !== 0) return pa;\n return (ORDER[a.method] ?? 99) - (ORDER[b.method] ?? 99);\n });\n groups.push({\n tag,\n description: tagDescriptions.get(tag),\n endpoints\n });\n }\n\n return { groups,\nallEndpoints };\n}\n\n/**\n * Resolve a $ref string (e.g. \"#/components/schemas/Author\") to a schema name.\n */\nexport function resolveRefName(ref: string): string {\n const parts = ref.split(\"/\");\n return parts[parts.length - 1];\n}\n\n/**\n * Resolve a $ref to its actual schema from the spec.\n */\nexport function resolveRef(spec: OpenApiSpec, ref: string): unknown {\n const parts = ref.replace(\"#/\", \"\").split(\"/\");\n let current: unknown = spec;\n for (const part of parts) {\n current = (current as Record<string, unknown>)?.[part];\n }\n return current ?? {};\n}\n","import React from \"react\";\nimport {\n ArrowRightFromLineIcon,\n Chip,\n cls,\n defaultBorderMixin,\n iconSize,\n SlidersHorizontalIcon,\n Typography,\n UploadIcon\n} from \"@rebasepro/ui\";\nimport type { ParsedEndpoint, OpenApiSpec, OpenApiSchema } from \"./types\";\nimport { resolveRef, resolveRefName } from \"./parseSpec\";\n\n/**\n * Renders the documentation view for a single API endpoint:\n * parameters, request body schema, response schemas.\n */\nexport function EndpointDetail({ endpoint, spec }: { endpoint: ParsedEndpoint; spec: OpenApiSpec }) {\n return (\n <div className=\"p-6 space-y-8 max-w-4xl\">\n {/* Summary / Description */}\n {(endpoint.summary || endpoint.description) && (\n <div>\n {endpoint.summary && (\n <Typography variant=\"h6\" className=\"font-semibold mb-1\">\n {endpoint.summary}\n </Typography>\n )}\n {endpoint.description && (\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark\">\n {endpoint.description}\n </Typography>\n )}\n </div>\n )}\n\n {/* Parameters */}\n {endpoint.parameters.length > 0 && (\n <section>\n <SectionHeading icon={<SlidersHorizontalIcon size={iconSize.small} className=\"text-text-secondary dark:text-text-secondary-dark\" />} title=\"Parameters\"/>\n <div className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"bg-surface-raised text-left\">\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n Name\n </th>\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n In\n </th>\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n Type\n </th>\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n Description\n </th>\n </tr>\n </thead>\n <tbody>\n {endpoint.parameters.map((p, i) => (\n <tr\n key={p.name + i}\n className={cls(\"border-t\", defaultBorderMixin)}\n >\n <td className=\"px-4 py-2.5\">\n <code className=\"text-xs font-mono font-semibold\">{p.name}</code>\n {p.required && <span className=\"text-red-500 ml-1 text-xs\">*</span>}\n </td>\n <td className=\"px-4 py-2.5\">\n <Chip\n size=\"smallest\"\n colorScheme={p.in === \"path\" ? \"orangeDarker\" : \"cyanDarker\"}\n >\n {p.in}\n </Chip>\n </td>\n <td className=\"px-4 py-2.5 text-xs font-mono text-text-secondary dark:text-text-secondary-dark\">\n {schemaTypeLabel(p.schema)}\n </td>\n <td className=\"px-4 py-2.5 text-xs text-text-secondary dark:text-text-secondary-dark\">\n {p.description ?? \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n )}\n\n {/* Request Body */}\n {endpoint.requestBody && (\n <section>\n <SectionHeading icon={<UploadIcon size={iconSize.small} className=\"text-text-secondary dark:text-text-secondary-dark\" />} title=\"Request Body\"/>\n {Object.entries(endpoint.requestBody.content ?? {}).map(([contentType, media]) => (\n <div key={contentType}>\n <Chip size=\"smallest\" colorScheme=\"blueDarker\" className=\"mb-3\">\n {contentType}\n </Chip>\n {media.schema && <SchemaBlock schema={media.schema} spec={spec} depth={0}/>}\n </div>\n ))}\n </section>\n )}\n\n {/* Responses */}\n <section>\n <SectionHeading icon={<ArrowRightFromLineIcon size={iconSize.small} className=\"text-text-secondary dark:text-text-secondary-dark\" />} title=\"Responses\"/>\n <div className=\"space-y-3\">\n {Object.entries(endpoint.responses).map(([code, res]) => (\n <div\n key={code}\n className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}\n >\n <div\n className={cls(\n \"flex items-center gap-3 px-4 py-2.5\",\n \"bg-surface-sheet\"\n )}\n >\n <StatusBadge code={code}/>\n <Typography\n variant=\"body2\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs\"\n >\n {res.description}\n </Typography>\n </div>\n {res.content &&\n Object.entries(res.content).map(\n ([ct, media]) =>\n media.schema && (\n <div\n key={ct}\n className={cls(\"px-4 py-3 border-t\", defaultBorderMixin)}\n >\n <SchemaBlock schema={media.schema} spec={spec} depth={0}/>\n </div>\n )\n )}\n </div>\n ))}\n </div>\n </section>\n </div>\n );\n}\n\n/* ── Schema Block ─────────────────────────────────────────────────── */\n\nfunction SchemaBlock({ schema, spec, depth }: { schema: OpenApiSchema; spec: OpenApiSpec; depth: number }) {\n // Resolve $ref\n if (schema.$ref) {\n const name = resolveRefName(schema.$ref);\n const resolved = resolveRef(spec, schema.$ref) as OpenApiSchema;\n return (\n <div>\n <Typography\n variant=\"caption\"\n className=\"text-primary dark:text-primary-dark font-mono text-xs mb-2 block\"\n >\n {name}\n </Typography>\n <SchemaBlock schema={resolved} spec={spec} depth={depth}/>\n </div>\n );\n }\n\n // Object with properties\n if (schema.properties) {\n const required = new Set(schema.required ?? []);\n return (\n <div\n className={cls(\n \"rounded-lg overflow-hidden\",\n depth > 0 && `border ml-4 mt-1 ${defaultBorderMixin}`\n )}\n >\n <table className=\"w-full text-xs\">\n <tbody>\n {Object.entries(schema.properties).map(([key, prop]) => (\n <tr\n key={key}\n className={cls(\"border-t first:border-t-0\", defaultBorderMixin)}\n >\n <td className=\"px-3 py-2 align-top w-36\">\n <code className=\"font-mono font-semibold text-text-primary dark:text-text-primary-dark\">\n {key}\n </code>\n {required.has(key) && <span className=\"text-red-500 ml-0.5\">*</span>}\n {prop.readOnly && (\n <span className=\"ml-1.5 text-[9px] text-text-secondary dark:text-text-secondary-dark italic\">\n read-only\n </span>\n )}\n </td>\n <td className=\"px-3 py-2 align-top w-28\">\n <span className=\"font-mono text-text-secondary dark:text-text-secondary-dark\">\n {schemaTypeLabel(prop)}\n </span>\n </td>\n <td className=\"px-3 py-2 align-top text-text-secondary dark:text-text-secondary-dark\">\n {prop.description ?? \"\"}\n {prop.enum && (\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {prop.enum.map((v) => (\n <span\n key={String(v)}\n className=\"px-1.5 py-0.5 rounded bg-surface-raised text-[10px] font-mono\"\n >\n {String(v)}\n </span>\n ))}\n </div>\n )}\n {prop.properties && <SchemaBlock schema={prop} spec={spec} depth={depth + 1}/>}\n {prop.$ref && <SchemaBlock schema={prop} spec={spec} depth={depth + 1}/>}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n }\n\n // Array\n if (schema.type === \"array\" && schema.items) {\n return (\n <div>\n <span className=\"font-mono text-xs text-text-secondary dark:text-text-secondary-dark\">Array of:</span>\n <SchemaBlock schema={schema.items} spec={spec} depth={depth + 1}/>\n </div>\n );\n }\n\n // Primitive\n return (\n <span className=\"font-mono text-xs text-text-secondary dark:text-text-secondary-dark\">\n {schemaTypeLabel(schema)}\n </span>\n );\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────── */\n\nfunction schemaTypeLabel(schema?: OpenApiSchema): string {\n if (!schema) return \"any\";\n if (schema.$ref) return resolveRefName(schema.$ref);\n if (schema.type === \"array\") return `${schemaTypeLabel(schema.items)}[]`;\n if (schema.format) return `${schema.type} (${schema.format})`;\n return schema.type ?? \"object\";\n}\n\nfunction SectionHeading({ icon, title }: { icon: React.ReactNode; title: string }) {\n return (\n <div className=\"flex items-center gap-2 mb-3\">\n {icon}\n <Typography variant=\"subtitle2\" className=\"font-semibold text-sm\">\n {title}\n </Typography>\n </div>\n );\n}\n\nfunction StatusBadge({ code }: { code: string }) {\n const n = parseInt(code, 10);\n const color =\n n < 300\n ? \"text-emerald-600 dark:text-emerald-400\"\n : n < 400\n ? \"text-blue-600 dark:text-blue-400\"\n : n < 500\n ? \"text-amber-600 dark:text-amber-400\"\n : \"text-red-600 dark:text-red-400\";\n\n return <span className={cls(\"text-xs font-semibold font-mono\", color)}>{code}</span>;\n}\n","import { useTranslation } from \"@rebasepro/app\";\nimport React, { useState, useCallback, useMemo, useEffect } from \"react\";\nimport {\n Button,\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n LoaderIcon,\n PlusIcon,\n SendIcon,\n TextField,\n Typography,\n XIcon\n} from \"@rebasepro/ui\";\nimport type { SelectableUser } from \"@rebasepro/app\";\nimport { AuthSimulationSelector } from \"../AuthSimulationSelector\";\nimport { useRunAsUsers } from \"../useRunAsUsers\";\nimport type { ParsedEndpoint } from \"./types\";\nimport { IMPERSONATE_HEADER, type User } from \"@rebasepro/types\";\n\ninterface TryItPanelProps {\n endpoint: ParsedEndpoint;\n apiUrl: string;\n getAuthToken: () => Promise<string | null | undefined>;\n user: User | null;\n basePath?: string;\n}\n\n/**\n * Interactive \"Try It\" panel that lets the user execute API requests\n * using their current JWT token directly from the Studio.\n *\n * An administrator can run a request as another user: it is sent with their\n * own token and the {@link IMPERSONATE_HEADER} header, and the server runs it\n * as that user — their uid and roles, under row-level security — or refuses\n * it. It never runs as the administrator instead.\n */\nexport function TryItPanel({ endpoint, apiUrl, getAuthToken, user, basePath = \"\" }: TryItPanelProps) {\n const storageKey = `rebase_apiexplorer_${endpoint.method}_${endpoint.path}`;\n\n const [pathParams, setPathParams] = useState<Record<string, string>>(() => {\n try { const v = localStorage.getItem(`${storageKey}_path`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n return {};\n });\n const [queryParams, setQueryParams] = useState<Record<string, string>>(() => {\n try { const v = localStorage.getItem(`${storageKey}_query`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n return {};\n });\n const [customHeaders, setCustomHeaders] = useState<Array<{ key: string; value: string }>>(() => {\n try { const v = localStorage.getItem(`${storageKey}_headers`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n // None until the caller adds one: every header here is sent.\n return [];\n });\n const [body, setBody] = useState(() => {\n try { const v = localStorage.getItem(`${storageKey}_body`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n return buildBodyTemplate(endpoint);\n });\n const [response, setResponse] = useState<{ status: number; statusText: string; body: string; time: number } | null>(\n null\n );\n const [loading, setLoading] = useState(false);\n const [authMode, setAuthMode] = useState<\"jwt\" | \"none\">(\"jwt\");\n const [validationError, setValidationError] = useState<string | null>(null);\n\n // An administrator is offered the project's users; anyone else, only\n // themselves — the server lets nobody else run a request as someone.\n const { users, currentUser, loading: usersLoading, onSearchTextChange, totalCount: userTotalCount } = useRunAsUsers();\n\n const [selectedUser, setSelectedUser] = useState<SelectableUser | null>(null);\n\n useEffect(() => {\n localStorage.setItem(`${storageKey}_path`, JSON.stringify(pathParams));\n localStorage.setItem(`${storageKey}_query`, JSON.stringify(queryParams));\n localStorage.setItem(`${storageKey}_headers`, JSON.stringify(customHeaders));\n localStorage.setItem(`${storageKey}_body`, JSON.stringify(body));\n }, [storageKey, pathParams, queryParams, customHeaders, body]);\n\n // Build the final URL\n const resolvedUrl = useMemo(() => {\n const base = basePath.startsWith(\"/\") ? basePath : `/${basePath}`;\n const cleanBase = base === \"/\" ? \"\" : base;\n let url = `${apiUrl.replace(/\\/+$/, \"\")}${cleanBase}${endpoint.path}`;\n // Replace path params\n for (const [key, val] of Object.entries(pathParams)) {\n url = url.replace(`{${key}}`, encodeURIComponent(val));\n }\n // Append query params\n const qp = Object.entries(queryParams).filter(([, v]) => v.trim() !== \"\");\n if (qp.length > 0) {\n url += \"?\" + qp.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join(\"&\");\n }\n return url;\n }, [apiUrl, basePath, endpoint.path, pathParams, queryParams]);\n\n const pathParamDefs = endpoint.parameters.filter((p) => p.in === \"path\");\n const queryParamDefs = endpoint.parameters.filter((p) => p.in === \"query\");\n const hasBody = [\"post\", \"put\", \"patch\"].includes(endpoint.method);\n\n const execute = useCallback(async () => {\n setValidationError(null);\n if (hasBody && body.trim()) {\n try {\n JSON.parse(body);\n } catch (err: unknown) {\n setValidationError(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`);\n return;\n }\n }\n\n setLoading(true);\n setResponse(null);\n const start = performance.now();\n\n try {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n\n for (const h of customHeaders) {\n if (h.key.trim()) headers[h.key.trim()] = h.value;\n }\n\n if (authMode === \"jwt\") {\n const token = await getAuthToken();\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n if (selectedUser && selectedUser.uid !== currentUser?.uid) {\n headers[IMPERSONATE_HEADER] = selectedUser.uid;\n }\n }\n\n const res = await fetch(resolvedUrl, {\n method: endpoint.method.toUpperCase(),\n headers,\n body: hasBody && body.trim() ? body : undefined\n });\n\n const elapsed = Math.round(performance.now() - start);\n let text: string;\n\n const rawText = await res.text();\n try {\n const json = JSON.parse(rawText);\n text = JSON.stringify(json, null, 2);\n } catch {\n text = rawText;\n }\n\n setResponse({ status: res.status,\nstatusText: res.statusText,\nbody: text,\ntime: elapsed });\n } catch (err: unknown) {\n setResponse({\n status: 0,\n statusText: \"Network Error\",\n body: err instanceof Error ? err.message : \"Request failed\",\n time: Math.round(performance.now() - start)\n });\n } finally {\n setLoading(false);\n }\n }, [resolvedUrl, endpoint.method, hasBody, body, authMode, getAuthToken, customHeaders, selectedUser, currentUser?.uid]);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"p-5 space-y-5 overflow-y-auto flex-1\">\n {/* Auth Mode */}\n <AuthSimulationSelector\n authMode={authMode}\n setAuthMode={setAuthMode}\n selectedUser={selectedUser}\n setSelectedUser={setSelectedUser}\n users={users}\n loading={usersLoading}\n onUserSearchTextChange={onSearchTextChange}\n userTotalCount={userTotalCount}\n currentUser={currentUser}\n />\n\n {/* Path Params */}\n {pathParamDefs.length > 0 && (\n <ParamSection\n title=\"Path Parameters\"\n params={pathParamDefs}\n values={pathParams}\n onChange={(k, v) => setPathParams((prev) => ({ ...prev,\n[k]: v }))}\n />\n )}\n\n {/* Query Params */}\n {queryParamDefs.length > 0 && (\n <ParamSection\n title=\"Query Parameters\"\n params={queryParamDefs}\n values={queryParams}\n onChange={(k, v) => setQueryParams((prev) => ({ ...prev,\n[k]: v }))}\n />\n )}\n\n {/* Custom Headers */}\n <CustomKeyValueSection\n title=\"Custom Headers\"\n values={customHeaders}\n onChange={(i, k, v) => {\n const next = [...customHeaders];\n next[i] = { key: k,\nvalue: v };\n setCustomHeaders(next);\n }}\n onAdd={() => setCustomHeaders((prev) => [...prev, { key: \"\",\nvalue: \"\" }])}\n onRemove={(i) => {\n const next = [...customHeaders];\n next.splice(i, 1);\n setCustomHeaders(next);\n }}\n />\n\n {/* Request Body */}\n {hasBody && (\n <div>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-semibold uppercase tracking-wider mb-2 block\"\n >\n Request Body\n </Typography>\n <TextField\n multiline\n minRows={10}\n aria-label=\"Request Body\"\n value={body}\n onChange={(e) => { setBody(e.target.value); setValidationError(null); }}\n spellCheck={false}\n error={!!validationError}\n className=\"w-full\"\n inputClassName=\"font-mono text-xs p-3 resize-y\"\n />\n {validationError && (\n <Typography variant=\"caption\" className=\"text-red-500 mt-1 block text-xs\">\n {validationError}\n </Typography>\n )}\n </div>\n )}\n\n {/* URL Preview */}\n <div className=\"rounded-lg bg-surface-raised p-3\">\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-[10px] uppercase tracking-wider block mb-1\"\n >\n Request URL\n </Typography>\n <code className=\"text-xs font-mono text-text-primary dark:text-text-primary-dark break-all\">\n {resolvedUrl}\n </code>\n </div>\n\n {/* Execute Button */}\n <Button variant=\"filled\" onClick={execute} disabled={loading} className=\"w-full\">\n {loading ? (\n <span className=\"flex items-center gap-2\">\n <LoaderIcon size={iconSize.small} className=\"animate-spin\" />\n Sending…\n </span>\n ) : (\n <span className=\"flex items-center gap-2\">\n <SendIcon size={iconSize.small} />\n Send Request\n </span>\n )}\n </Button>\n\n {/* Response */}\n {response && (\n <div className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}>\n <div\n className={cls(\n \"flex items-center justify-between px-4 py-2.5\",\n \"bg-surface-sheet\"\n )}\n >\n <div className=\"flex items-center gap-3\">\n <ResponseBadge status={response.status}/>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs\"\n >\n {response.statusText}\n </Typography>\n </div>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-mono\"\n >\n {response.time}ms\n </Typography>\n </div>\n <pre\n className={cls(\n \"p-4 text-xs font-mono overflow-auto max-h-96\",\n \"bg-surface-well text-emerald-700 dark:text-emerald-400\"\n )}\n >\n {response.body}\n </pre>\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Param Section ────────────────────────────────────────────────── */\n\nfunction ParamSection({\n title,\n params,\n values,\n onChange\n}: {\n title: string;\n params: ParsedEndpoint[\"parameters\"];\n values: Record<string, string>;\n onChange: (_key: string, _value: string) => void;\n}) {\n const paramIdBase = React.useId();\n return (\n <div>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-semibold uppercase tracking-wider mb-2 block\"\n >\n {title}\n </Typography>\n <div className=\"space-y-2\">\n {params.map((p, index) => (\n <div key={p.name} className=\"flex items-center gap-3\">\n <label className=\"w-32 shrink-0\" htmlFor={`${paramIdBase}-${index}-param`}>\n <code className=\"text-xs font-mono font-semibold\">{p.name}</code>\n {p.required && <span className=\"text-red-500 ml-0.5 text-xs\">*</span>}\n </label>\n <TextField\n id={`${paramIdBase}-${index}-param`}\n size=\"small\"\n placeholder={p.description ?? p.name}\n value={values[p.name] ?? \"\"}\n onChange={(e) => onChange(p.name, e.target.value)}\n className=\"flex-1\"\n inputClassName=\"font-mono text-xs\"\n />\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction CustomKeyValueSection({\n title,\n values,\n onChange,\n onAdd,\n onRemove\n}: {\n title: string;\n values: Array<{ key: string; value: string }>;\n onChange: (index: number, key: string, value: string) => void;\n onAdd: () => void;\n onRemove: (index: number) => void;\n}) {\n const { t } = useTranslation();\n return (\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-semibold uppercase tracking-wider block\"\n >\n {title}\n </Typography>\n <Button\n variant=\"text\"\n size=\"small\"\n color=\"primary\"\n onClick={onAdd}\n className=\"text-xs p-0 min-h-0\"\n >\n <PlusIcon size={iconSize.small} className=\"mr-1\" /> Add Header\n </Button>\n </div>\n <div className=\"space-y-2\">\n {values.map((v, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <TextField\n size=\"small\"\n aria-label={`Header ${i + 1} name`}\n placeholder=\"Header name\"\n value={v.key}\n onChange={(e) => onChange(i, e.target.value, v.value)}\n className=\"w-1/3\"\n inputClassName=\"font-mono text-xs\"\n />\n <TextField\n size=\"small\"\n aria-label={`Header ${i + 1} value`}\n placeholder=\"Value\"\n value={v.value}\n onChange={(e) => onChange(i, v.key, e.target.value)}\n className=\"flex-1\"\n inputClassName=\"font-mono text-xs\"\n />\n <IconButton aria-label={t(\"remove\")}\n size=\"small\"\n onClick={() => onRemove(i)}\n className=\"text-text-secondary hover:text-red-500 shrink-0\"\n title={t(\"remove\")}\n >\n <XIcon size={iconSize.small} />\n </IconButton>\n </div>\n ))}\n {values.length === 0 && (\n <Typography variant=\"caption\" className=\"text-text-secondary/50 italic text-xs\">\n No custom headers added.\n </Typography>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────── */\n\nfunction ResponseBadge({ status }: { status: number }) {\n let colorClass = \"text-red-500\";\n if (status >= 200 && status < 300) colorClass = \"text-emerald-500\";\n else if (status >= 300 && status < 400) colorClass = \"text-blue-500\";\n else if (status >= 400 && status < 500) colorClass = \"text-amber-500\";\n\n return (\n <span className={cls(\"text-xs font-semibold font-mono\", colorClass)}>\n {status || \"ERR\"}\n </span>\n );\n}\n\nfunction buildBodyTemplate(endpoint: ParsedEndpoint): string {\n if (!endpoint.requestBody?.content) return \"{\\n \\n}\";\n const json = endpoint.requestBody.content[\"application/json\"];\n if (!json?.schema?.properties) return \"{\\n \\n}\";\n\n const props = json.schema.properties;\n const lines: string[] = [\"{\"];\n const keys = Object.keys(props);\n keys.forEach((key, i) => {\n const prop = props[key];\n if (prop.readOnly) return;\n const comma = i < keys.length - 1 ? \",\" : \"\";\n const val = defaultValue(prop);\n lines.push(` \"${key}\": ${val}${comma}`);\n });\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction defaultValue(schema: { type?: string; format?: string; enum?: (string | number)[] }): string {\n if (schema.enum) return JSON.stringify(schema.enum[0]);\n switch (schema.type) {\n case \"string\":\n return schema.format === \"date-time\" ? `\"${new Date().toISOString()}\"` : '\"\"';\n case \"number\":\n case \"integer\":\n return \"0\";\n case \"boolean\":\n return \"false\";\n case \"array\":\n return \"[]\";\n default:\n return \"null\";\n }\n}\n","import React, { useState, useEffect, useMemo } from \"react\";\nimport { useApiBase, useApiConfig, useAuthController } from \"@rebasepro/app\";\nimport {\n CircularProgress,\n Typography,\n Alert,\n cls,\n Button,\n Chip,\n defaultBorderMixin,\n SearchBar,\n iconSize\n} from \"@rebasepro/ui\";\nimport { BookOpenIcon, PlayIcon } from \"@rebasepro/ui\";\nimport { EndpointDetail } from \"./EndpointDetail\";\nimport { TryItPanel } from \"./TryItPanel\";\nimport type { OpenApiSpec, ParsedEndpoint } from \"./types\";\nimport { parseOpenApiSpec } from \"./parseSpec\";\n\n/**\n * Custom-built API Explorer for Rebase Studio.\n * No external dependencies — renders the OpenAPI spec natively\n * with deep integration into the Rebase auth system.\n */\nexport function ApiExplorer() {\n const apiConfig = useApiConfig();\n const apiBase = useApiBase();\n const authController = useAuthController();\n const apiUrl = apiConfig?.apiUrl;\n\n const [spec, setSpec] = useState<OpenApiSpec | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const [selectedEndpoint, setSelectedEndpoint] = useState<ParsedEndpoint | null>(null);\n const [sidebarFilter, setSidebarFilter] = useState(\"\");\n const [tryItOpen, setTryItOpen] = useState(false);\n\n // Fetch OpenAPI spec\n useEffect(() => {\n if (!apiUrl) return;\n let cancelled = false;\n const specUrl = `${apiBase}/docs`;\n\n (async () => {\n try {\n // The spec endpoint itself is public on a stock backend, but\n // `apiUrl` may route through an authenticated proxy (the\n // console's Studio embed) — carry the token like every other\n // request in this view, and like LogsExplorer does.\n const getAuthToken = apiConfig?.getAuthToken ?? authController.getAuthToken;\n const token = getAuthToken ? await getAuthToken() : null;\n const res = await fetch(specUrl, token ? { headers: { Authorization: `Bearer ${token}` } } : undefined);\n if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);\n const data = await res.json();\n if (!cancelled) {\n setSpec(data);\n setLoading(false);\n }\n } catch (err: unknown) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : \"Failed to load API spec\");\n setLoading(false);\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [apiUrl, apiBase, apiConfig, authController]);\n\n // Parse spec into grouped endpoints\n const { groups, allEndpoints } = useMemo(() => {\n if (!spec) return { groups: [],\nallEndpoints: [] };\n return parseOpenApiSpec(spec);\n }, [spec]);\n\n // Filter\n const filteredGroups = useMemo(() => {\n if (!sidebarFilter.trim()) return groups;\n const q = sidebarFilter.toLowerCase();\n return groups\n .map((g) => ({\n ...g,\n endpoints: g.endpoints.filter(\n (e) =>\n e.path.toLowerCase().includes(q) ||\n e.summary.toLowerCase().includes(q) ||\n e.method.toLowerCase().includes(q)\n )\n }))\n .filter((g) => g.endpoints.length > 0);\n }, [groups, sidebarFilter]);\n\n // Auto-select first endpoint\n useEffect(() => {\n if (!selectedEndpoint && allEndpoints.length > 0) {\n setSelectedEndpoint(allEndpoints[0]);\n }\n }, [allEndpoints, selectedEndpoint]);\n\n // ── States ───────────────────────────────────────────────────────\n if (!apiUrl) {\n return (\n <div className=\"flex items-center justify-center h-full w-full p-8\">\n <Alert color=\"warning\">\n <Typography variant=\"body2\">\n No API URL configured. Ensure your app provides an{\" \"}\n <code className=\"font-mono text-xs\">apiUrl</code>.\n </Typography>\n </Alert>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"flex flex-col items-center justify-center h-full w-full gap-4\">\n <CircularProgress size=\"medium\"/>\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark animate-pulse\">\n Loading API specification…\n </Typography>\n </div>\n );\n }\n\n if (error || !spec) {\n // The API spec fetch rejects with whatever the transport says, and for\n // an expired console session that is the string \"401\". Rendering it\n // verbatim produced the worst screen in the console: a red box\n // containing three digits, no title, no cause, no way out — on the same\n // product whose storage browser writes four sentences explaining which\n // authorization hook refused a listing.\n //\n // The raw text is kept, below the sentence, because it is what someone\n // pastes into a bug report. It is just no longer the whole message.\n const status = (error ?? \"\").trim();\n const isAuth = /^(401|403)\\b/.test(status) || /unauthori[sz]ed|forbidden/i.test(status);\n return (\n <div className=\"flex items-center justify-center h-full w-full p-8\">\n <div className=\"max-w-md text-center\">\n <Typography variant=\"subtitle2\" className=\"block text-text-primary dark:text-text-primary-dark\">\n {isAuth ? \"This session cannot read the API specification\" : \"Could not load the API specification\"}\n </Typography>\n <Typography variant=\"body2\" className=\"block mt-2 text-text-secondary dark:text-text-secondary-dark\">\n {isAuth\n ? \"The console's access to this project's API was refused. It usually means the session expired — sign in again — or that console access has been turned off for this project in Settings.\"\n : \"The project answered, but not with a specification this explorer could read. Its API is unaffected; only this page is.\"}\n </Typography>\n <Button\n variant=\"outlined\"\n color=\"neutral\"\n size=\"small\"\n className=\"mt-4\"\n onClick={() => window.location.reload()}\n >\n Try again\n </Button>\n {status && (\n <Typography variant=\"caption\" className=\"block mt-4 font-mono text-text-disabled dark:text-text-disabled-dark\">\n {status}\n </Typography>\n )}\n </div>\n </div>\n );\n }\n\n const METHOD_COLORS: Record<string, string> = {\n get: \"text-blue-600 dark:text-blue-400\",\n post: \"text-emerald-600 dark:text-emerald-400\",\n put: \"text-amber-600 dark:text-amber-400\",\n patch: \"text-orange-600 dark:text-orange-400\",\n delete: \"text-red-600 dark:text-red-400\"\n };\n\n return (\n <div className=\"flex h-full w-full overflow-hidden\">\n {/* ── Sidebar ──────────────────────────────────────── */}\n <div\n className={cls(\n \"w-72 min-w-[272px] flex flex-col h-full overflow-hidden border-r\",\n defaultBorderMixin,\n \"bg-surface-sheet\"\n )}\n >\n {/* Header */}\n <div className=\"p-4 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <BookOpenIcon size={iconSize.medium} className=\"text-primary dark:text-primary-dark\" />\n <Typography variant=\"subtitle2\" className=\"font-semibold\">\n {spec.info?.title ?? \"API Reference\"}\n </Typography>\n </div>\n {spec.info?.version && (\n <Chip size=\"smallest\" colorScheme=\"cyanDarker\">\n v{spec.info.version}\n </Chip>\n )}\n {/* Search */}\n <div className=\"mb-2\">\n <SearchBar\n placeholder=\"Filter endpoints…\"\n size=\"small\"\n onTextSearch={(val) => setSidebarFilter(val ?? \"\")}\n />\n </div>\n\n {/* Auth status removed to avoid redundancy with the AuthSimulationSelector */}\n </div>\n\n {/* Endpoint list */}\n <div className=\"flex-1 overflow-y-auto px-2 pb-4\">\n {filteredGroups.map((group) => (\n <div key={group.tag} className=\"mb-3\">\n <Typography\n variant=\"caption\"\n className=\"px-2 py-1.5 text-text-secondary dark:text-text-secondary-dark uppercase tracking-wider font-semibold text-[10px]\"\n >\n {group.tag}\n </Typography>\n {group.endpoints.map((ep) => {\n const isSelected = selectedEndpoint?.id === ep.id;\n return (\n <Button\n key={ep.id}\n variant=\"text\"\n color=\"neutral\"\n fullWidth\n onClick={() => {\n setSelectedEndpoint(ep);\n setTryItOpen(false);\n }}\n className={cls(\n \"!justify-between !px-2.5 !py-1.5 !text-left !text-sm\",\n isSelected\n ? \"bg-surface-raised font-medium\"\n : \"text-text-primary dark:text-text-primary-dark\"\n )}\n >\n <span className=\"truncate text-[13px] opacity-90\">{ep.summary || ep.shortPath}</span>\n <span\n className={cls(\n \"text-[10px] font-semibold uppercase shrink-0\",\n METHOD_COLORS[ep.method] ?? \"text-text-secondary\"\n )}\n >\n {ep.method}\n </span>\n </Button>\n );\n })}\n </div>\n ))}\n {filteredGroups.length === 0 && (\n <Typography\n variant=\"body2\"\n className=\"text-center text-text-secondary dark:text-text-secondary-dark py-8\"\n >\n No endpoints match\n </Typography>\n )}\n </div>\n </div>\n\n {/* ── Main content ─────────────────────────────────── */}\n <div className=\"flex-1 flex flex-col h-full overflow-hidden\">\n {selectedEndpoint ? (\n <>\n {/* Top bar */}\n <div\n className={cls(\n \"flex items-center justify-between px-5 py-3 gap-4 shrink-0 border-b z-10\",\n defaultBorderMixin,\n \"bg-surface-sheet/90 backdrop-blur-md sticky top-0\"\n )}\n >\n <div className=\"flex items-center gap-3 min-w-0\">\n <span\n className={cls(\n \"text-xs font-semibold uppercase\",\n METHOD_COLORS[selectedEndpoint.method] ?? \"\"\n )}\n >\n {selectedEndpoint.method}\n </span>\n <code className=\"text-sm font-mono text-text-primary dark:text-text-primary-dark truncate\">\n {selectedEndpoint.path}\n </code>\n </div>\n <Button\n variant={tryItOpen ? \"filled\" : \"outlined\"}\n size=\"small\"\n onClick={() => setTryItOpen((v) => !v)}\n >\n <PlayIcon size={iconSize.small} className=\"mr-1\" />\n Try It\n </Button>\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto\">\n {tryItOpen ? (\n <TryItPanel\n key={selectedEndpoint.operationId || selectedEndpoint.path}\n endpoint={selectedEndpoint}\n apiUrl={apiUrl}\n getAuthToken={apiConfig?.getAuthToken ?? authController.getAuthToken}\n user={authController.user}\n basePath={spec?.servers?.[0]?.url || \"\"}\n />\n ) : (\n <EndpointDetail endpoint={selectedEndpoint} spec={spec}/>\n )}\n </div>\n </>\n ) : (\n <div className=\"flex items-center justify-center h-full\">\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark\">\n Select an endpoint from the sidebar\n </Typography>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nApiExplorer.displayName = \"ApiExplorer\";\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"ApiExplorer-B82tFVBX.js","names":[],"sources":["../src/components/ApiExplorer/parseSpec.ts","../src/components/ApiExplorer/EndpointDetail.tsx","../src/components/ApiExplorer/TryItPanel.tsx","../src/components/ApiExplorer/ApiExplorer.tsx"],"sourcesContent":["import type { OpenApiSpec, ParsedEndpoint, EndpointGroup } from \"./types\";\n\n/**\n * Parse an OpenAPI 3.x spec into grouped, sorted endpoints for the sidebar.\n */\nexport function parseOpenApiSpec(spec: OpenApiSpec): {\n groups: EndpointGroup[];\n allEndpoints: ParsedEndpoint[];\n} {\n const allEndpoints: ParsedEndpoint[] = [];\n const tagMap = new Map<string, ParsedEndpoint[]>();\n\n // Build tag description lookup\n const tagDescriptions = new Map<string, string>();\n for (const t of spec.tags ?? []) {\n tagDescriptions.set(t.name, t.description ?? \"\");\n }\n\n for (const [path, methods] of Object.entries(spec.paths ?? {})) {\n for (const [method, op] of Object.entries(methods)) {\n if ([\"get\", \"post\", \"put\", \"patch\", \"delete\"].indexOf(method) === -1) continue;\n\n const tags = op.tags?.length ? op.tags : [\"Other\"];\n const shortPath = path.replace(/^\\/api\\/data/, \"\");\n\n const endpoint: ParsedEndpoint = {\n id: `${method}:${path}`,\n method,\n path,\n shortPath: shortPath || \"/\",\n summary: op.summary ?? \"\",\n description: op.description ?? \"\",\n tags,\n parameters: op.parameters ?? [],\n requestBody: op.requestBody,\n responses: op.responses ?? {},\n security: op.security,\n operationId: op.operationId\n };\n\n allEndpoints.push(endpoint);\n for (const tag of tags) {\n if (!tagMap.has(tag)) tagMap.set(tag, []);\n tagMap.get(tag)!.push(endpoint);\n }\n }\n }\n\n // Method sort order\n const ORDER: Record<string, number> = { get: 0,\npost: 1,\nput: 2,\npatch: 3,\ndelete: 4 };\n\n const groups: EndpointGroup[] = [];\n // Sort tags: use spec.tags order if available, else alphabetical\n const tagOrder = (spec.tags ?? []).map((t) => t.name);\n const sortedTags = [...tagMap.keys()].sort((a, b) => {\n const ai = tagOrder.indexOf(a);\n const bi = tagOrder.indexOf(b);\n if (ai !== -1 && bi !== -1) return ai - bi;\n if (ai !== -1) return -1;\n if (bi !== -1) return 1;\n return a.localeCompare(b);\n });\n\n for (const tag of sortedTags) {\n const endpoints = tagMap.get(tag)!;\n endpoints.sort((a, b) => {\n const pa = a.path.localeCompare(b.path);\n if (pa !== 0) return pa;\n return (ORDER[a.method] ?? 99) - (ORDER[b.method] ?? 99);\n });\n groups.push({\n tag,\n description: tagDescriptions.get(tag),\n endpoints\n });\n }\n\n return { groups,\nallEndpoints };\n}\n\n/**\n * Resolve a $ref string (e.g. \"#/components/schemas/Author\") to a schema name.\n */\nexport function resolveRefName(ref: string): string {\n const parts = ref.split(\"/\");\n return parts[parts.length - 1];\n}\n\n/**\n * Resolve a $ref to its actual schema from the spec.\n */\nexport function resolveRef(spec: OpenApiSpec, ref: string): unknown {\n const parts = ref.replace(\"#/\", \"\").split(\"/\");\n let current: unknown = spec;\n for (const part of parts) {\n current = (current as Record<string, unknown>)?.[part];\n }\n return current ?? {};\n}\n","import React from \"react\";\nimport {\n ArrowRightFromLineIcon,\n Chip,\n cls,\n defaultBorderMixin,\n iconSize,\n SlidersHorizontalIcon,\n Typography,\n UploadIcon\n} from \"@rebasepro/ui\";\nimport type { ParsedEndpoint, OpenApiSpec, OpenApiSchema } from \"./types\";\nimport { resolveRef, resolveRefName } from \"./parseSpec\";\n\n/**\n * Renders the documentation view for a single API endpoint:\n * parameters, request body schema, response schemas.\n */\nexport function EndpointDetail({ endpoint, spec }: { endpoint: ParsedEndpoint; spec: OpenApiSpec }) {\n return (\n <div className=\"p-6 space-y-8 max-w-4xl\">\n {/* Summary / Description */}\n {(endpoint.summary || endpoint.description) && (\n <div>\n {endpoint.summary && (\n <Typography variant=\"h6\" className=\"font-semibold mb-1\">\n {endpoint.summary}\n </Typography>\n )}\n {endpoint.description && (\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark\">\n {endpoint.description}\n </Typography>\n )}\n </div>\n )}\n\n {/* Parameters */}\n {endpoint.parameters.length > 0 && (\n <section>\n <SectionHeading icon={<SlidersHorizontalIcon size={iconSize.small} className=\"text-text-secondary dark:text-text-secondary-dark\" />} title=\"Parameters\"/>\n <div className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"bg-surface-raised text-left\">\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n Name\n </th>\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n In\n </th>\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n Type\n </th>\n <th className=\"px-4 py-2 font-medium text-text-secondary dark:text-text-secondary-dark\">\n Description\n </th>\n </tr>\n </thead>\n <tbody>\n {endpoint.parameters.map((p, i) => (\n <tr\n key={p.name + i}\n className={cls(\"border-t\", defaultBorderMixin)}\n >\n <td className=\"px-4 py-2.5\">\n <code className=\"text-xs font-mono font-semibold\">{p.name}</code>\n {p.required && <span className=\"text-red-500 ml-1 text-xs\">*</span>}\n </td>\n <td className=\"px-4 py-2.5\">\n <Chip\n size=\"smallest\"\n colorScheme={p.in === \"path\" ? \"orangeDarker\" : \"cyanDarker\"}\n >\n {p.in}\n </Chip>\n </td>\n <td className=\"px-4 py-2.5 text-xs font-mono text-text-secondary dark:text-text-secondary-dark\">\n {schemaTypeLabel(p.schema)}\n </td>\n <td className=\"px-4 py-2.5 text-xs text-text-secondary dark:text-text-secondary-dark\">\n {p.description ?? \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n )}\n\n {/* Request Body */}\n {endpoint.requestBody && (\n <section>\n <SectionHeading icon={<UploadIcon size={iconSize.small} className=\"text-text-secondary dark:text-text-secondary-dark\" />} title=\"Request Body\"/>\n {Object.entries(endpoint.requestBody.content ?? {}).map(([contentType, media]) => (\n <div key={contentType}>\n <Chip size=\"smallest\" colorScheme=\"blueDarker\" className=\"mb-3\">\n {contentType}\n </Chip>\n {media.schema && <SchemaBlock schema={media.schema} spec={spec} depth={0}/>}\n </div>\n ))}\n </section>\n )}\n\n {/* Responses */}\n <section>\n <SectionHeading icon={<ArrowRightFromLineIcon size={iconSize.small} className=\"text-text-secondary dark:text-text-secondary-dark\" />} title=\"Responses\"/>\n <div className=\"space-y-3\">\n {Object.entries(endpoint.responses).map(([code, res]) => (\n <div\n key={code}\n className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}\n >\n <div\n className={cls(\n \"flex items-center gap-3 px-4 py-2.5\",\n \"bg-surface-sheet\"\n )}\n >\n <StatusBadge code={code}/>\n <Typography\n variant=\"body2\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs\"\n >\n {res.description}\n </Typography>\n </div>\n {res.content &&\n Object.entries(res.content).map(\n ([ct, media]) =>\n media.schema && (\n <div\n key={ct}\n className={cls(\"px-4 py-3 border-t\", defaultBorderMixin)}\n >\n <SchemaBlock schema={media.schema} spec={spec} depth={0}/>\n </div>\n )\n )}\n </div>\n ))}\n </div>\n </section>\n </div>\n );\n}\n\n/* ── Schema Block ─────────────────────────────────────────────────── */\n\nfunction SchemaBlock({ schema, spec, depth }: { schema: OpenApiSchema; spec: OpenApiSpec; depth: number }) {\n // Resolve $ref\n if (schema.$ref) {\n const name = resolveRefName(schema.$ref);\n const resolved = resolveRef(spec, schema.$ref) as OpenApiSchema;\n return (\n <div>\n <Typography\n variant=\"caption\"\n className=\"text-primary dark:text-primary-dark font-mono text-xs mb-2 block\"\n >\n {name}\n </Typography>\n <SchemaBlock schema={resolved} spec={spec} depth={depth}/>\n </div>\n );\n }\n\n // Object with properties\n if (schema.properties) {\n const required = new Set(schema.required ?? []);\n return (\n <div\n className={cls(\n \"rounded-lg overflow-hidden\",\n depth > 0 && `border ml-4 mt-1 ${defaultBorderMixin}`\n )}\n >\n <table className=\"w-full text-xs\">\n <tbody>\n {Object.entries(schema.properties).map(([key, prop]) => (\n <tr\n key={key}\n className={cls(\"border-t first:border-t-0\", defaultBorderMixin)}\n >\n <td className=\"px-3 py-2 align-top w-36\">\n <code className=\"font-mono font-semibold text-text-primary dark:text-text-primary-dark\">\n {key}\n </code>\n {required.has(key) && <span className=\"text-red-500 ml-0.5\">*</span>}\n {prop.readOnly && (\n <span className=\"ml-1.5 text-[9px] text-text-secondary dark:text-text-secondary-dark italic\">\n read-only\n </span>\n )}\n </td>\n <td className=\"px-3 py-2 align-top w-28\">\n <span className=\"font-mono text-text-secondary dark:text-text-secondary-dark\">\n {schemaTypeLabel(prop)}\n </span>\n </td>\n <td className=\"px-3 py-2 align-top text-text-secondary dark:text-text-secondary-dark\">\n {prop.description ?? \"\"}\n {prop.enum && (\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {prop.enum.map((v) => (\n <span\n key={String(v)}\n className=\"px-1.5 py-0.5 rounded bg-surface-raised text-[10px] font-mono\"\n >\n {String(v)}\n </span>\n ))}\n </div>\n )}\n {prop.properties && <SchemaBlock schema={prop} spec={spec} depth={depth + 1}/>}\n {prop.$ref && <SchemaBlock schema={prop} spec={spec} depth={depth + 1}/>}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n }\n\n // Array\n if (schema.type === \"array\" && schema.items) {\n return (\n <div>\n <span className=\"font-mono text-xs text-text-secondary dark:text-text-secondary-dark\">Array of:</span>\n <SchemaBlock schema={schema.items} spec={spec} depth={depth + 1}/>\n </div>\n );\n }\n\n // Primitive\n return (\n <span className=\"font-mono text-xs text-text-secondary dark:text-text-secondary-dark\">\n {schemaTypeLabel(schema)}\n </span>\n );\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────── */\n\nfunction schemaTypeLabel(schema?: OpenApiSchema): string {\n if (!schema) return \"any\";\n if (schema.$ref) return resolveRefName(schema.$ref);\n if (schema.type === \"array\") return `${schemaTypeLabel(schema.items)}[]`;\n if (schema.format) return `${schema.type} (${schema.format})`;\n return schema.type ?? \"object\";\n}\n\nfunction SectionHeading({ icon, title }: { icon: React.ReactNode; title: string }) {\n return (\n <div className=\"flex items-center gap-2 mb-3\">\n {icon}\n <Typography variant=\"subtitle2\" className=\"font-semibold text-sm\">\n {title}\n </Typography>\n </div>\n );\n}\n\nfunction StatusBadge({ code }: { code: string }) {\n const n = parseInt(code, 10);\n const color =\n n < 300\n ? \"text-emerald-600 dark:text-emerald-400\"\n : n < 400\n ? \"text-blue-600 dark:text-blue-400\"\n : n < 500\n ? \"text-amber-600 dark:text-amber-400\"\n : \"text-red-600 dark:text-red-400\";\n\n return <span className={cls(\"text-xs font-semibold font-mono\", color)}>{code}</span>;\n}\n","import { useTranslation } from \"@rebasepro/app\";\nimport React, { useState, useCallback, useMemo, useEffect } from \"react\";\nimport {\n Button,\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n LoaderIcon,\n PlusIcon,\n SendIcon,\n TextField,\n Typography,\n XIcon\n} from \"@rebasepro/ui\";\nimport type { SelectableUser } from \"@rebasepro/app\";\nimport { AuthSimulationSelector } from \"../AuthSimulationSelector\";\nimport { useRunAsUsers } from \"../useRunAsUsers\";\nimport type { ParsedEndpoint } from \"./types\";\nimport { IMPERSONATE_HEADER, type User } from \"@rebasepro/types\";\n\ninterface TryItPanelProps {\n endpoint: ParsedEndpoint;\n apiUrl: string;\n getAuthToken: () => Promise<string | null | undefined>;\n user: User | null;\n basePath?: string;\n}\n\n/**\n * Interactive \"Try It\" panel that lets the user execute API requests\n * using their current JWT token directly from the Studio.\n *\n * An administrator can run a request as another user: it is sent with their\n * own token and the {@link IMPERSONATE_HEADER} header, and the server runs it\n * as that user — their uid and roles, under row-level security — or refuses\n * it. It never runs as the administrator instead.\n */\nexport function TryItPanel({ endpoint, apiUrl, getAuthToken, user, basePath = \"\" }: TryItPanelProps) {\n const storageKey = `rebase_apiexplorer_${endpoint.method}_${endpoint.path}`;\n\n const [pathParams, setPathParams] = useState<Record<string, string>>(() => {\n try { const v = localStorage.getItem(`${storageKey}_path`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n return {};\n });\n const [queryParams, setQueryParams] = useState<Record<string, string>>(() => {\n try { const v = localStorage.getItem(`${storageKey}_query`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n return {};\n });\n const [customHeaders, setCustomHeaders] = useState<Array<{ key: string; value: string }>>(() => {\n try { const v = localStorage.getItem(`${storageKey}_headers`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n // None until the caller adds one: every header here is sent.\n return [];\n });\n const [body, setBody] = useState(() => {\n try { const v = localStorage.getItem(`${storageKey}_body`); if (v) return JSON.parse(v); } catch { /* ignore */ }\n return buildBodyTemplate(endpoint);\n });\n const [response, setResponse] = useState<{ status: number; statusText: string; body: string; time: number } | null>(\n null\n );\n const [loading, setLoading] = useState(false);\n const [authMode, setAuthMode] = useState<\"jwt\" | \"none\">(\"jwt\");\n const [validationError, setValidationError] = useState<string | null>(null);\n\n // An administrator is offered the project's users; anyone else, only\n // themselves — the server lets nobody else run a request as someone.\n const { users, currentUser, loading: usersLoading, onSearchTextChange, totalCount: userTotalCount } = useRunAsUsers();\n\n const [selectedUser, setSelectedUser] = useState<SelectableUser | null>(null);\n\n useEffect(() => {\n localStorage.setItem(`${storageKey}_path`, JSON.stringify(pathParams));\n localStorage.setItem(`${storageKey}_query`, JSON.stringify(queryParams));\n localStorage.setItem(`${storageKey}_headers`, JSON.stringify(customHeaders));\n localStorage.setItem(`${storageKey}_body`, JSON.stringify(body));\n }, [storageKey, pathParams, queryParams, customHeaders, body]);\n\n // Build the final URL\n const resolvedUrl = useMemo(() => {\n const base = basePath.startsWith(\"/\") ? basePath : `/${basePath}`;\n const cleanBase = base === \"/\" ? \"\" : base;\n let url = `${apiUrl.replace(/\\/+$/, \"\")}${cleanBase}${endpoint.path}`;\n // Replace path params\n for (const [key, val] of Object.entries(pathParams)) {\n url = url.replace(`{${key}}`, encodeURIComponent(val));\n }\n // Append query params\n const qp = Object.entries(queryParams).filter(([, v]) => v.trim() !== \"\");\n if (qp.length > 0) {\n url += \"?\" + qp.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join(\"&\");\n }\n return url;\n }, [apiUrl, basePath, endpoint.path, pathParams, queryParams]);\n\n const pathParamDefs = endpoint.parameters.filter((p) => p.in === \"path\");\n const queryParamDefs = endpoint.parameters.filter((p) => p.in === \"query\");\n const hasBody = [\"post\", \"put\", \"patch\"].includes(endpoint.method);\n\n const execute = useCallback(async () => {\n setValidationError(null);\n if (hasBody && body.trim()) {\n try {\n JSON.parse(body);\n } catch (err: unknown) {\n setValidationError(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`);\n return;\n }\n }\n\n setLoading(true);\n setResponse(null);\n const start = performance.now();\n\n try {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n\n for (const h of customHeaders) {\n if (h.key.trim()) headers[h.key.trim()] = h.value;\n }\n\n if (authMode === \"jwt\") {\n const token = await getAuthToken();\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n if (selectedUser && selectedUser.uid !== currentUser?.uid) {\n headers[IMPERSONATE_HEADER] = selectedUser.uid;\n }\n }\n\n const res = await fetch(resolvedUrl, {\n method: endpoint.method.toUpperCase(),\n headers,\n body: hasBody && body.trim() ? body : undefined\n });\n\n const elapsed = Math.round(performance.now() - start);\n let text: string;\n\n const rawText = await res.text();\n try {\n const json = JSON.parse(rawText);\n text = JSON.stringify(json, null, 2);\n } catch {\n text = rawText;\n }\n\n setResponse({ status: res.status,\nstatusText: res.statusText,\nbody: text,\ntime: elapsed });\n } catch (err: unknown) {\n setResponse({\n status: 0,\n statusText: \"Network Error\",\n body: err instanceof Error ? err.message : \"Request failed\",\n time: Math.round(performance.now() - start)\n });\n } finally {\n setLoading(false);\n }\n }, [resolvedUrl, endpoint.method, hasBody, body, authMode, getAuthToken, customHeaders, selectedUser, currentUser?.uid]);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"p-5 space-y-5 overflow-y-auto flex-1\">\n {/* Auth Mode */}\n <AuthSimulationSelector\n authMode={authMode}\n setAuthMode={setAuthMode}\n selectedUser={selectedUser}\n setSelectedUser={setSelectedUser}\n users={users}\n loading={usersLoading}\n onUserSearchTextChange={onSearchTextChange}\n userTotalCount={userTotalCount}\n currentUser={currentUser}\n />\n\n {/* Path Params */}\n {pathParamDefs.length > 0 && (\n <ParamSection\n title=\"Path Parameters\"\n params={pathParamDefs}\n values={pathParams}\n onChange={(k, v) => setPathParams((prev) => ({ ...prev,\n[k]: v }))}\n />\n )}\n\n {/* Query Params */}\n {queryParamDefs.length > 0 && (\n <ParamSection\n title=\"Query Parameters\"\n params={queryParamDefs}\n values={queryParams}\n onChange={(k, v) => setQueryParams((prev) => ({ ...prev,\n[k]: v }))}\n />\n )}\n\n {/* Custom Headers */}\n <CustomKeyValueSection\n title=\"Custom Headers\"\n values={customHeaders}\n onChange={(i, k, v) => {\n const next = [...customHeaders];\n next[i] = { key: k,\nvalue: v };\n setCustomHeaders(next);\n }}\n onAdd={() => setCustomHeaders((prev) => [...prev, { key: \"\",\nvalue: \"\" }])}\n onRemove={(i) => {\n const next = [...customHeaders];\n next.splice(i, 1);\n setCustomHeaders(next);\n }}\n />\n\n {/* Request Body */}\n {hasBody && (\n <div>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-semibold uppercase tracking-wider mb-2 block\"\n >\n Request Body\n </Typography>\n <TextField\n multiline\n minRows={10}\n aria-label=\"Request Body\"\n value={body}\n onChange={(e) => { setBody(e.target.value); setValidationError(null); }}\n spellCheck={false}\n error={!!validationError}\n className=\"w-full\"\n inputClassName=\"font-mono text-xs p-3 resize-y\"\n />\n {validationError && (\n <Typography variant=\"caption\" className=\"text-red-500 mt-1 block text-xs\">\n {validationError}\n </Typography>\n )}\n </div>\n )}\n\n {/* URL Preview */}\n <div className=\"rounded-lg bg-surface-raised p-3\">\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-[10px] uppercase tracking-wider block mb-1\"\n >\n Request URL\n </Typography>\n <code className=\"text-xs font-mono text-text-primary dark:text-text-primary-dark break-all\">\n {resolvedUrl}\n </code>\n </div>\n\n {/* Execute Button */}\n <Button variant=\"filled\" onClick={execute} disabled={loading} className=\"w-full\">\n {loading ? (\n <span className=\"flex items-center gap-2\">\n <LoaderIcon size={iconSize.small} className=\"animate-spin\" />\n Sending…\n </span>\n ) : (\n <span className=\"flex items-center gap-2\">\n <SendIcon size={iconSize.small} />\n Send Request\n </span>\n )}\n </Button>\n\n {/* Response */}\n {response && (\n <div className={cls(\"rounded-lg border overflow-hidden\", defaultBorderMixin)}>\n <div\n className={cls(\n \"flex items-center justify-between px-4 py-2.5\",\n \"bg-surface-sheet\"\n )}\n >\n <div className=\"flex items-center gap-3\">\n <ResponseBadge status={response.status}/>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs\"\n >\n {response.statusText}\n </Typography>\n </div>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-mono\"\n >\n {response.time}ms\n </Typography>\n </div>\n <pre\n className={cls(\n \"p-4 text-xs font-mono overflow-auto max-h-96\",\n \"bg-surface-well text-emerald-700 dark:text-emerald-400\"\n )}\n >\n {response.body}\n </pre>\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Param Section ────────────────────────────────────────────────── */\n\nfunction ParamSection({\n title,\n params,\n values,\n onChange\n}: {\n title: string;\n params: ParsedEndpoint[\"parameters\"];\n values: Record<string, string>;\n onChange: (_key: string, _value: string) => void;\n}) {\n const paramIdBase = React.useId();\n return (\n <div>\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-semibold uppercase tracking-wider mb-2 block\"\n >\n {title}\n </Typography>\n <div className=\"space-y-2\">\n {params.map((p, index) => (\n <div key={p.name} className=\"flex items-center gap-3\">\n <label className=\"w-32 shrink-0\" htmlFor={`${paramIdBase}-${index}-param`}>\n <code className=\"text-xs font-mono font-semibold\">{p.name}</code>\n {p.required && <span className=\"text-red-500 ml-0.5 text-xs\">*</span>}\n </label>\n <TextField\n id={`${paramIdBase}-${index}-param`}\n size=\"small\"\n placeholder={p.description ?? p.name}\n value={values[p.name] ?? \"\"}\n onChange={(e) => onChange(p.name, e.target.value)}\n className=\"flex-1\"\n inputClassName=\"font-mono text-xs\"\n />\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction CustomKeyValueSection({\n title,\n values,\n onChange,\n onAdd,\n onRemove\n}: {\n title: string;\n values: Array<{ key: string; value: string }>;\n onChange: (index: number, key: string, value: string) => void;\n onAdd: () => void;\n onRemove: (index: number) => void;\n}) {\n const { t } = useTranslation();\n return (\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <Typography\n variant=\"caption\"\n className=\"text-text-secondary dark:text-text-secondary-dark text-xs font-semibold uppercase tracking-wider block\"\n >\n {title}\n </Typography>\n <Button\n variant=\"text\"\n size=\"small\"\n color=\"primary\"\n onClick={onAdd}\n className=\"text-xs p-0 min-h-0\"\n >\n <PlusIcon size={iconSize.small} className=\"mr-1\" /> Add Header\n </Button>\n </div>\n <div className=\"space-y-2\">\n {values.map((v, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <TextField\n size=\"small\"\n aria-label={`Header ${i + 1} name`}\n placeholder=\"Header name\"\n value={v.key}\n onChange={(e) => onChange(i, e.target.value, v.value)}\n className=\"w-1/3\"\n inputClassName=\"font-mono text-xs\"\n />\n <TextField\n size=\"small\"\n aria-label={`Header ${i + 1} value`}\n placeholder=\"Value\"\n value={v.value}\n onChange={(e) => onChange(i, v.key, e.target.value)}\n className=\"flex-1\"\n inputClassName=\"font-mono text-xs\"\n />\n <IconButton aria-label={t(\"remove\")}\n size=\"small\"\n onClick={() => onRemove(i)}\n className=\"text-text-secondary hover:text-red-500 shrink-0\"\n title={t(\"remove\")}\n >\n <XIcon size={iconSize.small} />\n </IconButton>\n </div>\n ))}\n {values.length === 0 && (\n <Typography variant=\"caption\" className=\"text-text-secondary/50 italic text-xs\">\n No custom headers added.\n </Typography>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────── */\n\nfunction ResponseBadge({ status }: { status: number }) {\n let colorClass = \"text-red-500\";\n if (status >= 200 && status < 300) colorClass = \"text-emerald-500\";\n else if (status >= 300 && status < 400) colorClass = \"text-blue-500\";\n else if (status >= 400 && status < 500) colorClass = \"text-amber-500\";\n\n return (\n <span className={cls(\"text-xs font-semibold font-mono\", colorClass)}>\n {status || \"ERR\"}\n </span>\n );\n}\n\nfunction buildBodyTemplate(endpoint: ParsedEndpoint): string {\n if (!endpoint.requestBody?.content) return \"{\\n \\n}\";\n const json = endpoint.requestBody.content[\"application/json\"];\n if (!json?.schema?.properties) return \"{\\n \\n}\";\n\n const props = json.schema.properties;\n const lines: string[] = [\"{\"];\n const keys = Object.keys(props);\n keys.forEach((key, i) => {\n const prop = props[key];\n if (prop.readOnly) return;\n const comma = i < keys.length - 1 ? \",\" : \"\";\n const val = defaultValue(prop);\n lines.push(` \"${key}\": ${val}${comma}`);\n });\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction defaultValue(schema: { type?: string; format?: string; enum?: (string | number)[] }): string {\n if (schema.enum) return JSON.stringify(schema.enum[0]);\n switch (schema.type) {\n case \"string\":\n return schema.format === \"date-time\" ? `\"${new Date().toISOString()}\"` : '\"\"';\n case \"number\":\n case \"integer\":\n return \"0\";\n case \"boolean\":\n return \"false\";\n case \"array\":\n return \"[]\";\n default:\n return \"null\";\n }\n}\n","import React, { useState, useEffect, useMemo } from \"react\";\nimport { useApiBase, useApiConfig, useAuthController, useTranslation } from \"@rebasepro/app\";\nimport {\n CircularProgress,\n Typography,\n Alert,\n cls,\n Button,\n Chip,\n defaultBorderMixin,\n SearchBar,\n iconSize\n} from \"@rebasepro/ui\";\nimport { BookOpenIcon, PlayIcon } from \"@rebasepro/ui\";\nimport { EndpointDetail } from \"./EndpointDetail\";\nimport { TryItPanel } from \"./TryItPanel\";\nimport type { OpenApiSpec, ParsedEndpoint } from \"./types\";\nimport { parseOpenApiSpec } from \"./parseSpec\";\n\n/**\n * Custom-built API Explorer for Rebase Studio.\n * No external dependencies — renders the OpenAPI spec natively\n * with deep integration into the Rebase auth system.\n */\nexport function ApiExplorer() {\n const apiConfig = useApiConfig();\n const apiBase = useApiBase();\n const authController = useAuthController();\n const { t } = useTranslation();\n const apiUrl = apiConfig?.apiUrl;\n\n const [spec, setSpec] = useState<OpenApiSpec | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const [selectedEndpoint, setSelectedEndpoint] = useState<ParsedEndpoint | null>(null);\n const [sidebarFilter, setSidebarFilter] = useState(\"\");\n const [tryItOpen, setTryItOpen] = useState(false);\n\n // Fetch OpenAPI spec\n useEffect(() => {\n if (!apiUrl) return;\n let cancelled = false;\n const specUrl = `${apiBase}/docs`;\n\n (async () => {\n try {\n // The spec endpoint itself is public on a stock backend, but\n // `apiUrl` may route through an authenticated proxy (the\n // console's Studio embed) — carry the token like every other\n // request in this view, and like LogsExplorer does.\n const getAuthToken = apiConfig?.getAuthToken ?? authController.getAuthToken;\n const token = getAuthToken ? await getAuthToken() : null;\n const res = await fetch(specUrl, token ? { headers: { Authorization: `Bearer ${token}` } } : undefined);\n if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);\n const data = await res.json();\n if (!cancelled) {\n setSpec(data);\n setLoading(false);\n }\n } catch (err: unknown) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : \"Failed to load API spec\");\n setLoading(false);\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [apiUrl, apiBase, apiConfig, authController]);\n\n // Parse spec into grouped endpoints\n const { groups, allEndpoints } = useMemo(() => {\n if (!spec) return { groups: [],\nallEndpoints: [] };\n return parseOpenApiSpec(spec);\n }, [spec]);\n\n // Filter\n const filteredGroups = useMemo(() => {\n if (!sidebarFilter.trim()) return groups;\n const q = sidebarFilter.toLowerCase();\n return groups\n .map((g) => ({\n ...g,\n endpoints: g.endpoints.filter(\n (e) =>\n e.path.toLowerCase().includes(q) ||\n e.summary.toLowerCase().includes(q) ||\n e.method.toLowerCase().includes(q)\n )\n }))\n .filter((g) => g.endpoints.length > 0);\n }, [groups, sidebarFilter]);\n\n // Auto-select first endpoint\n useEffect(() => {\n if (!selectedEndpoint && allEndpoints.length > 0) {\n setSelectedEndpoint(allEndpoints[0]);\n }\n }, [allEndpoints, selectedEndpoint]);\n\n // ── States ───────────────────────────────────────────────────────\n if (!apiUrl) {\n return (\n <div className=\"flex items-center justify-center h-full w-full p-8\">\n <Alert color=\"warning\">\n <Typography variant=\"body2\">\n No API URL configured. Ensure your app provides an{\" \"}\n <code className=\"font-mono text-xs\">apiUrl</code>.\n </Typography>\n </Alert>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"flex flex-col items-center justify-center h-full w-full gap-4\">\n <CircularProgress size=\"medium\"/>\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark animate-pulse\">\n Loading API specification…\n </Typography>\n </div>\n );\n }\n\n if (error || !spec) {\n // The API spec fetch rejects with whatever the transport says, and for\n // an expired console session that is the string \"401\". Rendering it\n // verbatim produced the worst screen in the console: a red box\n // containing three digits, no title, no cause, no way out — on the same\n // product whose storage browser writes four sentences explaining which\n // authorization hook refused a listing.\n //\n // The raw text is kept, below the sentence, because it is what someone\n // pastes into a bug report. It is just no longer the whole message.\n const status = (error ?? \"\").trim();\n const isAuth = /^(401|403)\\b/.test(status) || /unauthori[sz]ed|forbidden/i.test(status);\n return (\n <div className=\"flex items-center justify-center h-full w-full p-8\">\n <div className=\"max-w-md text-center\">\n <Typography variant=\"subtitle2\" className=\"block text-text-primary dark:text-text-primary-dark\">\n {isAuth ? t(\"studio_api_explorer_spec_refused_title\") : t(\"studio_api_explorer_spec_failed_title\")}\n </Typography>\n <Typography variant=\"body2\" className=\"block mt-2 text-text-secondary dark:text-text-secondary-dark\">\n {isAuth\n ? t(\"studio_api_explorer_spec_refused_body\")\n : t(\"studio_api_explorer_spec_failed_body\")}\n </Typography>\n <Button\n variant=\"outlined\"\n color=\"neutral\"\n size=\"small\"\n className=\"mt-4\"\n onClick={() => window.location.reload()}\n >\n {t(\"retry\")}\n </Button>\n {status && (\n <Typography variant=\"caption\" className=\"block mt-4 font-mono text-text-disabled dark:text-text-disabled-dark\">\n {status}\n </Typography>\n )}\n </div>\n </div>\n );\n }\n\n const METHOD_COLORS: Record<string, string> = {\n get: \"text-blue-600 dark:text-blue-400\",\n post: \"text-emerald-600 dark:text-emerald-400\",\n put: \"text-amber-600 dark:text-amber-400\",\n patch: \"text-orange-600 dark:text-orange-400\",\n delete: \"text-red-600 dark:text-red-400\"\n };\n\n return (\n <div className=\"flex h-full w-full overflow-hidden\">\n {/* ── Sidebar ──────────────────────────────────────── */}\n <div\n className={cls(\n \"w-72 min-w-[272px] flex flex-col h-full overflow-hidden border-r\",\n defaultBorderMixin,\n \"bg-surface-sheet\"\n )}\n >\n {/* Header */}\n <div className=\"p-4 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <BookOpenIcon size={iconSize.medium} className=\"text-primary dark:text-primary-dark\" />\n <Typography variant=\"subtitle2\" className=\"font-semibold\">\n {spec.info?.title ?? \"API Reference\"}\n </Typography>\n </div>\n {spec.info?.version && (\n <Chip size=\"smallest\" colorScheme=\"cyanDarker\">\n v{spec.info.version}\n </Chip>\n )}\n {/* Search */}\n <div className=\"mb-2\">\n <SearchBar\n placeholder=\"Filter endpoints…\"\n size=\"small\"\n onTextSearch={(val) => setSidebarFilter(val ?? \"\")}\n />\n </div>\n\n {/* Auth status removed to avoid redundancy with the AuthSimulationSelector */}\n </div>\n\n {/* Endpoint list */}\n <div className=\"flex-1 overflow-y-auto px-2 pb-4\">\n {filteredGroups.map((group) => (\n <div key={group.tag} className=\"mb-3\">\n <Typography\n variant=\"caption\"\n className=\"px-2 py-1.5 text-text-secondary dark:text-text-secondary-dark uppercase tracking-wider font-semibold text-[10px]\"\n >\n {group.tag}\n </Typography>\n {group.endpoints.map((ep) => {\n const isSelected = selectedEndpoint?.id === ep.id;\n return (\n <Button\n key={ep.id}\n variant=\"text\"\n color=\"neutral\"\n fullWidth\n onClick={() => {\n setSelectedEndpoint(ep);\n setTryItOpen(false);\n }}\n className={cls(\n \"!justify-between !px-2.5 !py-1.5 !text-left !text-sm\",\n isSelected\n ? \"bg-surface-raised font-medium\"\n : \"text-text-primary dark:text-text-primary-dark\"\n )}\n >\n <span className=\"truncate text-[13px] opacity-90\">{ep.summary || ep.shortPath}</span>\n <span\n className={cls(\n \"text-[10px] font-semibold uppercase shrink-0\",\n METHOD_COLORS[ep.method] ?? \"text-text-secondary\"\n )}\n >\n {ep.method}\n </span>\n </Button>\n );\n })}\n </div>\n ))}\n {filteredGroups.length === 0 && (\n <Typography\n variant=\"body2\"\n className=\"text-center text-text-secondary dark:text-text-secondary-dark py-8\"\n >\n No endpoints match\n </Typography>\n )}\n </div>\n </div>\n\n {/* ── Main content ─────────────────────────────────── */}\n <div className=\"flex-1 flex flex-col h-full overflow-hidden\">\n {selectedEndpoint ? (\n <>\n {/* Top bar */}\n <div\n className={cls(\n \"flex items-center justify-between px-5 py-3 gap-4 shrink-0 border-b z-10\",\n defaultBorderMixin,\n \"bg-surface-sheet/90 backdrop-blur-md sticky top-0\"\n )}\n >\n <div className=\"flex items-center gap-3 min-w-0\">\n <span\n className={cls(\n \"text-xs font-semibold uppercase\",\n METHOD_COLORS[selectedEndpoint.method] ?? \"\"\n )}\n >\n {selectedEndpoint.method}\n </span>\n <code className=\"text-sm font-mono text-text-primary dark:text-text-primary-dark truncate\">\n {selectedEndpoint.path}\n </code>\n </div>\n <Button\n variant={tryItOpen ? \"filled\" : \"outlined\"}\n size=\"small\"\n onClick={() => setTryItOpen((v) => !v)}\n >\n <PlayIcon size={iconSize.small} className=\"mr-1\" />\n Try It\n </Button>\n </div>\n\n {/* Body */}\n <div className=\"flex-1 overflow-y-auto\">\n {tryItOpen ? (\n <TryItPanel\n key={selectedEndpoint.operationId || selectedEndpoint.path}\n endpoint={selectedEndpoint}\n apiUrl={apiUrl}\n getAuthToken={apiConfig?.getAuthToken ?? authController.getAuthToken}\n user={authController.user}\n basePath={spec?.servers?.[0]?.url || \"\"}\n />\n ) : (\n <EndpointDetail endpoint={selectedEndpoint} spec={spec}/>\n )}\n </div>\n </>\n ) : (\n <div className=\"flex items-center justify-center h-full\">\n <Typography variant=\"body2\" className=\"text-text-secondary dark:text-text-secondary-dark\">\n Select an endpoint from the sidebar\n </Typography>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nApiExplorer.displayName = \"ApiExplorer\";\n\n"],"mappings":"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"}
@@ -416,7 +416,7 @@ var PolicyEditor = ({ policy, schema, table, roleOptions, onSave, onCancel }) =>
416
416
  children: t("studio_policy_using_expr_desc")
417
417
  })]
418
418
  }), /* @__PURE__ */ jsx("div", {
419
- className: cls("h-32 border rounded-md overflow-hidden bg-white dark:bg-[#1e1e1e]", defaultBorderMixin),
419
+ className: cls("h-32 border rounded-md overflow-hidden bg-surface-card", defaultBorderMixin),
420
420
  children: /* @__PURE__ */ jsx(MonacoEditor, {
421
421
  ref: usingEditor,
422
422
  value: usingExpr,
@@ -439,7 +439,7 @@ var PolicyEditor = ({ policy, schema, table, roleOptions, onSave, onCancel }) =>
439
439
  children: t("studio_policy_check_expr_desc")
440
440
  })]
441
441
  }), /* @__PURE__ */ jsx("div", {
442
- className: cls("h-32 border rounded-md overflow-hidden bg-white dark:bg-[#1e1e1e]", defaultBorderMixin),
442
+ className: cls("h-32 border rounded-md overflow-hidden bg-surface-card", defaultBorderMixin),
443
443
  children: /* @__PURE__ */ jsx(MonacoEditor, {
444
444
  ref: checkEditor,
445
445
  value: checkExpr,
@@ -473,7 +473,7 @@ var PolicyEditor = ({ policy, schema, table, roleOptions, onSave, onCancel }) =>
473
473
  children: [
474
474
  /* @__PURE__ */ jsx(DialogTitle, {
475
475
  hidden: true,
476
- children: "Row-Level Security Help"
476
+ children: t("studio_policy_help_title")
477
477
  }),
478
478
  /* @__PURE__ */ jsxs(DialogContent, {
479
479
  className: "p-4 sm:p-6 lg:p-8 flex flex-col gap-6",
@@ -549,7 +549,8 @@ var PolicyEditor = ({ policy, schema, table, roleOptions, onSave, onCancel }) =>
549
549
  /* @__PURE__ */ jsxs("div", {
550
550
  className: cls("bg-surface-well px-3 py-2 rounded-md font-mono text-sm my-2", defaultBorderMixin),
551
551
  children: [
552
- "Example: ",
552
+ t("studio_policy_help_example"),
553
+ " ",
553
554
  RLS_UID_SQL,
554
555
  " = uid"
555
556
  ]
@@ -577,7 +578,8 @@ var PolicyEditor = ({ policy, schema, table, roleOptions, onSave, onCancel }) =>
577
578
  /* @__PURE__ */ jsxs("div", {
578
579
  className: cls("bg-surface-well px-3 py-2 rounded-md font-mono text-sm my-2", defaultBorderMixin),
579
580
  children: [
580
- "Example: ",
581
+ t("studio_policy_help_example"),
582
+ " ",
581
583
  RLS_UID_SQL,
582
584
  " = uid"
583
585
  ]
@@ -610,34 +612,46 @@ var PolicyEditor = ({ policy, schema, table, roleOptions, onSave, onCancel }) =>
610
612
  children: RLS_UID_SQL
611
613
  }), /* @__PURE__ */ jsxs("span", {
612
614
  className: "block mt-0.5",
613
- children: ["Returns the current user's ID as text. Example: ", /* @__PURE__ */ jsxs("code", {
614
- className: "bg-surface-well px-1 py-0.5 rounded text-[11px]",
615
- children: [RLS_UID_SQL, " = uid"]
616
- })]
615
+ children: [
616
+ t("studio_policy_help_auth_uid"),
617
+ " ",
618
+ /* @__PURE__ */ jsxs("code", {
619
+ className: "bg-surface-well px-1 py-0.5 rounded text-[11px]",
620
+ children: [RLS_UID_SQL, " = uid"]
621
+ })
622
+ ]
617
623
  })] }),
618
624
  /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("code", {
619
625
  className: "bg-surface-well px-1.5 py-0.5 rounded mr-1 whitespace-nowrap",
620
626
  children: RLS_JWT_SQL
621
627
  }), /* @__PURE__ */ jsxs("span", {
622
628
  className: "block mt-0.5",
623
- children: ["Returns the full JWT payload as JSONB so you can check custom claims. Example: ", /* @__PURE__ */ jsxs("code", {
624
- className: "bg-surface-well px-1 py-0.5 rounded text-[11px]",
625
- children: [RLS_JWT_SQL, " ->> 'email' = 'admin@example.com'"]
626
- })]
629
+ children: [
630
+ t("studio_policy_help_auth_jwt"),
631
+ " ",
632
+ /* @__PURE__ */ jsxs("code", {
633
+ className: "bg-surface-well px-1 py-0.5 rounded text-[11px]",
634
+ children: [RLS_JWT_SQL, " ->> 'email' = 'admin@example.com'"]
635
+ })
636
+ ]
627
637
  })] }),
628
638
  /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("code", {
629
639
  className: "bg-surface-well px-1.5 py-0.5 rounded mr-1 whitespace-nowrap",
630
640
  children: RLS_ROLES_SQL
631
641
  }), /* @__PURE__ */ jsxs("span", {
632
642
  className: "block mt-0.5",
633
- children: ["Returns the user's role IDs as a comma-separated string. Best used with: ", /* @__PURE__ */ jsxs("code", {
634
- className: "bg-surface-well px-1 py-0.5 rounded text-[11px]",
635
- children: [
636
- "string_to_array(",
637
- RLS_ROLES_SQL,
638
- ", ',') @> ARRAY['admin']"
639
- ]
640
- })]
643
+ children: [
644
+ t("studio_policy_help_auth_roles"),
645
+ " ",
646
+ /* @__PURE__ */ jsxs("code", {
647
+ className: "bg-surface-well px-1 py-0.5 rounded text-[11px]",
648
+ children: [
649
+ "string_to_array(",
650
+ RLS_ROLES_SQL,
651
+ ", ',') @> ARRAY['admin']"
652
+ ]
653
+ })
654
+ ]
641
655
  })] })
642
656
  ]
643
657
  })
@@ -2081,4 +2095,4 @@ var RLSEditor = ({ apiUrl = "" }) => {
2081
2095
  //#endregion
2082
2096
  export { RLSEditor };
2083
2097
 
2084
- //# sourceMappingURL=RLSEditor-CcA5fLSF.js.map
2098
+ //# sourceMappingURL=RLSEditor-DEjuy8XH.js.map