@websublime/vite-plugin-open-api-devtools 0.7.0 → 0.8.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/dist/{ModelsPage-CSuUHUuV.js → ModelsPage-DEKnJYaY.js} +5 -5
- package/dist/{ModelsPage-CSuUHUuV.js.map → ModelsPage-DEKnJYaY.js.map} +1 -1
- package/dist/{RoutesPage-D3FSr2Y6.js → RoutesPage-DJQFqkO5.js} +4 -4
- package/dist/{RoutesPage-D3FSr2Y6.js.map → RoutesPage-DJQFqkO5.js.map} +1 -1
- package/dist/{SimulatorPage-CzJrwWzc.js → SimulatorPage-DAwHHeu0.js} +4 -4
- package/dist/{SimulatorPage-CzJrwWzc.js.map → SimulatorPage-DAwHHeu0.js.map} +1 -1
- package/dist/{TimelinePage-HGh13pF3.js → TimelinePage-DdznQBTd.js} +7 -7
- package/dist/{TimelinePage-HGh13pF3.js.map → TimelinePage-DdznQBTd.js.map} +1 -1
- package/dist/{check-BLIoatWd.js → check-CZ-YsL8n.js} +2 -2
- package/dist/{check-BLIoatWd.js.map → check-CZ-YsL8n.js.map} +1 -1
- package/dist/devtools.css +1 -1
- package/dist/devtools.js +1 -1
- package/dist/devtools.umd.cjs +2 -2
- package/dist/devtools.umd.cjs.map +1 -1
- package/dist/{format-lBEBG5Y6.js → format-xvYNYz8d.js} +2 -2
- package/dist/{format-lBEBG5Y6.js.map → format-xvYNYz8d.js.map} +1 -1
- package/dist/{main-DKt7pJsx.js → main-C-2gO_cM.js} +250 -250
- package/dist/main-C-2gO_cM.js.map +1 -0
- package/dist/spa/assets/{ModelsPage-DqYHHuAQ.js → ModelsPage-Dlw4slrw.js} +3 -3
- package/dist/spa/assets/{ModelsPage-DqYHHuAQ.js.map → ModelsPage-Dlw4slrw.js.map} +1 -1
- package/dist/spa/assets/RoutesPage-DVkEOssu.js +2 -0
- package/dist/spa/assets/{RoutesPage-Bhnu6w5-.js.map → RoutesPage-DVkEOssu.js.map} +1 -1
- package/dist/spa/assets/SimulatorPage-C2EEtkx8.js +2 -0
- package/dist/spa/assets/{SimulatorPage-ROKoAmUT.js.map → SimulatorPage-C2EEtkx8.js.map} +1 -1
- package/dist/spa/assets/TimelinePage-C_LK2wKS.js +2 -0
- package/dist/spa/assets/{TimelinePage-CwR-Coxj.js.map → TimelinePage-C_LK2wKS.js.map} +1 -1
- package/dist/spa/assets/check-B_DaLrgB.js +2 -0
- package/dist/spa/assets/{check-DxJBRQqh.js.map → check-B_DaLrgB.js.map} +1 -1
- package/dist/spa/assets/{format-B1udViy3.js → format-r8dlo_ab.js} +2 -2
- package/dist/spa/assets/{format-B1udViy3.js.map → format-r8dlo_ab.js.map} +1 -1
- package/dist/spa/assets/index-CFIFFTBf.css +1 -0
- package/dist/spa/assets/index-Dff2RvrN.js +3 -0
- package/dist/spa/assets/index-Dff2RvrN.js.map +1 -0
- package/dist/spa/assets/{registry-Z11QUkpV.js → registry-DjJcdO1T.js} +2 -2
- package/dist/spa/assets/{registry-Z11QUkpV.js.map → registry-DjJcdO1T.js.map} +1 -1
- package/dist/spa/assets/{trash-2-CDyKV6GB.js → trash-2-6KJWHoOC.js} +2 -2
- package/dist/spa/assets/{trash-2-CDyKV6GB.js.map → trash-2-6KJWHoOC.js.map} +1 -1
- package/dist/spa/assets/{triangle-alert-CAGaIjAo.js → triangle-alert-Dx8lMHrF.js} +2 -2
- package/dist/spa/assets/{triangle-alert-CAGaIjAo.js.map → triangle-alert-Dx8lMHrF.js.map} +1 -1
- package/dist/spa/assets/{vue-vendor-CtA47il-.js → vue-vendor-Bkktf9yg.js} +2 -2
- package/dist/spa/assets/{vue-vendor-CtA47il-.js.map → vue-vendor-Bkktf9yg.js.map} +1 -1
- package/dist/spa/assets/x-B6bG8oob.js +2 -0
- package/dist/spa/assets/{x-zxrccEon.js.map → x-B6bG8oob.js.map} +1 -1
- package/dist/spa/index.html +3 -3
- package/dist/{trash-2-RxS9jzWT.js → trash-2-BiCAm7lq.js} +2 -2
- package/dist/{trash-2-RxS9jzWT.js.map → trash-2-BiCAm7lq.js.map} +1 -1
- package/dist/{triangle-alert-gLhIcFT5.js → triangle-alert-C8PD5_Zo.js} +2 -2
- package/dist/{triangle-alert-gLhIcFT5.js.map → triangle-alert-C8PD5_Zo.js.map} +1 -1
- package/dist/{x-UqfnjULc.js → x-Boe7tiDp.js} +2 -2
- package/dist/{x-UqfnjULc.js.map → x-Boe7tiDp.js.map} +1 -1
- package/package.json +12 -12
- package/dist/main-DKt7pJsx.js.map +0 -1
- package/dist/spa/assets/RoutesPage-Bhnu6w5-.js +0 -2
- package/dist/spa/assets/SimulatorPage-ROKoAmUT.js +0 -2
- package/dist/spa/assets/TimelinePage-CwR-Coxj.js +0 -2
- package/dist/spa/assets/check-DxJBRQqh.js +0 -2
- package/dist/spa/assets/index-9_6u4UTF.css +0 -1
- package/dist/spa/assets/index-GQ9qRqEi.js +0 -3
- package/dist/spa/assets/index-GQ9qRqEi.js.map +0 -1
- package/dist/spa/assets/useWebSocket-C2ttWF5T.js +0 -2
- package/dist/spa/assets/useWebSocket-C2ttWF5T.js.map +0 -1
- package/dist/spa/assets/x-zxrccEon.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoutesPage-D3FSr2Y6.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/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 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","props","__props","hasSecurity","computed","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","tag","_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","endpoint","handleGroupToggle","isSelected","group","$event","_createBlock","_resolveDynamicComponent","ChevronDown","ChevronRight","_vShow","registryStore","useRegistryStore","send","on","connected","useWebSocket","showFilters","ref","searchInputRef","httpMethods","fetchRegistry","handleRegistryData","data","handleSelectEndpoint","key","handleToggleGroup","handleSearchInput","event","target","clearSearch","toggleMethod","method","isMethodActive","toggleHandlerFilter","current","toggleSeedFilter","clearAllFilters","toggleFilters","hasActiveFilters","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]}
|
|
1
|
+
{"version":3,"file":"RoutesPage-DJQFqkO5.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/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 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","props","__props","hasSecurity","computed","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","tag","_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","endpoint","handleGroupToggle","isSelected","group","$event","_createBlock","_resolveDynamicComponent","ChevronDown","ChevronRight","_vShow","registryStore","useRegistryStore","send","on","connected","useWebSocket","showFilters","ref","searchInputRef","httpMethods","fetchRegistry","handleRegistryData","data","handleSelectEndpoint","key","handleToggleGroup","handleSearchInput","event","target","clearSearch","toggleMethod","method","isMethodActive","toggleHandlerFilter","current","toggleSeedFilter","clearAllFilters","toggleFilters","hasActiveFilters","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]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ref as y, computed as f, defineComponent as X, onMounted as Y, onUnmounted as ee, createElementBlock as d, openBlock as r, createElementVNode as a, createVNode as R, unref as u, createCommentVNode as $, withDirectives as V, Fragment as x, renderList as U, toDisplayString as b, vModelSelect as q, vModelText as te, normalizeClass as B, createBlock as O, resolveDynamicComponent as G } from "vue";
|
|
2
|
-
import { c as oe, u as se, Z as W, C as Z, _ as le } from "./main-
|
|
2
|
+
import { c as oe, u as se, Z as W, C as Z, _ as le } from "./main-C-2gO_cM.js";
|
|
3
3
|
import { u as ae } from "./registry-BQhccWMq.js";
|
|
4
4
|
import { defineStore as ne } from "pinia";
|
|
5
|
-
import { T as K } from "./triangle-alert-
|
|
6
|
-
import { T as j } from "./trash-2-
|
|
5
|
+
import { T as K } from "./triangle-alert-C8PD5_Zo.js";
|
|
6
|
+
import { T as j } from "./trash-2-BiCAm7lq.js";
|
|
7
7
|
const ie = oe("plus", [
|
|
8
8
|
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
9
9
|
["path", { d: "M12 5v14", key: "s699le" }]
|
|
@@ -422,4 +422,4 @@ const ie = oe("plus", [
|
|
|
422
422
|
export {
|
|
423
423
|
Fe as default
|
|
424
424
|
};
|
|
425
|
-
//# sourceMappingURL=SimulatorPage-
|
|
425
|
+
//# sourceMappingURL=SimulatorPage-DAwHHeu0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimulatorPage-CzJrwWzc.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/stores/simulation.ts","../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 * Simulation Store\n *\n * What: Pinia store for managing error and delay simulations\n * How: Manages simulation state and communicates with server via WebSocket\n * Why: Enables developers to test error handling and loading states\n *\n * @module stores/simulation\n */\n\nimport { defineStore } from 'pinia';\nimport { computed, ref } from 'vue';\n\n/**\n * Simulation preset type\n */\nexport type SimulationPresetType = 'delay' | 'error' | 'empty';\n\n/**\n * Simulation preset definition\n */\nexport interface SimulationPreset {\n id: string;\n label: string;\n description: string;\n type: SimulationPresetType;\n status: number;\n delay?: number;\n body?: unknown;\n}\n\n/**\n * Active simulation state\n */\nexport interface ActiveSimulation {\n path: string;\n operationId?: string;\n status: number;\n delay?: number;\n body?: unknown;\n presetId?: string;\n}\n\n/**\n * Preset definitions matching PRD FR-104 requirements\n */\nexport const SIMULATION_PRESETS: SimulationPreset[] = [\n {\n id: 'slow-network',\n label: 'Slow Network',\n description: '3000ms delay (3G simulation)',\n type: 'delay',\n status: 200,\n delay: 3000,\n },\n {\n id: 'server-error',\n label: 'Server Error',\n description: 'Returns HTTP 500',\n type: 'error',\n status: 500,\n body: { error: 'Internal Server Error', message: 'Simulated server error' },\n },\n {\n id: 'rate-limit',\n label: 'Rate Limited',\n description: 'Returns HTTP 429',\n type: 'error',\n status: 429,\n body: { error: 'Too Many Requests', message: 'Rate limit exceeded' },\n },\n {\n id: 'not-found',\n label: 'Not Found',\n description: 'Returns HTTP 404',\n type: 'error',\n status: 404,\n body: { error: 'Not Found', message: 'Resource not found' },\n },\n {\n id: 'request-timeout',\n label: 'Request Timeout',\n description: '30000ms delay (simulates timeout)',\n type: 'delay',\n status: 200,\n delay: 30000,\n },\n {\n id: 'empty-response',\n label: 'Empty Response',\n description: 'Returns HTTP 200 with empty body',\n type: 'empty',\n status: 200,\n body: null,\n },\n {\n id: 'unauthorized',\n label: 'Unauthorized',\n description: 'Returns HTTP 401',\n type: 'error',\n status: 401,\n body: { error: 'Unauthorized', message: 'Authentication required' },\n },\n];\n\n/**\n * Simulation store for managing endpoint simulations\n *\n * Provides:\n * - Active simulations storage and retrieval\n * - Preset definitions and lookup\n * - WebSocket command integration\n * - Simulation count and status tracking\n */\nexport const useSimulationStore = defineStore('simulation', () => {\n // ==========================================================================\n // State\n // ==========================================================================\n\n /**\n * Active simulations keyed by path\n * One simulation per path (enforced by Map)\n */\n const simulations = ref<Map<string, ActiveSimulation>>(new Map());\n\n /**\n * Previous simulation state for rollback on failure\n * Keyed by path, stores the simulation before optimistic update\n */\n const previousSimulations = ref<Map<string, ActiveSimulation | null>>(new Map());\n\n /**\n * Loading state for async operations\n */\n const isLoading = ref(false);\n\n /**\n * Error state\n */\n const error = ref<string | null>(null);\n\n // ==========================================================================\n // Getters / Computed\n // ==========================================================================\n\n /**\n * All active simulations as an array\n */\n const activeSimulations = computed(() => {\n return Array.from(simulations.value.values());\n });\n\n /**\n * Count of active simulations\n */\n const count = computed(() => simulations.value.size);\n\n /**\n * Available presets\n */\n const presets = computed(() => SIMULATION_PRESETS);\n\n /**\n * Check if any simulations are active\n */\n const hasActiveSimulations = computed(() => simulations.value.size > 0);\n\n /**\n * Get simulations grouped by type\n */\n const simulationsByType = computed(() => {\n const grouped = {\n delay: [] as ActiveSimulation[],\n error: [] as ActiveSimulation[],\n empty: [] as ActiveSimulation[],\n };\n\n for (const simulation of simulations.value.values()) {\n const type = getSimulationType(simulation);\n grouped[type].push(simulation);\n }\n\n return grouped;\n });\n\n /**\n * Determine simulation type from simulation config\n */\n function getSimulationType(simulation: ActiveSimulation): SimulationPresetType {\n const preset = simulation.presetId\n ? SIMULATION_PRESETS.find((p) => p.id === simulation.presetId)\n : null;\n\n if (preset) {\n return preset.type;\n }\n\n if (simulation.delay && simulation.delay > 0) {\n return 'delay';\n }\n\n if (simulation.body === null) {\n return 'empty';\n }\n\n return 'error';\n }\n\n // ==========================================================================\n // Actions\n // ==========================================================================\n\n /**\n * Set active simulations from server (e.g., on 'simulation:active' event)\n */\n function setSimulations(newSimulations: ActiveSimulation[]): void {\n simulations.value.clear();\n for (const simulation of newSimulations) {\n simulations.value.set(simulation.path, simulation);\n }\n error.value = null;\n }\n\n /**\n * Add a new simulation locally\n * Note: This updates local state only. Use addSimulation() to sync with server.\n * @param storeForRollback - If true, stores previous state for rollback\n */\n function addSimulationLocal(simulation: ActiveSimulation, storeForRollback = false): void {\n if (storeForRollback) {\n // Store previous state (null if didn't exist)\n const previous = simulations.value.get(simulation.path) || null;\n previousSimulations.value.set(simulation.path, previous);\n }\n simulations.value.set(simulation.path, simulation);\n }\n\n /**\n * Remove a simulation locally by path\n * Note: This updates local state only. Use removeSimulation() to sync with server.\n * @param storeForRollback - If true, stores previous state for rollback\n */\n function removeSimulationLocal(path: string, storeForRollback = false): boolean {\n if (storeForRollback) {\n // Store previous state before removing\n const previous = simulations.value.get(path) || null;\n previousSimulations.value.set(path, previous);\n }\n return simulations.value.delete(path);\n }\n\n /**\n * Clear all simulations locally\n * Note: This updates local state only. Use clearSimulations() to sync with server.\n */\n function clearSimulationsLocal(): void {\n simulations.value.clear();\n }\n\n /**\n * Get a simulation by path\n */\n function getSimulation(path: string): ActiveSimulation | undefined {\n return simulations.value.get(path);\n }\n\n /**\n * Check if a simulation exists for a path\n */\n function hasSimulation(path: string): boolean {\n return simulations.value.has(path);\n }\n\n /**\n * Get a preset by ID\n */\n function getPreset(id: string): SimulationPreset | undefined {\n return SIMULATION_PRESETS.find((p) => p.id === id);\n }\n\n /**\n * Create a simulation from a preset\n */\n function createSimulationFromPreset(\n path: string,\n presetId: string,\n operationId?: string,\n ): ActiveSimulation | null {\n const preset = getPreset(presetId);\n if (!preset) {\n error.value = `Preset not found: ${presetId}`;\n return null;\n }\n\n return {\n path,\n operationId,\n status: preset.status,\n delay: preset.delay,\n body: preset.body,\n presetId: preset.id,\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 * Rollback a simulation to its previous state\n * @param path - The path of the simulation to rollback\n */\n function rollbackSimulation(path: string): void {\n if (!previousSimulations.value.has(path)) {\n return;\n }\n\n const previous = previousSimulations.value.get(path);\n if (previous === null || previous === undefined) {\n // Was added optimistically, remove it\n simulations.value.delete(path);\n } else {\n // Restore previous state\n simulations.value.set(path, previous);\n }\n\n // Clear rollback data\n previousSimulations.value.delete(path);\n }\n\n /**\n * Handle simulation:added event from server\n */\n function handleSimulationAdded(data: { path: string }): void {\n // Server will send 'simulation:active' event with full state\n // This event is just a notification\n console.log('[Simulation] Added:', data.path);\n }\n\n /**\n * Handle simulation:removed event from server\n */\n function handleSimulationRemoved(data: { path: string }): void {\n removeSimulationLocal(data.path);\n console.log('[Simulation] Removed:', data.path);\n }\n\n /**\n * Handle simulations:cleared event from server\n */\n function handleSimulationsCleared(data: { count: number }): void {\n clearSimulationsLocal();\n console.log('[Simulation] Cleared all:', data.count);\n }\n\n /**\n * Handle simulation:set response from server\n */\n function handleSimulationSet(data: { path: string; success: boolean }): void {\n if (data.success) {\n // Clear rollback data on success\n previousSimulations.value.delete(data.path);\n console.log('[Simulation] Set successfully:', data.path);\n } else {\n // Rollback optimistic update on failure\n rollbackSimulation(data.path);\n setError(`Failed to set simulation for ${data.path}`);\n }\n setLoading(false);\n }\n\n /**\n * Handle simulation:cleared response from server\n */\n function handleSimulationCleared(data: { path: string; success: boolean }): void {\n if (data.success) {\n // Clear rollback data on success\n previousSimulations.value.delete(data.path);\n console.log('[Simulation] Cleared successfully:', data.path);\n } else {\n // Rollback optimistic removal on failure\n rollbackSimulation(data.path);\n setError(`Failed to clear simulation for ${data.path}`);\n }\n setLoading(false);\n }\n\n // ==========================================================================\n // Return\n // ==========================================================================\n\n return {\n // State\n simulations,\n isLoading,\n error,\n\n // Getters\n activeSimulations,\n count,\n presets,\n hasActiveSimulations,\n simulationsByType,\n\n // Actions\n setSimulations,\n addSimulationLocal,\n removeSimulationLocal,\n clearSimulationsLocal,\n getSimulation,\n hasSimulation,\n getPreset,\n createSimulationFromPreset,\n setLoading,\n setError,\n clearError,\n rollbackSimulation,\n\n // Event handlers\n handleSimulationAdded,\n handleSimulationRemoved,\n handleSimulationsCleared,\n handleSimulationSet,\n handleSimulationCleared,\n };\n});\n","<!--\n SimulatorPage.vue - Error Simulation Controls Page\n\n What: Provides controls for simulating various API error conditions\n How: Manages 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, onMounted, onUnmounted, ref } from 'vue';\nimport { useWebSocket } from '../composables/useWebSocket';\nimport { useRegistryStore } from '../stores/registry';\nimport type { ActiveSimulation } from '../stores/simulation';\nimport { useSimulationStore } from '../stores/simulation';\n\n// ==========================================================================\n// Types\n// ==========================================================================\n\ninterface SimulationActiveEvent {\n simulations: ActiveSimulation[];\n}\n\ninterface SimulationPathEvent {\n path: string;\n}\n\ninterface SimulationsClearedEvent {\n count: number;\n}\n\ninterface SimulationSetEvent {\n path: string;\n success: boolean;\n}\n\ninterface SimulationClearedEvent {\n path: string;\n success: boolean;\n}\n\n// ==========================================================================\n// Composables\n// ==========================================================================\n\nconst simulationStore = useSimulationStore();\nconst registryStore = useRegistryStore();\nconst { send, on } = useWebSocket();\n\n// ==========================================================================\n// State\n// ==========================================================================\n\n/** Path input for new simulation */\nconst newSimulationPath = ref('');\n\n/** Method input for new simulation */\nconst newSimulationMethod = ref('GET');\n\n/** Selected preset ID */\nconst selectedPresetId = ref<string | null>(null);\n\n/** Selected endpoint key (for dropdown selection) */\nconst selectedEndpointKey = ref<string | null>(null);\n\n/** Available HTTP methods */\nconst httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];\n\n/** WebSocket event unsubscribe functions (populated in onMounted) */\nlet unsubscribers: Array<() => void> = [];\n\n/** Simulations pending clear (for rollback on partial failures) */\nconst pendingClears = ref<Set<string>>(new Set());\n\n// ==========================================================================\n// Computed\n// ==========================================================================\n\n/**\n * Available endpoints for selection\n */\nconst availableEndpoints = computed(() => {\n return registryStore.endpoints.map((e) => ({\n key: e.key,\n label: `${e.method.toUpperCase()} ${e.path}`,\n method: e.method.toUpperCase(),\n path: e.path,\n operationId: e.operationId,\n }));\n});\n\n/**\n * Check if we can add a new simulation\n */\nconst canAddSimulation = computed(() => {\n const hasPath = newSimulationPath.value.trim() !== '';\n const hasPreset = selectedPresetId.value !== null;\n return hasPath && hasPreset;\n});\n\n/**\n * Active simulations for display\n */\nconst activeSimulations = computed(() => {\n return simulationStore.activeSimulations.map((sim) => {\n const preset = sim.presetId ? simulationStore.getPreset(sim.presetId) : null;\n return {\n ...sim,\n preset,\n };\n });\n});\n\n/**\n * Simulation count\n */\nconst simulationCount = computed(() => simulationStore.count);\n\n// ==========================================================================\n// Methods\n// ==========================================================================\n\n/**\n * Add a new simulation\n */\nfunction addSimulation(): void {\n if (!canAddSimulation.value || !selectedPresetId.value) return;\n\n const preset = simulationStore.getPreset(selectedPresetId.value);\n if (!preset) return;\n\n // Validate path input\n const trimmedPath = newSimulationPath.value.trim();\n\n // Path must start with /\n if (!trimmedPath.startsWith('/')) {\n simulationStore.setError('Path must start with /');\n return;\n }\n\n // Path must not be too long (reasonable limit)\n if (trimmedPath.length > 500) {\n simulationStore.setError('Path is too long (max 500 characters)');\n return;\n }\n\n // Path should only contain valid URL path characters\n if (!/^\\/[\\w\\-/{}:.]*$/.test(trimmedPath)) {\n simulationStore.setError('Path contains invalid characters');\n return;\n }\n\n // Combine method and path to create endpoint key (e.g., \"get:/pets\")\n const pathWithMethod = `${newSimulationMethod.value.toLowerCase()}:${trimmedPath}`;\n const simulation = simulationStore.createSimulationFromPreset(\n pathWithMethod,\n selectedPresetId.value,\n undefined,\n );\n\n if (!simulation) return;\n\n // Optimistically add to local state (store previous state for rollback)\n simulationStore.addSimulationLocal(simulation, true);\n simulationStore.setLoading(true);\n\n // Send command to server\n send({\n type: 'set:simulation',\n data: {\n path: simulation.path,\n status: simulation.status,\n delay: simulation.delay,\n body: simulation.body,\n },\n });\n\n // Reset form\n newSimulationPath.value = '';\n selectedPresetId.value = null;\n selectedEndpointKey.value = null;\n}\n\n/**\n * Remove an active simulation\n */\nfunction removeSimulation(path: string): void {\n // Optimistically remove from local state (store previous state for rollback)\n simulationStore.removeSimulationLocal(path, true);\n simulationStore.setLoading(true);\n\n // Send command to server\n send({\n type: 'clear:simulation',\n data: { path },\n });\n}\n\n/**\n * Clear all simulations\n */\nfunction clearAllSimulations(): void {\n if (simulationCount.value === 0) return;\n\n // Mark each simulation as pending clear and store for rollback\n for (const simulation of simulationStore.activeSimulations) {\n pendingClears.value.add(simulation.path);\n\n // Store previous state for rollback\n simulationStore.removeSimulationLocal(simulation.path, true);\n\n // Send clear command to server\n send({\n type: 'clear:simulation',\n data: { path: simulation.path },\n });\n }\n\n simulationStore.setLoading(true);\n\n // Note: Individual simulations will be removed from local state\n // only when we receive the corresponding \"simulation:cleared\" event\n // with success: true. Failed clears will be rolled back automatically.\n}\n\n/**\n * Handle endpoint selection from dropdown\n */\nfunction handleEndpointSelect(): void {\n if (!selectedEndpointKey.value) return;\n\n const endpoint = registryStore.endpoints.find((e) => e.key === selectedEndpointKey.value);\n if (!endpoint) return;\n\n newSimulationMethod.value = endpoint.method.toUpperCase();\n newSimulationPath.value = endpoint.path;\n}\n\n/**\n * Handle manual path/method input\n */\nfunction handleManualInput(): void {\n // Clear endpoint selection when user types manually\n selectedEndpointKey.value = null;\n}\n\n// ==========================================================================\n// Lifecycle\n// ==========================================================================\n\nonMounted(() => {\n // Subscribe to simulation events and collect unsubscribe functions\n unsubscribers = [\n on('simulation:active', (data: SimulationActiveEvent) => {\n simulationStore.setSimulations(data.simulations);\n }),\n\n on('simulation:added', (data: SimulationPathEvent) => {\n simulationStore.handleSimulationAdded(data);\n }),\n\n on('simulation:removed', (data: SimulationPathEvent) => {\n simulationStore.handleSimulationRemoved(data);\n }),\n\n on('simulations:cleared', (data: SimulationsClearedEvent) => {\n simulationStore.handleSimulationsCleared(data);\n }),\n\n on('simulation:set', (data: SimulationSetEvent) => {\n simulationStore.handleSimulationSet(data);\n }),\n\n on('simulation:cleared', (data: SimulationClearedEvent) => {\n // Remove from pending clears if it was part of clearAll\n if (pendingClears.value.has(data.path)) {\n pendingClears.value.delete(data.path);\n }\n\n // Delegate to store handler (handles success/failure and rollback)\n simulationStore.handleSimulationCleared(data);\n }),\n ];\n\n // Request current simulations from server\n send({ type: 'get:registry' });\n});\n\n// Cleanup on unmount to prevent memory leaks\nonUnmounted(() => {\n for (const unsub of unsubscribers) {\n unsub();\n }\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 <!-- Endpoint Selector (optional) -->\n <div v-if=\"availableEndpoints.length > 0\" class=\"simulator-form__row\">\n <label class=\"simulator-form__label\">Select Endpoint (optional):</label>\n <select\n v-model=\"selectedEndpointKey\"\n class=\"input\"\n @change=\"handleEndpointSelect\"\n >\n <option :value=\"null\">Manual entry...</option>\n <option\n v-for=\"endpoint in availableEndpoints\"\n :key=\"endpoint.key\"\n :value=\"endpoint.key\"\n >\n {{ endpoint.label }}\n </option>\n </select>\n </div>\n\n <!-- Method and Path -->\n <div class=\"simulator-form__row\">\n <select\n v-model=\"newSimulationMethod\"\n class=\"simulator-form__method input\"\n @change=\"handleManualInput\"\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\"\n @input=\"handleManualInput\"\n />\n </div>\n\n <!-- Preset Selection -->\n <div class=\"simulator-presets\">\n <button\n v-for=\"preset in simulationStore.presets\"\n :key=\"preset.id\"\n :class=\"[\n 'simulator-preset',\n { 'simulator-preset--selected': selectedPresetId === preset.id },\n `simulator-preset--${preset.type}`,\n ]\"\n :title=\"preset.description\"\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 || simulationStore.isLoading\"\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 ({{ simulationCount }})\n </span>\n <button\n v-if=\"simulationCount > 0\"\n class=\"btn btn--ghost\"\n :disabled=\"simulationStore.isLoading\"\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.path\"\n class=\"simulator-simulation card\"\n >\n <div class=\"simulator-simulation__info\">\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 'text-warning': simulation.preset?.type === 'delay',\n 'text-error': simulation.preset?.type === 'error',\n 'text-muted': simulation.preset?.type === 'empty',\n }\"\n />\n <span>\n {{ simulation.preset?.label || `HTTP ${simulation.status}` }}\n </span>\n <span v-if=\"simulation.delay\" class=\"text-muted\">\n ({{ simulation.delay }}ms)\n </span>\n </div>\n <button\n class=\"btn btn--ghost btn--icon\"\n title=\"Remove simulation\"\n :disabled=\"simulationStore.isLoading\"\n @click=\"removeSimulation(simulation.path)\"\n >\n <Trash2 :size=\"14\" />\n </button>\n </div>\n\n <!-- Empty State -->\n <div v-if=\"simulationCount === 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 flex-direction: column;\n gap: var(--devtools-space-xs);\n}\n\n.simulator-form__row:has(.simulator-form__method) {\n flex-direction: row;\n gap: var(--devtools-space-sm);\n}\n\n.simulator-form__label {\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-5);\n color: var(--devtools-text);\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--empty {\n color: var(--devtools-text-muted);\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\n.text-muted {\n color: var(--devtools-text-muted);\n}\n</style>\n"],"names":["Plus","createLucideIcon","SIMULATION_PRESETS","useSimulationStore","defineStore","simulations","ref","previousSimulations","isLoading","error","activeSimulations","computed","count","presets","hasActiveSimulations","simulationsByType","grouped","simulation","type","getSimulationType","preset","p","setSimulations","newSimulations","addSimulationLocal","storeForRollback","previous","removeSimulationLocal","path","clearSimulationsLocal","getSimulation","hasSimulation","getPreset","id","createSimulationFromPreset","presetId","operationId","setLoading","loading","setError","errorMessage","clearError","rollbackSimulation","handleSimulationAdded","data","handleSimulationRemoved","handleSimulationsCleared","handleSimulationSet","handleSimulationCleared","simulationStore","registryStore","useRegistryStore","send","on","useWebSocket","newSimulationPath","newSimulationMethod","selectedPresetId","selectedEndpointKey","httpMethods","unsubscribers","pendingClears","availableEndpoints","e","canAddSimulation","hasPath","hasPreset","sim","simulationCount","addSimulation","trimmedPath","pathWithMethod","removeSimulation","clearAllSimulations","handleEndpointSelect","endpoint","handleManualInput","onMounted","onUnmounted","unsub","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_createVNode","_unref","Zap","_cache","_hoisted_4","_hoisted_5","$event","_Fragment","_renderList","_toDisplayString","_hoisted_6","_hoisted_7","method","_hoisted_8","_hoisted_9","_normalizeClass","_createBlock","_resolveDynamicComponent","Clock","AlertTriangle","_hoisted_11","_hoisted_13","_hoisted_14","_hoisted_15","Trash2","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_23"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"SimulatorPage-DAwHHeu0.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/stores/simulation.ts","../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 * Simulation Store\n *\n * What: Pinia store for managing error and delay simulations\n * How: Manages simulation state and communicates with server via WebSocket\n * Why: Enables developers to test error handling and loading states\n *\n * @module stores/simulation\n */\n\nimport { defineStore } from 'pinia';\nimport { computed, ref } from 'vue';\n\n/**\n * Simulation preset type\n */\nexport type SimulationPresetType = 'delay' | 'error' | 'empty';\n\n/**\n * Simulation preset definition\n */\nexport interface SimulationPreset {\n id: string;\n label: string;\n description: string;\n type: SimulationPresetType;\n status: number;\n delay?: number;\n body?: unknown;\n}\n\n/**\n * Active simulation state\n */\nexport interface ActiveSimulation {\n path: string;\n operationId?: string;\n status: number;\n delay?: number;\n body?: unknown;\n presetId?: string;\n}\n\n/**\n * Preset definitions matching PRD FR-104 requirements\n */\nexport const SIMULATION_PRESETS: SimulationPreset[] = [\n {\n id: 'slow-network',\n label: 'Slow Network',\n description: '3000ms delay (3G simulation)',\n type: 'delay',\n status: 200,\n delay: 3000,\n },\n {\n id: 'server-error',\n label: 'Server Error',\n description: 'Returns HTTP 500',\n type: 'error',\n status: 500,\n body: { error: 'Internal Server Error', message: 'Simulated server error' },\n },\n {\n id: 'rate-limit',\n label: 'Rate Limited',\n description: 'Returns HTTP 429',\n type: 'error',\n status: 429,\n body: { error: 'Too Many Requests', message: 'Rate limit exceeded' },\n },\n {\n id: 'not-found',\n label: 'Not Found',\n description: 'Returns HTTP 404',\n type: 'error',\n status: 404,\n body: { error: 'Not Found', message: 'Resource not found' },\n },\n {\n id: 'request-timeout',\n label: 'Request Timeout',\n description: '30000ms delay (simulates timeout)',\n type: 'delay',\n status: 200,\n delay: 30000,\n },\n {\n id: 'empty-response',\n label: 'Empty Response',\n description: 'Returns HTTP 200 with empty body',\n type: 'empty',\n status: 200,\n body: null,\n },\n {\n id: 'unauthorized',\n label: 'Unauthorized',\n description: 'Returns HTTP 401',\n type: 'error',\n status: 401,\n body: { error: 'Unauthorized', message: 'Authentication required' },\n },\n];\n\n/**\n * Simulation store for managing endpoint simulations\n *\n * Provides:\n * - Active simulations storage and retrieval\n * - Preset definitions and lookup\n * - WebSocket command integration\n * - Simulation count and status tracking\n */\nexport const useSimulationStore = defineStore('simulation', () => {\n // ==========================================================================\n // State\n // ==========================================================================\n\n /**\n * Active simulations keyed by path\n * One simulation per path (enforced by Map)\n */\n const simulations = ref<Map<string, ActiveSimulation>>(new Map());\n\n /**\n * Previous simulation state for rollback on failure\n * Keyed by path, stores the simulation before optimistic update\n */\n const previousSimulations = ref<Map<string, ActiveSimulation | null>>(new Map());\n\n /**\n * Loading state for async operations\n */\n const isLoading = ref(false);\n\n /**\n * Error state\n */\n const error = ref<string | null>(null);\n\n // ==========================================================================\n // Getters / Computed\n // ==========================================================================\n\n /**\n * All active simulations as an array\n */\n const activeSimulations = computed(() => {\n return Array.from(simulations.value.values());\n });\n\n /**\n * Count of active simulations\n */\n const count = computed(() => simulations.value.size);\n\n /**\n * Available presets\n */\n const presets = computed(() => SIMULATION_PRESETS);\n\n /**\n * Check if any simulations are active\n */\n const hasActiveSimulations = computed(() => simulations.value.size > 0);\n\n /**\n * Get simulations grouped by type\n */\n const simulationsByType = computed(() => {\n const grouped = {\n delay: [] as ActiveSimulation[],\n error: [] as ActiveSimulation[],\n empty: [] as ActiveSimulation[],\n };\n\n for (const simulation of simulations.value.values()) {\n const type = getSimulationType(simulation);\n grouped[type].push(simulation);\n }\n\n return grouped;\n });\n\n /**\n * Determine simulation type from simulation config\n */\n function getSimulationType(simulation: ActiveSimulation): SimulationPresetType {\n const preset = simulation.presetId\n ? SIMULATION_PRESETS.find((p) => p.id === simulation.presetId)\n : null;\n\n if (preset) {\n return preset.type;\n }\n\n if (simulation.delay && simulation.delay > 0) {\n return 'delay';\n }\n\n if (simulation.body === null) {\n return 'empty';\n }\n\n return 'error';\n }\n\n // ==========================================================================\n // Actions\n // ==========================================================================\n\n /**\n * Set active simulations from server (e.g., on 'simulation:active' event)\n */\n function setSimulations(newSimulations: ActiveSimulation[]): void {\n simulations.value.clear();\n for (const simulation of newSimulations) {\n simulations.value.set(simulation.path, simulation);\n }\n error.value = null;\n }\n\n /**\n * Add a new simulation locally\n * Note: This updates local state only. Use addSimulation() to sync with server.\n * @param storeForRollback - If true, stores previous state for rollback\n */\n function addSimulationLocal(simulation: ActiveSimulation, storeForRollback = false): void {\n if (storeForRollback) {\n // Store previous state (null if didn't exist)\n const previous = simulations.value.get(simulation.path) || null;\n previousSimulations.value.set(simulation.path, previous);\n }\n simulations.value.set(simulation.path, simulation);\n }\n\n /**\n * Remove a simulation locally by path\n * Note: This updates local state only. Use removeSimulation() to sync with server.\n * @param storeForRollback - If true, stores previous state for rollback\n */\n function removeSimulationLocal(path: string, storeForRollback = false): boolean {\n if (storeForRollback) {\n // Store previous state before removing\n const previous = simulations.value.get(path) || null;\n previousSimulations.value.set(path, previous);\n }\n return simulations.value.delete(path);\n }\n\n /**\n * Clear all simulations locally\n * Note: This updates local state only. Use clearSimulations() to sync with server.\n */\n function clearSimulationsLocal(): void {\n simulations.value.clear();\n }\n\n /**\n * Get a simulation by path\n */\n function getSimulation(path: string): ActiveSimulation | undefined {\n return simulations.value.get(path);\n }\n\n /**\n * Check if a simulation exists for a path\n */\n function hasSimulation(path: string): boolean {\n return simulations.value.has(path);\n }\n\n /**\n * Get a preset by ID\n */\n function getPreset(id: string): SimulationPreset | undefined {\n return SIMULATION_PRESETS.find((p) => p.id === id);\n }\n\n /**\n * Create a simulation from a preset\n */\n function createSimulationFromPreset(\n path: string,\n presetId: string,\n operationId?: string,\n ): ActiveSimulation | null {\n const preset = getPreset(presetId);\n if (!preset) {\n error.value = `Preset not found: ${presetId}`;\n return null;\n }\n\n return {\n path,\n operationId,\n status: preset.status,\n delay: preset.delay,\n body: preset.body,\n presetId: preset.id,\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 * Rollback a simulation to its previous state\n * @param path - The path of the simulation to rollback\n */\n function rollbackSimulation(path: string): void {\n if (!previousSimulations.value.has(path)) {\n return;\n }\n\n const previous = previousSimulations.value.get(path);\n if (previous === null || previous === undefined) {\n // Was added optimistically, remove it\n simulations.value.delete(path);\n } else {\n // Restore previous state\n simulations.value.set(path, previous);\n }\n\n // Clear rollback data\n previousSimulations.value.delete(path);\n }\n\n /**\n * Handle simulation:added event from server\n */\n function handleSimulationAdded(data: { path: string }): void {\n // Server will send 'simulation:active' event with full state\n // This event is just a notification\n console.log('[Simulation] Added:', data.path);\n }\n\n /**\n * Handle simulation:removed event from server\n */\n function handleSimulationRemoved(data: { path: string }): void {\n removeSimulationLocal(data.path);\n console.log('[Simulation] Removed:', data.path);\n }\n\n /**\n * Handle simulations:cleared event from server\n */\n function handleSimulationsCleared(data: { count: number }): void {\n clearSimulationsLocal();\n console.log('[Simulation] Cleared all:', data.count);\n }\n\n /**\n * Handle simulation:set response from server\n */\n function handleSimulationSet(data: { path: string; success: boolean }): void {\n if (data.success) {\n // Clear rollback data on success\n previousSimulations.value.delete(data.path);\n console.log('[Simulation] Set successfully:', data.path);\n } else {\n // Rollback optimistic update on failure\n rollbackSimulation(data.path);\n setError(`Failed to set simulation for ${data.path}`);\n }\n setLoading(false);\n }\n\n /**\n * Handle simulation:cleared response from server\n */\n function handleSimulationCleared(data: { path: string; success: boolean }): void {\n if (data.success) {\n // Clear rollback data on success\n previousSimulations.value.delete(data.path);\n console.log('[Simulation] Cleared successfully:', data.path);\n } else {\n // Rollback optimistic removal on failure\n rollbackSimulation(data.path);\n setError(`Failed to clear simulation for ${data.path}`);\n }\n setLoading(false);\n }\n\n // ==========================================================================\n // Return\n // ==========================================================================\n\n return {\n // State\n simulations,\n isLoading,\n error,\n\n // Getters\n activeSimulations,\n count,\n presets,\n hasActiveSimulations,\n simulationsByType,\n\n // Actions\n setSimulations,\n addSimulationLocal,\n removeSimulationLocal,\n clearSimulationsLocal,\n getSimulation,\n hasSimulation,\n getPreset,\n createSimulationFromPreset,\n setLoading,\n setError,\n clearError,\n rollbackSimulation,\n\n // Event handlers\n handleSimulationAdded,\n handleSimulationRemoved,\n handleSimulationsCleared,\n handleSimulationSet,\n handleSimulationCleared,\n };\n});\n","<!--\n SimulatorPage.vue - Error Simulation Controls Page\n\n What: Provides controls for simulating various API error conditions\n How: Manages 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, onMounted, onUnmounted, ref } from 'vue';\nimport { useWebSocket } from '../composables/useWebSocket';\nimport { useRegistryStore } from '../stores/registry';\nimport type { ActiveSimulation } from '../stores/simulation';\nimport { useSimulationStore } from '../stores/simulation';\n\n// ==========================================================================\n// Types\n// ==========================================================================\n\ninterface SimulationActiveEvent {\n simulations: ActiveSimulation[];\n}\n\ninterface SimulationPathEvent {\n path: string;\n}\n\ninterface SimulationsClearedEvent {\n count: number;\n}\n\ninterface SimulationSetEvent {\n path: string;\n success: boolean;\n}\n\ninterface SimulationClearedEvent {\n path: string;\n success: boolean;\n}\n\n// ==========================================================================\n// Composables\n// ==========================================================================\n\nconst simulationStore = useSimulationStore();\nconst registryStore = useRegistryStore();\nconst { send, on } = useWebSocket();\n\n// ==========================================================================\n// State\n// ==========================================================================\n\n/** Path input for new simulation */\nconst newSimulationPath = ref('');\n\n/** Method input for new simulation */\nconst newSimulationMethod = ref('GET');\n\n/** Selected preset ID */\nconst selectedPresetId = ref<string | null>(null);\n\n/** Selected endpoint key (for dropdown selection) */\nconst selectedEndpointKey = ref<string | null>(null);\n\n/** Available HTTP methods */\nconst httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];\n\n/** WebSocket event unsubscribe functions (populated in onMounted) */\nlet unsubscribers: Array<() => void> = [];\n\n/** Simulations pending clear (for rollback on partial failures) */\nconst pendingClears = ref<Set<string>>(new Set());\n\n// ==========================================================================\n// Computed\n// ==========================================================================\n\n/**\n * Available endpoints for selection\n */\nconst availableEndpoints = computed(() => {\n return registryStore.endpoints.map((e) => ({\n key: e.key,\n label: `${e.method.toUpperCase()} ${e.path}`,\n method: e.method.toUpperCase(),\n path: e.path,\n operationId: e.operationId,\n }));\n});\n\n/**\n * Check if we can add a new simulation\n */\nconst canAddSimulation = computed(() => {\n const hasPath = newSimulationPath.value.trim() !== '';\n const hasPreset = selectedPresetId.value !== null;\n return hasPath && hasPreset;\n});\n\n/**\n * Active simulations for display\n */\nconst activeSimulations = computed(() => {\n return simulationStore.activeSimulations.map((sim) => {\n const preset = sim.presetId ? simulationStore.getPreset(sim.presetId) : null;\n return {\n ...sim,\n preset,\n };\n });\n});\n\n/**\n * Simulation count\n */\nconst simulationCount = computed(() => simulationStore.count);\n\n// ==========================================================================\n// Methods\n// ==========================================================================\n\n/**\n * Add a new simulation\n */\nfunction addSimulation(): void {\n if (!canAddSimulation.value || !selectedPresetId.value) return;\n\n const preset = simulationStore.getPreset(selectedPresetId.value);\n if (!preset) return;\n\n // Validate path input\n const trimmedPath = newSimulationPath.value.trim();\n\n // Path must start with /\n if (!trimmedPath.startsWith('/')) {\n simulationStore.setError('Path must start with /');\n return;\n }\n\n // Path must not be too long (reasonable limit)\n if (trimmedPath.length > 500) {\n simulationStore.setError('Path is too long (max 500 characters)');\n return;\n }\n\n // Path should only contain valid URL path characters\n if (!/^\\/[\\w\\-/{}:.]*$/.test(trimmedPath)) {\n simulationStore.setError('Path contains invalid characters');\n return;\n }\n\n // Combine method and path to create endpoint key (e.g., \"get:/pets\")\n const pathWithMethod = `${newSimulationMethod.value.toLowerCase()}:${trimmedPath}`;\n const simulation = simulationStore.createSimulationFromPreset(\n pathWithMethod,\n selectedPresetId.value,\n undefined,\n );\n\n if (!simulation) return;\n\n // Optimistically add to local state (store previous state for rollback)\n simulationStore.addSimulationLocal(simulation, true);\n simulationStore.setLoading(true);\n\n // Send command to server\n send({\n type: 'set:simulation',\n data: {\n path: simulation.path,\n status: simulation.status,\n delay: simulation.delay,\n body: simulation.body,\n },\n });\n\n // Reset form\n newSimulationPath.value = '';\n selectedPresetId.value = null;\n selectedEndpointKey.value = null;\n}\n\n/**\n * Remove an active simulation\n */\nfunction removeSimulation(path: string): void {\n // Optimistically remove from local state (store previous state for rollback)\n simulationStore.removeSimulationLocal(path, true);\n simulationStore.setLoading(true);\n\n // Send command to server\n send({\n type: 'clear:simulation',\n data: { path },\n });\n}\n\n/**\n * Clear all simulations\n */\nfunction clearAllSimulations(): void {\n if (simulationCount.value === 0) return;\n\n // Mark each simulation as pending clear and store for rollback\n for (const simulation of simulationStore.activeSimulations) {\n pendingClears.value.add(simulation.path);\n\n // Store previous state for rollback\n simulationStore.removeSimulationLocal(simulation.path, true);\n\n // Send clear command to server\n send({\n type: 'clear:simulation',\n data: { path: simulation.path },\n });\n }\n\n simulationStore.setLoading(true);\n\n // Note: Individual simulations will be removed from local state\n // only when we receive the corresponding \"simulation:cleared\" event\n // with success: true. Failed clears will be rolled back automatically.\n}\n\n/**\n * Handle endpoint selection from dropdown\n */\nfunction handleEndpointSelect(): void {\n if (!selectedEndpointKey.value) return;\n\n const endpoint = registryStore.endpoints.find((e) => e.key === selectedEndpointKey.value);\n if (!endpoint) return;\n\n newSimulationMethod.value = endpoint.method.toUpperCase();\n newSimulationPath.value = endpoint.path;\n}\n\n/**\n * Handle manual path/method input\n */\nfunction handleManualInput(): void {\n // Clear endpoint selection when user types manually\n selectedEndpointKey.value = null;\n}\n\n// ==========================================================================\n// Lifecycle\n// ==========================================================================\n\nonMounted(() => {\n // Subscribe to simulation events and collect unsubscribe functions\n unsubscribers = [\n on('simulation:active', (data: SimulationActiveEvent) => {\n simulationStore.setSimulations(data.simulations);\n }),\n\n on('simulation:added', (data: SimulationPathEvent) => {\n simulationStore.handleSimulationAdded(data);\n }),\n\n on('simulation:removed', (data: SimulationPathEvent) => {\n simulationStore.handleSimulationRemoved(data);\n }),\n\n on('simulations:cleared', (data: SimulationsClearedEvent) => {\n simulationStore.handleSimulationsCleared(data);\n }),\n\n on('simulation:set', (data: SimulationSetEvent) => {\n simulationStore.handleSimulationSet(data);\n }),\n\n on('simulation:cleared', (data: SimulationClearedEvent) => {\n // Remove from pending clears if it was part of clearAll\n if (pendingClears.value.has(data.path)) {\n pendingClears.value.delete(data.path);\n }\n\n // Delegate to store handler (handles success/failure and rollback)\n simulationStore.handleSimulationCleared(data);\n }),\n ];\n\n // Request current simulations from server\n send({ type: 'get:registry' });\n});\n\n// Cleanup on unmount to prevent memory leaks\nonUnmounted(() => {\n for (const unsub of unsubscribers) {\n unsub();\n }\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 <!-- Endpoint Selector (optional) -->\n <div v-if=\"availableEndpoints.length > 0\" class=\"simulator-form__row\">\n <label class=\"simulator-form__label\">Select Endpoint (optional):</label>\n <select\n v-model=\"selectedEndpointKey\"\n class=\"input\"\n @change=\"handleEndpointSelect\"\n >\n <option :value=\"null\">Manual entry...</option>\n <option\n v-for=\"endpoint in availableEndpoints\"\n :key=\"endpoint.key\"\n :value=\"endpoint.key\"\n >\n {{ endpoint.label }}\n </option>\n </select>\n </div>\n\n <!-- Method and Path -->\n <div class=\"simulator-form__row\">\n <select\n v-model=\"newSimulationMethod\"\n class=\"simulator-form__method input\"\n @change=\"handleManualInput\"\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\"\n @input=\"handleManualInput\"\n />\n </div>\n\n <!-- Preset Selection -->\n <div class=\"simulator-presets\">\n <button\n v-for=\"preset in simulationStore.presets\"\n :key=\"preset.id\"\n :class=\"[\n 'simulator-preset',\n { 'simulator-preset--selected': selectedPresetId === preset.id },\n `simulator-preset--${preset.type}`,\n ]\"\n :title=\"preset.description\"\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 || simulationStore.isLoading\"\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 ({{ simulationCount }})\n </span>\n <button\n v-if=\"simulationCount > 0\"\n class=\"btn btn--ghost\"\n :disabled=\"simulationStore.isLoading\"\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.path\"\n class=\"simulator-simulation card\"\n >\n <div class=\"simulator-simulation__info\">\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 'text-warning': simulation.preset?.type === 'delay',\n 'text-error': simulation.preset?.type === 'error',\n 'text-muted': simulation.preset?.type === 'empty',\n }\"\n />\n <span>\n {{ simulation.preset?.label || `HTTP ${simulation.status}` }}\n </span>\n <span v-if=\"simulation.delay\" class=\"text-muted\">\n ({{ simulation.delay }}ms)\n </span>\n </div>\n <button\n class=\"btn btn--ghost btn--icon\"\n title=\"Remove simulation\"\n :disabled=\"simulationStore.isLoading\"\n @click=\"removeSimulation(simulation.path)\"\n >\n <Trash2 :size=\"14\" />\n </button>\n </div>\n\n <!-- Empty State -->\n <div v-if=\"simulationCount === 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 flex-direction: column;\n gap: var(--devtools-space-xs);\n}\n\n.simulator-form__row:has(.simulator-form__method) {\n flex-direction: row;\n gap: var(--devtools-space-sm);\n}\n\n.simulator-form__label {\n font-size: var(--font-size-0);\n font-weight: var(--font-weight-5);\n color: var(--devtools-text);\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--empty {\n color: var(--devtools-text-muted);\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\n.text-muted {\n color: var(--devtools-text-muted);\n}\n</style>\n"],"names":["Plus","createLucideIcon","SIMULATION_PRESETS","useSimulationStore","defineStore","simulations","ref","previousSimulations","isLoading","error","activeSimulations","computed","count","presets","hasActiveSimulations","simulationsByType","grouped","simulation","type","getSimulationType","preset","p","setSimulations","newSimulations","addSimulationLocal","storeForRollback","previous","removeSimulationLocal","path","clearSimulationsLocal","getSimulation","hasSimulation","getPreset","id","createSimulationFromPreset","presetId","operationId","setLoading","loading","setError","errorMessage","clearError","rollbackSimulation","handleSimulationAdded","data","handleSimulationRemoved","handleSimulationsCleared","handleSimulationSet","handleSimulationCleared","simulationStore","registryStore","useRegistryStore","send","on","useWebSocket","newSimulationPath","newSimulationMethod","selectedPresetId","selectedEndpointKey","httpMethods","unsubscribers","pendingClears","availableEndpoints","e","canAddSimulation","hasPath","hasPreset","sim","simulationCount","addSimulation","trimmedPath","pathWithMethod","removeSimulation","clearAllSimulations","handleEndpointSelect","endpoint","handleManualInput","onMounted","onUnmounted","unsub","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_hoisted_3","_createVNode","_unref","Zap","_cache","_hoisted_4","_hoisted_5","$event","_Fragment","_renderList","_toDisplayString","_hoisted_6","_hoisted_7","method","_hoisted_8","_hoisted_9","_normalizeClass","_createBlock","_resolveDynamicComponent","Clock","AlertTriangle","_hoisted_11","_hoisted_13","_hoisted_14","_hoisted_15","Trash2","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_23"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ref as T, computed as v, defineComponent as ue, createElementBlock as u, openBlock as o, createVNode as x, createElementVNode as e, unref as a, normalizeClass as R, toDisplayString as c, createCommentVNode as k, createTextVNode as A, createBlock as $, resolveDynamicComponent as S, withDirectives as V, Fragment as M, renderList as j, vShow as W, withModifiers as ce, onMounted as pe, onUnmounted as he, watch as ge } from "vue";
|
|
2
|
-
import { g as _e, C as N, a as Z, S as me, F as be, b as xe } from "./format-
|
|
3
|
-
import { c as fe, C as P, Z as ve, _ as de, u as ke } from "./main-
|
|
4
|
-
import { C as oe } from "./check-
|
|
5
|
-
import { T as qe } from "./triangle-alert-
|
|
2
|
+
import { g as _e, C as N, a as Z, S as me, F as be, b as xe } from "./format-xvYNYz8d.js";
|
|
3
|
+
import { c as fe, C as P, Z as ve, _ as de, u as ke } from "./main-C-2gO_cM.js";
|
|
4
|
+
import { C as oe } from "./check-CZ-YsL8n.js";
|
|
5
|
+
import { T as qe } from "./triangle-alert-C8PD5_Zo.js";
|
|
6
6
|
import { defineStore as Ce } from "pinia";
|
|
7
|
-
import { X as ye } from "./x-
|
|
8
|
-
import { T as $e } from "./trash-2-
|
|
7
|
+
import { X as ye } from "./x-Boe7tiDp.js";
|
|
8
|
+
import { T as $e } from "./trash-2-BiCAm7lq.js";
|
|
9
9
|
const Se = fe("circle-check-big", [
|
|
10
10
|
["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
|
|
11
11
|
["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
|
|
@@ -846,4 +846,4 @@ const re = fe("copy", [
|
|
|
846
846
|
export {
|
|
847
847
|
xs as default
|
|
848
848
|
};
|
|
849
|
-
//# sourceMappingURL=TimelinePage-
|
|
849
|
+
//# sourceMappingURL=TimelinePage-DdznQBTd.js.map
|