@djangocfg/ui-tools 2.1.285 → 2.1.286
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/DocsLayout-BCVU6TTX.cjs +2027 -0
- package/dist/DocsLayout-BCVU6TTX.cjs.map +1 -0
- package/dist/DocsLayout-ERETJLLV.mjs +2020 -0
- package/dist/DocsLayout-ERETJLLV.mjs.map +1 -0
- package/dist/{PlaygroundLayout-O52C6HK5.css → DocsLayout-MBFIB4NO.css} +1 -1
- package/dist/{PrettyCode.client-SGDGQTYT.cjs → PrettyCode.client-5GABIN2I.cjs} +57 -35
- package/dist/PrettyCode.client-5GABIN2I.cjs.map +1 -0
- package/dist/{PrettyCode.client-DW5LTG47.mjs → PrettyCode.client-IZTXXYHG.mjs} +57 -35
- package/dist/PrettyCode.client-IZTXXYHG.mjs.map +1 -0
- package/dist/chunk-IULI4XII.cjs +1129 -0
- package/dist/chunk-IULI4XII.cjs.map +1 -0
- package/dist/chunk-VZGQC3NG.mjs +1100 -0
- package/dist/chunk-VZGQC3NG.mjs.map +1 -0
- package/dist/index.cjs +88 -552
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -6
- package/dist/index.d.ts +18 -6
- package/dist/index.mjs +25 -496
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/tools/OpenapiViewer/.claude/.sidecar/activity.jsonl +4 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/map_cache.json +30 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/usage.json +5 -0
- package/src/tools/OpenapiViewer/.claude/project-map.md +23 -0
- package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +28 -2
- package/src/tools/OpenapiViewer/README.md +104 -51
- package/src/tools/OpenapiViewer/components/DocsLayout/ApiIntroSection.tsx +64 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/DocsView.tsx +137 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc.tsx +268 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/SchemaCopyMenu.tsx +139 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar.tsx +211 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/SlideInPlayground.tsx +101 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/TryItSheet.tsx +57 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/anchor.ts +11 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +71 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/index.tsx +166 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/schemaFields.ts +121 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/sidebarLabel.ts +60 -0
- package/src/tools/OpenapiViewer/components/index.ts +5 -2
- package/src/tools/OpenapiViewer/components/shared/BodyFormEditor.tsx +422 -0
- package/src/tools/OpenapiViewer/components/shared/EndpointDraftSync.tsx +108 -0
- package/src/tools/OpenapiViewer/components/shared/EndpointResetButton.tsx +50 -0
- package/src/tools/OpenapiViewer/components/{PlaygroundLayout → shared}/RequestPanel.tsx +174 -87
- package/src/tools/OpenapiViewer/components/shared/SendButton.tsx +91 -0
- package/src/tools/OpenapiViewer/components/{PlaygroundLayout → shared}/ui.tsx +5 -4
- package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +82 -8
- package/src/tools/OpenapiViewer/hooks/useEndpointDraft.ts +142 -0
- package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +126 -13
- package/src/tools/OpenapiViewer/index.tsx +3 -7
- package/src/tools/OpenapiViewer/lazy.tsx +6 -27
- package/src/tools/OpenapiViewer/types.ts +44 -0
- package/src/tools/OpenapiViewer/utils/formatters.ts +2 -23
- package/src/tools/OpenapiViewer/utils/index.ts +3 -1
- package/src/tools/OpenapiViewer/utils/schemaExport.ts +206 -0
- package/src/tools/OpenapiViewer/utils/url.ts +202 -0
- package/src/tools/PrettyCode/PrettyCode.client.tsx +42 -8
- package/src/tools/PrettyCode/index.tsx +6 -0
- package/dist/PlaygroundLayout-DHUATCHB.cjs +0 -798
- package/dist/PlaygroundLayout-DHUATCHB.cjs.map +0 -1
- package/dist/PlaygroundLayout-NONWOVQR.mjs +0 -791
- package/dist/PlaygroundLayout-NONWOVQR.mjs.map +0 -1
- package/dist/PrettyCode.client-DW5LTG47.mjs.map +0 -1
- package/dist/PrettyCode.client-SGDGQTYT.cjs.map +0 -1
- package/dist/chunk-5FKE7OME.cjs +0 -369
- package/dist/chunk-5FKE7OME.cjs.map +0 -1
- package/dist/chunk-BKWDHJKF.mjs +0 -356
- package/dist/chunk-BKWDHJKF.mjs.map +0 -1
- package/src/tools/OpenapiViewer/components/PlaygroundLayout/EndpointList.tsx +0 -228
- package/src/tools/OpenapiViewer/components/PlaygroundLayout/index.tsx +0 -107
- /package/dist/{PlaygroundLayout-O52C6HK5.css.map → DocsLayout-MBFIB4NO.css.map} +0 -0
- /package/src/tools/OpenapiViewer/components/{PlaygroundLayout → shared}/ResponsePanel.tsx +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tools/PrettyCode/index.tsx","../src/tools/OpenapiViewer/utils/apiKeyManager.ts","../src/tools/OpenapiViewer/utils/versionManager.ts","../src/tools/OpenapiViewer/utils/formatters.ts","../src/tools/OpenapiViewer/context/PlaygroundContext.tsx"],"names":["lazy","__name","jsx","jsxs","Suspense","createContext","useContext","useReducer","useRef","React","useEffect","consola","useCallback"],"mappings":"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","file":"chunk-5FKE7OME.cjs","sourcesContent":["/**\n * PrettyCode Component - Dynamic Import Wrapper\n *\n * Lazy loads the heavy Prism library (~500KB) only when needed.\n * This significantly reduces the initial bundle size.\n */\n\n'use client';\n\nimport React, { lazy, Suspense } from 'react';\nimport type { Language } from 'prism-react-renderer';\n\n// Lazy load the client component\nconst PrettyCodeClient = lazy(() => import('./PrettyCode.client'));\n\n// Loading fallback component\nconst LoadingFallback = () => (\n <div className=\"relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900\">\n <div className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <div className=\"animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20\"></div>\n <span className=\"text-xs text-muted-foreground\">Loading code...</span>\n </div>\n </div>\n </div>\n);\n\nexport interface PrettyCodeProps {\n data: string | object;\n language: Language;\n className?: string;\n mode?: 'dark' | 'light';\n inline?: boolean;\n customBg?: string;\n isCompact?: boolean;\n /** Block scroll capture until user clicks (default: true) */\n scrollIsolation?: boolean;\n}\n\nconst PrettyCode: React.FC<PrettyCodeProps> = (props) => {\n return (\n <Suspense fallback={<LoadingFallback />}>\n <PrettyCodeClient {...props} />\n </Suspense>\n );\n};\n\nexport default PrettyCode;\nexport type { Language };\n","/**\n * API Key Management Utility\n *\n * Provides centralized functions for managing API keys in headers and requests.\n * This utility can be used across different components that need to handle API keys.\n */\n\nimport type { ApiKey } from '../types';\n\nexport type { ApiKey };\n\nexport interface HeadersWithApiKey {\n [key: string]: string;\n}\n\n/**\n * Add API key to request headers\n * @param headers - Existing headers object\n * @param apiKey - API key object or string\n * @returns Headers with API key added\n */\nexport function addApiKeyToHeaders(headers: HeadersWithApiKey, apiKey: ApiKey | string | null): HeadersWithApiKey {\n if (!apiKey) {\n return headers;\n }\n\n // ``secret`` is the raw key that goes in the X-API-Key header.\n // Falls back to ``id`` for backwards compatibility — older callers\n // only had ``id`` and used it as both selector and secret.\n const keyValue = typeof apiKey === 'string' ? apiKey : (apiKey.secret || apiKey.id || '');\n\n return {\n ...headers,\n 'X-API-Key': keyValue,\n };\n}\n\n/**\n * Remove API key from headers object\n * @param headers - Headers object\n * @returns Headers without API key\n */\nexport function removeApiKeyFromHeaders(headers: HeadersWithApiKey): HeadersWithApiKey {\n const { 'X-API-Key': removed, ...remainingHeaders } = headers;\n return remainingHeaders;\n}\n\n/**\n * Remove API key from headers JSON string\n * @param headersJson - JSON string of headers\n * @returns JSON string without API key\n */\nexport function removeApiKeyFromHeadersJson(headersJson: string): string {\n try {\n const headers = JSON.parse(headersJson);\n const updatedHeaders = removeApiKeyFromHeaders(headers);\n return JSON.stringify(updatedHeaders, null, 2);\n } catch (error) {\n console.error('Error parsing headers JSON:', error);\n return headersJson;\n }\n}\n\n/**\n * Update headers JSON string with API key\n * @param headersJson - JSON string of headers\n * @param apiKey - API key object or string\n * @returns Updated JSON string\n */\nexport function updateHeadersJsonWithApiKey(headersJson: string, apiKey: ApiKey | string | null): string {\n try {\n const headers = JSON.parse(headersJson);\n const updatedHeaders = addApiKeyToHeaders(headers, apiKey);\n return JSON.stringify(updatedHeaders, null, 2);\n } catch (error) {\n console.error('Error parsing headers JSON:', error);\n return headersJson;\n }\n}\n\n/**\n * Find API key by ID in a list of API keys\n * @param apiKeys - Array of API keys\n * @param keyId - ID of the API key to find\n * @returns API key object or null\n */\nexport function findApiKeyById(apiKeys: ApiKey[], keyId: string): ApiKey | null {\n return apiKeys.find((key) => key.id === keyId) || null;\n}\n\n/**\n * Validate API key format\n * @param apiKey - API key string to validate\n * @returns Whether the API key format is valid\n */\nexport function validateApiKeyFormat(apiKey: string): boolean {\n // Basic validation - adjust based on your API key format requirements\n return typeof apiKey === 'string' && apiKey.length > 0 && apiKey.trim() !== '';\n}\n\n/**\n * Create default headers with API key\n * @param apiKey - API key object or string\n * @returns Default headers with API key\n */\nexport function createDefaultHeaders(apiKey?: ApiKey | string): HeadersWithApiKey {\n const defaultHeaders: HeadersWithApiKey = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n return addApiKeyToHeaders(defaultHeaders, apiKey);\n }\n\n return defaultHeaders;\n}\n\n/**\n * Merge headers with API key\n * @param baseHeaders - Base headers object\n * @param additionalHeaders - Additional headers to merge\n * @param apiKey - API key to add\n * @returns Merged headers with API key\n */\nexport function mergeHeadersWithApiKey(baseHeaders: HeadersWithApiKey, additionalHeaders: HeadersWithApiKey, apiKey?: ApiKey | string): HeadersWithApiKey {\n const mergedHeaders = { ...baseHeaders, ...additionalHeaders };\n\n if (apiKey) {\n return addApiKeyToHeaders(mergedHeaders, apiKey);\n }\n\n return mergedHeaders;\n}\n\n/**\n * Log API key usage (for debugging/analytics)\n * @param apiKey - API key that was used\n * @param endpoint - Endpoint that was called\n * @param success - Whether the request was successful\n */\nexport function logApiKeyUsage(apiKey: ApiKey | string, endpoint: string, success: boolean): void {\n const keyValue = typeof apiKey === 'string' ? apiKey : (apiKey.secret || apiKey.id || '');\n const keyName = typeof apiKey === 'string' ? 'Unknown' : apiKey.name;\n\n console.log(`API Key Usage:`, {\n keyName,\n keyValue: keyValue.substring(0, 8) + '...',\n endpoint,\n success,\n timestamp: new Date().toISOString(),\n });\n}\n","/**\n * API Version Management Utilities\n * Handles version detection, filtering, and URL transformation\n */\n\nimport type { ApiEndpoint } from '../types';\n\nexport interface ApiVersion {\n id: string;\n name: string;\n description: string;\n isDefault: boolean;\n}\n\n// Available API versions\nexport const API_VERSIONS: ApiVersion[] = [\n {\n id: 'v1',\n name: 'v1',\n description: 'Current stable version',\n isDefault: true,\n },\n];\n\n/**\n * Detect version from endpoint path\n */\nexport const detectEndpointVersion = (path: string): string => {\n // Check for versioned paths like /api/vehicles_api/v1/...\n const versionMatch = path.match(/\\/api\\/[^/]+\\/(v\\d+)\\//);\n if (versionMatch && versionMatch[1]) {\n return versionMatch[1];\n }\n \n // If no version found, default to v1\n return 'v1';\n};\n\n/**\n * Check if endpoint belongs to specific version\n */\nexport const isEndpointInVersion = (endpoint: ApiEndpoint, version: string): boolean => {\n const endpointVersion = detectEndpointVersion(endpoint.path);\n return endpointVersion === version;\n};\n\n/**\n * Filter endpoints by version\n */\nexport const filterEndpointsByVersion = (endpoints: ApiEndpoint[], version: string): ApiEndpoint[] => {\n return endpoints.filter(endpoint => isEndpointInVersion(endpoint, version));\n};\n\n/**\n * Remove duplicate endpoints across versions\n * Keeps only the specified version, removes duplicates from other versions\n */\nexport const deduplicateEndpoints = (endpoints: ApiEndpoint[], preferredVersion: string): ApiEndpoint[] => {\n const endpointMap = new Map<string, ApiEndpoint>();\n \n // Group endpoints by normalized path (without version)\n const groupedEndpoints = new Map<string, ApiEndpoint[]>();\n \n endpoints.forEach(endpoint => {\n const normalizedPath = normalizeEndpointPath(endpoint.path);\n if (!groupedEndpoints.has(normalizedPath)) {\n groupedEndpoints.set(normalizedPath, []);\n }\n groupedEndpoints.get(normalizedPath)!.push(endpoint);\n });\n \n // For each group, pick the endpoint from preferred version\n groupedEndpoints.forEach((endpointGroup, normalizedPath) => {\n let selectedEndpoint: ApiEndpoint | null = null;\n \n // Try to find endpoint in preferred version\n const versionEndpoint = endpointGroup.find(ep => isEndpointInVersion(ep, preferredVersion));\n if (versionEndpoint) {\n selectedEndpoint = versionEndpoint;\n } else if (endpointGroup.length > 0) {\n // Fallback to first available endpoint\n selectedEndpoint = endpointGroup[0] || null;\n }\n \n if (selectedEndpoint) {\n endpointMap.set(normalizedPath, selectedEndpoint);\n }\n });\n \n return Array.from(endpointMap.values());\n};\n\n/**\n * Normalize endpoint path by removing version prefix\n * /api/vehicles_api/v1/vehicles/ -> /api/vehicles_api/vehicles/\n * /api/vehicles_api/vehicles/ -> /api/vehicles_api/vehicles/\n */\nexport const normalizeEndpointPath = (path: string): string => {\n // Remove version prefix like /v1/, /v2/, etc.\n return path.replace(/\\/v\\d+\\//, '/');\n};\n\n/**\n * Convert endpoint path to specific version\n */\nexport const convertEndpointToVersion = (endpoint: ApiEndpoint, targetVersion: string): ApiEndpoint => {\n const currentVersion = detectEndpointVersion(endpoint.path);\n \n // If already in target version, return as is\n if (currentVersion === targetVersion) {\n return endpoint;\n }\n \n let newPath = endpoint.path;\n \n // Replace version: /api/vehicles_api/v1/vehicles/ -> /api/vehicles_api/v2/vehicles/\n newPath = newPath.replace(/\\/v\\d+\\//, `/${targetVersion}/`);\n \n return {\n ...endpoint,\n path: newPath,\n };\n};\n\n/**\n * Get version info by ID\n */\nexport const getVersionById = (versionId: string): ApiVersion | undefined => {\n return API_VERSIONS.find(v => v.id === versionId);\n};\n\n/**\n * Get default version\n */\nexport const getDefaultVersion = (): ApiVersion => {\n const defaultVersion = API_VERSIONS.find(v => v.isDefault);\n if (defaultVersion) {\n return defaultVersion;\n }\n \n // Fallback to first version if no default is set\n if (API_VERSIONS.length > 0 && API_VERSIONS[0]) {\n return API_VERSIONS[0];\n }\n \n // This should never happen, but TypeScript requires it\n throw new Error('No API versions defined');\n};\n\n/**\n * Get version statistics from endpoints\n */\nexport const getVersionStats = (endpoints: ApiEndpoint[]): Record<string, number> => {\n const stats: Record<string, number> = {};\n \n API_VERSIONS.forEach(version => {\n stats[version.id] = filterEndpointsByVersion(endpoints, version.id).length;\n });\n \n return stats;\n};\n","import type { ApiKey } from '../types';\nimport { HTTP_METHOD_COLORS, HTTP_STATUS_COLORS } from '../constants';\n\nexport const getMethodColor = (\n method: string\n): 'success' | 'primary' | 'warning' | 'error' | 'default' => {\n return HTTP_METHOD_COLORS[method.toUpperCase() as keyof typeof HTTP_METHOD_COLORS] || 'default';\n};\n\nexport const getStatusColor = (\n status: number\n): 'success' | 'warning' | 'error' | 'default' => {\n const firstDigit = Math.floor(status / 100).toString();\n return HTTP_STATUS_COLORS[firstDigit as keyof typeof HTTP_STATUS_COLORS] || 'default';\n};\n\nexport const formatApiKeyDisplay = (apiKey: ApiKey): string => {\n const preview = apiKey.id.substring(0, 8);\n return `${apiKey.name} (${preview}...)`;\n};\n\nexport const isValidJson = (str: string): boolean => {\n if (!str || typeof str !== 'string') return false;\n try {\n JSON.parse(str);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const formatRequestHeaders = (headers: Record<string, string>): string => {\n return JSON.stringify(headers, null, 2);\n};\n\nexport const parseRequestHeaders = (headersString: string): Record<string, string> => {\n if (!headersString || typeof headersString !== 'string') {\n return { 'Content-Type': 'application/json' };\n }\n\n try {\n const parsed = JSON.parse(headersString);\n return typeof parsed === 'object' && parsed !== null ? parsed : { 'Content-Type': 'application/json' };\n } catch {\n return { 'Content-Type': 'application/json' };\n }\n};\n\n// Substitute URL parameters like {id}, {userId}, etc.\nexport const substituteUrlParameters = (\n url: string,\n parameters: Record<string, string>\n): string => {\n let substitutedUrl = url;\n\n Object.entries(parameters).forEach(([key, value]) => {\n if (value && value.trim() !== '') {\n // Replace both {key} and %7Bkey%7D patterns (URL encoded version)\n const patterns = [\n new RegExp(`\\\\{${key}\\\\}`, 'g'),\n new RegExp(`%7B${key}%7D`, 'gi'),\n ];\n\n patterns.forEach((pattern) => {\n substitutedUrl = substitutedUrl.replace(pattern, encodeURIComponent(value));\n });\n }\n });\n\n return substitutedUrl;\n};\n","'use client';\n\nimport consola from 'consola';\nimport React, {\n createContext, ReactNode, useCallback, useContext, useEffect, useReducer, useRef\n} from 'react';\n\nimport type {\n ApiEndpoint, ApiResponse, PlaygroundConfig, PlaygroundContextType, PlaygroundState,\n PlaygroundStep\n} from '../types';\nimport { parseRequestHeaders, substituteUrlParameters } from '../utils';\nimport { getDefaultVersion } from '../utils/versionManager';\n\n// ─── Initial state ────────────────────────────────────────────────────────────\n\nconst createInitialState = (): PlaygroundState => ({\n currentStep: 'endpoints',\n steps: ['endpoints', 'request', 'response'],\n selectedEndpoint: null,\n selectedCategory: 'All',\n searchTerm: '',\n selectedVersion: getDefaultVersion().id,\n requestUrl: '',\n requestMethod: 'GET',\n requestHeaders: '{\\n \"Content-Type\": \"application/json\"\\n}',\n requestBody: '',\n selectedApiKey: null,\n manualApiToken: '',\n parameters: {},\n response: null,\n loading: false,\n sidebarOpen: false,\n});\n\n// ─── Actions ──────────────────────────────────────────────────────────────────\n\ntype Action =\n | { type: 'SET_STEP'; step: PlaygroundStep }\n | { type: 'NEXT_STEP' }\n | { type: 'PREV_STEP' }\n | { type: 'SELECT_ENDPOINT'; endpoint: ApiEndpoint | null }\n | { type: 'SET_CATEGORY'; category: string }\n | { type: 'SET_SEARCH'; term: string }\n | { type: 'SET_VERSION'; version: string }\n | { type: 'SET_REQUEST_URL'; url: string }\n | { type: 'SET_REQUEST_METHOD'; method: string }\n | { type: 'SET_REQUEST_HEADERS'; headers: string }\n | { type: 'SET_REQUEST_BODY'; body: string }\n | { type: 'SET_API_KEY'; apiKeyId: string | null }\n | { type: 'SET_MANUAL_TOKEN'; token: string }\n | { type: 'SET_PARAMETERS'; parameters: Record<string, string> }\n | { type: 'SET_RESPONSE'; response: ApiResponse | null }\n | { type: 'SET_LOADING'; loading: boolean }\n // Batched: set loading + clear response atomically (avoids two renders on send)\n | { type: 'REQUEST_START' }\n // Batched: set response + loading=false + advance step atomically (avoids three renders)\n | { type: 'REQUEST_SUCCESS'; response: ApiResponse }\n // Batched: set error response + loading=false atomically\n | { type: 'REQUEST_ERROR'; response: ApiResponse }\n | { type: 'SET_SIDEBAR'; open: boolean }\n | { type: 'SYNC_API_KEY_HEADER'; headers: string }\n | { type: 'CLEAR_API_KEY_SELECTION' }\n | { type: 'SYNC_URL'; url: string }\n | { type: 'RESET' };\n\n// ─── Reducer ──────────────────────────────────────────────────────────────────\n\nfunction reducer(state: PlaygroundState, action: Action): PlaygroundState {\n switch (action.type) {\n case 'SET_STEP':\n return { ...state, currentStep: action.step };\n\n case 'NEXT_STEP': {\n const i = state.steps.indexOf(state.currentStep);\n return i < state.steps.length - 1\n ? { ...state, currentStep: state.steps[i + 1]! }\n : state;\n }\n\n case 'PREV_STEP': {\n const i = state.steps.indexOf(state.currentStep);\n return i > 0 ? { ...state, currentStep: state.steps[i - 1]! } : state;\n }\n\n case 'SELECT_ENDPOINT':\n if (!action.endpoint) return { ...state, selectedEndpoint: null };\n return {\n ...state,\n selectedEndpoint: action.endpoint,\n requestMethod: action.endpoint.method,\n requestUrl: action.endpoint.path,\n parameters: {},\n currentStep: 'request',\n };\n\n case 'SET_CATEGORY': return { ...state, selectedCategory: action.category };\n case 'SET_SEARCH': return { ...state, searchTerm: action.term };\n case 'SET_VERSION': return { ...state, selectedVersion: action.version };\n case 'SET_REQUEST_URL': return { ...state, requestUrl: action.url };\n case 'SET_REQUEST_METHOD': return { ...state, requestMethod: action.method };\n case 'SET_REQUEST_HEADERS': return { ...state, requestHeaders: action.headers };\n case 'SET_REQUEST_BODY': return { ...state, requestBody: action.body };\n case 'SET_API_KEY': return { ...state, selectedApiKey: action.apiKeyId };\n case 'SET_MANUAL_TOKEN': return { ...state, manualApiToken: action.token };\n case 'SET_PARAMETERS': return { ...state, parameters: action.parameters };\n case 'SET_RESPONSE': return { ...state, response: action.response };\n case 'SET_LOADING': return { ...state, loading: action.loading };\n\n case 'REQUEST_START':\n return { ...state, loading: true, response: null };\n\n case 'REQUEST_SUCCESS':\n return { ...state, loading: false, response: action.response, currentStep: 'response' };\n\n case 'REQUEST_ERROR':\n return { ...state, loading: false, response: action.response };\n\n case 'SET_SIDEBAR': return { ...state, sidebarOpen: action.open };\n case 'SYNC_API_KEY_HEADER': return { ...state, requestHeaders: action.headers };\n case 'CLEAR_API_KEY_SELECTION': return { ...state, selectedApiKey: null };\n case 'SYNC_URL': return { ...state, requestUrl: action.url };\n case 'RESET': return createInitialState();\n\n default: return state;\n }\n}\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nconst PlaygroundContext = createContext<PlaygroundContextType | undefined>(undefined);\n\nexport const usePlaygroundContext = () => {\n const context = useContext(PlaygroundContext);\n if (!context) throw new Error('usePlaygroundContext must be used within a PlaygroundProvider');\n return context;\n};\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\ninterface PlaygroundProviderProps {\n children: ReactNode;\n config: PlaygroundConfig;\n}\n\nexport const PlaygroundProvider: React.FC<PlaygroundProviderProps> = ({ children, config }) => {\n const [state, dispatch] = useReducer(reducer, undefined, createInitialState);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n // API keys come from the caller via ``config.apiKeys``. Empty\n // fallback keeps the playground working when the caller hasn't\n // wired any keys yet (public docs / unauthenticated demo).\n const apiKeys = React.useMemo(\n () => config.apiKeys ?? [],\n [config.apiKeys],\n );\n const isLoadingApiKeys = config.apiKeysLoading ?? false;\n\n // Auto-select first API key\n useEffect(() => {\n if (!isLoadingApiKeys && apiKeys.length > 0 && !state.selectedApiKey) {\n dispatch({ type: 'SET_API_KEY', apiKeyId: apiKeys[0]?.id || null });\n }\n }, [apiKeys, isLoadingApiKeys, state.selectedApiKey]);\n\n // Sync X-API-Key header when selected key changes\n useEffect(() => {\n try {\n const headers = parseRequestHeaders(state.requestHeaders);\n\n if (state.selectedApiKey) {\n const apiKey = apiKeys.find((k) => k.id === state.selectedApiKey);\n if (!apiKey) {\n dispatch({ type: 'CLEAR_API_KEY_SELECTION' });\n return;\n }\n // Header carries the raw ``secret`` (not the row id) — that's\n // what the server validates. Falls back to ``id`` for legacy\n // callers still on the old ApiKey shape.\n const keyValue = apiKey.secret || apiKey.id;\n if (headers['X-API-Key'] !== keyValue) {\n headers['X-API-Key'] = keyValue;\n dispatch({ type: 'SYNC_API_KEY_HEADER', headers: JSON.stringify(headers, null, 2) });\n }\n } else if (headers['X-API-Key']) {\n delete headers['X-API-Key'];\n dispatch({ type: 'SYNC_API_KEY_HEADER', headers: JSON.stringify(headers, null, 2) });\n }\n } catch (error) {\n consola.error('Error updating headers:', error);\n }\n }, [state.selectedApiKey, apiKeys]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Sync URL when path parameters change\n useEffect(() => {\n if (!state.selectedEndpoint) return;\n const updated = substituteUrlParameters(state.selectedEndpoint.path, state.parameters);\n if (updated !== state.requestUrl) {\n dispatch({ type: 'SYNC_URL', url: updated });\n }\n }, [state.parameters, state.selectedEndpoint]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Stable action dispatchers ─────────────────────────────────────────────\n\n const setCurrentStep = useCallback((step: PlaygroundStep) => dispatch({ type: 'SET_STEP', step }), []);\n const goToNextStep = useCallback(() => dispatch({ type: 'NEXT_STEP' }), []);\n const goToPreviousStep = useCallback(() => dispatch({ type: 'PREV_STEP' }), []);\n\n const setSelectedEndpoint = useCallback((endpoint: ApiEndpoint | null) =>\n dispatch({ type: 'SELECT_ENDPOINT', endpoint }), []);\n\n const setSelectedCategory = useCallback((category: string) =>\n dispatch({ type: 'SET_CATEGORY', category }), []);\n\n const setSearchTerm = useCallback((term: string) => dispatch({ type: 'SET_SEARCH', term }), []);\n const setSelectedVersion = useCallback((version: string) => dispatch({ type: 'SET_VERSION', version }), []);\n const setRequestUrl = useCallback((url: string) => dispatch({ type: 'SET_REQUEST_URL', url }), []);\n const setRequestMethod = useCallback((method: string) => dispatch({ type: 'SET_REQUEST_METHOD', method }), []);\n const setRequestHeaders = useCallback((headers: string) => dispatch({ type: 'SET_REQUEST_HEADERS', headers }), []);\n const setRequestBody = useCallback((body: string) => dispatch({ type: 'SET_REQUEST_BODY', body }), []);\n const setSelectedApiKey = useCallback((apiKeyId: string | null) => dispatch({ type: 'SET_API_KEY', apiKeyId }), []);\n const setManualApiToken = useCallback((token: string) => dispatch({ type: 'SET_MANUAL_TOKEN', token }), []);\n const setParameters = useCallback((parameters: Record<string, string>) =>\n dispatch({ type: 'SET_PARAMETERS', parameters }), []);\n const setResponse = useCallback((response: ApiResponse | null) =>\n dispatch({ type: 'SET_RESPONSE', response }), []);\n const setLoading = useCallback((loading: boolean) => dispatch({ type: 'SET_LOADING', loading }), []);\n const setSidebarOpen = useCallback((open: boolean) => dispatch({ type: 'SET_SIDEBAR', open }), []);\n const clearAll = useCallback(() => dispatch({ type: 'RESET' }), []);\n\n // ── Send request ──────────────────────────────────────────────────────────\n\n const sendRequest = useCallback(async () => {\n if (!state.requestUrl) {\n consola.error('No URL provided');\n return;\n }\n\n abortControllerRef.current?.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n // Single dispatch: loading=true + clear response\n dispatch({ type: 'REQUEST_START' });\n\n const startTime = Date.now();\n\n try {\n const headers = parseRequestHeaders(state.requestHeaders);\n\n let bearerToken: string | null = null;\n if (state.manualApiToken) {\n bearerToken = state.manualApiToken;\n } else if (typeof window !== 'undefined') {\n bearerToken = window.localStorage.getItem('auth_token');\n }\n\n if (bearerToken) headers['Authorization'] = `Bearer ${bearerToken}`;\n\n const requestOptions: RequestInit = {\n method: state.requestMethod,\n headers,\n signal: controller.signal,\n };\n\n if (state.requestBody && state.requestMethod !== 'GET') {\n requestOptions.body = state.requestBody;\n }\n\n const response = await fetch(state.requestUrl, requestOptions);\n const duration = Date.now() - startTime;\n const responseText = await response.text();\n\n let responseData: unknown;\n try { responseData = JSON.parse(responseText); }\n catch { responseData = responseText; }\n\n // Single dispatch: response + loading=false + step='response'\n dispatch({\n type: 'REQUEST_SUCCESS',\n response: {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n data: responseData,\n duration,\n },\n });\n\n consola.success(`${state.requestMethod} ${state.requestUrl} → ${response.status} (${duration}ms)`);\n } catch (error) {\n if (error instanceof DOMException && error.name === 'AbortError') return;\n consola.error('Request failed:', error);\n\n // Single dispatch: error response + loading=false\n dispatch({\n type: 'REQUEST_ERROR',\n response: {\n error: error instanceof Error ? error.message : 'Request failed',\n duration: Date.now() - startTime,\n },\n });\n }\n }, [state.requestUrl, state.requestHeaders, state.manualApiToken, state.requestMethod, state.requestBody]);\n\n // ── Context value ─────────────────────────────────────────────────────────\n\n const contextValue: PlaygroundContextType = {\n state,\n config,\n apiKeys,\n apiKeysLoading: isLoadingApiKeys,\n setCurrentStep,\n goToNextStep,\n goToPreviousStep,\n setSelectedEndpoint,\n setSelectedCategory,\n setSearchTerm,\n setSelectedVersion,\n setRequestUrl,\n setRequestMethod,\n setRequestHeaders,\n setRequestBody,\n setSelectedApiKey,\n setManualApiToken,\n setParameters,\n setResponse,\n setLoading,\n setSidebarOpen,\n clearAll,\n sendRequest,\n };\n\n return <PlaygroundContext.Provider value={contextValue}>{children}</PlaygroundContext.Provider>;\n};\n"]}
|
package/dist/chunk-BKWDHJKF.mjs
DELETED
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { __name } from './chunk-CGILA3WO.mjs';
|
|
2
|
-
import React2, { lazy, createContext, Suspense, useContext, useReducer, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
-
import consola from 'consola';
|
|
5
|
-
|
|
6
|
-
var PrettyCodeClient = lazy(() => import('./PrettyCode.client-DW5LTG47.mjs'));
|
|
7
|
-
var LoadingFallback = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx("div", { className: "relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900", children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8
|
-
/* @__PURE__ */ jsx("div", { className: "animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20" }),
|
|
9
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Loading code..." })
|
|
10
|
-
] }) }) }), "LoadingFallback");
|
|
11
|
-
var PrettyCode = /* @__PURE__ */ __name((props) => {
|
|
12
|
-
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingFallback, {}), children: /* @__PURE__ */ jsx(PrettyCodeClient, { ...props }) });
|
|
13
|
-
}, "PrettyCode");
|
|
14
|
-
var PrettyCode_default = PrettyCode;
|
|
15
|
-
|
|
16
|
-
// src/tools/OpenapiViewer/utils/apiKeyManager.ts
|
|
17
|
-
function findApiKeyById(apiKeys, keyId) {
|
|
18
|
-
return apiKeys.find((key) => key.id === keyId) || null;
|
|
19
|
-
}
|
|
20
|
-
__name(findApiKeyById, "findApiKeyById");
|
|
21
|
-
|
|
22
|
-
// src/tools/OpenapiViewer/utils/versionManager.ts
|
|
23
|
-
var API_VERSIONS = [
|
|
24
|
-
{
|
|
25
|
-
id: "v1",
|
|
26
|
-
name: "v1",
|
|
27
|
-
description: "Current stable version",
|
|
28
|
-
isDefault: true
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
var detectEndpointVersion = /* @__PURE__ */ __name((path) => {
|
|
32
|
-
const versionMatch = path.match(/\/api\/[^/]+\/(v\d+)\//);
|
|
33
|
-
if (versionMatch && versionMatch[1]) {
|
|
34
|
-
return versionMatch[1];
|
|
35
|
-
}
|
|
36
|
-
return "v1";
|
|
37
|
-
}, "detectEndpointVersion");
|
|
38
|
-
var isEndpointInVersion = /* @__PURE__ */ __name((endpoint, version) => {
|
|
39
|
-
const endpointVersion = detectEndpointVersion(endpoint.path);
|
|
40
|
-
return endpointVersion === version;
|
|
41
|
-
}, "isEndpointInVersion");
|
|
42
|
-
var deduplicateEndpoints = /* @__PURE__ */ __name((endpoints, preferredVersion) => {
|
|
43
|
-
const endpointMap = /* @__PURE__ */ new Map();
|
|
44
|
-
const groupedEndpoints = /* @__PURE__ */ new Map();
|
|
45
|
-
endpoints.forEach((endpoint) => {
|
|
46
|
-
const normalizedPath = normalizeEndpointPath(endpoint.path);
|
|
47
|
-
if (!groupedEndpoints.has(normalizedPath)) {
|
|
48
|
-
groupedEndpoints.set(normalizedPath, []);
|
|
49
|
-
}
|
|
50
|
-
groupedEndpoints.get(normalizedPath).push(endpoint);
|
|
51
|
-
});
|
|
52
|
-
groupedEndpoints.forEach((endpointGroup, normalizedPath) => {
|
|
53
|
-
let selectedEndpoint = null;
|
|
54
|
-
const versionEndpoint = endpointGroup.find((ep) => isEndpointInVersion(ep, preferredVersion));
|
|
55
|
-
if (versionEndpoint) {
|
|
56
|
-
selectedEndpoint = versionEndpoint;
|
|
57
|
-
} else if (endpointGroup.length > 0) {
|
|
58
|
-
selectedEndpoint = endpointGroup[0] || null;
|
|
59
|
-
}
|
|
60
|
-
if (selectedEndpoint) {
|
|
61
|
-
endpointMap.set(normalizedPath, selectedEndpoint);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
return Array.from(endpointMap.values());
|
|
65
|
-
}, "deduplicateEndpoints");
|
|
66
|
-
var normalizeEndpointPath = /* @__PURE__ */ __name((path) => {
|
|
67
|
-
return path.replace(/\/v\d+\//, "/");
|
|
68
|
-
}, "normalizeEndpointPath");
|
|
69
|
-
var getDefaultVersion = /* @__PURE__ */ __name(() => {
|
|
70
|
-
const defaultVersion = API_VERSIONS.find((v) => v.isDefault);
|
|
71
|
-
if (defaultVersion) {
|
|
72
|
-
return defaultVersion;
|
|
73
|
-
}
|
|
74
|
-
if (API_VERSIONS.length > 0 && API_VERSIONS[0]) {
|
|
75
|
-
return API_VERSIONS[0];
|
|
76
|
-
}
|
|
77
|
-
throw new Error("No API versions defined");
|
|
78
|
-
}, "getDefaultVersion");
|
|
79
|
-
|
|
80
|
-
// src/tools/OpenapiViewer/utils/formatters.ts
|
|
81
|
-
var isValidJson = /* @__PURE__ */ __name((str) => {
|
|
82
|
-
if (!str || typeof str !== "string") return false;
|
|
83
|
-
try {
|
|
84
|
-
JSON.parse(str);
|
|
85
|
-
return true;
|
|
86
|
-
} catch {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}, "isValidJson");
|
|
90
|
-
var parseRequestHeaders = /* @__PURE__ */ __name((headersString) => {
|
|
91
|
-
if (!headersString || typeof headersString !== "string") {
|
|
92
|
-
return { "Content-Type": "application/json" };
|
|
93
|
-
}
|
|
94
|
-
try {
|
|
95
|
-
const parsed = JSON.parse(headersString);
|
|
96
|
-
return typeof parsed === "object" && parsed !== null ? parsed : { "Content-Type": "application/json" };
|
|
97
|
-
} catch {
|
|
98
|
-
return { "Content-Type": "application/json" };
|
|
99
|
-
}
|
|
100
|
-
}, "parseRequestHeaders");
|
|
101
|
-
var substituteUrlParameters = /* @__PURE__ */ __name((url, parameters) => {
|
|
102
|
-
let substitutedUrl = url;
|
|
103
|
-
Object.entries(parameters).forEach(([key, value]) => {
|
|
104
|
-
if (value && value.trim() !== "") {
|
|
105
|
-
const patterns = [
|
|
106
|
-
new RegExp(`\\{${key}\\}`, "g"),
|
|
107
|
-
new RegExp(`%7B${key}%7D`, "gi")
|
|
108
|
-
];
|
|
109
|
-
patterns.forEach((pattern) => {
|
|
110
|
-
substitutedUrl = substitutedUrl.replace(pattern, encodeURIComponent(value));
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
return substitutedUrl;
|
|
115
|
-
}, "substituteUrlParameters");
|
|
116
|
-
var createInitialState = /* @__PURE__ */ __name(() => ({
|
|
117
|
-
currentStep: "endpoints",
|
|
118
|
-
steps: ["endpoints", "request", "response"],
|
|
119
|
-
selectedEndpoint: null,
|
|
120
|
-
selectedCategory: "All",
|
|
121
|
-
searchTerm: "",
|
|
122
|
-
selectedVersion: getDefaultVersion().id,
|
|
123
|
-
requestUrl: "",
|
|
124
|
-
requestMethod: "GET",
|
|
125
|
-
requestHeaders: '{\n "Content-Type": "application/json"\n}',
|
|
126
|
-
requestBody: "",
|
|
127
|
-
selectedApiKey: null,
|
|
128
|
-
manualApiToken: "",
|
|
129
|
-
parameters: {},
|
|
130
|
-
response: null,
|
|
131
|
-
loading: false,
|
|
132
|
-
sidebarOpen: false
|
|
133
|
-
}), "createInitialState");
|
|
134
|
-
function reducer(state, action) {
|
|
135
|
-
switch (action.type) {
|
|
136
|
-
case "SET_STEP":
|
|
137
|
-
return { ...state, currentStep: action.step };
|
|
138
|
-
case "NEXT_STEP": {
|
|
139
|
-
const i = state.steps.indexOf(state.currentStep);
|
|
140
|
-
return i < state.steps.length - 1 ? { ...state, currentStep: state.steps[i + 1] } : state;
|
|
141
|
-
}
|
|
142
|
-
case "PREV_STEP": {
|
|
143
|
-
const i = state.steps.indexOf(state.currentStep);
|
|
144
|
-
return i > 0 ? { ...state, currentStep: state.steps[i - 1] } : state;
|
|
145
|
-
}
|
|
146
|
-
case "SELECT_ENDPOINT":
|
|
147
|
-
if (!action.endpoint) return { ...state, selectedEndpoint: null };
|
|
148
|
-
return {
|
|
149
|
-
...state,
|
|
150
|
-
selectedEndpoint: action.endpoint,
|
|
151
|
-
requestMethod: action.endpoint.method,
|
|
152
|
-
requestUrl: action.endpoint.path,
|
|
153
|
-
parameters: {},
|
|
154
|
-
currentStep: "request"
|
|
155
|
-
};
|
|
156
|
-
case "SET_CATEGORY":
|
|
157
|
-
return { ...state, selectedCategory: action.category };
|
|
158
|
-
case "SET_SEARCH":
|
|
159
|
-
return { ...state, searchTerm: action.term };
|
|
160
|
-
case "SET_VERSION":
|
|
161
|
-
return { ...state, selectedVersion: action.version };
|
|
162
|
-
case "SET_REQUEST_URL":
|
|
163
|
-
return { ...state, requestUrl: action.url };
|
|
164
|
-
case "SET_REQUEST_METHOD":
|
|
165
|
-
return { ...state, requestMethod: action.method };
|
|
166
|
-
case "SET_REQUEST_HEADERS":
|
|
167
|
-
return { ...state, requestHeaders: action.headers };
|
|
168
|
-
case "SET_REQUEST_BODY":
|
|
169
|
-
return { ...state, requestBody: action.body };
|
|
170
|
-
case "SET_API_KEY":
|
|
171
|
-
return { ...state, selectedApiKey: action.apiKeyId };
|
|
172
|
-
case "SET_MANUAL_TOKEN":
|
|
173
|
-
return { ...state, manualApiToken: action.token };
|
|
174
|
-
case "SET_PARAMETERS":
|
|
175
|
-
return { ...state, parameters: action.parameters };
|
|
176
|
-
case "SET_RESPONSE":
|
|
177
|
-
return { ...state, response: action.response };
|
|
178
|
-
case "SET_LOADING":
|
|
179
|
-
return { ...state, loading: action.loading };
|
|
180
|
-
case "REQUEST_START":
|
|
181
|
-
return { ...state, loading: true, response: null };
|
|
182
|
-
case "REQUEST_SUCCESS":
|
|
183
|
-
return { ...state, loading: false, response: action.response, currentStep: "response" };
|
|
184
|
-
case "REQUEST_ERROR":
|
|
185
|
-
return { ...state, loading: false, response: action.response };
|
|
186
|
-
case "SET_SIDEBAR":
|
|
187
|
-
return { ...state, sidebarOpen: action.open };
|
|
188
|
-
case "SYNC_API_KEY_HEADER":
|
|
189
|
-
return { ...state, requestHeaders: action.headers };
|
|
190
|
-
case "CLEAR_API_KEY_SELECTION":
|
|
191
|
-
return { ...state, selectedApiKey: null };
|
|
192
|
-
case "SYNC_URL":
|
|
193
|
-
return { ...state, requestUrl: action.url };
|
|
194
|
-
case "RESET":
|
|
195
|
-
return createInitialState();
|
|
196
|
-
default:
|
|
197
|
-
return state;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
__name(reducer, "reducer");
|
|
201
|
-
var PlaygroundContext = createContext(void 0);
|
|
202
|
-
var usePlaygroundContext = /* @__PURE__ */ __name(() => {
|
|
203
|
-
const context = useContext(PlaygroundContext);
|
|
204
|
-
if (!context) throw new Error("usePlaygroundContext must be used within a PlaygroundProvider");
|
|
205
|
-
return context;
|
|
206
|
-
}, "usePlaygroundContext");
|
|
207
|
-
var PlaygroundProvider = /* @__PURE__ */ __name(({ children, config }) => {
|
|
208
|
-
const [state, dispatch] = useReducer(reducer, void 0, createInitialState);
|
|
209
|
-
const abortControllerRef = useRef(null);
|
|
210
|
-
const apiKeys = React2.useMemo(
|
|
211
|
-
() => config.apiKeys ?? [],
|
|
212
|
-
[config.apiKeys]
|
|
213
|
-
);
|
|
214
|
-
const isLoadingApiKeys = config.apiKeysLoading ?? false;
|
|
215
|
-
useEffect(() => {
|
|
216
|
-
if (!isLoadingApiKeys && apiKeys.length > 0 && !state.selectedApiKey) {
|
|
217
|
-
dispatch({ type: "SET_API_KEY", apiKeyId: apiKeys[0]?.id || null });
|
|
218
|
-
}
|
|
219
|
-
}, [apiKeys, isLoadingApiKeys, state.selectedApiKey]);
|
|
220
|
-
useEffect(() => {
|
|
221
|
-
try {
|
|
222
|
-
const headers = parseRequestHeaders(state.requestHeaders);
|
|
223
|
-
if (state.selectedApiKey) {
|
|
224
|
-
const apiKey = apiKeys.find((k) => k.id === state.selectedApiKey);
|
|
225
|
-
if (!apiKey) {
|
|
226
|
-
dispatch({ type: "CLEAR_API_KEY_SELECTION" });
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const keyValue = apiKey.secret || apiKey.id;
|
|
230
|
-
if (headers["X-API-Key"] !== keyValue) {
|
|
231
|
-
headers["X-API-Key"] = keyValue;
|
|
232
|
-
dispatch({ type: "SYNC_API_KEY_HEADER", headers: JSON.stringify(headers, null, 2) });
|
|
233
|
-
}
|
|
234
|
-
} else if (headers["X-API-Key"]) {
|
|
235
|
-
delete headers["X-API-Key"];
|
|
236
|
-
dispatch({ type: "SYNC_API_KEY_HEADER", headers: JSON.stringify(headers, null, 2) });
|
|
237
|
-
}
|
|
238
|
-
} catch (error) {
|
|
239
|
-
consola.error("Error updating headers:", error);
|
|
240
|
-
}
|
|
241
|
-
}, [state.selectedApiKey, apiKeys]);
|
|
242
|
-
useEffect(() => {
|
|
243
|
-
if (!state.selectedEndpoint) return;
|
|
244
|
-
const updated = substituteUrlParameters(state.selectedEndpoint.path, state.parameters);
|
|
245
|
-
if (updated !== state.requestUrl) {
|
|
246
|
-
dispatch({ type: "SYNC_URL", url: updated });
|
|
247
|
-
}
|
|
248
|
-
}, [state.parameters, state.selectedEndpoint]);
|
|
249
|
-
const setCurrentStep = useCallback((step) => dispatch({ type: "SET_STEP", step }), []);
|
|
250
|
-
const goToNextStep = useCallback(() => dispatch({ type: "NEXT_STEP" }), []);
|
|
251
|
-
const goToPreviousStep = useCallback(() => dispatch({ type: "PREV_STEP" }), []);
|
|
252
|
-
const setSelectedEndpoint = useCallback((endpoint) => dispatch({ type: "SELECT_ENDPOINT", endpoint }), []);
|
|
253
|
-
const setSelectedCategory = useCallback((category) => dispatch({ type: "SET_CATEGORY", category }), []);
|
|
254
|
-
const setSearchTerm = useCallback((term) => dispatch({ type: "SET_SEARCH", term }), []);
|
|
255
|
-
const setSelectedVersion = useCallback((version) => dispatch({ type: "SET_VERSION", version }), []);
|
|
256
|
-
const setRequestUrl = useCallback((url) => dispatch({ type: "SET_REQUEST_URL", url }), []);
|
|
257
|
-
const setRequestMethod = useCallback((method) => dispatch({ type: "SET_REQUEST_METHOD", method }), []);
|
|
258
|
-
const setRequestHeaders = useCallback((headers) => dispatch({ type: "SET_REQUEST_HEADERS", headers }), []);
|
|
259
|
-
const setRequestBody = useCallback((body) => dispatch({ type: "SET_REQUEST_BODY", body }), []);
|
|
260
|
-
const setSelectedApiKey = useCallback((apiKeyId) => dispatch({ type: "SET_API_KEY", apiKeyId }), []);
|
|
261
|
-
const setManualApiToken = useCallback((token) => dispatch({ type: "SET_MANUAL_TOKEN", token }), []);
|
|
262
|
-
const setParameters = useCallback((parameters) => dispatch({ type: "SET_PARAMETERS", parameters }), []);
|
|
263
|
-
const setResponse = useCallback((response) => dispatch({ type: "SET_RESPONSE", response }), []);
|
|
264
|
-
const setLoading = useCallback((loading) => dispatch({ type: "SET_LOADING", loading }), []);
|
|
265
|
-
const setSidebarOpen = useCallback((open) => dispatch({ type: "SET_SIDEBAR", open }), []);
|
|
266
|
-
const clearAll = useCallback(() => dispatch({ type: "RESET" }), []);
|
|
267
|
-
const sendRequest = useCallback(async () => {
|
|
268
|
-
if (!state.requestUrl) {
|
|
269
|
-
consola.error("No URL provided");
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
abortControllerRef.current?.abort();
|
|
273
|
-
const controller = new AbortController();
|
|
274
|
-
abortControllerRef.current = controller;
|
|
275
|
-
dispatch({ type: "REQUEST_START" });
|
|
276
|
-
const startTime = Date.now();
|
|
277
|
-
try {
|
|
278
|
-
const headers = parseRequestHeaders(state.requestHeaders);
|
|
279
|
-
let bearerToken = null;
|
|
280
|
-
if (state.manualApiToken) {
|
|
281
|
-
bearerToken = state.manualApiToken;
|
|
282
|
-
} else if (typeof window !== "undefined") {
|
|
283
|
-
bearerToken = window.localStorage.getItem("auth_token");
|
|
284
|
-
}
|
|
285
|
-
if (bearerToken) headers["Authorization"] = `Bearer ${bearerToken}`;
|
|
286
|
-
const requestOptions = {
|
|
287
|
-
method: state.requestMethod,
|
|
288
|
-
headers,
|
|
289
|
-
signal: controller.signal
|
|
290
|
-
};
|
|
291
|
-
if (state.requestBody && state.requestMethod !== "GET") {
|
|
292
|
-
requestOptions.body = state.requestBody;
|
|
293
|
-
}
|
|
294
|
-
const response = await fetch(state.requestUrl, requestOptions);
|
|
295
|
-
const duration = Date.now() - startTime;
|
|
296
|
-
const responseText = await response.text();
|
|
297
|
-
let responseData;
|
|
298
|
-
try {
|
|
299
|
-
responseData = JSON.parse(responseText);
|
|
300
|
-
} catch {
|
|
301
|
-
responseData = responseText;
|
|
302
|
-
}
|
|
303
|
-
dispatch({
|
|
304
|
-
type: "REQUEST_SUCCESS",
|
|
305
|
-
response: {
|
|
306
|
-
status: response.status,
|
|
307
|
-
statusText: response.statusText,
|
|
308
|
-
headers: Object.fromEntries(response.headers.entries()),
|
|
309
|
-
data: responseData,
|
|
310
|
-
duration
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
consola.success(`${state.requestMethod} ${state.requestUrl} \u2192 ${response.status} (${duration}ms)`);
|
|
314
|
-
} catch (error) {
|
|
315
|
-
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
316
|
-
consola.error("Request failed:", error);
|
|
317
|
-
dispatch({
|
|
318
|
-
type: "REQUEST_ERROR",
|
|
319
|
-
response: {
|
|
320
|
-
error: error instanceof Error ? error.message : "Request failed",
|
|
321
|
-
duration: Date.now() - startTime
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
}, [state.requestUrl, state.requestHeaders, state.manualApiToken, state.requestMethod, state.requestBody]);
|
|
326
|
-
const contextValue = {
|
|
327
|
-
state,
|
|
328
|
-
config,
|
|
329
|
-
apiKeys,
|
|
330
|
-
apiKeysLoading: isLoadingApiKeys,
|
|
331
|
-
setCurrentStep,
|
|
332
|
-
goToNextStep,
|
|
333
|
-
goToPreviousStep,
|
|
334
|
-
setSelectedEndpoint,
|
|
335
|
-
setSelectedCategory,
|
|
336
|
-
setSearchTerm,
|
|
337
|
-
setSelectedVersion,
|
|
338
|
-
setRequestUrl,
|
|
339
|
-
setRequestMethod,
|
|
340
|
-
setRequestHeaders,
|
|
341
|
-
setRequestBody,
|
|
342
|
-
setSelectedApiKey,
|
|
343
|
-
setManualApiToken,
|
|
344
|
-
setParameters,
|
|
345
|
-
setResponse,
|
|
346
|
-
setLoading,
|
|
347
|
-
setSidebarOpen,
|
|
348
|
-
clearAll,
|
|
349
|
-
sendRequest
|
|
350
|
-
};
|
|
351
|
-
return /* @__PURE__ */ jsx(PlaygroundContext.Provider, { value: contextValue, children });
|
|
352
|
-
}, "PlaygroundProvider");
|
|
353
|
-
|
|
354
|
-
export { PlaygroundProvider, PrettyCode_default, deduplicateEndpoints, findApiKeyById, isValidJson, parseRequestHeaders, usePlaygroundContext };
|
|
355
|
-
//# sourceMappingURL=chunk-BKWDHJKF.mjs.map
|
|
356
|
-
//# sourceMappingURL=chunk-BKWDHJKF.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tools/PrettyCode/index.tsx","../src/tools/OpenapiViewer/utils/apiKeyManager.ts","../src/tools/OpenapiViewer/utils/versionManager.ts","../src/tools/OpenapiViewer/utils/formatters.ts","../src/tools/OpenapiViewer/context/PlaygroundContext.tsx"],"names":["React","jsx"],"mappings":"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","file":"chunk-BKWDHJKF.mjs","sourcesContent":["/**\n * PrettyCode Component - Dynamic Import Wrapper\n *\n * Lazy loads the heavy Prism library (~500KB) only when needed.\n * This significantly reduces the initial bundle size.\n */\n\n'use client';\n\nimport React, { lazy, Suspense } from 'react';\nimport type { Language } from 'prism-react-renderer';\n\n// Lazy load the client component\nconst PrettyCodeClient = lazy(() => import('./PrettyCode.client'));\n\n// Loading fallback component\nconst LoadingFallback = () => (\n <div className=\"relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900\">\n <div className=\"p-4\">\n <div className=\"flex items-center gap-2\">\n <div className=\"animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20\"></div>\n <span className=\"text-xs text-muted-foreground\">Loading code...</span>\n </div>\n </div>\n </div>\n);\n\nexport interface PrettyCodeProps {\n data: string | object;\n language: Language;\n className?: string;\n mode?: 'dark' | 'light';\n inline?: boolean;\n customBg?: string;\n isCompact?: boolean;\n /** Block scroll capture until user clicks (default: true) */\n scrollIsolation?: boolean;\n}\n\nconst PrettyCode: React.FC<PrettyCodeProps> = (props) => {\n return (\n <Suspense fallback={<LoadingFallback />}>\n <PrettyCodeClient {...props} />\n </Suspense>\n );\n};\n\nexport default PrettyCode;\nexport type { Language };\n","/**\n * API Key Management Utility\n *\n * Provides centralized functions for managing API keys in headers and requests.\n * This utility can be used across different components that need to handle API keys.\n */\n\nimport type { ApiKey } from '../types';\n\nexport type { ApiKey };\n\nexport interface HeadersWithApiKey {\n [key: string]: string;\n}\n\n/**\n * Add API key to request headers\n * @param headers - Existing headers object\n * @param apiKey - API key object or string\n * @returns Headers with API key added\n */\nexport function addApiKeyToHeaders(headers: HeadersWithApiKey, apiKey: ApiKey | string | null): HeadersWithApiKey {\n if (!apiKey) {\n return headers;\n }\n\n // ``secret`` is the raw key that goes in the X-API-Key header.\n // Falls back to ``id`` for backwards compatibility — older callers\n // only had ``id`` and used it as both selector and secret.\n const keyValue = typeof apiKey === 'string' ? apiKey : (apiKey.secret || apiKey.id || '');\n\n return {\n ...headers,\n 'X-API-Key': keyValue,\n };\n}\n\n/**\n * Remove API key from headers object\n * @param headers - Headers object\n * @returns Headers without API key\n */\nexport function removeApiKeyFromHeaders(headers: HeadersWithApiKey): HeadersWithApiKey {\n const { 'X-API-Key': removed, ...remainingHeaders } = headers;\n return remainingHeaders;\n}\n\n/**\n * Remove API key from headers JSON string\n * @param headersJson - JSON string of headers\n * @returns JSON string without API key\n */\nexport function removeApiKeyFromHeadersJson(headersJson: string): string {\n try {\n const headers = JSON.parse(headersJson);\n const updatedHeaders = removeApiKeyFromHeaders(headers);\n return JSON.stringify(updatedHeaders, null, 2);\n } catch (error) {\n console.error('Error parsing headers JSON:', error);\n return headersJson;\n }\n}\n\n/**\n * Update headers JSON string with API key\n * @param headersJson - JSON string of headers\n * @param apiKey - API key object or string\n * @returns Updated JSON string\n */\nexport function updateHeadersJsonWithApiKey(headersJson: string, apiKey: ApiKey | string | null): string {\n try {\n const headers = JSON.parse(headersJson);\n const updatedHeaders = addApiKeyToHeaders(headers, apiKey);\n return JSON.stringify(updatedHeaders, null, 2);\n } catch (error) {\n console.error('Error parsing headers JSON:', error);\n return headersJson;\n }\n}\n\n/**\n * Find API key by ID in a list of API keys\n * @param apiKeys - Array of API keys\n * @param keyId - ID of the API key to find\n * @returns API key object or null\n */\nexport function findApiKeyById(apiKeys: ApiKey[], keyId: string): ApiKey | null {\n return apiKeys.find((key) => key.id === keyId) || null;\n}\n\n/**\n * Validate API key format\n * @param apiKey - API key string to validate\n * @returns Whether the API key format is valid\n */\nexport function validateApiKeyFormat(apiKey: string): boolean {\n // Basic validation - adjust based on your API key format requirements\n return typeof apiKey === 'string' && apiKey.length > 0 && apiKey.trim() !== '';\n}\n\n/**\n * Create default headers with API key\n * @param apiKey - API key object or string\n * @returns Default headers with API key\n */\nexport function createDefaultHeaders(apiKey?: ApiKey | string): HeadersWithApiKey {\n const defaultHeaders: HeadersWithApiKey = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n return addApiKeyToHeaders(defaultHeaders, apiKey);\n }\n\n return defaultHeaders;\n}\n\n/**\n * Merge headers with API key\n * @param baseHeaders - Base headers object\n * @param additionalHeaders - Additional headers to merge\n * @param apiKey - API key to add\n * @returns Merged headers with API key\n */\nexport function mergeHeadersWithApiKey(baseHeaders: HeadersWithApiKey, additionalHeaders: HeadersWithApiKey, apiKey?: ApiKey | string): HeadersWithApiKey {\n const mergedHeaders = { ...baseHeaders, ...additionalHeaders };\n\n if (apiKey) {\n return addApiKeyToHeaders(mergedHeaders, apiKey);\n }\n\n return mergedHeaders;\n}\n\n/**\n * Log API key usage (for debugging/analytics)\n * @param apiKey - API key that was used\n * @param endpoint - Endpoint that was called\n * @param success - Whether the request was successful\n */\nexport function logApiKeyUsage(apiKey: ApiKey | string, endpoint: string, success: boolean): void {\n const keyValue = typeof apiKey === 'string' ? apiKey : (apiKey.secret || apiKey.id || '');\n const keyName = typeof apiKey === 'string' ? 'Unknown' : apiKey.name;\n\n console.log(`API Key Usage:`, {\n keyName,\n keyValue: keyValue.substring(0, 8) + '...',\n endpoint,\n success,\n timestamp: new Date().toISOString(),\n });\n}\n","/**\n * API Version Management Utilities\n * Handles version detection, filtering, and URL transformation\n */\n\nimport type { ApiEndpoint } from '../types';\n\nexport interface ApiVersion {\n id: string;\n name: string;\n description: string;\n isDefault: boolean;\n}\n\n// Available API versions\nexport const API_VERSIONS: ApiVersion[] = [\n {\n id: 'v1',\n name: 'v1',\n description: 'Current stable version',\n isDefault: true,\n },\n];\n\n/**\n * Detect version from endpoint path\n */\nexport const detectEndpointVersion = (path: string): string => {\n // Check for versioned paths like /api/vehicles_api/v1/...\n const versionMatch = path.match(/\\/api\\/[^/]+\\/(v\\d+)\\//);\n if (versionMatch && versionMatch[1]) {\n return versionMatch[1];\n }\n \n // If no version found, default to v1\n return 'v1';\n};\n\n/**\n * Check if endpoint belongs to specific version\n */\nexport const isEndpointInVersion = (endpoint: ApiEndpoint, version: string): boolean => {\n const endpointVersion = detectEndpointVersion(endpoint.path);\n return endpointVersion === version;\n};\n\n/**\n * Filter endpoints by version\n */\nexport const filterEndpointsByVersion = (endpoints: ApiEndpoint[], version: string): ApiEndpoint[] => {\n return endpoints.filter(endpoint => isEndpointInVersion(endpoint, version));\n};\n\n/**\n * Remove duplicate endpoints across versions\n * Keeps only the specified version, removes duplicates from other versions\n */\nexport const deduplicateEndpoints = (endpoints: ApiEndpoint[], preferredVersion: string): ApiEndpoint[] => {\n const endpointMap = new Map<string, ApiEndpoint>();\n \n // Group endpoints by normalized path (without version)\n const groupedEndpoints = new Map<string, ApiEndpoint[]>();\n \n endpoints.forEach(endpoint => {\n const normalizedPath = normalizeEndpointPath(endpoint.path);\n if (!groupedEndpoints.has(normalizedPath)) {\n groupedEndpoints.set(normalizedPath, []);\n }\n groupedEndpoints.get(normalizedPath)!.push(endpoint);\n });\n \n // For each group, pick the endpoint from preferred version\n groupedEndpoints.forEach((endpointGroup, normalizedPath) => {\n let selectedEndpoint: ApiEndpoint | null = null;\n \n // Try to find endpoint in preferred version\n const versionEndpoint = endpointGroup.find(ep => isEndpointInVersion(ep, preferredVersion));\n if (versionEndpoint) {\n selectedEndpoint = versionEndpoint;\n } else if (endpointGroup.length > 0) {\n // Fallback to first available endpoint\n selectedEndpoint = endpointGroup[0] || null;\n }\n \n if (selectedEndpoint) {\n endpointMap.set(normalizedPath, selectedEndpoint);\n }\n });\n \n return Array.from(endpointMap.values());\n};\n\n/**\n * Normalize endpoint path by removing version prefix\n * /api/vehicles_api/v1/vehicles/ -> /api/vehicles_api/vehicles/\n * /api/vehicles_api/vehicles/ -> /api/vehicles_api/vehicles/\n */\nexport const normalizeEndpointPath = (path: string): string => {\n // Remove version prefix like /v1/, /v2/, etc.\n return path.replace(/\\/v\\d+\\//, '/');\n};\n\n/**\n * Convert endpoint path to specific version\n */\nexport const convertEndpointToVersion = (endpoint: ApiEndpoint, targetVersion: string): ApiEndpoint => {\n const currentVersion = detectEndpointVersion(endpoint.path);\n \n // If already in target version, return as is\n if (currentVersion === targetVersion) {\n return endpoint;\n }\n \n let newPath = endpoint.path;\n \n // Replace version: /api/vehicles_api/v1/vehicles/ -> /api/vehicles_api/v2/vehicles/\n newPath = newPath.replace(/\\/v\\d+\\//, `/${targetVersion}/`);\n \n return {\n ...endpoint,\n path: newPath,\n };\n};\n\n/**\n * Get version info by ID\n */\nexport const getVersionById = (versionId: string): ApiVersion | undefined => {\n return API_VERSIONS.find(v => v.id === versionId);\n};\n\n/**\n * Get default version\n */\nexport const getDefaultVersion = (): ApiVersion => {\n const defaultVersion = API_VERSIONS.find(v => v.isDefault);\n if (defaultVersion) {\n return defaultVersion;\n }\n \n // Fallback to first version if no default is set\n if (API_VERSIONS.length > 0 && API_VERSIONS[0]) {\n return API_VERSIONS[0];\n }\n \n // This should never happen, but TypeScript requires it\n throw new Error('No API versions defined');\n};\n\n/**\n * Get version statistics from endpoints\n */\nexport const getVersionStats = (endpoints: ApiEndpoint[]): Record<string, number> => {\n const stats: Record<string, number> = {};\n \n API_VERSIONS.forEach(version => {\n stats[version.id] = filterEndpointsByVersion(endpoints, version.id).length;\n });\n \n return stats;\n};\n","import type { ApiKey } from '../types';\nimport { HTTP_METHOD_COLORS, HTTP_STATUS_COLORS } from '../constants';\n\nexport const getMethodColor = (\n method: string\n): 'success' | 'primary' | 'warning' | 'error' | 'default' => {\n return HTTP_METHOD_COLORS[method.toUpperCase() as keyof typeof HTTP_METHOD_COLORS] || 'default';\n};\n\nexport const getStatusColor = (\n status: number\n): 'success' | 'warning' | 'error' | 'default' => {\n const firstDigit = Math.floor(status / 100).toString();\n return HTTP_STATUS_COLORS[firstDigit as keyof typeof HTTP_STATUS_COLORS] || 'default';\n};\n\nexport const formatApiKeyDisplay = (apiKey: ApiKey): string => {\n const preview = apiKey.id.substring(0, 8);\n return `${apiKey.name} (${preview}...)`;\n};\n\nexport const isValidJson = (str: string): boolean => {\n if (!str || typeof str !== 'string') return false;\n try {\n JSON.parse(str);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const formatRequestHeaders = (headers: Record<string, string>): string => {\n return JSON.stringify(headers, null, 2);\n};\n\nexport const parseRequestHeaders = (headersString: string): Record<string, string> => {\n if (!headersString || typeof headersString !== 'string') {\n return { 'Content-Type': 'application/json' };\n }\n\n try {\n const parsed = JSON.parse(headersString);\n return typeof parsed === 'object' && parsed !== null ? parsed : { 'Content-Type': 'application/json' };\n } catch {\n return { 'Content-Type': 'application/json' };\n }\n};\n\n// Substitute URL parameters like {id}, {userId}, etc.\nexport const substituteUrlParameters = (\n url: string,\n parameters: Record<string, string>\n): string => {\n let substitutedUrl = url;\n\n Object.entries(parameters).forEach(([key, value]) => {\n if (value && value.trim() !== '') {\n // Replace both {key} and %7Bkey%7D patterns (URL encoded version)\n const patterns = [\n new RegExp(`\\\\{${key}\\\\}`, 'g'),\n new RegExp(`%7B${key}%7D`, 'gi'),\n ];\n\n patterns.forEach((pattern) => {\n substitutedUrl = substitutedUrl.replace(pattern, encodeURIComponent(value));\n });\n }\n });\n\n return substitutedUrl;\n};\n","'use client';\n\nimport consola from 'consola';\nimport React, {\n createContext, ReactNode, useCallback, useContext, useEffect, useReducer, useRef\n} from 'react';\n\nimport type {\n ApiEndpoint, ApiResponse, PlaygroundConfig, PlaygroundContextType, PlaygroundState,\n PlaygroundStep\n} from '../types';\nimport { parseRequestHeaders, substituteUrlParameters } from '../utils';\nimport { getDefaultVersion } from '../utils/versionManager';\n\n// ─── Initial state ────────────────────────────────────────────────────────────\n\nconst createInitialState = (): PlaygroundState => ({\n currentStep: 'endpoints',\n steps: ['endpoints', 'request', 'response'],\n selectedEndpoint: null,\n selectedCategory: 'All',\n searchTerm: '',\n selectedVersion: getDefaultVersion().id,\n requestUrl: '',\n requestMethod: 'GET',\n requestHeaders: '{\\n \"Content-Type\": \"application/json\"\\n}',\n requestBody: '',\n selectedApiKey: null,\n manualApiToken: '',\n parameters: {},\n response: null,\n loading: false,\n sidebarOpen: false,\n});\n\n// ─── Actions ──────────────────────────────────────────────────────────────────\n\ntype Action =\n | { type: 'SET_STEP'; step: PlaygroundStep }\n | { type: 'NEXT_STEP' }\n | { type: 'PREV_STEP' }\n | { type: 'SELECT_ENDPOINT'; endpoint: ApiEndpoint | null }\n | { type: 'SET_CATEGORY'; category: string }\n | { type: 'SET_SEARCH'; term: string }\n | { type: 'SET_VERSION'; version: string }\n | { type: 'SET_REQUEST_URL'; url: string }\n | { type: 'SET_REQUEST_METHOD'; method: string }\n | { type: 'SET_REQUEST_HEADERS'; headers: string }\n | { type: 'SET_REQUEST_BODY'; body: string }\n | { type: 'SET_API_KEY'; apiKeyId: string | null }\n | { type: 'SET_MANUAL_TOKEN'; token: string }\n | { type: 'SET_PARAMETERS'; parameters: Record<string, string> }\n | { type: 'SET_RESPONSE'; response: ApiResponse | null }\n | { type: 'SET_LOADING'; loading: boolean }\n // Batched: set loading + clear response atomically (avoids two renders on send)\n | { type: 'REQUEST_START' }\n // Batched: set response + loading=false + advance step atomically (avoids three renders)\n | { type: 'REQUEST_SUCCESS'; response: ApiResponse }\n // Batched: set error response + loading=false atomically\n | { type: 'REQUEST_ERROR'; response: ApiResponse }\n | { type: 'SET_SIDEBAR'; open: boolean }\n | { type: 'SYNC_API_KEY_HEADER'; headers: string }\n | { type: 'CLEAR_API_KEY_SELECTION' }\n | { type: 'SYNC_URL'; url: string }\n | { type: 'RESET' };\n\n// ─── Reducer ──────────────────────────────────────────────────────────────────\n\nfunction reducer(state: PlaygroundState, action: Action): PlaygroundState {\n switch (action.type) {\n case 'SET_STEP':\n return { ...state, currentStep: action.step };\n\n case 'NEXT_STEP': {\n const i = state.steps.indexOf(state.currentStep);\n return i < state.steps.length - 1\n ? { ...state, currentStep: state.steps[i + 1]! }\n : state;\n }\n\n case 'PREV_STEP': {\n const i = state.steps.indexOf(state.currentStep);\n return i > 0 ? { ...state, currentStep: state.steps[i - 1]! } : state;\n }\n\n case 'SELECT_ENDPOINT':\n if (!action.endpoint) return { ...state, selectedEndpoint: null };\n return {\n ...state,\n selectedEndpoint: action.endpoint,\n requestMethod: action.endpoint.method,\n requestUrl: action.endpoint.path,\n parameters: {},\n currentStep: 'request',\n };\n\n case 'SET_CATEGORY': return { ...state, selectedCategory: action.category };\n case 'SET_SEARCH': return { ...state, searchTerm: action.term };\n case 'SET_VERSION': return { ...state, selectedVersion: action.version };\n case 'SET_REQUEST_URL': return { ...state, requestUrl: action.url };\n case 'SET_REQUEST_METHOD': return { ...state, requestMethod: action.method };\n case 'SET_REQUEST_HEADERS': return { ...state, requestHeaders: action.headers };\n case 'SET_REQUEST_BODY': return { ...state, requestBody: action.body };\n case 'SET_API_KEY': return { ...state, selectedApiKey: action.apiKeyId };\n case 'SET_MANUAL_TOKEN': return { ...state, manualApiToken: action.token };\n case 'SET_PARAMETERS': return { ...state, parameters: action.parameters };\n case 'SET_RESPONSE': return { ...state, response: action.response };\n case 'SET_LOADING': return { ...state, loading: action.loading };\n\n case 'REQUEST_START':\n return { ...state, loading: true, response: null };\n\n case 'REQUEST_SUCCESS':\n return { ...state, loading: false, response: action.response, currentStep: 'response' };\n\n case 'REQUEST_ERROR':\n return { ...state, loading: false, response: action.response };\n\n case 'SET_SIDEBAR': return { ...state, sidebarOpen: action.open };\n case 'SYNC_API_KEY_HEADER': return { ...state, requestHeaders: action.headers };\n case 'CLEAR_API_KEY_SELECTION': return { ...state, selectedApiKey: null };\n case 'SYNC_URL': return { ...state, requestUrl: action.url };\n case 'RESET': return createInitialState();\n\n default: return state;\n }\n}\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nconst PlaygroundContext = createContext<PlaygroundContextType | undefined>(undefined);\n\nexport const usePlaygroundContext = () => {\n const context = useContext(PlaygroundContext);\n if (!context) throw new Error('usePlaygroundContext must be used within a PlaygroundProvider');\n return context;\n};\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\ninterface PlaygroundProviderProps {\n children: ReactNode;\n config: PlaygroundConfig;\n}\n\nexport const PlaygroundProvider: React.FC<PlaygroundProviderProps> = ({ children, config }) => {\n const [state, dispatch] = useReducer(reducer, undefined, createInitialState);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n // API keys come from the caller via ``config.apiKeys``. Empty\n // fallback keeps the playground working when the caller hasn't\n // wired any keys yet (public docs / unauthenticated demo).\n const apiKeys = React.useMemo(\n () => config.apiKeys ?? [],\n [config.apiKeys],\n );\n const isLoadingApiKeys = config.apiKeysLoading ?? false;\n\n // Auto-select first API key\n useEffect(() => {\n if (!isLoadingApiKeys && apiKeys.length > 0 && !state.selectedApiKey) {\n dispatch({ type: 'SET_API_KEY', apiKeyId: apiKeys[0]?.id || null });\n }\n }, [apiKeys, isLoadingApiKeys, state.selectedApiKey]);\n\n // Sync X-API-Key header when selected key changes\n useEffect(() => {\n try {\n const headers = parseRequestHeaders(state.requestHeaders);\n\n if (state.selectedApiKey) {\n const apiKey = apiKeys.find((k) => k.id === state.selectedApiKey);\n if (!apiKey) {\n dispatch({ type: 'CLEAR_API_KEY_SELECTION' });\n return;\n }\n // Header carries the raw ``secret`` (not the row id) — that's\n // what the server validates. Falls back to ``id`` for legacy\n // callers still on the old ApiKey shape.\n const keyValue = apiKey.secret || apiKey.id;\n if (headers['X-API-Key'] !== keyValue) {\n headers['X-API-Key'] = keyValue;\n dispatch({ type: 'SYNC_API_KEY_HEADER', headers: JSON.stringify(headers, null, 2) });\n }\n } else if (headers['X-API-Key']) {\n delete headers['X-API-Key'];\n dispatch({ type: 'SYNC_API_KEY_HEADER', headers: JSON.stringify(headers, null, 2) });\n }\n } catch (error) {\n consola.error('Error updating headers:', error);\n }\n }, [state.selectedApiKey, apiKeys]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Sync URL when path parameters change\n useEffect(() => {\n if (!state.selectedEndpoint) return;\n const updated = substituteUrlParameters(state.selectedEndpoint.path, state.parameters);\n if (updated !== state.requestUrl) {\n dispatch({ type: 'SYNC_URL', url: updated });\n }\n }, [state.parameters, state.selectedEndpoint]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Stable action dispatchers ─────────────────────────────────────────────\n\n const setCurrentStep = useCallback((step: PlaygroundStep) => dispatch({ type: 'SET_STEP', step }), []);\n const goToNextStep = useCallback(() => dispatch({ type: 'NEXT_STEP' }), []);\n const goToPreviousStep = useCallback(() => dispatch({ type: 'PREV_STEP' }), []);\n\n const setSelectedEndpoint = useCallback((endpoint: ApiEndpoint | null) =>\n dispatch({ type: 'SELECT_ENDPOINT', endpoint }), []);\n\n const setSelectedCategory = useCallback((category: string) =>\n dispatch({ type: 'SET_CATEGORY', category }), []);\n\n const setSearchTerm = useCallback((term: string) => dispatch({ type: 'SET_SEARCH', term }), []);\n const setSelectedVersion = useCallback((version: string) => dispatch({ type: 'SET_VERSION', version }), []);\n const setRequestUrl = useCallback((url: string) => dispatch({ type: 'SET_REQUEST_URL', url }), []);\n const setRequestMethod = useCallback((method: string) => dispatch({ type: 'SET_REQUEST_METHOD', method }), []);\n const setRequestHeaders = useCallback((headers: string) => dispatch({ type: 'SET_REQUEST_HEADERS', headers }), []);\n const setRequestBody = useCallback((body: string) => dispatch({ type: 'SET_REQUEST_BODY', body }), []);\n const setSelectedApiKey = useCallback((apiKeyId: string | null) => dispatch({ type: 'SET_API_KEY', apiKeyId }), []);\n const setManualApiToken = useCallback((token: string) => dispatch({ type: 'SET_MANUAL_TOKEN', token }), []);\n const setParameters = useCallback((parameters: Record<string, string>) =>\n dispatch({ type: 'SET_PARAMETERS', parameters }), []);\n const setResponse = useCallback((response: ApiResponse | null) =>\n dispatch({ type: 'SET_RESPONSE', response }), []);\n const setLoading = useCallback((loading: boolean) => dispatch({ type: 'SET_LOADING', loading }), []);\n const setSidebarOpen = useCallback((open: boolean) => dispatch({ type: 'SET_SIDEBAR', open }), []);\n const clearAll = useCallback(() => dispatch({ type: 'RESET' }), []);\n\n // ── Send request ──────────────────────────────────────────────────────────\n\n const sendRequest = useCallback(async () => {\n if (!state.requestUrl) {\n consola.error('No URL provided');\n return;\n }\n\n abortControllerRef.current?.abort();\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n // Single dispatch: loading=true + clear response\n dispatch({ type: 'REQUEST_START' });\n\n const startTime = Date.now();\n\n try {\n const headers = parseRequestHeaders(state.requestHeaders);\n\n let bearerToken: string | null = null;\n if (state.manualApiToken) {\n bearerToken = state.manualApiToken;\n } else if (typeof window !== 'undefined') {\n bearerToken = window.localStorage.getItem('auth_token');\n }\n\n if (bearerToken) headers['Authorization'] = `Bearer ${bearerToken}`;\n\n const requestOptions: RequestInit = {\n method: state.requestMethod,\n headers,\n signal: controller.signal,\n };\n\n if (state.requestBody && state.requestMethod !== 'GET') {\n requestOptions.body = state.requestBody;\n }\n\n const response = await fetch(state.requestUrl, requestOptions);\n const duration = Date.now() - startTime;\n const responseText = await response.text();\n\n let responseData: unknown;\n try { responseData = JSON.parse(responseText); }\n catch { responseData = responseText; }\n\n // Single dispatch: response + loading=false + step='response'\n dispatch({\n type: 'REQUEST_SUCCESS',\n response: {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n data: responseData,\n duration,\n },\n });\n\n consola.success(`${state.requestMethod} ${state.requestUrl} → ${response.status} (${duration}ms)`);\n } catch (error) {\n if (error instanceof DOMException && error.name === 'AbortError') return;\n consola.error('Request failed:', error);\n\n // Single dispatch: error response + loading=false\n dispatch({\n type: 'REQUEST_ERROR',\n response: {\n error: error instanceof Error ? error.message : 'Request failed',\n duration: Date.now() - startTime,\n },\n });\n }\n }, [state.requestUrl, state.requestHeaders, state.manualApiToken, state.requestMethod, state.requestBody]);\n\n // ── Context value ─────────────────────────────────────────────────────────\n\n const contextValue: PlaygroundContextType = {\n state,\n config,\n apiKeys,\n apiKeysLoading: isLoadingApiKeys,\n setCurrentStep,\n goToNextStep,\n goToPreviousStep,\n setSelectedEndpoint,\n setSelectedCategory,\n setSearchTerm,\n setSelectedVersion,\n setRequestUrl,\n setRequestMethod,\n setRequestHeaders,\n setRequestBody,\n setSelectedApiKey,\n setManualApiToken,\n setParameters,\n setResponse,\n setLoading,\n setSidebarOpen,\n clearAll,\n sendRequest,\n };\n\n return <PlaygroundContext.Provider value={contextValue}>{children}</PlaygroundContext.Provider>;\n};\n"]}
|