@websublime/vite-plugin-open-api-devtools 0.4.0
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/LICENSE +21 -0
- package/README.md +180 -0
- package/dist/ModelsPage-D-qLEz14.js +93 -0
- package/dist/ModelsPage-D-qLEz14.js.map +1 -0
- package/dist/RoutesPage-D7H_CupP.js +665 -0
- package/dist/RoutesPage-D7H_CupP.js.map +1 -0
- package/dist/SimulatorPage-9sBeAxQI.js +229 -0
- package/dist/SimulatorPage-9sBeAxQI.js.map +1 -0
- package/dist/TimelinePage-CMchXIlE.js +847 -0
- package/dist/TimelinePage-CMchXIlE.js.map +1 -0
- package/dist/devtools.css +1 -0
- package/dist/devtools.js +9 -0
- package/dist/devtools.js.map +1 -0
- package/dist/devtools.umd.cjs +2 -0
- package/dist/devtools.umd.cjs.map +1 -0
- package/dist/format-CE7KDbll.js +40 -0
- package/dist/format-CE7KDbll.js.map +1 -0
- package/dist/main-AUiFaD93.js +537 -0
- package/dist/main-AUiFaD93.js.map +1 -0
- package/dist/triangle-alert-ZH4fYFnz.js +24 -0
- package/dist/triangle-alert-ZH4fYFnz.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoutesPage-D7H_CupP.js","sources":["../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/code.js","../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/file-json.js","../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/lock.js","../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/shield.js","../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/sprout.js","../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/tag.js","../src/stores/registry.ts","../src/components/EndpointDetail.vue","../src/components/EndpointList.vue","../src/pages/RoutesPage.vue"],"sourcesContent":["/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Code = createLucideIcon(\"code\", [\n [\"path\", { d: \"m16 18 6-6-6-6\", key: \"eg8j8\" }],\n [\"path\", { d: \"m8 6-6 6 6 6\", key: \"ppft3o\" }]\n]);\n\nexport { Code as default };\n//# sourceMappingURL=code.js.map\n","/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileJson = createLucideIcon(\"file-json\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\n \"path\",\n { d: \"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1\", key: \"1oajmo\" }\n ],\n [\n \"path\",\n { d: \"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1\", key: \"mpwhp6\" }\n ]\n]);\n\nexport { FileJson as default };\n//# sourceMappingURL=file-json.js.map\n","/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Lock = createLucideIcon(\"lock\", [\n [\"rect\", { width: \"18\", height: \"11\", x: \"3\", y: \"11\", rx: \"2\", ry: \"2\", key: \"1w4ew1\" }],\n [\"path\", { d: \"M7 11V7a5 5 0 0 1 10 0v4\", key: \"fwvmzm\" }]\n]);\n\nexport { Lock as default };\n//# sourceMappingURL=lock.js.map\n","/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Shield = createLucideIcon(\"shield\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.js.map\n","/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Sprout = createLucideIcon(\"sprout\", [\n [\"path\", { d: \"M7 20h10\", key: \"e6iznv\" }],\n [\"path\", { d: \"M10 20c5.5-2.5.8-6.4 3-10\", key: \"161w41\" }],\n [\n \"path\",\n {\n d: \"M9.5 9.4c1.1.8 1.8 2.2 2.3 3.7-2 .4-3.5.4-4.8-.3-1.2-.6-2.3-1.9-3-4.2 2.8-.5 4.4 0 5.5.8z\",\n key: \"9gtqwd\"\n }\n ],\n [\n \"path\",\n {\n d: \"M14.1 6a7 7 0 0 0-1.1 4c1.9-.1 3.3-.6 4.3-1.4 1-1 1.6-2.3 1.7-4.6-2.7.1-4 1-4.9 2z\",\n key: \"bkxnd2\"\n }\n ]\n]);\n\nexport { Sprout as default };\n//# sourceMappingURL=sprout.js.map\n","/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tag = createLucideIcon(\"tag\", [\n [\n \"path\",\n {\n d: \"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"vktsd0\"\n }\n ],\n [\"circle\", { cx: \"7.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"kqv944\" }]\n]);\n\nexport { Tag as default };\n//# sourceMappingURL=tag.js.map\n","/**\n * Registry Store\n *\n * What: Pinia store for managing endpoint registry data\n * How: Fetches and caches endpoint data from the server via WebSocket\n * Why: Provides reactive access to endpoint data for the Routes Page\n *\n * @module stores/registry\n */\n\nimport { defineStore } from 'pinia';\nimport { computed, ref } from 'vue';\n\n/**\n * HTTP method type\n */\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options' | 'head' | 'trace';\n\n/**\n * Security requirement from OpenAPI spec\n */\nexport interface SecurityRequirement {\n name: string;\n scopes: string[];\n}\n\n/**\n * Endpoint entry from the server\n */\nexport interface EndpointEntry {\n key: string;\n operationId: string;\n method: HttpMethod;\n path: string;\n summary?: string;\n description?: string;\n tags: string[];\n responseSchema?: string;\n hasHandler: boolean;\n hasSeed: boolean;\n security: SecurityRequirement[];\n}\n\n/**\n * Registry statistics\n */\nexport interface RegistryStats {\n totalEndpoints: number;\n withCustomHandler: number;\n totalSchemas: number;\n withCustomSeed: number;\n autoGenerated: number;\n}\n\n/**\n * Registry data from server\n */\nexport interface RegistryData {\n endpoints: EndpointEntry[];\n stats: RegistryStats;\n}\n\n/**\n * Grouped endpoints by tag\n */\nexport interface EndpointGroup {\n tag: string;\n endpoints: EndpointEntry[];\n isExpanded: boolean;\n}\n\n/**\n * Filter options for endpoints\n */\nexport interface EndpointFilter {\n methods: HttpMethod[];\n hasHandler: boolean | null;\n hasSeed: boolean | null;\n tags: string[];\n}\n\n/**\n * Registry store for endpoint data management\n *\n * Provides:\n * - Endpoint data storage and retrieval\n * - Grouping by tags\n * - Search and filter functionality\n * - Selected endpoint tracking\n */\nexport const useRegistryStore = defineStore('registry', () => {\n // ==========================================================================\n // State\n // ==========================================================================\n\n /** All endpoints from the server */\n const endpoints = ref<EndpointEntry[]>([]);\n\n /** Registry statistics */\n const stats = ref<RegistryStats>({\n totalEndpoints: 0,\n withCustomHandler: 0,\n totalSchemas: 0,\n withCustomSeed: 0,\n autoGenerated: 0,\n });\n\n /** Loading state */\n const isLoading = ref(false);\n\n /** Error state */\n const error = ref<string | null>(null);\n\n /** Search query */\n const searchQuery = ref('');\n\n /** Active filters */\n const filter = ref<EndpointFilter>({\n methods: [],\n hasHandler: null,\n hasSeed: null,\n tags: [],\n });\n\n /** Currently selected endpoint key */\n const selectedEndpointKey = ref<string | null>(null);\n\n /** Expanded tag groups */\n const expandedTags = ref<Set<string>>(new Set());\n\n // ==========================================================================\n // Getters / Computed\n // ==========================================================================\n\n /**\n * All unique tags from endpoints\n */\n const allTags = computed(() => {\n const tagSet = new Set<string>();\n for (const endpoint of endpoints.value) {\n for (const tag of endpoint.tags) {\n tagSet.add(tag);\n }\n }\n return Array.from(tagSet).sort();\n });\n\n /**\n * All unique response schemas\n */\n const allSchemas = computed(() => {\n const schemaSet = new Set<string>();\n for (const endpoint of endpoints.value) {\n if (endpoint.responseSchema) {\n schemaSet.add(endpoint.responseSchema);\n }\n }\n return Array.from(schemaSet).sort();\n });\n\n /**\n * Filtered endpoints based on search and filters\n */\n const filteredEndpoints = computed(() => {\n let result = endpoints.value;\n\n // Apply search query\n if (searchQuery.value.trim()) {\n const query = searchQuery.value.toLowerCase().trim();\n result = result.filter((endpoint) => {\n return (\n endpoint.path.toLowerCase().includes(query) ||\n endpoint.operationId.toLowerCase().includes(query) ||\n endpoint.summary?.toLowerCase().includes(query) ||\n endpoint.tags.some((tag) => tag.toLowerCase().includes(query))\n );\n });\n }\n\n // Apply method filter\n if (filter.value.methods.length > 0) {\n result = result.filter((endpoint) => filter.value.methods.includes(endpoint.method));\n }\n\n // Apply handler filter\n if (filter.value.hasHandler !== null) {\n result = result.filter((endpoint) => endpoint.hasHandler === filter.value.hasHandler);\n }\n\n // Apply seed filter\n if (filter.value.hasSeed !== null) {\n result = result.filter((endpoint) => endpoint.hasSeed === filter.value.hasSeed);\n }\n\n // Apply tag filter\n if (filter.value.tags.length > 0) {\n result = result.filter((endpoint) =>\n endpoint.tags.some((tag) => filter.value.tags.includes(tag)),\n );\n }\n\n return result;\n });\n\n /**\n * Endpoints grouped by tag\n *\n * Grouping logic (from PRD):\n * 1. By tags (if they exist in spec)\n * 2. Fallback: By response schema\n * 3. Final fallback: By first path segment\n */\n const groupedEndpoints = computed((): EndpointGroup[] => {\n const groups = new Map<string, EndpointEntry[]>();\n\n for (const endpoint of filteredEndpoints.value) {\n // Determine group key\n let groupKey: string;\n\n if (endpoint.tags.length > 0) {\n // Use first tag as group\n groupKey = endpoint.tags[0];\n } else if (endpoint.responseSchema) {\n // Fallback to response schema\n groupKey = endpoint.responseSchema;\n } else {\n // Final fallback: first path segment\n const segments = endpoint.path.split('/').filter(Boolean);\n groupKey = segments[0] || 'Other';\n }\n\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)?.push(endpoint);\n }\n\n // Convert to array and sort\n return Array.from(groups.entries())\n .map(([tag, eps]) => ({\n tag,\n endpoints: eps.sort((a, b) => a.path.localeCompare(b.path)),\n isExpanded: expandedTags.value.has(tag),\n }))\n .sort((a, b) => a.tag.localeCompare(b.tag));\n });\n\n /**\n * Currently selected endpoint\n */\n const selectedEndpoint = computed(() => {\n if (!selectedEndpointKey.value) return null;\n return endpoints.value.find((e) => e.key === selectedEndpointKey.value) ?? null;\n });\n\n /**\n * Count of endpoints with custom handlers\n */\n const handlerCount = computed(() => endpoints.value.filter((e) => e.hasHandler).length);\n\n /**\n * Count of endpoints with seed data\n */\n const seedCount = computed(() => endpoints.value.filter((e) => e.hasSeed).length);\n\n // ==========================================================================\n // Actions\n // ==========================================================================\n\n /**\n * Set registry data from server response\n */\n function setRegistryData(data: RegistryData): void {\n endpoints.value = data.endpoints;\n stats.value = data.stats;\n error.value = null;\n\n // Auto-expand all groups initially\n for (const endpoint of data.endpoints) {\n if (endpoint.tags.length > 0) {\n expandedTags.value.add(endpoint.tags[0]);\n }\n }\n }\n\n /**\n * Set loading state\n */\n function setLoading(loading: boolean): void {\n isLoading.value = loading;\n }\n\n /**\n * Set error state\n */\n function setError(errorMessage: string): void {\n error.value = errorMessage;\n isLoading.value = false;\n }\n\n /**\n * Clear error state\n */\n function clearError(): void {\n error.value = null;\n }\n\n /**\n * Set search query\n */\n function setSearchQuery(query: string): void {\n searchQuery.value = query;\n }\n\n /**\n * Toggle method filter\n */\n function toggleMethodFilter(method: HttpMethod): void {\n const index = filter.value.methods.indexOf(method);\n if (index === -1) {\n filter.value.methods.push(method);\n } else {\n filter.value.methods.splice(index, 1);\n }\n }\n\n /**\n * Set handler filter\n */\n function setHandlerFilter(hasHandler: boolean | null): void {\n filter.value.hasHandler = hasHandler;\n }\n\n /**\n * Set seed filter\n */\n function setSeedFilter(hasSeed: boolean | null): void {\n filter.value.hasSeed = hasSeed;\n }\n\n /**\n * Toggle tag filter\n */\n function toggleTagFilter(tag: string): void {\n const index = filter.value.tags.indexOf(tag);\n if (index === -1) {\n filter.value.tags.push(tag);\n } else {\n filter.value.tags.splice(index, 1);\n }\n }\n\n /**\n * Clear all filters\n */\n function clearFilters(): void {\n filter.value = {\n methods: [],\n hasHandler: null,\n hasSeed: null,\n tags: [],\n };\n searchQuery.value = '';\n }\n\n /**\n * Check if any filter is active\n */\n function hasActiveFilters(): boolean {\n return (\n searchQuery.value.trim() !== '' ||\n filter.value.methods.length > 0 ||\n filter.value.hasHandler !== null ||\n filter.value.hasSeed !== null ||\n filter.value.tags.length > 0\n );\n }\n\n /**\n * Select an endpoint by key\n */\n function selectEndpoint(key: string | null): void {\n selectedEndpointKey.value = key;\n }\n\n /**\n * Toggle group expansion\n */\n function toggleGroup(tag: string): void {\n if (expandedTags.value.has(tag)) {\n expandedTags.value.delete(tag);\n } else {\n expandedTags.value.add(tag);\n }\n }\n\n /**\n * Expand all groups\n */\n function expandAllGroups(): void {\n for (const group of groupedEndpoints.value) {\n expandedTags.value.add(group.tag);\n }\n }\n\n /**\n * Collapse all groups\n */\n function collapseAllGroups(): void {\n expandedTags.value.clear();\n }\n\n /**\n * Update handler status for endpoints\n * Called when handlers are reloaded\n */\n function updateHandlerStatus(handlerOperationIds: string[]): void {\n const handlerSet = new Set(handlerOperationIds);\n for (const endpoint of endpoints.value) {\n endpoint.hasHandler = handlerSet.has(endpoint.operationId);\n }\n }\n\n /**\n * Update seed status for endpoints\n * Called when seeds are reloaded\n */\n function updateSeedStatus(seedSchemas: string[]): void {\n const seedSet = new Set(seedSchemas);\n for (const endpoint of endpoints.value) {\n endpoint.hasSeed = endpoint.responseSchema ? seedSet.has(endpoint.responseSchema) : false;\n }\n }\n\n // ==========================================================================\n // Return\n // ==========================================================================\n\n return {\n // State\n endpoints,\n stats,\n isLoading,\n error,\n searchQuery,\n filter,\n selectedEndpointKey,\n expandedTags,\n\n // Getters\n allTags,\n allSchemas,\n filteredEndpoints,\n groupedEndpoints,\n selectedEndpoint,\n handlerCount,\n seedCount,\n\n // Actions\n setRegistryData,\n setLoading,\n setError,\n clearError,\n setSearchQuery,\n toggleMethodFilter,\n setHandlerFilter,\n setSeedFilter,\n toggleTagFilter,\n clearFilters,\n hasActiveFilters,\n selectEndpoint,\n toggleGroup,\n expandAllGroups,\n collapseAllGroups,\n updateHandlerStatus,\n updateSeedStatus,\n };\n});\n","<!--\n EndpointDetail.vue - Endpoint Detail Panel Component\n\n What: Displays detailed information about a selected API endpoint\n How: Shows method, path, operation ID, tags, summary, description, and status indicators\n Why: Provides comprehensive endpoint information for developers using the DevTools\n-->\n\n<script setup lang=\"ts\">\nimport { Code, FileJson, Lock, Shield, Sprout, Tag } from 'lucide-vue-next';\nimport { computed } from 'vue';\n\nimport type { EndpointEntry } from '@/stores/registry';\nimport { getMethodLabel } from '@/utils/format';\n\n/**\n * Component props\n */\ninterface Props {\n /** Endpoint to display details for */\n endpoint: EndpointEntry | null;\n}\n\nconst props = defineProps<Props>();\n\n/**\n * Check if endpoint has security requirements\n */\nconst hasSecurity = computed(() => {\n return props.endpoint?.security && props.endpoint.security.length > 0;\n});\n\n/**\n * Format security requirements for display\n */\nconst securityDisplay = computed(() => {\n if (!props.endpoint?.security) return [];\n return props.endpoint.security.map((sec) => ({\n name: sec.name,\n scopes: sec.scopes.length > 0 ? sec.scopes.join(', ') : 'No scopes',\n }));\n});\n</script>\n\n<template>\n <div class=\"endpoint-detail\">\n <!-- Empty state when no endpoint selected -->\n <div v-if=\"!endpoint\" class=\"endpoint-detail__empty\">\n <FileJson :size=\"48\" class=\"endpoint-detail__empty-icon\" />\n <h3 class=\"endpoint-detail__empty-title\">No endpoint selected</h3>\n <p class=\"endpoint-detail__empty-text text-muted\">\n Select an endpoint from the list to view its details\n </p>\n </div>\n\n <!-- Endpoint details -->\n <div v-else class=\"endpoint-detail__content\">\n <!-- Header with method and path -->\n <header class=\"endpoint-detail__header\">\n <span\n :class=\"[\n 'method-badge',\n 'method-badge--large',\n `method-badge--${endpoint.method}`\n ]\"\n >\n {{ getMethodLabel(endpoint.method) }}\n </span>\n <h2 class=\"endpoint-detail__path font-mono\">\n {{ endpoint.path }}\n </h2>\n </header>\n\n <!-- Status indicators -->\n <div class=\"endpoint-detail__status\">\n <div\n v-if=\"endpoint.hasHandler\"\n class=\"endpoint-detail__status-item endpoint-detail__status-item--handler\"\n >\n <Code :size=\"14\" />\n <span>Has custom handler</span>\n </div>\n <div\n v-if=\"endpoint.hasSeed\"\n class=\"endpoint-detail__status-item endpoint-detail__status-item--seed\"\n >\n <Sprout :size=\"14\" />\n <span>Has seed data</span>\n </div>\n <div\n v-if=\"hasSecurity\"\n class=\"endpoint-detail__status-item endpoint-detail__status-item--security\"\n >\n <Lock :size=\"14\" />\n <span>Requires authentication</span>\n </div>\n <div\n v-if=\"!endpoint.hasHandler && !endpoint.hasSeed\"\n class=\"endpoint-detail__status-item endpoint-detail__status-item--auto\"\n >\n <FileJson :size=\"14\" />\n <span>Auto-generated response</span>\n </div>\n </div>\n\n <!-- Info sections -->\n <div class=\"endpoint-detail__sections\">\n <!-- Operation ID -->\n <section class=\"endpoint-detail__section\">\n <h3 class=\"endpoint-detail__section-title\">Operation</h3>\n <p class=\"endpoint-detail__section-content font-mono\">\n {{ endpoint.operationId }}\n </p>\n </section>\n\n <!-- Tags -->\n <section v-if=\"endpoint.tags.length > 0\" class=\"endpoint-detail__section\">\n <h3 class=\"endpoint-detail__section-title\">\n <Tag :size=\"14\" />\n Tags\n </h3>\n <div class=\"endpoint-detail__tags\">\n <span\n v-for=\"tag in endpoint.tags\"\n :key=\"tag\"\n class=\"endpoint-detail__tag\"\n >\n {{ tag }}\n </span>\n </div>\n </section>\n\n <!-- Summary -->\n <section v-if=\"endpoint.summary\" class=\"endpoint-detail__section\">\n <h3 class=\"endpoint-detail__section-title\">Summary</h3>\n <p class=\"endpoint-detail__section-content\">\n {{ endpoint.summary }}\n </p>\n </section>\n\n <!-- Description -->\n <section v-if=\"endpoint.description\" class=\"endpoint-detail__section\">\n <h3 class=\"endpoint-detail__section-title\">Description</h3>\n <p class=\"endpoint-detail__section-content endpoint-detail__description\">\n {{ endpoint.description }}\n </p>\n </section>\n\n <!-- Response Schema -->\n <section v-if=\"endpoint.responseSchema\" class=\"endpoint-detail__section\">\n <h3 class=\"endpoint-detail__section-title\">\n <FileJson :size=\"14\" />\n Response Schema\n </h3>\n <p class=\"endpoint-detail__section-content font-mono\">\n {{ endpoint.responseSchema }}\n </p>\n </section>\n\n <!-- Security -->\n <section v-if=\"hasSecurity\" class=\"endpoint-detail__section\">\n <h3 class=\"endpoint-detail__section-title\">\n <Shield :size=\"14\" />\n Security\n </h3>\n <div class=\"endpoint-detail__security\">\n <div\n v-for=\"sec in securityDisplay\"\n :key=\"sec.name\"\n class=\"endpoint-detail__security-item\"\n >\n <span class=\"endpoint-detail__security-name font-mono\">\n {{ sec.name }}\n </span>\n <span class=\"endpoint-detail__security-scopes text-muted\">\n {{ sec.scopes }}\n </span>\n </div>\n </div>\n </section>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.endpoint-detail {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n/* Empty state */\n.endpoint-detail__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: var(--devtools-space-xl);\n text-align: center;\n}\n\n.endpoint-detail__empty-icon {\n color: var(--devtools-text-muted);\n opacity: 0.5;\n margin-bottom: var(--devtools-space-md);\n}\n\n.endpoint-detail__empty-title {\n font-size: var(--font-size-2);\n font-weight: var(--font-weight-5);\n color: var(--devtools-text);\n margin: 0 0 var(--devtools-space-sm);\n}\n\n.endpoint-detail__empty-text {\n font-size: var(--font-size-1);\n margin: 0;\n}\n\n/* Content */\n.endpoint-detail__content {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow-y: auto;\n padding: var(--devtools-space-md);\n}\n\n/* Header */\n.endpoint-detail__header {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-md);\n margin-bottom: var(--devtools-space-md);\n padding-bottom: var(--devtools-space-md);\n border-bottom: 1px solid var(--devtools-border);\n}\n\n.endpoint-detail__path {\n font-size: var(--font-size-2);\n font-weight: var(--font-weight-5);\n color: var(--devtools-text);\n margin: 0;\n word-break: break-all;\n}\n\n/* Large method badge */\n.method-badge--large {\n font-size: var(--font-size-0);\n padding: var(--devtools-space-sm) var(--devtools-space-md);\n min-width: 70px;\n}\n\n/* Status indicators */\n.endpoint-detail__status {\n display: flex;\n flex-wrap: wrap;\n gap: var(--devtools-space-sm);\n margin-bottom: var(--devtools-space-md);\n}\n\n.endpoint-detail__status-item {\n display: inline-flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n padding: var(--devtools-space-xs) var(--devtools-space-sm);\n border-radius: var(--devtools-radius-sm);\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-5);\n}\n\n.endpoint-detail__status-item--handler {\n background-color: color-mix(in srgb, var(--devtools-info) 15%, transparent);\n color: var(--devtools-info);\n}\n\n.endpoint-detail__status-item--seed {\n background-color: color-mix(in srgb, var(--devtools-success) 15%, transparent);\n color: var(--devtools-success);\n}\n\n.endpoint-detail__status-item--security {\n background-color: color-mix(in srgb, var(--devtools-warning) 15%, transparent);\n color: var(--devtools-warning);\n}\n\n.endpoint-detail__status-item--auto {\n background-color: color-mix(in srgb, var(--devtools-text-muted) 15%, transparent);\n color: var(--devtools-text-muted);\n}\n\n/* Sections */\n.endpoint-detail__sections {\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-md);\n}\n\n.endpoint-detail__section {\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-xs);\n}\n\n.endpoint-detail__section-title {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-6);\n color: var(--devtools-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.endpoint-detail__section-content {\n font-size: var(--font-size-1);\n color: var(--devtools-text);\n margin: 0;\n line-height: var(--font-lineheight-3);\n}\n\n.endpoint-detail__description {\n white-space: pre-wrap;\n}\n\n/* Tags */\n.endpoint-detail__tags {\n display: flex;\n flex-wrap: wrap;\n gap: var(--devtools-space-xs);\n}\n\n.endpoint-detail__tag {\n display: inline-flex;\n align-items: center;\n padding: var(--devtools-space-xs) var(--devtools-space-sm);\n background-color: var(--devtools-surface-elevated);\n border-radius: var(--devtools-radius-sm);\n font-size: var(--font-size-0);\n color: var(--devtools-text);\n}\n\n/* Security */\n.endpoint-detail__security {\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-xs);\n}\n\n.endpoint-detail__security-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: var(--devtools-space-sm);\n background-color: var(--devtools-surface-elevated);\n border-radius: var(--devtools-radius-sm);\n}\n\n.endpoint-detail__security-name {\n font-size: var(--font-size-1);\n font-weight: var(--font-weight-5);\n}\n\n.endpoint-detail__security-scopes {\n font-size: var(--font-size-0);\n}\n</style>\n","<!--\n EndpointList.vue - Grouped Endpoint Listing Component\n\n What: Displays a list of API endpoints grouped by tags with collapsible sections\n How: Renders endpoint groups from registry store with method badges and selection support\n Why: Provides organized navigation through available mock endpoints\n-->\n\n<script setup lang=\"ts\">\nimport { ChevronDown, ChevronRight, Code, Sprout } from 'lucide-vue-next';\n\nimport type { EndpointEntry, EndpointGroup } from '@/stores/registry';\nimport { getMethodLabel } from '@/utils/format';\n\n/**\n * Component props\n */\ninterface Props {\n /** Grouped endpoints to display */\n groups: EndpointGroup[];\n /** Currently selected endpoint key */\n selectedKey: string | null;\n}\n\nconst props = defineProps<Props>();\n\n/**\n * Component events\n */\nconst emit = defineEmits<{\n /** Emitted when an endpoint is selected */\n (e: 'select', key: string): void;\n /** Emitted when a group is toggled */\n (e: 'toggle-group', tag: string): void;\n}>();\n\n/**\n * Handle endpoint click\n */\nfunction handleEndpointClick(endpoint: EndpointEntry): void {\n emit('select', endpoint.key);\n}\n\n/**\n * Handle group toggle\n */\nfunction handleGroupToggle(tag: string): void {\n emit('toggle-group', tag);\n}\n\n/**\n * Check if endpoint is selected\n */\nfunction isSelected(endpoint: EndpointEntry): boolean {\n return props.selectedKey === endpoint.key;\n}\n</script>\n\n<template>\n <div class=\"endpoint-list\">\n <!-- Empty state -->\n <div v-if=\"groups.length === 0\" class=\"endpoint-list__empty\">\n <p class=\"text-muted\">No endpoints found</p>\n </div>\n\n <!-- Endpoint groups -->\n <div v-else class=\"endpoint-list__groups\">\n <div\n v-for=\"group in groups\"\n :key=\"group.tag\"\n class=\"endpoint-group\"\n >\n <!-- Group header -->\n <button\n type=\"button\"\n class=\"endpoint-group__header\"\n :aria-expanded=\"group.isExpanded\"\n :aria-controls=\"`group-${group.tag}`\"\n @click=\"handleGroupToggle(group.tag)\"\n >\n <component\n :is=\"group.isExpanded ? ChevronDown : ChevronRight\"\n :size=\"16\"\n class=\"endpoint-group__chevron\"\n />\n <span class=\"endpoint-group__tag\">{{ group.tag }}</span>\n <span class=\"endpoint-group__count text-muted\">\n ({{ group.endpoints.length }})\n </span>\n </button>\n\n <!-- Group endpoints -->\n <div\n v-show=\"group.isExpanded\"\n :id=\"`group-${group.tag}`\"\n class=\"endpoint-group__items\"\n role=\"group\"\n :aria-label=\"`${group.tag} endpoints`\"\n >\n <button\n v-for=\"endpoint in group.endpoints\"\n :key=\"endpoint.key\"\n type=\"button\"\n :class=\"[\n 'endpoint-item',\n { 'endpoint-item--selected': isSelected(endpoint) }\n ]\"\n :aria-selected=\"isSelected(endpoint)\"\n @click=\"handleEndpointClick(endpoint)\"\n >\n <!-- Method badge -->\n <span\n :class=\"[\n 'method-badge',\n `method-badge--${endpoint.method}`\n ]\"\n >\n {{ getMethodLabel(endpoint.method) }}\n </span>\n\n <!-- Path -->\n <span class=\"endpoint-item__path font-mono\">\n {{ endpoint.path }}\n </span>\n\n <!-- Status indicators -->\n <div class=\"endpoint-item__indicators\">\n <span\n v-if=\"endpoint.hasHandler\"\n class=\"endpoint-item__indicator endpoint-item__indicator--handler\"\n title=\"Has custom handler\"\n >\n <Code :size=\"12\" />\n </span>\n <span\n v-if=\"endpoint.hasSeed\"\n class=\"endpoint-item__indicator endpoint-item__indicator--seed\"\n title=\"Has seed data\"\n >\n <Sprout :size=\"12\" />\n </span>\n </div>\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.endpoint-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.endpoint-list__empty {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--devtools-space-lg);\n}\n\n.endpoint-list__groups {\n flex: 1;\n overflow-y: auto;\n padding: var(--devtools-space-xs);\n}\n\n/* Group styles */\n.endpoint-group {\n margin-bottom: var(--devtools-space-xs);\n}\n\n.endpoint-group__header {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n width: 100%;\n padding: var(--devtools-space-sm) var(--devtools-space-sm);\n background: none;\n border: none;\n border-radius: var(--devtools-radius-sm);\n font-family: var(--devtools-font-sans);\n font-size: var(--font-size-1);\n font-weight: var(--font-weight-5);\n color: var(--devtools-text);\n text-align: left;\n cursor: pointer;\n transition: background-color var(--devtools-transition-fast);\n}\n\n.endpoint-group__header:hover {\n background-color: var(--devtools-surface-elevated);\n}\n\n.endpoint-group__header:focus {\n outline: none;\n}\n\n.endpoint-group__header:focus-visible {\n outline: 2px solid var(--devtools-primary);\n outline-offset: -2px;\n}\n\n.endpoint-group__chevron {\n flex-shrink: 0;\n color: var(--devtools-text-muted);\n}\n\n.endpoint-group__tag {\n flex: 1;\n text-transform: capitalize;\n}\n\n.endpoint-group__count {\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-4);\n}\n\n.endpoint-group__items {\n padding-left: var(--devtools-space-md);\n}\n\n/* Endpoint item styles */\n.endpoint-item {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-sm);\n width: 100%;\n padding: var(--devtools-space-xs) var(--devtools-space-sm);\n background: none;\n border: none;\n border-radius: var(--devtools-radius-sm);\n font-family: var(--devtools-font-sans);\n text-align: left;\n cursor: pointer;\n transition: background-color var(--devtools-transition-fast);\n}\n\n.endpoint-item:hover {\n background-color: var(--devtools-surface-elevated);\n}\n\n.endpoint-item:focus {\n outline: none;\n}\n\n.endpoint-item:focus-visible {\n outline: 2px solid var(--devtools-primary);\n outline-offset: -2px;\n}\n\n.endpoint-item--selected {\n background-color: color-mix(in srgb, var(--devtools-primary) 15%, transparent);\n}\n\n.endpoint-item--selected:hover {\n background-color: color-mix(in srgb, var(--devtools-primary) 20%, transparent);\n}\n\n.endpoint-item__path {\n flex: 1;\n font-size: var(--font-size-0);\n color: var(--devtools-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.endpoint-item__indicators {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n}\n\n.endpoint-item__indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: var(--devtools-radius-sm);\n}\n\n.endpoint-item__indicator--handler {\n background-color: color-mix(in srgb, var(--devtools-info) 15%, transparent);\n color: var(--devtools-info);\n}\n\n.endpoint-item__indicator--seed {\n background-color: color-mix(in srgb, var(--devtools-success) 15%, transparent);\n color: var(--devtools-success);\n}\n</style>\n","<!--\n RoutesPage.vue - Endpoint Listing Page\n\n What: Displays a list of all available API endpoints from the OpenAPI spec\n How: Fetches endpoint data via WebSocket and displays in a searchable/filterable list\n Why: Allows developers to quickly browse and inspect available mock endpoints\n-->\n\n<script setup lang=\"ts\">\nimport { ChevronDown, ChevronUp, Code, Filter, Route, Search, Sprout, X } from 'lucide-vue-next';\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue';\n\nimport EndpointDetail from '@/components/EndpointDetail.vue';\nimport EndpointList from '@/components/EndpointList.vue';\nimport { useWebSocket } from '@/composables/useWebSocket';\nimport { type HttpMethod, type RegistryData, useRegistryStore } from '@/stores/registry';\n\n// Store and WebSocket\nconst registryStore = useRegistryStore();\nconst { send, on, connected } = useWebSocket();\n\n// Local UI state\nconst showFilters = ref(false);\nconst searchInputRef = ref<HTMLInputElement | null>(null);\n\n// HTTP methods for filter (matches HttpMethod type from registry store)\nconst httpMethods: HttpMethod[] = [\n 'get',\n 'post',\n 'put',\n 'patch',\n 'delete',\n 'options',\n 'head',\n 'trace',\n];\n\n/**\n * Fetch registry data when connected\n */\nfunction fetchRegistry(): void {\n if (connected.value) {\n registryStore.setLoading(true);\n send({ type: 'get:registry' });\n }\n}\n\n/**\n * Handle registry data from server\n */\nfunction handleRegistryData(data: RegistryData): void {\n registryStore.setRegistryData(data);\n registryStore.setLoading(false);\n}\n\n/**\n * Handle endpoint selection\n */\nfunction handleSelectEndpoint(key: string): void {\n registryStore.selectEndpoint(key);\n}\n\n/**\n * Handle group toggle\n */\nfunction handleToggleGroup(tag: string): void {\n registryStore.toggleGroup(tag);\n}\n\n/**\n * Handle search input\n */\nfunction handleSearchInput(event: Event): void {\n const target = event.target as HTMLInputElement;\n registryStore.setSearchQuery(target.value);\n}\n\n/**\n * Clear search\n */\nfunction clearSearch(): void {\n registryStore.setSearchQuery('');\n searchInputRef.value?.focus();\n}\n\n/**\n * Toggle method filter\n */\nfunction toggleMethod(method: HttpMethod): void {\n registryStore.toggleMethodFilter(method);\n}\n\n/**\n * Check if method is active in filter\n */\nfunction isMethodActive(method: HttpMethod): boolean {\n return registryStore.filter.methods.includes(method);\n}\n\n/**\n * Toggle handler filter\n */\nfunction toggleHandlerFilter(): void {\n const current = registryStore.filter.hasHandler;\n registryStore.setHandlerFilter(current === true ? null : true);\n}\n\n/**\n * Toggle seed filter\n */\nfunction toggleSeedFilter(): void {\n const current = registryStore.filter.hasSeed;\n registryStore.setSeedFilter(current === true ? null : true);\n}\n\n/**\n * Clear all filters\n */\nfunction clearAllFilters(): void {\n registryStore.clearFilters();\n}\n\n/**\n * Toggle filter panel visibility\n */\nfunction toggleFilters(): void {\n showFilters.value = !showFilters.value;\n}\n\n/**\n * Computed: Has active filters\n */\nconst hasActiveFilters = computed(() => registryStore.hasActiveFilters());\n\n// Event cleanup functions for WebSocket subscriptions\nlet unsubRegistry: (() => void) | null = null;\nlet unsubHandlers: (() => void) | null = null;\nlet unsubSeeds: (() => void) | null = null;\n\n// Subscribe to registry events and setup cleanup\nonMounted(() => {\n // Subscribe to WebSocket events (on() returns unsubscribe function)\n unsubRegistry = on<RegistryData>('registry', handleRegistryData);\n unsubHandlers = on('handlers:updated', () => fetchRegistry());\n unsubSeeds = on('seeds:updated', () => fetchRegistry());\n\n // Fetch registry when already connected\n if (connected.value) {\n fetchRegistry();\n }\n});\n\n// Cleanup event subscriptions on unmount to prevent memory leaks\nonUnmounted(() => {\n unsubRegistry?.();\n unsubHandlers?.();\n unsubSeeds?.();\n});\n\n// Re-fetch when connection is established\nwatch(connected, (isConnected) => {\n if (isConnected) {\n fetchRegistry();\n }\n});\n</script>\n\n<template>\n <div class=\"routes-page\">\n <!-- Toolbar -->\n <div class=\"routes-toolbar\">\n <!-- Search -->\n <div class=\"routes-search\">\n <Search :size=\"16\" class=\"routes-search__icon\" />\n <input\n ref=\"searchInputRef\"\n type=\"text\"\n class=\"routes-search__input input\"\n placeholder=\"Search endpoints...\"\n :value=\"registryStore.searchQuery\"\n @input=\"handleSearchInput\"\n />\n <button\n v-if=\"registryStore.searchQuery\"\n type=\"button\"\n class=\"routes-search__clear btn btn--ghost btn--icon\"\n title=\"Clear search\"\n @click=\"clearSearch\"\n >\n <X :size=\"14\" />\n </button>\n </div>\n\n <!-- Filter toggle -->\n <button\n type=\"button\"\n :class=\"[\n 'routes-filter-toggle btn btn--secondary',\n { 'routes-filter-toggle--active': hasActiveFilters }\n ]\"\n :aria-expanded=\"showFilters\"\n @click=\"toggleFilters\"\n >\n <Filter :size=\"16\" />\n <span>Filters</span>\n <span v-if=\"hasActiveFilters\" class=\"routes-filter-toggle__badge\">\n {{ registryStore.filter.methods.length +\n (registryStore.filter.hasHandler ? 1 : 0) +\n (registryStore.filter.hasSeed ? 1 : 0) }}\n </span>\n <component :is=\"showFilters ? ChevronUp : ChevronDown\" :size=\"14\" />\n </button>\n\n <!-- Stats -->\n <div class=\"routes-stats\">\n <span class=\"routes-stats__item\">\n {{ registryStore.filteredEndpoints.length }} endpoints\n </span>\n <span class=\"routes-stats__separator\">|</span>\n <span class=\"routes-stats__item\">\n {{ registryStore.allTags.length }} tags\n </span>\n </div>\n </div>\n\n <!-- Filter panel -->\n <div v-if=\"showFilters\" class=\"routes-filters\">\n <!-- Method filters -->\n <div class=\"routes-filters__section\">\n <h4 class=\"routes-filters__title\">Methods</h4>\n <div class=\"routes-filters__methods\">\n <button\n v-for=\"method in httpMethods\"\n :key=\"method\"\n type=\"button\"\n :class=\"[\n 'method-badge',\n `method-badge--${method}`,\n { 'method-badge--inactive': !isMethodActive(method) && registryStore.filter.methods.length > 0 }\n ]\"\n @click=\"toggleMethod(method)\"\n >\n {{ method.toUpperCase() }}\n </button>\n </div>\n </div>\n\n <!-- Status filters -->\n <div class=\"routes-filters__section\">\n <h4 class=\"routes-filters__title\">Status</h4>\n <div class=\"routes-filters__status\">\n <button\n type=\"button\"\n :class=\"[\n 'routes-filters__status-btn',\n { 'routes-filters__status-btn--active': registryStore.filter.hasHandler }\n ]\"\n @click=\"toggleHandlerFilter\"\n >\n <Code :size=\"14\" />\n <span>Has Handler</span>\n </button>\n <button\n type=\"button\"\n :class=\"[\n 'routes-filters__status-btn',\n { 'routes-filters__status-btn--active': registryStore.filter.hasSeed }\n ]\"\n @click=\"toggleSeedFilter\"\n >\n <Sprout :size=\"14\" />\n <span>Has Seed</span>\n </button>\n </div>\n </div>\n\n <!-- Clear filters -->\n <div v-if=\"hasActiveFilters\" class=\"routes-filters__actions\">\n <button\n type=\"button\"\n class=\"btn btn--ghost\"\n @click=\"clearAllFilters\"\n >\n <X :size=\"14\" />\n Clear all filters\n </button>\n </div>\n </div>\n\n <!-- Main content: split panel -->\n <div class=\"routes-content\">\n <!-- Loading state -->\n <div v-if=\"registryStore.isLoading\" class=\"routes-loading\">\n <div class=\"routes-loading__spinner\" />\n <span class=\"text-muted\">Loading endpoints...</span>\n </div>\n\n <!-- Error state -->\n <div v-else-if=\"registryStore.error\" class=\"routes-error\">\n <p class=\"routes-error__message\">{{ registryStore.error }}</p>\n <button type=\"button\" class=\"btn btn--primary\" @click=\"fetchRegistry\">\n Retry\n </button>\n </div>\n\n <!-- Empty state -->\n <div v-else-if=\"registryStore.endpoints.length === 0\" class=\"routes-empty empty-state\">\n <Route :size=\"48\" class=\"empty-state__icon\" />\n <h3 class=\"empty-state__title\">No endpoints found</h3>\n <p class=\"empty-state__description\">\n No API endpoints are available. Make sure your OpenAPI spec is loaded.\n </p>\n </div>\n\n <!-- No results state -->\n <div v-else-if=\"registryStore.filteredEndpoints.length === 0\" class=\"routes-empty empty-state\">\n <Search :size=\"48\" class=\"empty-state__icon\" />\n <h3 class=\"empty-state__title\">No matching endpoints</h3>\n <p class=\"empty-state__description\">\n Try adjusting your search or filters.\n </p>\n <button\n v-if=\"hasActiveFilters\"\n type=\"button\"\n class=\"btn btn--secondary\"\n @click=\"clearAllFilters\"\n >\n Clear filters\n </button>\n </div>\n\n <!-- Split panel layout -->\n <template v-else>\n <!-- Endpoint list panel -->\n <div class=\"routes-list-panel\">\n <EndpointList\n :groups=\"registryStore.groupedEndpoints\"\n :selected-key=\"registryStore.selectedEndpointKey\"\n @select=\"handleSelectEndpoint\"\n @toggle-group=\"handleToggleGroup\"\n />\n </div>\n\n <!-- Endpoint detail panel -->\n <div class=\"routes-detail-panel\">\n <EndpointDetail :endpoint=\"registryStore.selectedEndpoint\" />\n </div>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.routes-page {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n/* Toolbar */\n.routes-toolbar {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-md);\n padding: var(--devtools-space-md);\n background-color: var(--devtools-surface);\n border-bottom: 1px solid var(--devtools-border);\n}\n\n.routes-search {\n position: relative;\n flex: 1;\n max-width: 400px;\n}\n\n.routes-search__icon {\n position: absolute;\n left: var(--devtools-space-sm);\n top: 50%;\n transform: translateY(-50%);\n color: var(--devtools-text-muted);\n pointer-events: none;\n}\n\n.routes-search__input {\n padding-left: calc(var(--devtools-space-sm) + 24px);\n padding-right: calc(var(--devtools-space-sm) + 24px);\n}\n\n.routes-search__clear {\n position: absolute;\n right: var(--devtools-space-xs);\n top: 50%;\n transform: translateY(-50%);\n padding: var(--devtools-space-xs);\n}\n\n.routes-filter-toggle {\n flex-shrink: 0;\n}\n\n.routes-filter-toggle--active {\n background-color: color-mix(in srgb, var(--devtools-primary) 15%, transparent);\n border-color: var(--devtools-primary);\n color: var(--devtools-primary);\n}\n\n.routes-filter-toggle__badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 var(--devtools-space-xs);\n background-color: var(--devtools-primary);\n color: var(--devtools-text-inverted);\n border-radius: 9px;\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-6);\n}\n\n.routes-stats {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-sm);\n margin-left: auto;\n font-size: var(--font-size-0);\n color: var(--devtools-text-muted);\n}\n\n.routes-stats__separator {\n opacity: 0.5;\n}\n\n/* Filter panel */\n.routes-filters {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n gap: var(--devtools-space-lg);\n padding: var(--devtools-space-md);\n background-color: var(--devtools-surface-elevated);\n border-bottom: 1px solid var(--devtools-border);\n}\n\n.routes-filters__section {\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-sm);\n}\n\n.routes-filters__title {\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-6);\n color: var(--devtools-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.routes-filters__methods {\n display: flex;\n flex-wrap: wrap;\n gap: var(--devtools-space-xs);\n}\n\n.routes-filters__methods .method-badge {\n cursor: pointer;\n transition: all var(--devtools-transition-fast);\n}\n\n.routes-filters__methods .method-badge--inactive {\n opacity: 0.4;\n}\n\n.routes-filters__status {\n display: flex;\n gap: var(--devtools-space-sm);\n}\n\n.routes-filters__status-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n padding: var(--devtools-space-xs) var(--devtools-space-sm);\n background-color: var(--devtools-surface);\n border: 1px solid var(--devtools-border);\n border-radius: var(--devtools-radius-sm);\n font-family: var(--devtools-font-sans);\n font-size: var(--font-size-0);\n color: var(--devtools-text-muted);\n cursor: pointer;\n transition: all var(--devtools-transition-fast);\n}\n\n.routes-filters__status-btn:hover {\n background-color: var(--devtools-surface-elevated);\n color: var(--devtools-text);\n}\n\n.routes-filters__status-btn--active {\n background-color: color-mix(in srgb, var(--devtools-primary) 15%, transparent);\n border-color: var(--devtools-primary);\n color: var(--devtools-primary);\n}\n\n.routes-filters__actions {\n display: flex;\n align-items: flex-end;\n margin-left: auto;\n}\n\n/* Main content */\n.routes-content {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n/* Loading state */\n.routes-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n gap: var(--devtools-space-md);\n}\n\n.routes-loading__spinner {\n width: 32px;\n height: 32px;\n border: 3px solid var(--devtools-border);\n border-top-color: var(--devtools-primary);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Error state */\n.routes-error {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n gap: var(--devtools-space-md);\n padding: var(--devtools-space-xl);\n}\n\n.routes-error__message {\n color: var(--devtools-error);\n margin: 0;\n}\n\n/* Empty state */\n.routes-empty {\n width: 100%;\n}\n\n/* Split panels */\n.routes-list-panel {\n width: var(--devtools-sidebar-width);\n min-width: 200px;\n max-width: 400px;\n border-right: 1px solid var(--devtools-border);\n background-color: var(--devtools-surface);\n overflow: hidden;\n}\n\n.routes-detail-panel {\n flex: 1;\n overflow: hidden;\n background-color: var(--devtools-bg);\n}\n</style>\n"],"names":["Code","createLucideIcon","FileJson","Lock","Shield","Sprout","Tag","useRegistryStore","defineStore","endpoints","ref","stats","isLoading","error","searchQuery","filter","selectedEndpointKey","expandedTags","allTags","computed","tagSet","endpoint","tag","allSchemas","schemaSet","filteredEndpoints","result","query","groupedEndpoints","groups","groupKey","eps","a","b","selectedEndpoint","e","handlerCount","seedCount","setRegistryData","data","setLoading","loading","setError","errorMessage","clearError","setSearchQuery","toggleMethodFilter","method","index","setHandlerFilter","hasHandler","setSeedFilter","hasSeed","toggleTagFilter","clearFilters","hasActiveFilters","selectEndpoint","key","toggleGroup","expandAllGroups","group","collapseAllGroups","updateHandlerStatus","handlerOperationIds","handlerSet","updateSeedStatus","seedSchemas","seedSet","props","__props","hasSecurity","securityDisplay","sec","_openBlock","_createElementBlock","_hoisted_1","_hoisted_3","_createElementVNode","_hoisted_4","_normalizeClass","_unref","getMethodLabel","_hoisted_5","_toDisplayString","_hoisted_6","_hoisted_7","_createVNode","_cache","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_Fragment","_renderList","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_26","_hoisted_27","_hoisted_28","_hoisted_2","emit","__emit","handleEndpointClick","handleGroupToggle","isSelected","$event","_createBlock","_resolveDynamicComponent","ChevronDown","ChevronRight","_vShow","registryStore","send","on","connected","useWebSocket","showFilters","searchInputRef","httpMethods","fetchRegistry","handleRegistryData","handleSelectEndpoint","handleToggleGroup","handleSearchInput","event","target","clearSearch","toggleMethod","isMethodActive","toggleHandlerFilter","current","toggleSeedFilter","clearAllFilters","toggleFilters","unsubRegistry","unsubHandlers","unsubSeeds","onMounted","onUnmounted","watch","isConnected","Search","X","Filter","ChevronUp","Route","EndpointList","EndpointDetail"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5]}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { defineComponent as V, ref as m, computed as D, createElementBlock as r, openBlock as o, createElementVNode as e, createVNode as c, unref as l, withDirectives as f, Fragment as v, renderList as y, toDisplayString as d, vModelSelect as L, vModelText as N, normalizeClass as h, createBlock as S, resolveDynamicComponent as g, createCommentVNode as k } from "vue";
|
|
2
|
+
import { c as U, Z as C, C as T, _ as B } from "./main-AUiFaD93.js";
|
|
3
|
+
import { T as w, a as A } from "./triangle-alert-ZH4fYFnz.js";
|
|
4
|
+
const G = U("plus", [
|
|
5
|
+
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
6
|
+
["path", { d: "M12 5v14", key: "s699le" }]
|
|
7
|
+
]), I = { class: "simulator-page" }, F = { class: "simulator-form card" }, $ = { class: "simulator-form__header" }, q = { class: "simulator-form__body" }, Z = { class: "simulator-form__row" }, H = ["value"], O = { class: "simulator-presets" }, j = ["onClick"], J = { class: "simulator-preset__label" }, K = ["disabled"], Q = { class: "simulator-active" }, W = { class: "simulator-active__header" }, X = { class: "simulator-active__title" }, Y = { class: "simulator-active__list" }, ee = { class: "simulator-simulation__info" }, te = { class: "simulator-simulation__path font-mono" }, se = { class: "simulator-simulation__preset" }, oe = ["onClick"], le = {
|
|
8
|
+
key: 0,
|
|
9
|
+
class: "empty-state"
|
|
10
|
+
}, ae = /* @__PURE__ */ V({
|
|
11
|
+
__name: "SimulatorPage",
|
|
12
|
+
setup(ie) {
|
|
13
|
+
const p = [
|
|
14
|
+
{
|
|
15
|
+
id: "slow",
|
|
16
|
+
label: "Slow Response",
|
|
17
|
+
description: "Add 2 second delay",
|
|
18
|
+
type: "delay",
|
|
19
|
+
delay: 2e3
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "very-slow",
|
|
23
|
+
label: "Very Slow",
|
|
24
|
+
description: "Add 5 second delay",
|
|
25
|
+
type: "delay",
|
|
26
|
+
delay: 5e3
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "timeout",
|
|
30
|
+
label: "Timeout",
|
|
31
|
+
description: "Simulate request timeout (30s)",
|
|
32
|
+
type: "delay",
|
|
33
|
+
delay: 3e4
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "error-400",
|
|
37
|
+
label: "Bad Request",
|
|
38
|
+
description: "Return 400 status",
|
|
39
|
+
type: "error",
|
|
40
|
+
status: 400
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "error-401",
|
|
44
|
+
label: "Unauthorized",
|
|
45
|
+
description: "Return 401 status",
|
|
46
|
+
type: "error",
|
|
47
|
+
status: 401
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "error-403",
|
|
51
|
+
label: "Forbidden",
|
|
52
|
+
description: "Return 403 status",
|
|
53
|
+
type: "error",
|
|
54
|
+
status: 403
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "error-404",
|
|
58
|
+
label: "Not Found",
|
|
59
|
+
description: "Return 404 status",
|
|
60
|
+
type: "error",
|
|
61
|
+
status: 404
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "error-429",
|
|
65
|
+
label: "Rate Limited",
|
|
66
|
+
description: "Return 429 status",
|
|
67
|
+
type: "error",
|
|
68
|
+
status: 429
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "error-500",
|
|
72
|
+
label: "Server Error",
|
|
73
|
+
description: "Return 500 status",
|
|
74
|
+
type: "error",
|
|
75
|
+
status: 500
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "error-503",
|
|
79
|
+
label: "Unavailable",
|
|
80
|
+
description: "Return 503 status",
|
|
81
|
+
type: "error",
|
|
82
|
+
status: 503
|
|
83
|
+
}
|
|
84
|
+
], a = m([
|
|
85
|
+
{
|
|
86
|
+
id: "1",
|
|
87
|
+
path: "/pets",
|
|
88
|
+
method: "GET",
|
|
89
|
+
preset: p[0]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "2",
|
|
93
|
+
path: "/pets/{petId}",
|
|
94
|
+
method: "GET",
|
|
95
|
+
preset: p[6]
|
|
96
|
+
}
|
|
97
|
+
]), u = m(""), _ = m("GET"), n = m(null), R = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
98
|
+
function E(i) {
|
|
99
|
+
return p.find((s) => s.id === i);
|
|
100
|
+
}
|
|
101
|
+
const b = D(() => u.value.trim() !== "" && n.value !== null);
|
|
102
|
+
function z() {
|
|
103
|
+
if (!b.value || !n.value) return;
|
|
104
|
+
const i = E(n.value);
|
|
105
|
+
i && (a.value.push({
|
|
106
|
+
id: Date.now().toString(),
|
|
107
|
+
path: u.value.trim(),
|
|
108
|
+
method: _.value,
|
|
109
|
+
preset: i
|
|
110
|
+
}), u.value = "", n.value = null);
|
|
111
|
+
}
|
|
112
|
+
function P(i) {
|
|
113
|
+
a.value = a.value.filter((s) => s.id !== i);
|
|
114
|
+
}
|
|
115
|
+
function x() {
|
|
116
|
+
a.value = [];
|
|
117
|
+
}
|
|
118
|
+
return (i, s) => (o(), r("div", I, [
|
|
119
|
+
e("div", F, [
|
|
120
|
+
e("div", $, [
|
|
121
|
+
c(l(C), { size: 18 }),
|
|
122
|
+
s[2] || (s[2] = e("span", null, "Add Simulation", -1))
|
|
123
|
+
]),
|
|
124
|
+
e("div", q, [
|
|
125
|
+
e("div", Z, [
|
|
126
|
+
f(e("select", {
|
|
127
|
+
"onUpdate:modelValue": s[0] || (s[0] = (t) => _.value = t),
|
|
128
|
+
class: "simulator-form__method input"
|
|
129
|
+
}, [
|
|
130
|
+
(o(), r(v, null, y(R, (t) => e("option", {
|
|
131
|
+
key: t,
|
|
132
|
+
value: t
|
|
133
|
+
}, d(t), 9, H)), 64))
|
|
134
|
+
], 512), [
|
|
135
|
+
[L, _.value]
|
|
136
|
+
]),
|
|
137
|
+
f(e("input", {
|
|
138
|
+
"onUpdate:modelValue": s[1] || (s[1] = (t) => u.value = t),
|
|
139
|
+
type: "text",
|
|
140
|
+
class: "simulator-form__path input",
|
|
141
|
+
placeholder: "/api/path or * for all"
|
|
142
|
+
}, null, 512), [
|
|
143
|
+
[N, u.value]
|
|
144
|
+
])
|
|
145
|
+
]),
|
|
146
|
+
e("div", O, [
|
|
147
|
+
(o(), r(v, null, y(p, (t) => e("button", {
|
|
148
|
+
key: t.id,
|
|
149
|
+
class: h([
|
|
150
|
+
"simulator-preset",
|
|
151
|
+
{ "simulator-preset--selected": n.value === t.id },
|
|
152
|
+
t.type === "delay" ? "simulator-preset--delay" : "simulator-preset--error"
|
|
153
|
+
]),
|
|
154
|
+
onClick: (M) => n.value = t.id
|
|
155
|
+
}, [
|
|
156
|
+
(o(), S(g(t.type === "delay" ? l(T) : l(w)), { size: 14 })),
|
|
157
|
+
e("span", J, d(t.label), 1)
|
|
158
|
+
], 10, j)), 64))
|
|
159
|
+
]),
|
|
160
|
+
e("button", {
|
|
161
|
+
class: "btn btn--primary",
|
|
162
|
+
disabled: !b.value,
|
|
163
|
+
onClick: z
|
|
164
|
+
}, [
|
|
165
|
+
c(l(G), { size: 16 }),
|
|
166
|
+
s[3] || (s[3] = e("span", null, "Add Simulation", -1))
|
|
167
|
+
], 8, K)
|
|
168
|
+
])
|
|
169
|
+
]),
|
|
170
|
+
e("div", Q, [
|
|
171
|
+
e("div", W, [
|
|
172
|
+
e("span", X, " Active Simulations (" + d(a.value.length) + ") ", 1),
|
|
173
|
+
a.value.length > 0 ? (o(), r("button", {
|
|
174
|
+
key: 0,
|
|
175
|
+
class: "btn btn--ghost",
|
|
176
|
+
onClick: x
|
|
177
|
+
}, [
|
|
178
|
+
c(l(A), { size: 14 }),
|
|
179
|
+
s[4] || (s[4] = e("span", null, "Clear All", -1))
|
|
180
|
+
])) : k("", !0)
|
|
181
|
+
]),
|
|
182
|
+
e("div", Y, [
|
|
183
|
+
(o(!0), r(v, null, y(a.value, (t) => (o(), r("div", {
|
|
184
|
+
key: t.id,
|
|
185
|
+
class: "simulator-simulation card"
|
|
186
|
+
}, [
|
|
187
|
+
e("div", ee, [
|
|
188
|
+
e("span", {
|
|
189
|
+
class: h([
|
|
190
|
+
"method-badge",
|
|
191
|
+
`method-badge--${t.method.toLowerCase()}`
|
|
192
|
+
])
|
|
193
|
+
}, d(t.method), 3),
|
|
194
|
+
e("span", te, d(t.path), 1)
|
|
195
|
+
]),
|
|
196
|
+
e("div", se, [
|
|
197
|
+
(o(), S(g(t.preset.type === "delay" ? l(T) : l(w)), {
|
|
198
|
+
size: 14,
|
|
199
|
+
class: h(
|
|
200
|
+
t.preset.type === "delay" ? "text-warning" : "text-error"
|
|
201
|
+
)
|
|
202
|
+
}, null, 8, ["class"])),
|
|
203
|
+
e("span", null, d(t.preset.label), 1)
|
|
204
|
+
]),
|
|
205
|
+
e("button", {
|
|
206
|
+
class: "btn btn--ghost btn--icon",
|
|
207
|
+
title: "Remove simulation",
|
|
208
|
+
onClick: (M) => P(t.id)
|
|
209
|
+
}, [
|
|
210
|
+
c(l(A), { size: 14 })
|
|
211
|
+
], 8, oe)
|
|
212
|
+
]))), 128)),
|
|
213
|
+
a.value.length === 0 ? (o(), r("div", le, [
|
|
214
|
+
c(l(C), {
|
|
215
|
+
size: 48,
|
|
216
|
+
class: "empty-state__icon"
|
|
217
|
+
}),
|
|
218
|
+
s[5] || (s[5] = e("h3", { class: "empty-state__title" }, "No active simulations", -1)),
|
|
219
|
+
s[6] || (s[6] = e("p", { class: "empty-state__description" }, " Add a simulation above to test error handling and slow responses. ", -1))
|
|
220
|
+
])) : k("", !0)
|
|
221
|
+
])
|
|
222
|
+
])
|
|
223
|
+
]));
|
|
224
|
+
}
|
|
225
|
+
}), ue = /* @__PURE__ */ B(ae, [["__scopeId", "data-v-cf6df4d2"]]);
|
|
226
|
+
export {
|
|
227
|
+
ue as default
|
|
228
|
+
};
|
|
229
|
+
//# sourceMappingURL=SimulatorPage-9sBeAxQI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SimulatorPage-9sBeAxQI.js","sources":["../../../node_modules/.pnpm/lucide-vue-next@0.513.0_vue@3.5.27_typescript@5.9.3_/node_modules/lucide-vue-next/dist/esm/icons/plus.js","../src/pages/SimulatorPage.vue"],"sourcesContent":["/**\n * @license lucide-vue-next v0.513.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Plus = createLucideIcon(\"plus\", [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n]);\n\nexport { Plus as default };\n//# sourceMappingURL=plus.js.map\n","<!--\n SimulatorPage.vue - Error Simulation Controls Page\n\n What: Provides controls for simulating various API error conditions\n How: Will manage simulation state via simulation store and WebSocket commands\n Why: Allows developers to test error handling without modifying backend code\n-->\n\n<script setup lang=\"ts\">\nimport { AlertTriangle, Clock, Plus, Trash2, Zap } from 'lucide-vue-next';\nimport { computed, ref } from 'vue';\n\n/**\n * Simulation preset type definition\n */\ninterface SimulationPreset {\n id: string;\n label: string;\n description: string;\n type: 'delay' | 'error';\n delay?: number;\n status?: number;\n}\n\n/**\n * Active simulation type definition\n */\ninterface ActiveSimulation {\n id: string;\n path: string;\n method: string;\n preset: SimulationPreset;\n}\n\n// Available simulation presets\nconst presets: SimulationPreset[] = [\n {\n id: 'slow',\n label: 'Slow Response',\n description: 'Add 2 second delay',\n type: 'delay',\n delay: 2000,\n },\n {\n id: 'very-slow',\n label: 'Very Slow',\n description: 'Add 5 second delay',\n type: 'delay',\n delay: 5000,\n },\n {\n id: 'timeout',\n label: 'Timeout',\n description: 'Simulate request timeout (30s)',\n type: 'delay',\n delay: 30000,\n },\n {\n id: 'error-400',\n label: 'Bad Request',\n description: 'Return 400 status',\n type: 'error',\n status: 400,\n },\n {\n id: 'error-401',\n label: 'Unauthorized',\n description: 'Return 401 status',\n type: 'error',\n status: 401,\n },\n {\n id: 'error-403',\n label: 'Forbidden',\n description: 'Return 403 status',\n type: 'error',\n status: 403,\n },\n {\n id: 'error-404',\n label: 'Not Found',\n description: 'Return 404 status',\n type: 'error',\n status: 404,\n },\n {\n id: 'error-429',\n label: 'Rate Limited',\n description: 'Return 429 status',\n type: 'error',\n status: 429,\n },\n {\n id: 'error-500',\n label: 'Server Error',\n description: 'Return 500 status',\n type: 'error',\n status: 500,\n },\n {\n id: 'error-503',\n label: 'Unavailable',\n description: 'Return 503 status',\n type: 'error',\n status: 503,\n },\n];\n\n// TODO: Will be replaced with data from simulation store\nconst activeSimulations = ref<ActiveSimulation[]>([\n {\n id: '1',\n path: '/pets',\n method: 'GET',\n preset: presets[0],\n },\n {\n id: '2',\n path: '/pets/{petId}',\n method: 'GET',\n preset: presets[6],\n },\n]);\n\n// Path input for new simulation\nconst newSimulationPath = ref('');\nconst newSimulationMethod = ref('GET');\nconst selectedPresetId = ref<string | null>(null);\n\n// Available HTTP methods\nconst httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\n\n/**\n * Get preset by ID\n */\nfunction getPreset(id: string): SimulationPreset | undefined {\n return presets.find((p) => p.id === id);\n}\n\n/**\n * Check if we can add a new simulation\n */\nconst canAddSimulation = computed(() => {\n return newSimulationPath.value.trim() !== '' && selectedPresetId.value !== null;\n});\n\n/**\n * Add a new simulation\n */\nfunction addSimulation(): void {\n if (!canAddSimulation.value || !selectedPresetId.value) return;\n\n const preset = getPreset(selectedPresetId.value);\n if (!preset) return;\n\n // TODO: Will send WebSocket command to add simulation\n activeSimulations.value.push({\n id: Date.now().toString(),\n path: newSimulationPath.value.trim(),\n method: newSimulationMethod.value,\n preset,\n });\n\n // Reset form\n newSimulationPath.value = '';\n selectedPresetId.value = null;\n}\n\n/**\n * Remove an active simulation\n */\nfunction removeSimulation(id: string): void {\n // TODO: Will send WebSocket command to remove simulation\n activeSimulations.value = activeSimulations.value.filter((s) => s.id !== id);\n}\n\n/**\n * Clear all simulations\n */\nfunction clearAllSimulations(): void {\n // TODO: Will send WebSocket command to clear all simulations\n activeSimulations.value = [];\n}\n</script>\n\n<template>\n <div class=\"simulator-page\">\n <!-- Add Simulation Form -->\n <div class=\"simulator-form card\">\n <div class=\"simulator-form__header\">\n <Zap :size=\"18\" />\n <span>Add Simulation</span>\n </div>\n\n <div class=\"simulator-form__body\">\n <!-- Method and Path -->\n <div class=\"simulator-form__row\">\n <select\n v-model=\"newSimulationMethod\"\n class=\"simulator-form__method input\"\n >\n <option v-for=\"method in httpMethods\" :key=\"method\" :value=\"method\">\n {{ method }}\n </option>\n </select>\n <input\n v-model=\"newSimulationPath\"\n type=\"text\"\n class=\"simulator-form__path input\"\n placeholder=\"/api/path or * for all\"\n />\n </div>\n\n <!-- Preset Selection -->\n <div class=\"simulator-presets\">\n <button\n v-for=\"preset in presets\"\n :key=\"preset.id\"\n :class=\"[\n 'simulator-preset',\n { 'simulator-preset--selected': selectedPresetId === preset.id },\n preset.type === 'delay'\n ? 'simulator-preset--delay'\n : 'simulator-preset--error',\n ]\"\n @click=\"selectedPresetId = preset.id\"\n >\n <component\n :is=\"preset.type === 'delay' ? Clock : AlertTriangle\"\n :size=\"14\"\n />\n <span class=\"simulator-preset__label\">{{ preset.label }}</span>\n </button>\n </div>\n\n <!-- Add Button -->\n <button\n class=\"btn btn--primary\"\n :disabled=\"!canAddSimulation\"\n @click=\"addSimulation\"\n >\n <Plus :size=\"16\" />\n <span>Add Simulation</span>\n </button>\n </div>\n </div>\n\n <!-- Active Simulations -->\n <div class=\"simulator-active\">\n <div class=\"simulator-active__header\">\n <span class=\"simulator-active__title\">\n Active Simulations ({{ activeSimulations.length }})\n </span>\n <button\n v-if=\"activeSimulations.length > 0\"\n class=\"btn btn--ghost\"\n @click=\"clearAllSimulations\"\n >\n <Trash2 :size=\"14\" />\n <span>Clear All</span>\n </button>\n </div>\n\n <div class=\"simulator-active__list\">\n <div\n v-for=\"simulation in activeSimulations\"\n :key=\"simulation.id\"\n class=\"simulator-simulation card\"\n >\n <div class=\"simulator-simulation__info\">\n <span\n :class=\"[\n 'method-badge',\n `method-badge--${simulation.method.toLowerCase()}`,\n ]\"\n >\n {{ simulation.method }}\n </span>\n <span class=\"simulator-simulation__path font-mono\">\n {{ simulation.path }}\n </span>\n </div>\n <div class=\"simulator-simulation__preset\">\n <component\n :is=\"simulation.preset.type === 'delay' ? Clock : AlertTriangle\"\n :size=\"14\"\n :class=\"\n simulation.preset.type === 'delay'\n ? 'text-warning'\n : 'text-error'\n \"\n />\n <span>{{ simulation.preset.label }}</span>\n </div>\n <button\n class=\"btn btn--ghost btn--icon\"\n title=\"Remove simulation\"\n @click=\"removeSimulation(simulation.id)\"\n >\n <Trash2 :size=\"14\" />\n </button>\n </div>\n\n <!-- Empty State -->\n <div v-if=\"activeSimulations.length === 0\" class=\"empty-state\">\n <Zap :size=\"48\" class=\"empty-state__icon\" />\n <h3 class=\"empty-state__title\">No active simulations</h3>\n <p class=\"empty-state__description\">\n Add a simulation above to test error handling and slow responses.\n </p>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.simulator-page {\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-lg);\n height: 100%;\n padding: var(--devtools-space-md);\n overflow-y: auto;\n}\n\n/* Form */\n.simulator-form {\n flex-shrink: 0;\n}\n\n.simulator-form__header {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-sm);\n padding-bottom: var(--devtools-space-md);\n margin-bottom: var(--devtools-space-md);\n border-bottom: 1px solid var(--devtools-border);\n font-weight: var(--font-weight-6);\n font-size: var(--font-size-1);\n}\n\n.simulator-form__body {\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-md);\n}\n\n.simulator-form__row {\n display: flex;\n gap: var(--devtools-space-sm);\n}\n\n.simulator-form__method {\n width: 100px;\n flex-shrink: 0;\n}\n\n.simulator-form__path {\n flex: 1;\n}\n\n/* Presets */\n.simulator-presets {\n display: flex;\n flex-wrap: wrap;\n gap: var(--devtools-space-xs);\n}\n\n.simulator-preset {\n display: inline-flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n padding: var(--devtools-space-xs) var(--devtools-space-sm);\n background-color: var(--devtools-surface-elevated);\n border: 1px solid var(--devtools-border);\n border-radius: var(--devtools-radius-sm);\n font-family: var(--devtools-font-sans);\n font-size: var(--font-size-0);\n cursor: pointer;\n transition: all var(--devtools-transition-fast);\n}\n\n.simulator-preset:hover {\n background-color: var(--devtools-border);\n}\n\n.simulator-preset--selected {\n border-color: var(--devtools-primary);\n background-color: color-mix(\n in srgb,\n var(--devtools-primary) 15%,\n transparent\n );\n}\n\n.simulator-preset--delay {\n color: var(--devtools-warning);\n}\n\n.simulator-preset--error {\n color: var(--devtools-error);\n}\n\n.simulator-preset__label {\n color: var(--devtools-text);\n}\n\n/* Active Simulations */\n.simulator-active {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.simulator-active__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--devtools-space-md);\n}\n\n.simulator-active__title {\n font-weight: var(--font-weight-6);\n font-size: var(--font-size-1);\n}\n\n.simulator-active__list {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: var(--devtools-space-xs);\n}\n\n/* Simulation Item */\n.simulator-simulation {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-md);\n padding: var(--devtools-space-sm) var(--devtools-space-md);\n}\n\n.simulator-simulation__info {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-sm);\n flex: 1;\n}\n\n.simulator-simulation__path {\n font-size: var(--font-size-1);\n color: var(--devtools-text);\n}\n\n.simulator-simulation__preset {\n display: flex;\n align-items: center;\n gap: var(--devtools-space-xs);\n font-size: var(--font-size-0);\n color: var(--devtools-text-muted);\n}\n\n/* Color utilities */\n.text-warning {\n color: var(--devtools-warning);\n}\n\n.text-error {\n color: var(--devtools-error);\n}\n</style>\n"],"names":["Plus","createLucideIcon","presets","activeSimulations","ref","newSimulationPath","newSimulationMethod","selectedPresetId","httpMethods","getPreset","id","p","canAddSimulation","computed","addSimulation","preset","removeSimulation","clearAllSimulations","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_createVNode","_unref","Zap","_cache","_hoisted_4","_hoisted_5","$event","_Fragment","_renderList","method","_hoisted_6","_hoisted_7","_normalizeClass","_createBlock","_resolveDynamicComponent","Clock","AlertTriangle","_hoisted_9","_toDisplayString","_hoisted_11","_hoisted_12","_hoisted_13","Trash2","_hoisted_14","simulation","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_19"],"mappings":"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","x_google_ignoreList":[0]}
|