@websublime/vite-plugin-open-api-server 0.24.0-next.13 → 0.24.0-next.14

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/index.js CHANGED
@@ -590,7 +590,7 @@ function configureMultiProxy(vite, instances, port) {
590
590
 
591
591
  // package.json
592
592
  var package_default = {
593
- version: "0.24.0-next.12"};
593
+ version: "0.24.0-next.13"};
594
594
 
595
595
  // src/multi-internal-api.ts
596
596
  var PACKAGE_VERSION = package_default.version;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/banner.ts","../src/utils.ts","../src/handlers.ts","../src/seeds.ts","../src/hot-reload.ts","../src/multi-proxy.ts","../package.json","../src/multi-internal-api.ts","../src/multi-command.ts","../src/multi-ws.ts","../src/types.ts","../src/proxy-path.ts","../src/spec-id.ts","../src/orchestrator.ts","../src/plugin.ts","../src/devtools.ts"],"names":["path","fg","PACKAGE_VERSION","id","executeSeeds","existsSync","Hono","require"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Startup Banner\n *\n * What: Prints a colorful startup banner with server information\n * How: Uses picocolors for ANSI color output\n * Why: Provides clear feedback about server status and configuration\n *\n * @module banner\n */\n\nimport type { EndpointRegistry } from '@websublime/vite-plugin-open-api-core';\nimport pc from 'picocolors';\nimport type { ResolvedOptions } from './types.js';\n\n/**\n * Banner configuration\n */\nexport interface BannerInfo {\n /** Server port */\n port: number;\n /** Proxy path in Vite */\n proxyPath: string;\n /** OpenAPI spec title */\n title: string;\n /** OpenAPI spec version */\n version: string;\n /** Number of endpoints */\n endpointCount: number;\n /** Number of loaded handlers */\n handlerCount: number;\n /** Number of loaded seeds */\n seedCount: number;\n /** DevTools enabled */\n devtools: boolean;\n}\n\n/**\n * Print the startup banner\n *\n * @param info - Banner information\n * @param options - Resolved plugin options\n */\nexport function printBanner(info: BannerInfo, options: ResolvedOptions): void {\n if (options.silent) {\n return;\n }\n\n const logger = options.logger ?? console;\n const log = (msg: string) => logger.info(msg);\n\n // Box drawing characters\n const BOX = {\n topLeft: '╭',\n topRight: '╮',\n bottomLeft: '╰',\n bottomRight: '╯',\n horizontal: '─',\n vertical: '│',\n };\n\n const width = 56;\n const horizontalLine = BOX.horizontal.repeat(width - 2);\n\n log('');\n log(pc.cyan(`${BOX.topLeft}${horizontalLine}${BOX.topRight}`));\n log(\n pc.cyan(BOX.vertical) + centerText('🚀 OpenAPI Mock Server', width - 2) + pc.cyan(BOX.vertical),\n );\n log(pc.cyan(`${BOX.bottomLeft}${horizontalLine}${BOX.bottomRight}`));\n log('');\n\n // API Info\n log(\n ` ${pc.bold(pc.white('API:'))} ${pc.green(info.title)} ${pc.dim(`v${info.version}`)}`,\n );\n log(` ${pc.bold(pc.white('Server:'))} ${pc.cyan(`http://localhost:${info.port}`)}`);\n log(\n ` ${pc.bold(pc.white('Proxy:'))} ${pc.yellow(info.proxyPath)} ${pc.dim('→')} ${pc.dim(`localhost:${info.port}`)}`,\n );\n log('');\n\n // Stats\n const stats = [\n { label: 'Endpoints', value: info.endpointCount, color: pc.blue },\n { label: 'Handlers', value: info.handlerCount, color: pc.green },\n { label: 'Seeds', value: info.seedCount, color: pc.magenta },\n ];\n\n const statsLine = stats\n .map((s) => `${pc.dim(`${s.label}:`)} ${s.color(String(s.value))}`)\n .join(pc.dim(' │ '));\n log(` ${statsLine}`);\n log('');\n\n // DevTools\n if (info.devtools) {\n log(\n ` ${pc.bold(pc.white('DevTools:'))} ${pc.cyan(`http://localhost:${info.port}/_devtools`)}`,\n );\n log(` ${pc.bold(pc.white('API Info:'))} ${pc.cyan(`http://localhost:${info.port}/_api`)}`);\n log('');\n }\n\n // Footer\n log(pc.dim(' Press Ctrl+C to stop the server'));\n log('');\n}\n\n/**\n * Center text within a given width\n *\n * @param text - Text to center\n * @param width - Total width\n * @returns Centered text with padding\n */\n// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes require control characters\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[0-9;]*m/g;\n\nfunction centerText(text: string, width: number): string {\n // Account for ANSI codes - get visible length\n const visibleLength = text.replace(ANSI_ESCAPE_REGEX, '').length;\n const padding = Math.max(0, width - visibleLength);\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + text + ' '.repeat(rightPad);\n}\n\n/**\n * Extract banner info from server registry and document\n *\n * Note: This is the v0.x single-spec banner. It will be redesigned for\n * multi-spec display in Task 1.7 (vite-qq9.7). Currently only shows the\n * first spec's information.\n *\n * @param registry - Endpoint registry\n * @param document - OpenAPI document\n * @param handlerCount - Number of loaded handlers\n * @param seedCount - Number of loaded seed schemas\n * @param options - Resolved options (must contain at least one spec)\n * @returns Banner info\n */\nexport function extractBannerInfo(\n registry: EndpointRegistry,\n document: { info: { title: string; version: string } },\n handlerCount: number,\n seedCount: number,\n options: ResolvedOptions,\n): BannerInfo {\n return {\n port: options.port,\n proxyPath: options.specs[0]?.proxyPath || '(pending resolution)',\n title: document.info.title,\n version: document.info.version,\n endpointCount: registry.endpoints.size,\n handlerCount,\n seedCount,\n devtools: options.devtools,\n };\n}\n\n/**\n * Print a hot reload notification\n *\n * @param type - Type of reload ('handlers' | 'seeds')\n * @param count - Number of reloaded items\n * @param options - Resolved options\n */\nexport function printReloadNotification(\n type: 'handlers' | 'seeds',\n count: number,\n options: ResolvedOptions,\n): void {\n if (options.silent) {\n return;\n }\n\n const logger = options.logger ?? console;\n const icon = type === 'handlers' ? '🔄' : '🌱';\n const label = type === 'handlers' ? 'Handlers' : 'Seeds';\n const color = type === 'handlers' ? pc.green : pc.magenta;\n\n logger.info(` ${icon} ${color(label)} reloaded: ${pc.bold(String(count))} ${type}`);\n}\n\n/**\n * Print an error message\n *\n * @param message - Error message\n * @param error - Optional error object\n * @param options - Resolved options\n */\nexport function printError(message: string, error: unknown, options: ResolvedOptions): void {\n const logger = options.logger ?? console;\n logger.error(`${pc.red('✖')} ${pc.bold(pc.red('Error:'))} ${message}`);\n if (error instanceof Error) {\n logger.error(pc.dim(` ${error.message}`));\n }\n}\n\n/**\n * Print a warning message\n *\n * @param message - Warning message\n * @param options - Resolved options\n */\nexport function printWarning(message: string, options: ResolvedOptions): void {\n if (options.silent) {\n return;\n }\n\n const logger = options.logger ?? console;\n logger.warn(`${pc.yellow('⚠')} ${pc.yellow('Warning:')} ${message}`);\n}\n","/**\n * Filesystem Utilities\n *\n * What: Shared utility functions for filesystem operations\n * How: Uses Node.js fs/promises module with error handling\n * Why: Provides reusable utilities for handler and seed loading\n *\n * @module utils\n */\n\n/**\n * Check if a directory exists\n *\n * @param dirPath - Path to check\n * @returns Promise resolving to true if directory exists\n */\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n const fs = await import('node:fs/promises');\n const stats = await fs.stat(dirPath);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n","/**\n * Handler Loading\n *\n * What: Loads handler files from a directory using glob patterns\n * How: Uses Vite's ssrLoadModule to transform and load TypeScript files\n * Why: Enables users to define custom handlers for operationIds in TypeScript\n *\n * @module handlers\n */\n\nimport path from 'node:path';\nimport type { HandlerDefinition, HandlerFn, Logger } from '@websublime/vite-plugin-open-api-core';\nimport fg from 'fast-glob';\nimport type { ViteDevServer } from 'vite';\nimport { directoryExists } from './utils.js';\n\n/**\n * Result of loading handlers\n */\nexport interface LoadHandlersResult {\n /** Map of operationId to handler function */\n handlers: Map<string, HandlerFn>;\n /** Number of handler files loaded */\n fileCount: number;\n /** List of loaded file paths (relative) */\n files: string[];\n}\n\n/**\n * Load handlers from a directory\n *\n * Searches for handler files matching the pattern `*.handlers.{ts,js,mjs}`\n * in the specified directory. Each file should export an object with\n * operationId keys and handler functions as values.\n *\n * Uses Vite's ssrLoadModule to transform TypeScript files on-the-fly.\n *\n * @example\n * ```typescript\n * // mocks/handlers/pets.handlers.ts\n * import { defineHandlers } from '@websublime/vite-plugin-open-api-core';\n *\n * export default defineHandlers({\n * getPetById: async ({ req, store }) => {\n * const pet = store.get('Pet', req.params.petId);\n * return pet ?? { status: 404, data: { message: 'Pet not found' } };\n * },\n * });\n * ```\n *\n * @param handlersDir - Directory to search for handler files\n * @param viteServer - Vite dev server instance for ssrLoadModule\n * @param cwd - Current working directory (defaults to process.cwd())\n * @param logger - Optional logger for warnings/errors\n * @returns Promise resolving to loaded handlers\n */\nexport async function loadHandlers(\n handlersDir: string,\n viteServer: ViteDevServer,\n cwd: string = process.cwd(),\n logger: Logger = console,\n): Promise<LoadHandlersResult> {\n const handlers = new Map<string, HandlerFn>();\n const absoluteDir = path.resolve(cwd, handlersDir);\n\n // Check if directory exists\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return {\n handlers,\n fileCount: 0,\n files: [],\n };\n }\n\n // Find handler files (supports TypeScript via Vite's transform)\n const pattern = '**/*.handlers.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: false,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n // Load each file using Vite's ssrLoadModule\n for (const file of files) {\n const absolutePath = path.join(absoluteDir, file);\n const fileHandlers = await loadHandlerFile(absolutePath, viteServer, logger);\n\n // Merge handlers\n for (const [operationId, handler] of Object.entries(fileHandlers)) {\n if (handlers.has(operationId)) {\n logger.warn(\n `[vite-plugin-open-api-server] Duplicate handler for operationId \"${operationId}\" in ${file}. Using last definition.`,\n );\n }\n handlers.set(operationId, handler);\n }\n }\n\n return {\n handlers,\n fileCount: files.length,\n files,\n };\n}\n\n/**\n * Load a single handler file using Vite's ssrLoadModule\n *\n * @param filePath - Absolute path to the handler file\n * @param viteServer - Vite dev server instance\n * @param logger - Logger for warnings/errors\n * @returns Promise resolving to handler definition object\n */\nasync function loadHandlerFile(\n filePath: string,\n viteServer: ViteDevServer,\n logger: Logger,\n): Promise<HandlerDefinition> {\n try {\n // Invalidate module cache for hot reload\n const moduleNode = viteServer.moduleGraph.getModuleById(filePath);\n if (moduleNode) {\n viteServer.moduleGraph.invalidateModule(moduleNode);\n }\n\n // Use Vite's ssrLoadModule to transform and load the file\n // This handles TypeScript, ESM, and other transforms automatically\n const module = await viteServer.ssrLoadModule(filePath);\n\n // Support both default export and named export\n const handlers = module.default ?? module.handlers ?? module;\n\n // Validate handlers object\n if (!handlers || typeof handlers !== 'object') {\n logger.warn(\n `[vite-plugin-open-api-server] Invalid handler file ${filePath}: expected object export`,\n );\n return {};\n }\n\n // Filter to only handler functions\n const validHandlers: HandlerDefinition = {};\n for (const [key, value] of Object.entries(handlers)) {\n if (typeof value === 'function') {\n validHandlers[key] = value as HandlerFn;\n }\n }\n\n return validHandlers;\n } catch (error) {\n logger.error(\n `[vite-plugin-open-api-server] Failed to load handler file ${filePath}:`,\n error instanceof Error ? error.message : error,\n );\n return {};\n }\n}\n\n/**\n * Get list of handler files in a directory\n *\n * Useful for file watching setup.\n *\n * @param handlersDir - Directory to search\n * @param cwd - Current working directory\n * @returns Promise resolving to list of absolute file paths\n */\nexport async function getHandlerFiles(\n handlersDir: string,\n cwd: string = process.cwd(),\n): Promise<string[]> {\n const absoluteDir = path.resolve(cwd, handlersDir);\n\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return [];\n }\n\n const pattern = '**/*.handlers.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: true,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n return files;\n}\n","/**\n * Seed Loading and Utilities\n *\n * What: Loads seed files from a directory and provides seed data utilities\n * How: Uses Vite's ssrLoadModule to transform and load TypeScript files\n * Why: Enables users to define seed data for schemas in TypeScript\n *\n * @module seeds\n */\n\nimport path from 'node:path';\nimport type {\n AnySeedFn,\n Logger,\n SeedDefinition,\n Store,\n} from '@websublime/vite-plugin-open-api-core';\nimport fg from 'fast-glob';\nimport type { ViteDevServer } from 'vite';\nimport { directoryExists } from './utils.js';\n\n/**\n * Result of loading seeds\n */\nexport interface LoadSeedsResult {\n /** Map of schema name to seed function */\n seeds: Map<string, AnySeedFn>;\n /** Number of seed files loaded */\n fileCount: number;\n /** List of loaded file paths (relative) */\n files: string[];\n}\n\n/**\n * Load seeds from a directory\n *\n * Searches for seed files matching the pattern `*.seeds.{ts,js,mjs}`\n * in the specified directory. Each file should export an object with\n * schema name keys and seed functions as values.\n *\n * Uses Vite's ssrLoadModule to transform TypeScript files on-the-fly.\n *\n * @example\n * ```typescript\n * // mocks/seeds/pets.seeds.ts\n * import { defineSeeds } from '@websublime/vite-plugin-open-api-core';\n *\n * export default defineSeeds({\n * Pet: ({ seed, faker }) => {\n * return seed.count(10, () => ({\n * id: faker.number.int({ min: 1, max: 1000 }),\n * name: faker.animal.dog(),\n * status: faker.helpers.arrayElement(['available', 'pending', 'sold']),\n * }));\n * },\n * });\n * ```\n *\n * @param seedsDir - Directory to search for seed files\n * @param viteServer - Vite dev server instance for ssrLoadModule\n * @param cwd - Current working directory (defaults to process.cwd())\n * @param logger - Optional logger for warnings/errors\n * @returns Promise resolving to loaded seeds\n */\nexport async function loadSeeds(\n seedsDir: string,\n viteServer: ViteDevServer,\n cwd: string = process.cwd(),\n logger: Logger = console,\n): Promise<LoadSeedsResult> {\n const seeds = new Map<string, AnySeedFn>();\n const absoluteDir = path.resolve(cwd, seedsDir);\n\n // Check if directory exists\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return {\n seeds,\n fileCount: 0,\n files: [],\n };\n }\n\n // Find seed files (supports TypeScript via Vite's transform)\n const pattern = '**/*.seeds.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: false,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n // Load each file using Vite's ssrLoadModule\n for (const file of files) {\n const absolutePath = path.join(absoluteDir, file);\n const fileSeeds = await loadSeedFile(absolutePath, viteServer, logger);\n\n // Merge seeds\n for (const [schemaName, seedFn] of Object.entries(fileSeeds)) {\n if (seeds.has(schemaName)) {\n logger.warn(\n `[vite-plugin-open-api-server] Duplicate seed for schema \"${schemaName}\" in ${file}. Using last definition.`,\n );\n }\n seeds.set(schemaName, seedFn);\n }\n }\n\n return {\n seeds,\n fileCount: files.length,\n files,\n };\n}\n\n/**\n * Load a single seed file using Vite's ssrLoadModule\n *\n * @param filePath - Absolute path to the seed file\n * @param viteServer - Vite dev server instance\n * @param logger - Logger for warnings/errors\n * @returns Promise resolving to seed definition object\n */\nasync function loadSeedFile(\n filePath: string,\n viteServer: ViteDevServer,\n logger: Logger,\n): Promise<SeedDefinition> {\n try {\n // Invalidate module cache for hot reload\n const moduleNode = viteServer.moduleGraph.getModuleById(filePath);\n if (moduleNode) {\n viteServer.moduleGraph.invalidateModule(moduleNode);\n }\n\n // Use Vite's ssrLoadModule to transform and load the file\n // This handles TypeScript, ESM, and other transforms automatically\n const module = await viteServer.ssrLoadModule(filePath);\n\n // Support both default export and named export\n const seeds = module.default ?? module.seeds ?? module;\n\n // Validate seeds object\n if (!seeds || typeof seeds !== 'object') {\n logger.warn(\n `[vite-plugin-open-api-server] Invalid seed file ${filePath}: expected object export`,\n );\n return {};\n }\n\n // Filter to only seed functions\n const validSeeds: SeedDefinition = {};\n for (const [key, value] of Object.entries(seeds)) {\n if (typeof value === 'function') {\n validSeeds[key] = value as AnySeedFn;\n }\n }\n\n return validSeeds;\n } catch (error) {\n logger.error(\n `[vite-plugin-open-api-server] Failed to load seed file ${filePath}:`,\n error instanceof Error ? error.message : error,\n );\n return {};\n }\n}\n\n/**\n * Get list of seed files in a directory\n *\n * Useful for file watching setup.\n *\n * @param seedsDir - Directory to search\n * @param cwd - Current working directory\n * @returns Promise resolving to list of absolute file paths\n */\nexport async function getSeedFiles(\n seedsDir: string,\n cwd: string = process.cwd(),\n): Promise<string[]> {\n const absoluteDir = path.resolve(cwd, seedsDir);\n\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return [];\n }\n\n const pattern = '**/*.seeds.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: true,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n return files;\n}\n\n/**\n * Build a seed data Map from the store's current contents.\n *\n * After `executeSeeds()` populates the store, this function reads back\n * the materialized data so it can be passed to `server.updateSeeds()`.\n * The route builder's seed map needs static `Map<string, unknown[]>`\n * data (not seed functions), which is exactly what the store contains\n * after execution.\n *\n * @param store - Store populated by executeSeeds()\n * @returns Map of schema name to array of items\n */\nexport function buildSeedMapFromStore(store: Store): Map<string, unknown[]> {\n const seedMap = new Map<string, unknown[]>();\n for (const schemaName of store.getSchemas()) {\n const items = store.list(schemaName);\n if (items.length > 0) {\n seedMap.set(schemaName, items);\n }\n }\n return seedMap;\n}\n","/**\n * Hot Reload\n *\n * What: File watcher for hot reloading handlers and seeds with per-spec isolation\n * How: Uses chokidar to watch for file changes, one watcher per spec instance\n * Why: Enables rapid development iteration without server restart; per-spec\n * isolation ensures handler/seed changes in one spec don't affect others\n *\n * @module hot-reload\n */\n\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { executeSeeds, type Logger } from '@websublime/vite-plugin-open-api-core';\nimport type { FSWatcher } from 'chokidar';\nimport type { ViteDevServer } from 'vite';\nimport { printError, printReloadNotification } from './banner.js';\nimport { loadHandlers } from './handlers.js';\nimport type { SpecInstance } from './orchestrator.js';\nimport { buildSeedMapFromStore, loadSeeds } from './seeds.js';\nimport type { ResolvedOptions } from './types.js';\n\n// Segment-boundary patterns: match \"node_modules\" or \"dist\" as a directory\n// segment, not as a substring (avoids false positives like \"distribution/\").\nconst nodeModulesRe = /(^|[\\\\/])node_modules([\\\\/]|$)/;\nconst distRe = /(^|[\\\\/])dist([\\\\/]|$)/;\n\n/**\n * File watcher configuration\n */\nexport interface FileWatcherOptions {\n /** Directory containing handler files */\n handlersDir?: string;\n /** Directory containing seed files */\n seedsDir?: string;\n /** Callback when a handler file changes */\n onHandlerChange?: (filePath: string) => Promise<void> | void;\n /** Callback when a seed file changes */\n onSeedChange?: (filePath: string) => Promise<void> | void;\n /** Current working directory */\n cwd?: string;\n /** Logger for error messages */\n logger?: Logger;\n}\n\n/**\n * File watcher instance\n */\nexport interface FileWatcher {\n /** Close the watcher and release resources */\n close(): Promise<void>;\n /** Check if watcher is active */\n readonly isWatching: boolean;\n /** Promise that resolves when all watchers are ready */\n readonly ready: Promise<void>;\n}\n\n/**\n * Create a file watcher for handlers and seeds\n *\n * Watches for changes to handler and seed files and invokes\n * callbacks when changes are detected. Supports add, change,\n * and unlink events.\n *\n * @example\n * ```typescript\n * const watcher = await createFileWatcher({\n * handlersDir: './mocks/handlers',\n * seedsDir: './mocks/seeds',\n * onHandlerChange: async (file) => {\n * console.log('Handler changed:', file);\n * const handlers = await loadHandlers('./mocks/handlers');\n * server.updateHandlers(handlers.handlers);\n * },\n * onSeedChange: async (file) => {\n * console.log('Seed changed:', file);\n * const seeds = await loadSeeds('./mocks/seeds');\n * // Re-execute seeds...\n * },\n * });\n *\n * // Later, clean up\n * await watcher.close();\n * ```\n *\n * @param options - Watcher configuration\n * @returns Promise resolving to file watcher instance\n */\nexport async function createFileWatcher(options: FileWatcherOptions): Promise<FileWatcher> {\n const {\n handlersDir,\n seedsDir,\n onHandlerChange,\n onSeedChange,\n cwd = process.cwd(),\n logger = console,\n } = options;\n\n // Dynamic import chokidar to avoid bundling issues\n const { watch } = await import('chokidar');\n\n const watchers: FSWatcher[] = [];\n const readyPromises: Promise<void>[] = [];\n let isWatching = true;\n\n // File extension filters — chokidar v4+/v5 removed glob support,\n // so we watch the directory and filter via the `ignored` callback.\n const handlerRe = /\\.handlers\\.(ts|js|mjs)$/;\n const seedRe = /\\.seeds\\.(ts|js|mjs)$/;\n\n /**\n * Wrapper to safely invoke async callbacks and log errors\n * Prevents unhandled promise rejections from file watcher events\n */\n const safeInvoke = (\n callback: (filePath: string) => Promise<void> | void,\n filePath: string,\n context: string,\n ): void => {\n Promise.resolve()\n .then(() => callback(filePath))\n .catch((error) => {\n logger.error(\n `[vite-plugin-open-api-server] ${context} callback error for ${filePath}:`,\n error,\n );\n });\n };\n\n /**\n * Build an `ignored` function for chokidar that accepts only files\n * matching the given pattern and skips node_modules/dist directories.\n */\n const buildIgnored = (pattern: RegExp) => {\n return (filePath: string, stats?: { isFile(): boolean }): boolean => {\n // Always ignore node_modules and dist directories\n if (nodeModulesRe.test(filePath) || distRe.test(filePath)) {\n return true;\n }\n // When stats is unavailable (chokidar's initial pass), allow\n // traversal so subdirectories are not accidentally skipped.\n if (!stats) {\n return false;\n }\n // Allow confirmed directories to be traversed so chokidar\n // descends into sub-folders even though they won't match the\n // file-extension pattern.\n if (!stats.isFile()) {\n return false;\n }\n // Ignore files that don't match the expected pattern\n return !pattern.test(filePath);\n };\n };\n\n try {\n // Watch handlers directory\n if (handlersDir && onHandlerChange) {\n const absoluteHandlersDir = path.resolve(cwd, handlersDir);\n if (!existsSync(absoluteHandlersDir)) {\n logger.warn(\n `[vite-plugin-open-api-server] Handlers directory does not exist, skipping watcher: ${absoluteHandlersDir}`,\n );\n } else {\n const handlerWatcher = watch(absoluteHandlersDir, {\n ignoreInitial: true,\n ignored: buildIgnored(handlerRe),\n persistent: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n handlerWatcher.on('add', (file) => {\n safeInvoke(onHandlerChange, file, 'Handler add');\n });\n\n handlerWatcher.on('change', (file) => {\n safeInvoke(onHandlerChange, file, 'Handler change');\n });\n\n handlerWatcher.on('unlink', (file) => {\n safeInvoke(onHandlerChange, file, 'Handler unlink');\n });\n\n handlerWatcher.on('error', (error) => {\n logger.error('[vite-plugin-open-api-server] Handler watcher error:', error);\n });\n\n // Track ready promise for this watcher\n readyPromises.push(\n new Promise<void>((resolve) => {\n handlerWatcher.on('ready', () => resolve());\n }),\n );\n\n watchers.push(handlerWatcher);\n }\n }\n\n // Watch seeds directory\n if (seedsDir && onSeedChange) {\n const absoluteSeedsDir = path.resolve(cwd, seedsDir);\n if (!existsSync(absoluteSeedsDir)) {\n logger.warn(\n `[vite-plugin-open-api-server] Seeds directory does not exist, skipping watcher: ${absoluteSeedsDir}`,\n );\n } else {\n const seedWatcher = watch(absoluteSeedsDir, {\n ignoreInitial: true,\n ignored: buildIgnored(seedRe),\n persistent: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n seedWatcher.on('add', (file) => {\n safeInvoke(onSeedChange, file, 'Seed add');\n });\n\n seedWatcher.on('change', (file) => {\n safeInvoke(onSeedChange, file, 'Seed change');\n });\n\n seedWatcher.on('unlink', (file) => {\n safeInvoke(onSeedChange, file, 'Seed unlink');\n });\n\n seedWatcher.on('error', (error) => {\n logger.error('[vite-plugin-open-api-server] Seed watcher error:', error);\n });\n\n // Track ready promise for this watcher\n readyPromises.push(\n new Promise<void>((resolve) => {\n seedWatcher.on('ready', () => resolve());\n }),\n );\n\n watchers.push(seedWatcher);\n }\n }\n } catch (error) {\n // Clean up any already-created FSWatchers before re-throwing\n await Promise.allSettled(watchers.map((w) => w.close()));\n throw error;\n }\n\n // Create combined ready promise\n const readyPromise = Promise.all(readyPromises).then(() => {});\n\n return {\n async close(): Promise<void> {\n isWatching = false;\n await Promise.allSettled(watchers.map((w) => w.close()));\n },\n get isWatching(): boolean {\n return isWatching;\n },\n get ready(): Promise<void> {\n return readyPromise;\n },\n };\n}\n\n/**\n * Debounced function with cancel support\n */\nexport interface DebouncedFunction<T extends (...args: unknown[]) => unknown> {\n (...args: Parameters<T>): void;\n /** Cancel any pending debounce timer and queued execution */\n cancel(): void;\n}\n\n/**\n * Debounce a function with async execution guard\n *\n * Useful for preventing multiple rapid reloads when\n * multiple files change at once (e.g., during save all).\n *\n * This implementation prevents overlapping async executions:\n * - If the function is already running, the call is queued\n * - When the running function completes, it executes with the latest args\n * - Multiple calls during execution are coalesced into one\n *\n * @param fn - Function to debounce (can be sync or async)\n * @param delay - Debounce delay in milliseconds\n * @returns Debounced function with cancel() method\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number,\n): DebouncedFunction<T> {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let isRunning = false;\n let pendingArgs: Parameters<T> | null = null;\n let cancelled = false;\n\n const execute = async (...args: Parameters<T>): Promise<void> => {\n if (cancelled || isRunning) {\n if (isRunning && !cancelled) {\n // Queue the latest args for execution after current run completes\n pendingArgs = args;\n }\n return;\n }\n\n isRunning = true;\n try {\n // Wrap in try-catch to handle sync throws, then await for async rejections\n // This prevents both sync errors and async rejections from propagating\n try {\n await fn(...args);\n } catch {\n // Silently catch errors - the caller is responsible for error handling\n // This prevents unhandled rejections from breaking the debounce chain\n }\n } finally {\n isRunning = false;\n\n // If there were calls during execution, run with the latest args\n if (pendingArgs !== null && !cancelled) {\n const nextArgs = pendingArgs;\n pendingArgs = null;\n // Use setTimeout to avoid deep recursion\n setTimeout(() => execute(...nextArgs), 0);\n }\n }\n };\n\n const debouncedFn = (...args: Parameters<T>): void => {\n if (cancelled) return;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n timeoutId = null;\n execute(...args);\n }, delay);\n };\n\n debouncedFn.cancel = (): void => {\n cancelled = true;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n pendingArgs = null;\n };\n\n return debouncedFn;\n}\n\n// =============================================================================\n// Per-Spec Hot Reload\n// =============================================================================\n\n/**\n * Create file watchers for all spec instances\n *\n * Each spec gets independent watchers for its handlers and seeds directories.\n * Changes to one spec's files only trigger reload for that spec instance.\n *\n * @param instances - All spec instances to watch\n * @param vite - Vite dev server (for ssrLoadModule / module invalidation)\n * @param cwd - Project root directory\n * @param options - Resolved plugin options\n * @returns Promise resolving to array of file watchers (one per spec)\n */\nexport async function createPerSpecFileWatchers(\n instances: SpecInstance[],\n vite: ViteDevServer,\n cwd: string,\n options: ResolvedOptions,\n): Promise<FileWatcher[]> {\n const watchers: FileWatcher[] = [];\n const allDebouncedFns: DebouncedFunction<(...args: unknown[]) => unknown>[] = [];\n\n try {\n for (const instance of instances) {\n const debouncedHandlerReload = debounce(\n () => reloadSpecHandlers(instance, vite, cwd, options),\n 100,\n );\n const debouncedSeedReload = debounce(\n () => reloadSpecSeeds(instance, vite, cwd, options),\n 100,\n );\n allDebouncedFns.push(debouncedHandlerReload, debouncedSeedReload);\n\n const innerWatcher = await createFileWatcher({\n handlersDir: instance.config.handlersDir,\n seedsDir: instance.config.seedsDir,\n cwd,\n logger: options.logger,\n onHandlerChange: debouncedHandlerReload,\n onSeedChange: debouncedSeedReload,\n });\n\n // Wrap each FileWatcher so close() also cancels its debounced timers,\n // preventing post-teardown execution of reload functions.\n watchers.push({\n async close(): Promise<void> {\n debouncedHandlerReload.cancel();\n debouncedSeedReload.cancel();\n await innerWatcher.close();\n },\n get isWatching(): boolean {\n return innerWatcher.isWatching;\n },\n get ready(): Promise<void> {\n return innerWatcher.ready;\n },\n });\n }\n } catch (error) {\n // Cancel all debounced timers before closing watchers\n for (const fn of allDebouncedFns) fn.cancel();\n await Promise.allSettled(watchers.map((w) => w.close()));\n throw error;\n }\n\n return watchers;\n}\n\n/**\n * Reload handlers for a specific spec instance\n *\n * Loads fresh handlers from disk via Vite's ssrLoadModule, updates\n * the spec's server, broadcasts a WebSocket event, and logs the result.\n *\n * @param instance - The spec instance to reload handlers for\n * @param vite - Vite dev server\n * @param cwd - Project root directory\n * @param options - Resolved plugin options\n */\nexport async function reloadSpecHandlers(\n instance: SpecInstance,\n vite: ViteDevServer,\n cwd: string,\n options: ResolvedOptions,\n): Promise<void> {\n try {\n const logger = options.logger ?? console;\n const handlersResult = await loadHandlers(instance.config.handlersDir, vite, cwd, logger);\n\n // updateHandlers() broadcasts 'handlers:updated' internally — no explicit broadcast needed.\n // In Epic 3 (Task 3.1), the broadcast wrapper will add specId automatically.\n instance.server.updateHandlers(handlersResult.handlers);\n\n printReloadNotification('handlers', handlersResult.handlers.size, options);\n } catch (error) {\n printError(`Failed to reload handlers for spec \"${instance.id}\"`, error, options);\n }\n}\n\n/**\n * Reload seeds for a specific spec instance\n *\n * Loads fresh seeds from disk, clears the spec's store, re-executes\n * seeds, and syncs the route builder's seed map via `updateSeeds()`.\n * Broadcasts a WebSocket event and logs the result.\n *\n * Note: This operation is not fully atomic — there's a brief window between\n * clearing the store and repopulating it where requests may see empty data.\n * For development tooling, this tradeoff is acceptable.\n *\n * @param instance - The spec instance to reload seeds for\n * @param vite - Vite dev server\n * @param cwd - Project root directory\n * @param options - Resolved plugin options\n */\nexport async function reloadSpecSeeds(\n instance: SpecInstance,\n vite: ViteDevServer,\n cwd: string,\n options: ResolvedOptions,\n): Promise<void> {\n try {\n // Load seeds first (before clearing) to minimize the window where store is empty.\n const logger = options.logger ?? console;\n const seedsResult = await loadSeeds(instance.config.seedsDir, vite, cwd, logger);\n\n instance.server.store.clearAll();\n\n if (seedsResult.seeds.size > 0) {\n try {\n await executeSeeds(seedsResult.seeds, instance.server.store, instance.server.document);\n } catch (execError) {\n // Store was already cleared — warn that it's now empty due to seed execution failure.\n // Sync an empty seed map so the route builder doesn't serve stale data.\n instance.server.updateSeeds(new Map());\n printError(\n `Seeds loaded but executeSeeds failed for spec \"${instance.id}\"; store is now empty`,\n execError,\n options,\n );\n return;\n }\n }\n\n // Sync the route builder's seed map from the now-populated store.\n // updateSeeds() handles: in-place map mutation, registry hasSeed flags,\n // WebSocket broadcast, and logging.\n const seedMap = buildSeedMapFromStore(instance.server.store);\n instance.server.updateSeeds(seedMap);\n\n if (seedMap.size > 0) {\n printReloadNotification('seeds', seedMap.size, options);\n }\n } catch (error) {\n printError(`Failed to reload seeds for spec \"${instance.id}\"`, error, options);\n }\n}\n","/**\n * Multi-Path Proxy Configuration\n *\n * What: Configures Vite proxy for multiple OpenAPI spec instances\n * How: Generates one proxy entry per spec with path rewriting and X-Spec-Id header,\n * plus shared service proxies for DevTools, Internal API, and WebSocket\n * Why: Enables each spec's API requests to be routed through Vite to the shared server\n *\n * @module multi-proxy\n */\n\nimport type { ProxyOptions, ViteDevServer } from 'vite';\n\nimport type { SpecInstance } from './orchestrator.js';\n\n/**\n * Shared service proxy path prefixes.\n *\n * These constants are the single source of truth for the reserved proxy paths\n * used by the DevTools iframe, internal API, and WebSocket connections.\n * Both `configureMultiProxy()` and the virtual DevTools tab module in\n * `plugin.ts` reference these to prevent divergence.\n */\nexport const DEVTOOLS_PROXY_PATH = '/_devtools';\nexport const API_PROXY_PATH = '/_api';\nexport const WS_PROXY_PATH = '/_ws';\n\n/**\n * Ensure `vite.config.server.proxy` exists and return a mutable reference.\n *\n * Returns `null` when `vite.config.server` is falsy, which can happen if\n * the function is called outside the normal Vite plugin lifecycle (e.g.,\n * a custom integration). Callers should early-return on `null`.\n *\n * @internal\n */\nfunction getProxyConfig(vite: ViteDevServer): Record<string, ProxyOptions> | null {\n if (!vite.config.server) {\n return null;\n }\n\n vite.config.server.proxy ??= {};\n return vite.config.server.proxy as Record<string, ProxyOptions>;\n}\n\n/**\n * Configure Vite proxy for multiple spec instances and shared services.\n *\n * Generates:\n * 1. **Per-spec proxy entries** — one per spec, with path rewriting (prefix\n * stripping) and an `X-Spec-Id` header so the shared Hono server can\n * route to the correct spec instance.\n * 2. **Shared service proxies** — spec-agnostic entries for `/_devtools`,\n * `/_api`, and `/_ws` that forward to the same server without path\n * rewriting or spec headers.\n *\n * Uses `startsWith`/`slice` for path rewriting instead of the regex approach\n * described in the tech spec (Section 5.7). Literal prefix matching is safer\n * because it correctly handles regex metacharacters in proxy paths (e.g.,\n * `/api.v3` matches literally, not as `/api<any>v3`).\n *\n * @param vite - Vite dev server instance\n * @param instances - Resolved spec instances from the orchestrator\n * @param port - Shared server port\n */\nexport function configureMultiProxy(\n vite: ViteDevServer,\n instances: SpecInstance[],\n port: number,\n): void {\n const proxyConfig = getProxyConfig(vite);\n if (!proxyConfig) {\n return;\n }\n\n const httpTarget = `http://localhost:${port}`;\n\n // ── Per-spec proxy entries ──────────────────────────────────────────────\n\n for (const instance of instances) {\n const prefix = instance.config.proxyPath;\n\n proxyConfig[prefix] = {\n target: httpTarget,\n changeOrigin: true,\n rewrite: (path: string) => {\n // Guard against prefix collisions: only rewrite when the path equals\n // the prefix exactly or continues with a '/' or '?' segment boundary.\n // e.g. prefix '/api' must NOT rewrite '/api2/users'.\n if (path !== prefix && !path.startsWith(`${prefix}/`) && !path.startsWith(`${prefix}?`))\n return path;\n const rest = path.slice(prefix.length);\n if (rest === '' || rest === '/') return '/';\n if (rest.startsWith('?')) return `/${rest}`;\n return rest;\n },\n headers: { 'x-spec-id': instance.id },\n };\n }\n\n // ── Shared service proxies ─────────────────────────────────────────────\n // Placed after per-spec entries so they overwrite (last-writer-wins on\n // object keys) any per-spec entry that happens to use a reserved path.\n // In practice validateUniqueProxyPaths() guards against such collisions\n // before this function is reached.\n\n proxyConfig[DEVTOOLS_PROXY_PATH] = {\n target: httpTarget,\n changeOrigin: true,\n };\n\n proxyConfig[API_PROXY_PATH] = {\n target: httpTarget,\n changeOrigin: true,\n };\n\n proxyConfig[WS_PROXY_PATH] = {\n target: `ws://localhost:${port}`,\n changeOrigin: true,\n ws: true,\n };\n}\n","{\n \"name\": \"@websublime/vite-plugin-open-api-server\",\n \"version\": \"0.24.0-next.12\",\n \"description\": \"Vite plugin for OpenAPI mock server with DevTools integration\",\n \"keywords\": [\n \"vite\",\n \"plugin\",\n \"openapi\",\n \"mock\",\n \"server\",\n \"devtools\"\n ],\n \"license\": \"MIT\",\n \"author\": \"Websublime\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"main\": \"./dist/index.js\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/websublime/vite-open-api-server.git\",\n \"directory\": \"packages/server\"\n },\n \"scripts\": {\n \"typecheck\": \"tsc --noEmit\",\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup && pnpm run copy:devtools-spa\",\n \"copy:devtools-spa\": \"node scripts/copy-devtools-spa.mjs\"\n },\n \"dependencies\": {\n \"@vue/devtools-api\": \"^8.0.6\",\n \"@websublime/vite-plugin-open-api-core\": \"workspace:*\",\n \"fast-glob\": \"^3.3.3\",\n \"chokidar\": \"^5.0.0\",\n \"picocolors\": \"^1.1.1\"\n },\n \"devDependencies\": {\n \"@hono/node-ws\": \"^1.3.0\",\n \"@scalar/openapi-types\": \"^0.5.3\",\n \"typescript\": \"^5.9.0\",\n \"vite\": \"^7.0.0\",\n \"vue\": \"^3.5.27\",\n \"@types/node\": \"^20.17.10\",\n \"hono\": \"^4.11.4\",\n \"@websublime/vite-plugin-open-api-devtools\": \"workspace:*\",\n \"tsup\": \"^8.5.0\",\n \"@hono/node-server\": \"^1.14.3\"\n },\n \"peerDependencies\": {\n \"hono\": \"^4.11.4\",\n \"@hono/node-server\": \"^1.14.0\",\n \"vite\": \"^5.0.0 || ^6.0.0 || ^7.0.0\",\n \"vue\": \"^3.0.0\",\n \"@hono/node-ws\": \"^1.3.0\"\n },\n \"peerDependenciesMeta\": {\n \"@hono/node-ws\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"private\": false,\n \"type\": \"module\",\n \"types\": \"./dist/index.d.ts\",\n \"module\": \"./dist/index.js\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n }\n}","/**\n * Multi-Spec Internal API\n *\n * What: HTTP API routes for multi-spec DevTools and management\n * How: Aggregated routes across all specs + per-spec routes via :specId param\n * Why: Enables DevTools and external tools to query/manage individual spec instances\n *\n * TODO: Task 5.4.7/5.4.8 will add integration tests for these routes\n * TODO: Export response types when DevTools client (Epic 4) consumes them\n * TODO: Write routes (POST/DELETE store, POST/DELETE simulations, DELETE timeline)\n * are deferred — mutations use WebSocket commands (task 3.2.4). Add HTTP write\n * routes if needed by external tooling.\n *\n * @module multi-internal-api\n */\n\nimport { Hono } from 'hono';\nimport packageJson from '../package.json' with { type: 'json' };\nimport type { SpecInstance } from './orchestrator.js';\n\n/** Hono environment with per-spec middleware variables */\ntype SpecEnv = { Variables: { specInstance: SpecInstance } };\n\n/**\n * Package version from package.json\n */\nconst PACKAGE_VERSION = packageJson.version;\n\n/**\n * Mount multi-spec internal API routes on the main Hono app.\n *\n * Aggregated routes:\n * GET /_api/specs - List all specs with metadata\n * GET /_api/registry - Aggregated registry across all specs\n * GET /_api/health - Aggregated health check\n *\n * Per-spec routes (resolved via middleware):\n * GET /_api/specs/:specId/registry - Registry for one spec\n * GET /_api/specs/:specId/store - List schemas for one spec\n * GET /_api/specs/:specId/store/:schema - Store data for one spec\n * GET /_api/specs/:specId/document - OpenAPI document for one spec\n * GET /_api/specs/:specId/simulations - Simulations for one spec\n * GET /_api/specs/:specId/timeline - Timeline for one spec\n *\n * @param app - Main Hono application\n * @param instances - All resolved spec instances\n */\nexport function mountMultiSpecInternalApi(app: Hono, instances: SpecInstance[]): void {\n const seen = new Set<string>();\n for (const inst of instances) {\n if (seen.has(inst.id)) {\n throw new Error(\n `[vite-plugin-open-api-server] Duplicate specId \"${inst.id}\" in instances array`,\n );\n }\n seen.add(inst.id);\n }\n const instanceMap = new Map(instances.map((i) => [i.id, i]));\n\n // ========================================================================\n // Aggregated Routes\n // ========================================================================\n\n /**\n * GET /_api/specs\n * List all spec instances with metadata\n */\n app.get('/_api/specs', (c) => {\n const specs = instances.map((i) => ({\n id: i.id,\n title: i.info.title,\n version: i.info.version,\n proxyPath: i.config.proxyPath,\n color: i.info.color,\n endpoints: i.server.registry.endpoints.size,\n schemas: i.server.store.getSchemas().length,\n simulations: i.server.simulationManager.count(),\n }));\n return c.json({ specs, count: specs.length });\n });\n\n /**\n * GET /_api/registry\n * Aggregated registry across all specs\n */\n app.get('/_api/registry', (c) => {\n const registries = instances.map((i) => ({\n specId: i.id,\n specTitle: i.info.title,\n specColor: i.info.color,\n endpoints: Array.from(i.server.registry.endpoints.entries()).map(([key, entry]) => ({\n ...entry,\n key,\n })),\n stats: i.server.registry.stats,\n }));\n\n const totalEndpoints = registries.reduce((sum, r) => sum + r.endpoints.length, 0);\n\n return c.json({\n specs: registries,\n totalEndpoints,\n totalSpecs: registries.length,\n });\n });\n\n /**\n * GET /_api/health\n * Aggregated health check with PACKAGE_VERSION\n */\n app.get('/_api/health', (c) => {\n const specs = instances.map((i) => ({\n id: i.id,\n endpoints: i.server.registry.endpoints.size,\n schemas: i.server.store.getSchemas().length,\n simulations: i.server.simulationManager.count(),\n }));\n\n return c.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n version: PACKAGE_VERSION,\n totalSpecs: instances.length,\n totalEndpoints: specs.reduce((s, i) => s + i.endpoints, 0),\n specs,\n });\n });\n\n // ========================================================================\n // Per-Spec Routes (typed sub-app with middleware)\n // ========================================================================\n\n const specApi = new Hono<SpecEnv>();\n\n /**\n * Middleware: resolve spec instance from :specId param.\n * Returns 404 for unknown specId. Sets resolved instance on context\n * for downstream route handlers.\n */\n specApi.use('/:specId/*', async (c, next) => {\n const specId = c.req.param('specId');\n const instance = instanceMap.get(specId);\n if (!instance) {\n return c.json({ error: `Unknown spec: ${specId}` }, 404);\n }\n c.set('specInstance', instance);\n await next();\n });\n\n /**\n * GET /_api/specs/:specId/registry\n * Registry for one spec\n */\n specApi.get('/:specId/registry', (c) => {\n const instance = c.get('specInstance');\n\n return c.json({\n specId: instance.id,\n endpoints: Array.from(instance.server.registry.endpoints.entries()).map(([key, entry]) => ({\n ...entry,\n key,\n })),\n stats: instance.server.registry.stats,\n });\n });\n\n /**\n * GET /_api/specs/:specId/store\n * List schemas for one spec\n */\n specApi.get('/:specId/store', (c) => {\n const instance = c.get('specInstance');\n\n const schemas = instance.server.store.getSchemas().map((schema) => ({\n name: schema,\n count: instance.server.store.getCount(schema),\n idField: instance.server.store.getIdField(schema),\n }));\n return c.json({ specId: instance.id, schemas });\n });\n\n /**\n * GET /_api/specs/:specId/store/:schema\n * Store data for one spec. Supports optional `limit` and `offset` query params.\n *\n * Default limit = min(total, 1000). Store data is typically small so most\n * requests return all items. Capped at 1000 per request in all cases.\n */\n specApi.get('/:specId/store/:schema', (c) => {\n const instance = c.get('specInstance');\n\n const schema = c.req.param('schema');\n const allItems = instance.server.store.list(schema);\n const total = allItems.length;\n\n const rawOffset = Number(c.req.query('offset'));\n const offset = Number.isFinite(rawOffset) ? Math.max(Math.floor(rawOffset), 0) : 0;\n\n const rawLimit = Number(c.req.query('limit'));\n const limit = Number.isFinite(rawLimit)\n ? Math.min(Math.max(Math.floor(rawLimit), 0), 1000)\n : Math.min(total, 1000);\n\n const items = limit === 0 ? [] : allItems.slice(offset, offset + limit);\n return c.json({\n specId: instance.id,\n schema,\n idField: instance.server.store.getIdField(schema),\n items,\n count: items.length,\n total,\n offset,\n limit,\n });\n });\n\n /**\n * GET /_api/specs/:specId/document\n * OpenAPI document for one spec\n */\n specApi.get('/:specId/document', (c) => {\n const instance = c.get('specInstance');\n return c.json(instance.server.document);\n });\n\n /**\n * GET /_api/specs/:specId/simulations\n * Simulations for one spec\n */\n specApi.get('/:specId/simulations', (c) => {\n const instance = c.get('specInstance');\n\n return c.json({\n specId: instance.id,\n simulations: instance.server.simulationManager.list(),\n count: instance.server.simulationManager.count(),\n });\n });\n\n /**\n * GET /_api/specs/:specId/timeline\n * Timeline for one spec.\n *\n * Default limit = 100 (most recent entries) because timeline can grow\n * unbounded during a dev session. Capped at 1000 per request.\n */\n specApi.get('/:specId/timeline', (c) => {\n const instance = c.get('specInstance');\n\n const parsed = Number(c.req.query('limit'));\n const limit = Number.isFinite(parsed) ? Math.min(Math.max(Math.floor(parsed), 0), 1000) : 100;\n const timeline = instance.server.getTimeline();\n const entries = limit === 0 ? [] : timeline.slice(-limit);\n return c.json({\n specId: instance.id,\n entries,\n count: entries.length,\n total: timeline.length,\n limit,\n });\n });\n\n // Mount per-spec sub-app under /_api/specs\n app.route('/_api/specs', specApi);\n}\n","/**\n * Multi-Spec Command Handler\n *\n * What: Routes WebSocket commands to the correct spec instance\n * How: Global commands aggregate across specs; spec-scoped commands delegate to instances\n * Why: Enables DevTools to interact with multiple spec instances through a single WebSocket\n *\n * @module multi-command\n */\n\nimport type {\n SpecInfo,\n WebSocketClient,\n WebSocketHub,\n} from '@websublime/vite-plugin-open-api-core';\nimport type { SpecInstance } from './orchestrator.js';\n\n/**\n * Dependencies for the multi-spec command handler\n */\nexport interface MultiCommandHandlerDeps {\n /** Shared WebSocket hub (the multi-spec hub) */\n hub: WebSocketHub;\n\n /** All spec instances */\n instances: SpecInstance[];\n\n /** Spec metadata array */\n specsInfo: SpecInfo[];\n\n /** Server version string */\n serverVersion: string;\n}\n\n/**\n * Spec-scoped command types that require a `specId` parameter\n */\nconst SPEC_SCOPED_COMMANDS = new Set([\n 'get:store',\n 'set:store',\n 'clear:store',\n 'set:simulation',\n 'clear:simulation',\n 'reseed',\n]);\n\n/** Parsed command shape from client */\ninterface ParsedCommand {\n type: string;\n data?: { specId?: string; [key: string]: unknown };\n}\n\n/**\n * Send an error response to a client\n */\nfunction sendError(\n hub: WebSocketHub,\n client: WebSocketClient,\n command: string,\n message: string,\n): void {\n // biome-ignore lint/suspicious/noExplicitAny: error event data shape compatible with ServerEvent\n hub.sendTo(client, { type: 'error', data: { command, message } } as any);\n}\n\n/**\n * Resolve a spec instance from a specId, sending an error if not found.\n * Returns the instance or undefined if invalid.\n *\n * Dual-use contract:\n * - Falsy specId → returns undefined without error. Aggregated handlers\n * (handleGetRegistry, handleGetTimeline, handleClearTimeline) rely on this\n * to iterate all specs when no specId is provided.\n * - Truthy specId not in map → sends an error to the client and returns undefined.\n * - Spec-scoped handlers (handleSpecScoped) perform their own specId-required\n * validation before calling this function.\n */\nfunction resolveInstance(\n specId: string | undefined,\n instanceMap: Map<string, SpecInstance>,\n hub: WebSocketHub,\n client: WebSocketClient,\n commandType: string,\n): SpecInstance | undefined {\n if (!specId) return undefined;\n const instance = instanceMap.get(specId);\n if (!instance) {\n sendError(hub, client, commandType, `Unknown spec: ${specId}`);\n }\n return instance;\n}\n\n/**\n * Handle get:specs — return enhanced connected event\n */\nfunction handleGetSpecs(\n hub: WebSocketHub,\n client: WebSocketClient,\n specsInfo: SpecInfo[],\n serverVersion: string,\n): void {\n // biome-ignore lint/suspicious/noExplicitAny: MultiSpecServerEvent connected data extends ServerEvent\n hub.sendTo(client, { type: 'connected', data: { serverVersion, specs: specsInfo } } as any);\n}\n\n/**\n * Handle get:registry — single spec (by specId) or all specs.\n *\n * Constructs the registry response directly (with specId) rather than\n * delegating to per-spec hubs, for consistency with other handlers.\n */\nfunction handleGetRegistry(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instances: SpecInstance[],\n instanceMap: Map<string, SpecInstance>,\n): void {\n const sendRegistry = (instance: SpecInstance, id: string) => {\n const registryEvent = {\n type: 'registry',\n data: {\n specId: id,\n endpoints: Array.from(instance.server.registry.endpoints.entries()).map(([key, entry]) => ({\n ...entry,\n key,\n })),\n stats: { ...instance.server.registry.stats },\n },\n };\n // biome-ignore lint/suspicious/noExplicitAny: registry data with specId extends ServerEvent\n hub.sendTo(client, registryEvent as any);\n };\n\n const specId = cmd.data?.specId;\n if (specId) {\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n sendRegistry(instance, specId);\n } else {\n for (const instance of instances) {\n sendRegistry(instance, instance.id);\n }\n }\n}\n\n/**\n * Handle get:timeline — single spec or all specs\n */\nfunction handleGetTimeline(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instances: SpecInstance[],\n instanceMap: Map<string, SpecInstance>,\n): void {\n const specId = cmd.data?.specId;\n const rawLimit = Number(cmd.data?.limit);\n const limit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.floor(rawLimit), 0), 1000) : 100;\n\n const sendTimeline = (instance: SpecInstance, id: string) => {\n const timeline = instance.server.getTimeline();\n const entries = limit === 0 ? [] : timeline.slice(-limit);\n const timelineEvent = {\n type: 'timeline',\n data: {\n specId: id,\n entries,\n count: entries.length,\n total: timeline.length,\n },\n };\n // biome-ignore lint/suspicious/noExplicitAny: timeline data with specId extends ServerEvent\n hub.sendTo(client, timelineEvent as any);\n };\n\n if (specId) {\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n sendTimeline(instance, specId);\n } else {\n for (const instance of instances) {\n sendTimeline(instance, instance.id);\n }\n }\n}\n\n/**\n * Handle clear:timeline — single spec or all specs\n */\nfunction handleClearTimeline(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instances: SpecInstance[],\n instanceMap: Map<string, SpecInstance>,\n): void {\n const specId = cmd.data?.specId;\n\n const clearAndNotify = (instance: SpecInstance, id: string) => {\n const count = instance.server.clearTimeline();\n // biome-ignore lint/suspicious/noExplicitAny: cleared data with specId\n hub.sendTo(client, { type: 'timeline:cleared', data: { specId: id, count } } as any);\n };\n\n if (specId) {\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n clearAndNotify(instance, specId);\n } else {\n for (const instance of instances) {\n clearAndNotify(instance, instance.id);\n }\n }\n}\n\n/**\n * Handle spec-scoped commands — delegate to the correct instance's command handler\n */\nfunction handleSpecScoped(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instanceMap: Map<string, SpecInstance>,\n): void {\n const specId = cmd.data?.specId;\n if (!specId) {\n sendError(hub, client, cmd.type, 'specId is required for this command');\n return;\n }\n\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n\n // Forward to the instance's command handler, stripping specId\n // (core command handler doesn't know about specId)\n const { specId: _, ...coreData } = cmd.data ?? {};\n const coreCommand =\n Object.keys(coreData).length > 0 ? { type: cmd.type, data: coreData } : { type: cmd.type };\n\n instance.server.wsHub.handleMessage(client, JSON.stringify(coreCommand));\n}\n\n/**\n * Create a multi-spec command handler that routes commands to the correct spec instance.\n *\n * Command routing:\n * - `get:specs` — returns enhanced connected event with all specs metadata\n * - `get:registry` — aggregates across all specs (no specId) or single spec (with specId)\n * - `get:timeline` / `clear:timeline` — global (all specs) or single spec\n * - Spec-scoped commands (`get:store`, `set:store`, `clear:store`, `set:simulation`,\n * `clear:simulation`, `reseed`) — require specId, delegate to instance's command handler\n *\n * @param deps - Dependencies for command routing\n * @returns Command handler function compatible with `hub.setCommandHandler()`\n */\nexport function createMultiSpecCommandHandler(\n deps: MultiCommandHandlerDeps,\n): (client: WebSocketClient, command: unknown) => void {\n const { hub, instances, specsInfo, serverVersion } = deps;\n const instanceMap = new Map(instances.map((i) => [i.id, i]));\n\n return (client: WebSocketClient, command: unknown) => {\n if (!command || typeof command !== 'object' || !('type' in command)) {\n return;\n }\n const cmd = command as ParsedCommand;\n if (typeof cmd.type !== 'string') {\n return;\n }\n\n switch (cmd.type) {\n case 'get:specs':\n handleGetSpecs(hub, client, specsInfo, serverVersion);\n break;\n case 'get:registry':\n handleGetRegistry(cmd, hub, client, instances, instanceMap);\n break;\n case 'get:timeline':\n handleGetTimeline(cmd, hub, client, instances, instanceMap);\n break;\n case 'clear:timeline':\n handleClearTimeline(cmd, hub, client, instances, instanceMap);\n break;\n default:\n if (SPEC_SCOPED_COMMANDS.has(cmd.type)) {\n handleSpecScoped(cmd, hub, client, instanceMap);\n } else {\n sendError(hub, client, cmd.type, `Unknown command type: ${cmd.type}`);\n }\n break;\n }\n };\n}\n","/**\n * Multi-Spec WebSocket Hub\n *\n * What: Creates a single WebSocket hub for all spec instances\n * How: Wraps the core hub with broadcast interception and enhanced connected event\n * Why: Enables spec-aware real-time communication with DevTools\n *\n * @module multi-ws\n */\n\nimport {\n createWebSocketHub,\n type SpecInfo,\n type WebSocketClient,\n type WebSocketHub,\n} from '@websublime/vite-plugin-open-api-core';\nimport packageJson from '../package.json' with { type: 'json' };\nimport { createMultiSpecCommandHandler } from './multi-command.js';\nimport type { SpecInstance } from './orchestrator.js';\n\n/**\n * Package version from package.json\n */\nconst PACKAGE_VERSION = packageJson.version;\n\n/**\n * Command types that exist only in multi-spec mode and are NOT in\n * the core hub's CLIENT_COMMAND_TYPES. These need special handling\n * because the core hub rejects unknown command types.\n */\nconst MULTI_SPEC_ONLY_COMMANDS = new Set(['get:specs']);\n\n/**\n * Create a multi-spec aware WebSocket hub.\n *\n * Strategy:\n * - Single WebSocket hub for all connections (`autoConnect: false`)\n * - `addClient()` is overridden to send an enhanced `connected` event with\n * `specs` metadata and `PACKAGE_VERSION`\n * - Each core server's `wsHub.broadcast()` is intercepted to add `specId`\n * to event data before broadcasting on the shared hub\n * - Client commands are routed to the correct spec instance via the\n * multi-spec command handler\n *\n * @param instances - All resolved spec instances\n * @param specsInfo - Spec metadata array (for the `connected` event)\n * @returns Shared WebSocket hub with multi-spec support\n */\nexport function createMultiSpecWebSocketHub(\n instances: SpecInstance[],\n specsInfo: SpecInfo[],\n): WebSocketHub {\n // autoConnect: false prevents the hub from sending its own 'connected'\n // event in addClient(). We send an enhanced version instead.\n const hub = createWebSocketHub({ autoConnect: false });\n\n // --- Override addClient to send enhanced connected event ---\n const originalAddClient = hub.addClient.bind(hub);\n hub.addClient = (ws: WebSocketClient) => {\n originalAddClient(ws);\n\n // Send multi-spec enhanced connected event\n hub.sendTo(ws, {\n type: 'connected',\n // biome-ignore lint/suspicious/noExplicitAny: MultiSpecServerEvent extends ServerEvent with specs[]\n data: { serverVersion: PACKAGE_VERSION, specs: specsInfo } as any,\n });\n };\n\n // --- Wire each core server's broadcasts to add specId ---\n for (const instance of instances) {\n instance.server.wsHub.broadcast = (event) => {\n // Add specId to the event data and broadcast on the shared hub\n // biome-ignore lint/suspicious/noExplicitAny: enriching ServerEvent with specId at runtime\n const enriched = { type: event.type, data: { ...(event as any).data, specId: instance.id } };\n // biome-ignore lint/suspicious/noExplicitAny: enriched event compatible with ServerEvent\n hub.broadcast(enriched as any);\n };\n\n // Also intercept sendTo for direct responses that go through the core hub\n instance.server.wsHub.sendTo = (client, event) => {\n // Add specId to direct responses too\n // biome-ignore lint/suspicious/noExplicitAny: enriching ServerEvent with specId at runtime\n const enriched = { type: event.type, data: { ...(event as any).data, specId: instance.id } };\n // biome-ignore lint/suspicious/noExplicitAny: enriched event compatible with ServerEvent\n return hub.sendTo(client, enriched as any);\n };\n }\n\n // --- Set up multi-spec command handler ---\n const commandHandler = createMultiSpecCommandHandler({\n hub,\n instances,\n specsInfo,\n serverVersion: PACKAGE_VERSION,\n });\n\n hub.setCommandHandler(commandHandler);\n\n // --- Override handleMessage to accept multi-spec-only commands ---\n // The core hub's handleMessage validates command types against CLIENT_COMMAND_TYPES,\n // which doesn't include multi-spec commands like 'get:specs'. We intercept these\n // before the core validation and route them directly to the command handler.\n const originalHandleMessage = hub.handleMessage.bind(hub);\n hub.handleMessage = (client: WebSocketClient, message: string | unknown) => {\n try {\n const parsed = typeof message === 'string' ? JSON.parse(message) : message;\n if (parsed && typeof parsed === 'object' && 'type' in parsed) {\n const cmd = parsed as { type: string };\n if (MULTI_SPEC_ONLY_COMMANDS.has(cmd.type)) {\n commandHandler(client, cmd as never);\n return;\n }\n }\n } catch {\n // Fall through to core handleMessage which handles parse errors\n }\n originalHandleMessage(client, message);\n };\n\n return hub;\n}\n","/**\n * Vite Plugin Types\n *\n * What: Type definitions for the OpenAPI server Vite plugin\n * How: Defines configuration options, resolved types, and validation errors\n * Why: Provides type safety and documentation for plugin consumers\n *\n * @module types\n */\n\nimport type { Logger } from '@websublime/vite-plugin-open-api-core';\n\n// =============================================================================\n// Validation Error Codes (Appendix B)\n// =============================================================================\n\n/**\n * Error codes for configuration validation errors.\n *\n * Used across Tasks 1.2–1.4 for typed error handling.\n * Matches TECHNICAL-SPECIFICATION-V2.md Appendix B.\n */\nexport type ValidationErrorCode =\n | 'SPEC_ID_MISSING'\n | 'SPEC_ID_DUPLICATE'\n | 'PROXY_PATH_MISSING'\n | 'PROXY_PATH_TOO_BROAD'\n | 'PROXY_PATH_DUPLICATE'\n | 'PROXY_PATH_OVERLAP'\n | 'PROXY_PATH_PREFIX_COLLISION'\n | 'SPEC_NOT_FOUND'\n | 'SPECS_EMPTY';\n\n/**\n * Typed validation error for configuration issues.\n *\n * Thrown by resolveOptions() and validation functions in spec-id.ts\n * and proxy-path.ts. Consumers can catch and inspect the `code` field\n * for programmatic error handling.\n *\n * @example\n * ```typescript\n * try {\n * resolveOptions({ specs: [] });\n * } catch (error) {\n * if (error instanceof ValidationError && error.code === 'SPECS_EMPTY') {\n * // handle empty specs\n * }\n * }\n * ```\n */\nexport class ValidationError extends Error {\n readonly code: ValidationErrorCode;\n\n constructor(code: ValidationErrorCode, message: string) {\n super(message);\n this.name = 'ValidationError';\n this.code = code;\n }\n}\n\n// =============================================================================\n// Shared Type Aliases\n// =============================================================================\n\n/**\n * How a proxy path was determined.\n *\n * - `'explicit'` — set directly in SpecConfig.proxyPath\n * - `'auto'` — auto-derived from the OpenAPI document's servers[0].url\n *\n * Used by both DeriveProxyPathResult and ResolvedSpecConfig to ensure\n * the two sources of this value stay in sync.\n */\nexport type ProxyPathSource = 'auto' | 'explicit';\n\n// =============================================================================\n// User-Facing Configuration Types\n// =============================================================================\n\n/**\n * Configuration for a single OpenAPI spec instance\n *\n * @example\n * ```typescript\n * const petstore: SpecConfig = {\n * spec: './openapi/petstore.yaml',\n * id: 'petstore',\n * proxyPath: '/api/v3',\n * handlersDir: './mocks/petstore/handlers',\n * seedsDir: './mocks/petstore/seeds',\n * idFields: { Pet: 'petId' },\n * };\n * ```\n */\nexport interface SpecConfig {\n /**\n * Path to OpenAPI spec file (required)\n *\n * Supports: file paths, URLs, YAML, JSON\n *\n * @example './openapi/petstore.yaml'\n * @example 'https://petstore3.swagger.io/api/v3/openapi.json'\n */\n spec: string;\n\n /**\n * Unique identifier for this spec instance\n *\n * Used for routing, DevTools grouping, logging, default directory names.\n * If omitted, auto-derived from spec's info.title (slugified).\n *\n * @example 'petstore'\n */\n id?: string;\n\n /**\n * Base path for request proxy\n *\n * If omitted, auto-derived from spec's servers[0].url.\n * Must be unique across all specs.\n *\n * @example '/api/v3'\n */\n proxyPath?: string;\n\n /**\n * Directory containing handler files for this spec\n * @default './mocks/{specId}/handlers'\n */\n handlersDir?: string;\n\n /**\n * Directory containing seed files for this spec\n * @default './mocks/{specId}/seeds'\n */\n seedsDir?: string;\n\n /**\n * ID field configuration per schema for this spec\n * @default {} (uses 'id' for all schemas)\n */\n idFields?: Record<string, string>;\n}\n\n/**\n * Plugin configuration options\n *\n * @example\n * ```typescript\n * import { openApiServer } from '@websublime/vite-plugin-open-api-server';\n *\n * export default defineConfig({\n * plugins: [\n * openApiServer({\n * specs: [\n * { spec: './openapi/petstore.yaml' },\n * { spec: './openapi/inventory.yaml', id: 'inventory' },\n * ],\n * port: 4000,\n * }),\n * ],\n * });\n * ```\n */\nexport interface OpenApiServerOptions {\n /**\n * Array of OpenAPI spec configurations (required)\n * Each entry runs as an isolated instance.\n */\n specs: SpecConfig[];\n\n /**\n * Server port — all spec instances share this port\n * @default 4000\n */\n port?: number;\n\n /**\n * Enable/disable plugin\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Maximum timeline events per spec\n * @default 500\n */\n timelineLimit?: number;\n\n /**\n * Enable DevTools integration\n * @default true\n */\n devtools?: boolean;\n\n /**\n * Enable CORS\n * @default true\n */\n cors?: boolean;\n\n /**\n * CORS origin configuration\n * @default '*'\n */\n corsOrigin?: string | string[];\n\n /**\n * Custom logger instance\n */\n logger?: Logger;\n\n /**\n * Suppress startup banner\n * @default false\n */\n silent?: boolean;\n}\n\n// =============================================================================\n// Internal Resolved Types\n// =============================================================================\n\n/**\n * Resolved spec config with all defaults applied\n *\n * Exported for advanced use cases (e.g., custom orchestrators or\n * test utilities that need to inspect resolved configuration).\n */\nexport interface ResolvedSpecConfig {\n spec: string;\n /** Empty string until orchestrator resolution; guaranteed non-empty after `createOrchestrator()` */\n id: string;\n /** Empty string until orchestrator resolution; guaranteed non-empty after `createOrchestrator()` */\n proxyPath: string;\n /**\n * How proxyPath was determined — used for banner display.\n *\n * Written back by the orchestrator after document processing.\n * Used by the startup banner to display `(auto-derived)` vs\n * `(explicit)` next to each proxy path.\n */\n proxyPathSource: ProxyPathSource;\n handlersDir: string;\n seedsDir: string;\n idFields: Record<string, string>;\n}\n\n/**\n * Resolved options with defaults applied\n *\n * Exported for advanced use cases (e.g., custom orchestrators or\n * test utilities that need to inspect resolved configuration).\n */\nexport interface ResolvedOptions {\n specs: ResolvedSpecConfig[];\n port: number;\n enabled: boolean;\n timelineLimit: number;\n devtools: boolean;\n cors: boolean;\n corsOrigin: string | string[];\n silent: boolean;\n logger?: Logger;\n}\n\n// =============================================================================\n// Option Resolution\n// =============================================================================\n\n/**\n * Validate that specs array is non-empty and each entry has a valid spec field.\n *\n * @param specs - Array of spec configurations to validate\n * @throws {ValidationError} SPECS_EMPTY if specs array is missing or empty\n * @throws {ValidationError} SPEC_NOT_FOUND if a spec entry has empty spec field\n */\nexport function validateSpecs(specs: SpecConfig[]): void {\n if (!specs || !Array.isArray(specs) || specs.length === 0) {\n throw new ValidationError(\n 'SPECS_EMPTY',\n 'specs is required and must be a non-empty array of SpecConfig',\n );\n }\n\n for (let i = 0; i < specs.length; i++) {\n const spec = specs[i];\n if (!spec || typeof spec !== 'object') {\n throw new ValidationError(\n 'SPEC_NOT_FOUND',\n `specs[${i}]: must be a SpecConfig object, got ${spec === null ? 'null' : typeof spec}`,\n );\n }\n if (!spec.spec || typeof spec.spec !== 'string' || spec.spec.trim() === '') {\n const identifier = spec.id ? ` (id: \"${spec.id}\")` : '';\n throw new ValidationError(\n 'SPEC_NOT_FOUND',\n `specs[${i}]${identifier}: spec field is required and must be a non-empty string (path or URL to OpenAPI spec)`,\n );\n }\n }\n}\n\n/**\n * Resolve options with defaults.\n *\n * Note: spec ID and proxyPath resolution requires processing the OpenAPI document\n * first, so they are resolved later in the orchestrator.\n * This function only resolves static defaults.\n *\n * @param options - User-provided options\n * @returns Resolved options with all defaults applied\n */\nexport function resolveOptions(options: OpenApiServerOptions): ResolvedOptions {\n validateSpecs(options.specs);\n\n return {\n specs: options.specs.map((s) => ({\n spec: s.spec,\n // Placeholder — populated by orchestrator after document processing\n id: s.id ?? '',\n // Placeholder — populated by orchestrator after document processing\n proxyPath: s.proxyPath ?? '',\n // Preliminary — overwritten by deriveProxyPath() during orchestration\n proxyPathSource: s.proxyPath?.trim() ? 'explicit' : 'auto',\n handlersDir: s.handlersDir ?? '',\n seedsDir: s.seedsDir ?? '',\n idFields: s.idFields ?? {},\n })),\n port: options.port ?? 4000,\n enabled: options.enabled ?? true,\n timelineLimit: options.timelineLimit ?? 500,\n devtools: options.devtools ?? true,\n cors: options.cors ?? true,\n corsOrigin: options.corsOrigin ?? '*',\n silent: options.silent ?? false,\n logger: options.logger,\n };\n}\n","/**\n * Proxy Path Auto-Detection\n *\n * What: Functions to derive and validate proxy paths for spec instances\n * How: Extracts path from explicit config or auto-derives from servers[0].url\n * Why: Each spec instance needs a unique, non-overlapping proxy path for\n * Vite proxy configuration and request routing\n *\n * @module proxy-path\n */\n\nimport type { OpenAPIV3_1 } from '@scalar/openapi-types';\n\nimport { API_PROXY_PATH, DEVTOOLS_PROXY_PATH, WS_PROXY_PATH } from './multi-proxy.js';\nimport type { ProxyPathSource } from './types.js';\nimport { ValidationError } from './types.js';\n\n/**\n * Reserved proxy path prefixes used by shared services.\n *\n * User-defined `proxyPath` values must not collide with these.\n */\nconst RESERVED_PROXY_PATHS: readonly string[] = [\n DEVTOOLS_PROXY_PATH,\n API_PROXY_PATH,\n WS_PROXY_PATH,\n];\n\n// =============================================================================\n// Result Types\n// =============================================================================\n\n/**\n * Result of proxy path derivation\n *\n * Includes the normalized path and how it was determined,\n * so the startup banner can display \"(auto-derived)\" vs \"(explicit)\".\n */\nexport interface DeriveProxyPathResult {\n /** Normalized proxy path (e.g., \"/api/v3\") */\n proxyPath: string;\n /** How the path was determined */\n proxyPathSource: ProxyPathSource;\n}\n\n// =============================================================================\n// deriveProxyPath()\n// =============================================================================\n\n/**\n * Derive the proxy path from config or OpenAPI document's servers field\n *\n * Priority:\n * 1. Explicit proxyPath from config (if non-empty after trimming)\n * 2. Path portion of servers[0].url\n *\n * Full URLs (e.g., \"https://api.example.com/api/v3\") have their path\n * extracted via the URL constructor. Relative paths (e.g., \"/api/v3\")\n * are used directly.\n *\n * @param explicitPath - proxyPath from SpecConfig (may be empty)\n * @param document - Processed OpenAPI document\n * @param specId - Spec ID for error messages\n * @returns Normalized proxy path with source indication\n * @throws {ValidationError} PROXY_PATH_MISSING if path cannot be derived\n * @throws {ValidationError} PROXY_PATH_TOO_BROAD if path resolves to \"/\" (e.g., \"/\", \".\", \"..\")\n *\n * @example\n * // Explicit path\n * deriveProxyPath('/api/v3', document, 'petstore')\n * // → { proxyPath: '/api/v3', proxyPathSource: 'explicit' }\n *\n * @example\n * // Auto-derived from servers[0].url = \"https://api.example.com/api/v3\"\n * deriveProxyPath('', document, 'petstore')\n * // → { proxyPath: '/api/v3', proxyPathSource: 'auto' }\n */\nexport function deriveProxyPath(\n explicitPath: string,\n document: OpenAPIV3_1.Document,\n specId: string,\n): DeriveProxyPathResult {\n if (explicitPath.trim()) {\n return {\n proxyPath: normalizeProxyPath(explicitPath.trim(), specId),\n proxyPathSource: 'explicit',\n };\n }\n\n const servers = document.servers;\n const serverUrl = servers?.[0]?.url?.trim();\n if (!serverUrl) {\n throw new ValidationError(\n 'PROXY_PATH_MISSING',\n `[${specId}] Cannot derive proxyPath: no servers defined in the OpenAPI document. ` +\n 'Set an explicit proxyPath in the spec configuration.',\n );\n }\n\n let path: string;\n let parsedUrl: URL | undefined;\n\n try {\n parsedUrl = new URL(serverUrl);\n } catch {\n // Not a full URL — treat as relative path\n }\n\n if (parsedUrl) {\n try {\n // Decode percent-encoded characters (e.g., URL constructor encodes\n // OpenAPI template variable braces: /{version} → /%7Bversion%7D)\n path = decodeURIComponent(parsedUrl.pathname);\n } catch {\n // Malformed percent-encoding — fall back to the raw pathname\n path = parsedUrl.pathname;\n }\n } else {\n path = serverUrl;\n }\n\n return {\n proxyPath: normalizeProxyPath(path, specId),\n proxyPathSource: 'auto',\n };\n}\n\n// =============================================================================\n// normalizeProxyPath()\n// =============================================================================\n\n/**\n * Normalize and validate a proxy path\n *\n * Rules:\n * - Strip query strings and fragments\n * - Ensure leading slash\n * - Collapse consecutive slashes\n * - Resolve dot segments (\".\" and \"..\" per RFC 3986 §5.2.4)\n * - Remove trailing slash\n * - Reject \"/\" as too broad (would capture all requests, including dot-segments that resolve to \"/\")\n *\n * @param path - Raw path string to normalize\n * @param specId - Spec ID for error messages\n * @returns Normalized path (e.g., \"/api/v3\")\n * @throws {ValidationError} PROXY_PATH_TOO_BROAD if path resolves to \"/\" (e.g., \"/\", \".\", \"..\")\n *\n * @example\n * normalizeProxyPath('api/v3', 'petstore') → '/api/v3'\n * normalizeProxyPath('/api/v3/', 'petstore') → '/api/v3'\n */\nexport function normalizeProxyPath(path: string, specId: string): string {\n // Trim leading/trailing whitespace (e.g., \" /api/v3 \" → \"/api/v3\")\n path = path.trim();\n\n // Strip query string and fragment (e.g., \"/api/v3?debug=true#section\" → \"/api/v3\")\n const queryIdx = path.indexOf('?');\n const hashIdx = path.indexOf('#');\n const cutIdx = Math.min(\n queryIdx >= 0 ? queryIdx : path.length,\n hashIdx >= 0 ? hashIdx : path.length,\n );\n let normalized = path.slice(0, cutIdx);\n\n // Ensure leading slash\n normalized = normalized.startsWith('/') ? normalized : `/${normalized}`;\n\n // Collapse consecutive slashes (e.g., \"//api//v3\" → \"/api/v3\")\n normalized = normalized.replace(/\\/{2,}/g, '/');\n\n // Resolve dot segments per RFC 3986 §5.2.4 (e.g., \"/api/../v3\" → \"/v3\")\n // HTTP clients canonicalize these, so proxy paths must match the resolved form\n const segments = normalized.split('/');\n const resolved: string[] = [];\n for (const segment of segments) {\n if (segment === '.') {\n continue;\n }\n if (segment === '..') {\n // Don't pop beyond root\n if (resolved.length > 1) {\n resolved.pop();\n }\n continue;\n }\n resolved.push(segment);\n }\n normalized = resolved.join('/') || '/';\n\n // Remove trailing slash (but not if path is just \"/\")\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n if (normalized === '/') {\n throw new ValidationError(\n 'PROXY_PATH_TOO_BROAD',\n `[${specId}] proxyPath \"/\" is too broad — it would capture all requests. ` +\n 'Set a more specific proxyPath (e.g., \"/api/v1\").',\n );\n }\n\n return normalized;\n}\n\n// =============================================================================\n// validateUniqueProxyPaths()\n// =============================================================================\n\n/**\n * Validate proxy paths are unique and non-overlapping\n *\n * Checks for:\n * 1. Duplicate paths — two specs with the same proxyPath\n * 2. Overlapping paths — one path is a prefix of another at a segment boundary\n * (e.g., \"/api\" and \"/api/v1\") which would cause routing ambiguity\n * 3. String-prefix collisions — one path is a raw string prefix of another\n * without a segment boundary (e.g., \"/api\" and \"/api2\"). Vite's internal\n * proxy matching uses plain `url.startsWith(context)` with no segment\n * awareness, so \"/api\" would incorrectly capture \"/api2/users\" requests.\n *\n * @remarks\n * Entries with an empty or falsy `proxyPath` are silently skipped. These\n * represent specs whose proxy path has not yet been resolved (e.g., during\n * early option resolution before the OpenAPI document is processed). Callers\n * should expect unresolved entries to be excluded from uniqueness checks\n * rather than triggering false-positive errors.\n *\n * @param specs - Array of spec entries with id and proxyPath.\n * Entries with empty/falsy proxyPath are skipped (unresolved).\n * @throws {ValidationError} PROXY_PATH_DUPLICATE if duplicate paths found\n * @throws {ValidationError} PROXY_PATH_OVERLAP if overlapping paths found (segment boundary)\n * @throws {ValidationError} PROXY_PATH_PREFIX_COLLISION if one path is a raw string prefix\n * of another without a segment boundary (e.g., \"/api\" and \"/api2\")\n *\n * @example\n * // Throws PROXY_PATH_DUPLICATE\n * validateUniqueProxyPaths([\n * { id: 'petstore', proxyPath: '/api/v3' },\n * { id: 'inventory', proxyPath: '/api/v3' },\n * ]);\n *\n * @example\n * // Throws PROXY_PATH_OVERLAP\n * validateUniqueProxyPaths([\n * { id: 'petstore', proxyPath: '/api' },\n * { id: 'inventory', proxyPath: '/api/v1' },\n * ]);\n *\n * @example\n * // Throws PROXY_PATH_PREFIX_COLLISION\n * validateUniqueProxyPaths([\n * { id: 'petstore', proxyPath: '/api' },\n * { id: 'inventory', proxyPath: '/api2' },\n * ]);\n */\nexport function validateUniqueProxyPaths(specs: Array<{ id: string; proxyPath: string }>): void {\n const paths = new Map<string, string>();\n\n for (const spec of specs) {\n // Skip entries with empty/whitespace-only proxyPath — they haven't been resolved yet\n const path = spec.proxyPath?.trim();\n if (!path) {\n continue;\n }\n\n validateNotReservedPath(path, spec.id);\n\n if (paths.has(path)) {\n throw new ValidationError(\n 'PROXY_PATH_DUPLICATE',\n `Duplicate proxyPath \"${path}\" used by specs \"${paths.get(path)}\" ` +\n `and \"${spec.id}\". Each spec must have a unique proxyPath.`,\n );\n }\n paths.set(path, spec.id);\n }\n\n validateNoPrefixOverlaps(paths);\n}\n\n/**\n * Throw if the given path collides with a reserved shared-service prefix\n * (e.g. `/_devtools`, `/_api`, `/_ws`).\n */\nfunction validateNotReservedPath(path: string, specId: string): void {\n for (const reserved of RESERVED_PROXY_PATHS) {\n if (path === reserved || path.startsWith(`${reserved}/`) || reserved.startsWith(path)) {\n throw new ValidationError(\n 'PROXY_PATH_OVERLAP',\n `[${specId}] proxyPath \"${path}\" collides with reserved path \"${reserved}\" ` +\n 'used by the shared DevTools/API/WebSocket service.',\n );\n }\n }\n}\n\n/**\n * Detect segment-boundary overlaps (`/api` vs `/api/v1`) and raw\n * string-prefix collisions (`/api` vs `/api2`) among validated proxy paths.\n *\n * Vite's proxy matching uses `url.startsWith(context)` with no segment\n * awareness, so `/api` would incorrectly capture `/api2/*` requests.\n */\nfunction validateNoPrefixOverlaps(paths: Map<string, string>): void {\n const sortedPaths = Array.from(paths.entries()).sort(([a], [b]) => a.length - b.length);\n for (let i = 0; i < sortedPaths.length; i++) {\n for (let j = i + 1; j < sortedPaths.length; j++) {\n const [shorter, shorterId] = sortedPaths[i];\n const [longer, longerId] = sortedPaths[j];\n\n // Segment-boundary overlap: \"/api\" is a parent of \"/api/v1\"\n if (longer.startsWith(`${shorter}/`)) {\n throw new ValidationError(\n 'PROXY_PATH_OVERLAP',\n `Overlapping proxyPaths: \"${shorter}\" (${shorterId}) is a prefix of ` +\n `\"${longer}\" (${longerId}). This would cause routing ambiguity.`,\n );\n }\n\n // Raw string-prefix collision: \"/api\" is a string prefix of \"/api2\".\n if (longer.startsWith(shorter)) {\n throw new ValidationError(\n 'PROXY_PATH_PREFIX_COLLISION',\n `Proxy path prefix collision: \"${shorter}\" (${shorterId}) is a string prefix of ` +\n `\"${longer}\" (${longerId}). Vite's proxy uses startsWith matching, so ` +\n `\"${shorter}\" would incorrectly capture requests meant for \"${longer}\".`,\n );\n }\n }\n }\n}\n","/**\n * Spec ID Derivation\n *\n * What: Functions to derive and validate spec identifiers\n * How: Slugifies explicit IDs or auto-derives from OpenAPI info.title\n * Why: Each spec instance needs a unique, URL-safe identifier for routing,\n * DevTools grouping, logging, and default directory names\n *\n * @module spec-id\n */\n\nimport type { OpenAPIV3_1 } from '@scalar/openapi-types';\n\nimport { ValidationError } from './types.js';\n\n/**\n * Slugify a string for use as a spec identifier\n *\n * Rules:\n * - Lowercase\n * - Replace spaces and special chars with hyphens\n * - Remove consecutive hyphens\n * - Trim leading/trailing hyphens\n *\n * @example\n * slugify(\"Swagger Petstore\") → \"swagger-petstore\"\n * slugify(\"Billing API v2\") → \"billing-api-v2\"\n * slugify(\"café\") → \"cafe\"\n */\nexport function slugify(input: string): string {\n return input\n .normalize('NFD')\n .replace(/\\p{M}/gu, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\n/**\n * Derive a spec ID from the processed OpenAPI document\n *\n * Priority:\n * 1. Explicit id from config (if non-empty)\n * 2. Slugified info.title from the processed document\n *\n * @param explicitId - ID from SpecConfig.id (may be empty)\n * @param document - Processed OpenAPI document\n * @returns Stable, URL-safe spec identifier\n * @throws {ValidationError} SPEC_ID_MISSING if no ID can be derived (missing title and no explicit id)\n */\nexport function deriveSpecId(explicitId: string, document: OpenAPIV3_1.Document): string {\n if (explicitId.trim()) {\n const id = slugify(explicitId);\n if (!id) {\n throw new ValidationError(\n 'SPEC_ID_MISSING',\n `Cannot derive spec ID: explicit id \"${explicitId}\" produces an empty slug. ` +\n 'Please provide an id containing ASCII letters or numbers.',\n );\n }\n return id;\n }\n\n const title = document.info?.title;\n if (!title || !title.trim()) {\n throw new ValidationError(\n 'SPEC_ID_MISSING',\n 'Cannot derive spec ID: info.title is missing from the OpenAPI document. ' +\n 'Please set an explicit id in the spec configuration.',\n );\n }\n\n const id = slugify(title);\n if (!id) {\n throw new ValidationError(\n 'SPEC_ID_MISSING',\n `Cannot derive spec ID: info.title \"${title}\" produces an empty slug. ` +\n 'Please set an explicit id in the spec configuration.',\n );\n }\n\n return id;\n}\n\n/**\n * Validate spec IDs are unique across all specs\n *\n * Collects all duplicated IDs and reports them in a single error.\n *\n * @param ids - Array of resolved spec IDs\n * @throws {ValidationError} SPEC_ID_DUPLICATE if duplicate IDs found\n */\nexport function validateUniqueIds(ids: string[]): void {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of ids) {\n if (seen.has(id)) {\n duplicates.add(id);\n }\n seen.add(id);\n }\n if (duplicates.size > 0) {\n const list = [...duplicates].join(', ');\n throw new ValidationError(\n 'SPEC_ID_DUPLICATE',\n `Duplicate spec IDs: ${list}. Each spec must have a unique ID. ` +\n 'Set explicit ids in spec configuration to resolve.',\n );\n }\n}\n","/**\n * Multi-Spec Orchestrator\n *\n * What: Central orchestrator that creates N spec instances and mounts them on a single Hono app\n * How: Three phases — process specs, validate uniqueness, build main Hono app with dispatch middleware\n * Why: Enables multiple OpenAPI specs to run on a single server with isolated stores and handlers\n *\n * @module orchestrator\n */\n\nimport { existsSync } from 'node:fs';\nimport type { Server as NodeServer } from 'node:http';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n createOpenApiServer,\n executeSeeds,\n type Logger,\n mountDevToolsRoutes,\n type OpenApiServer,\n type SpecInfo,\n type WebSocketHub,\n} from '@websublime/vite-plugin-open-api-core';\nimport { type Context, Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport type { ViteDevServer } from 'vite';\nimport { loadHandlers } from './handlers.js';\nimport { mountMultiSpecInternalApi } from './multi-internal-api.js';\nimport { createMultiSpecWebSocketHub } from './multi-ws.js';\nimport { deriveProxyPath, validateUniqueProxyPaths } from './proxy-path.js';\nimport { buildSeedMapFromStore, loadSeeds } from './seeds.js';\nimport { deriveSpecId, slugify, validateUniqueIds } from './spec-id.js';\nimport type { ResolvedOptions, ResolvedSpecConfig } from './types.js';\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/**\n * Deterministic color palette for spec identification in DevTools.\n *\n * Colors are assigned by index: spec 0 gets green, spec 1 gets blue, etc.\n * Wraps around for >8 specs.\n */\nexport const SPEC_COLORS: readonly string[] = [\n '#4ade80', // green\n '#60a5fa', // blue\n '#f472b6', // pink\n '#facc15', // yellow\n '#a78bfa', // purple\n '#fb923c', // orange\n '#2dd4bf', // teal\n '#f87171', // red\n];\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Resolved spec instance with all runtime data.\n *\n * Created during Phase 1 of orchestration. Each instance owns\n * an isolated core `OpenApiServer` with its own store, registry,\n * handlers, seeds, and timeline.\n */\nexport interface SpecInstance {\n /** Unique spec identifier (explicit or auto-derived from info.title) */\n id: string;\n\n /** Spec metadata for DevTools display and WebSocket protocol */\n info: SpecInfo;\n\n /** Core server instance (isolated Hono app, store, registry, etc.) */\n server: OpenApiServer;\n\n /** Resolved configuration for this spec */\n config: ResolvedSpecConfig;\n}\n\n/**\n * Orchestrator result — returned by `createOrchestrator()`.\n *\n * Provides access to the main Hono app (all specs mounted),\n * individual spec instances, aggregated metadata, and lifecycle methods.\n */\nexport interface OrchestratorResult {\n /**\n * Main Hono app with all specs mounted via X-Spec-Id dispatch.\n *\n * **Note**: Consumers using this property directly must have `hono`\n * as a dependency. The `start()`/`stop()` lifecycle methods do not\n * require direct interaction with this Hono instance.\n */\n app: Hono;\n\n /** All spec instances (in config order) */\n instances: SpecInstance[];\n\n /** Spec metadata array for WebSocket `connected` event */\n specsInfo: SpecInfo[];\n\n /**\n * Shared WebSocket hub for the orchestrator.\n *\n * Created via `createMultiSpecWebSocketHub()` with:\n * - `autoConnect: false` to suppress default connected events\n * - Enhanced `addClient()` that sends specs metadata\n * - Broadcast interception that adds `specId` to all events\n * - Multi-spec command handler for spec-scoped routing\n */\n wsHub: WebSocketHub;\n\n /** Start the shared HTTP server on the configured port */\n start(): Promise<void>;\n\n /** Stop the HTTP server and clean up resources */\n stop(): Promise<void>;\n\n /** Actual bound port after start() resolves (0 before start or after stop) */\n readonly port: number;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Resolved values produced by `processSpec` for a single spec.\n *\n * Returned instead of mutating the input `ResolvedSpecConfig` so that\n * the caller (`createOrchestrator`) decides how to propagate the values.\n */\ninterface ProcessedSpec {\n instance: SpecInstance;\n resolvedConfig: {\n id: string;\n proxyPath: string;\n proxyPathSource: 'auto' | 'explicit';\n handlersDir: string;\n seedsDir: string;\n };\n}\n\n/**\n * Process a single spec configuration into a resolved SpecInstance.\n *\n * Loads handlers and seeds, creates the core OpenApiServer, derives the\n * spec ID and proxy path, and builds the SpecInfo metadata.\n *\n * Does **not** mutate `specConfig`. Returns resolved values separately\n * so the caller can assign them back.\n */\nasync function processSpec(\n specConfig: ResolvedSpecConfig,\n index: number,\n options: ResolvedOptions,\n vite: ViteDevServer,\n cwd: string,\n logger: Logger,\n): Promise<ProcessedSpec> {\n // ---- Step 1: Create core server to parse the OpenAPI document ----\n // Pass empty handlers and seeds — they will be loaded from the correct\n // directory once the spec ID is finalized (step 3).\n const server = await createOpenApiServer({\n spec: specConfig.spec,\n port: options.port,\n idFields: specConfig.idFields,\n handlers: new Map(),\n seeds: new Map(),\n timelineLimit: options.timelineLimit,\n cors: false, // CORS handled at main app level\n devtools: false, // DevTools mounted at main app level\n logger,\n });\n\n // ---- Step 2: Derive spec ID and resolve directories ----\n // Now that the document is parsed, we can derive the final spec ID\n // and compute the correct default directory paths.\n // deriveSpecId() always returns a slugified string, so no need to re-slugify.\n const id = deriveSpecId(specConfig.id, server.document);\n const handlersDir = specConfig.handlersDir || `./mocks/${id}/handlers`;\n const seedsDir = specConfig.seedsDir || `./mocks/${id}/seeds`;\n\n // ---- Step 3: Load handlers and seeds from the correct directories ----\n const handlersResult = await loadHandlers(handlersDir, vite, cwd, logger);\n const seedsResult = await loadSeeds(seedsDir, vite, cwd, logger);\n\n // Register loaded handlers on the server (silent: suppress broadcast/log during initial setup)\n if (handlersResult.handlers.size > 0) {\n server.updateHandlers(handlersResult.handlers, { silent: true });\n }\n\n // Execute seed functions to populate the store, then sync route builder\n if (seedsResult.seeds.size > 0) {\n await executeSeeds(seedsResult.seeds, server.store, server.document);\n\n // Sync the route builder's seed map from the now-populated store.\n // executeSeeds() only writes to the store — the route builder's seed map\n // (used for the seed response priority path) is a separate reference that\n // must be updated explicitly via updateSeeds().\n const seedMap = buildSeedMapFromStore(server.store);\n server.updateSeeds(seedMap);\n }\n\n // Derive proxy path (from explicit config or servers[0].url)\n const { proxyPath, proxyPathSource } = deriveProxyPath(specConfig.proxyPath, server.document, id);\n\n // Build SpecInfo metadata for DevTools and WebSocket protocol\n const info: SpecInfo = {\n id,\n title: server.document.info?.title ?? id,\n version: server.document.info?.version ?? 'unknown',\n proxyPath,\n color: SPEC_COLORS[index % SPEC_COLORS.length],\n endpointCount: server.registry.endpoints.size,\n schemaCount: server.store.getSchemas().length,\n };\n\n return {\n instance: { id, info, server, config: specConfig },\n resolvedConfig: { id, proxyPath, proxyPathSource, handlersDir, seedsDir },\n };\n}\n\n// =============================================================================\n// Phase 3 Helpers (extracted for cognitive complexity)\n// =============================================================================\n\n/** CORS configuration used by both mainApp and sub-instance middleware */\ninterface CorsConfig {\n origin: string | string[];\n allowMethods: string[];\n allowHeaders: string[];\n exposeHeaders: string[];\n maxAge: number;\n credentials: boolean;\n}\n\n/**\n * Build the CORS configuration from resolved options.\n *\n * Normalizes `['*']` to `'*'` (Hono's array branch uses `.includes(origin)`\n * which never matches browser-sent origins against the literal `'*'`).\n */\nfunction buildCorsConfig(options: ResolvedOptions): CorsConfig {\n const isWildcardOrigin =\n options.corsOrigin === '*' ||\n (Array.isArray(options.corsOrigin) && options.corsOrigin.includes('*'));\n\n const effectiveCorsOrigin: string | string[] = isWildcardOrigin ? '*' : options.corsOrigin;\n\n return {\n origin: effectiveCorsOrigin,\n allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],\n allowHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'X-Spec-Id'],\n exposeHeaders: ['Content-Length', 'X-Request-Id'],\n maxAge: 86400,\n credentials: !isWildcardOrigin,\n };\n}\n\n/**\n * Mount the DevTools SPA on the main Hono app.\n *\n * Resolves the SPA directory relative to this file's location.\n * Logs a warning if the built SPA is not found.\n */\nfunction mountDevToolsSpa(mainApp: Hono, logger: Logger): void {\n const pluginDir = dirname(fileURLToPath(import.meta.url));\n const spaDir = join(pluginDir, 'devtools-spa');\n const devtoolsSpaDir = existsSync(spaDir) ? spaDir : undefined;\n\n if (!devtoolsSpaDir) {\n logger.warn?.(\n '[vite-plugin-open-api-server] DevTools SPA not found at',\n spaDir,\n '- serving placeholder. Run \"pnpm build\" to include the SPA.',\n );\n }\n\n mountDevToolsRoutes(mainApp, {\n spaDir: devtoolsSpaDir,\n logger,\n });\n}\n\n/**\n * Result of WebSocket route setup.\n *\n * Contains the injection function that must be called on `start()` to\n * hook the Node.js HTTP server's `upgrade` event for WS handshakes.\n */\ninterface WebSocketRouteResult {\n // biome-ignore lint/suspicious/noExplicitAny: @hono/node-ws types expect node http.Server but we store generically\n injectWebSocket: ((server: any) => void) | null;\n}\n\n/**\n * Mount the `/_ws` WebSocket route on the main Hono app.\n *\n * Attempts to dynamically import `@hono/node-ws`. On success, registers\n * the upgrade middleware and returns the `injectWebSocket` function for\n * use during `start()`. On failure (optional peer not installed), mounts\n * a 501 placeholder.\n */\nasync function mountWebSocketRoute(\n mainApp: Hono,\n wsHub: WebSocketHub,\n logger: Logger,\n): Promise<WebSocketRouteResult> {\n // Isolate the dynamic import so only module-not-found errors produce\n // the 501 fallback. Runtime errors from createNodeWebSocket or route\n // registration are real bugs and must propagate.\n let nodeWsModule: typeof import('@hono/node-ws');\n try {\n nodeWsModule = await import('@hono/node-ws');\n } catch (err: unknown) {\n const isModuleNotFound =\n err instanceof Error &&\n ('code' in err\n ? (err as NodeJS.ErrnoException).code === 'ERR_MODULE_NOT_FOUND'\n : err.message.includes('@hono/node-ws'));\n\n if (!isModuleNotFound) {\n throw err;\n }\n\n // @hono/node-ws not available — serve 501 placeholder\n mainApp.get('/_ws', (c) => {\n return c.json(\n {\n message: 'WebSocket endpoint - use ws:// protocol',\n note: 'Install @hono/node-ws to enable WebSocket support',\n },\n 501,\n );\n });\n\n logger.debug?.(\n '[vite-plugin-open-api-server] @hono/node-ws not available, WebSocket upgrade disabled',\n );\n return { injectWebSocket: null };\n }\n\n // Module loaded — wire up the WebSocket route. Errors here (e.g., from\n // createNodeWebSocket or mainApp.get) are bugs and must propagate.\n const nodeWs = nodeWsModule.createNodeWebSocket({ app: mainApp });\n\n mainApp.get(\n '/_ws',\n nodeWs.upgradeWebSocket(() => ({\n onOpen(_event, ws) {\n wsHub.addClient(ws);\n },\n onMessage(event, ws) {\n wsHub.handleMessage(ws, event.data);\n },\n onClose(_event, ws) {\n wsHub.removeClient(ws);\n },\n })),\n );\n\n logger.debug?.('[vite-plugin-open-api-server] WebSocket upgrade enabled at /_ws');\n return { injectWebSocket: nodeWs.injectWebSocket };\n}\n\n/**\n * Create the X-Spec-Id dispatch middleware.\n *\n * Uses slugify() to normalize the incoming header so it matches the\n * instanceMap keys produced by deriveSpecId().\n *\n * **Note**: Dispatched requests bypass `mainApp` response middleware\n * because `instance.server.app.fetch()` returns a raw `Response`.\n * Shared response concerns (e.g., CORS) are applied per-instance.\n */\nfunction createDispatchMiddleware(\n instanceMap: Map<string, SpecInstance>,\n): (c: Context, next: () => Promise<void>) => Promise<Response | undefined> {\n return async (c: Context, next: () => Promise<void>): Promise<Response | undefined> => {\n const rawSpecId = c.req.header('x-spec-id');\n if (!rawSpecId) {\n await next();\n return;\n }\n\n const specId = slugify(rawSpecId.trim());\n if (!specId) {\n await next();\n return;\n }\n\n const instance = instanceMap.get(specId);\n if (!instance) {\n return c.json({ error: `Unknown spec: ${specId}` }, 404);\n }\n\n return instance.server.app.fetch(c.req.raw);\n };\n}\n\n// =============================================================================\n// Orchestrator Factory\n// =============================================================================\n\n/**\n * Create the multi-spec orchestrator.\n *\n * Flow:\n * 1. **Phase 1 — Process specs**: For each spec config, load handlers/seeds,\n * create a core `OpenApiServer` instance, derive ID and proxy path.\n * 2. **Phase 2 — Validate uniqueness**: Ensure all spec IDs and proxy paths\n * are unique and non-overlapping.\n * 3. **Phase 3 — Build main app**: Create a single Hono app with CORS,\n * DevTools, Internal API, and X-Spec-Id dispatch middleware.\n *\n * **Note**: This function populates the resolved values (id, proxyPath,\n * proxyPathSource, handlersDir, seedsDir) on each `options.specs[i]` object.\n * Since `instances[i].config` is the same object reference, consumers should\n * access resolved values through `instances[i].config` (the authoritative view).\n *\n * @param options - Resolved plugin options (from `resolveOptions()`)\n * @param vite - Vite dev server instance (for ssrLoadModule)\n * @param cwd - Project root directory\n * @returns Orchestrator result with app, instances, and lifecycle methods\n */\nexport async function createOrchestrator(\n options: ResolvedOptions,\n vite: ViteDevServer,\n cwd: string,\n): Promise<OrchestratorResult> {\n const logger = options.logger ?? console;\n\n // ========================================================================\n // Phase 1: Process each spec — load handlers/seeds, create core instances\n // ========================================================================\n\n const instances: SpecInstance[] = [];\n for (let i = 0; i < options.specs.length; i++) {\n const { instance, resolvedConfig } = await processSpec(\n options.specs[i],\n i,\n options,\n vite,\n cwd,\n logger,\n );\n\n // Populate the resolved values on the shared spec config object.\n // `instance.config` and `options.specs[i]` are the same reference,\n // so these writes are visible through both. This is intentional:\n // downstream consumers (banner, file watcher, plugin.ts) access\n // the final values via `instance.config`.\n instance.config.id = resolvedConfig.id;\n instance.config.proxyPath = resolvedConfig.proxyPath;\n instance.config.proxyPathSource = resolvedConfig.proxyPathSource;\n instance.config.handlersDir = resolvedConfig.handlersDir;\n instance.config.seedsDir = resolvedConfig.seedsDir;\n\n instances.push(instance);\n }\n\n // ========================================================================\n // Phase 2: Validate uniqueness of IDs and proxy paths\n // ========================================================================\n\n validateUniqueIds(instances.map((inst) => inst.id));\n validateUniqueProxyPaths(\n instances.map((inst) => ({\n id: inst.id,\n proxyPath: inst.config.proxyPath,\n })),\n );\n\n // ========================================================================\n // Phase 3: Build main Hono app\n // ========================================================================\n\n const mainApp = new Hono();\n\n // --- CORS ---\n const corsConfig = buildCorsConfig(options);\n if (options.cors) {\n // mainApp CORS covers shared services (/_devtools, /_api).\n mainApp.use('*', cors(corsConfig));\n // Sub-instance CORS covers dispatched requests (app.fetch() bypasses mainApp middleware).\n for (const inst of instances) {\n inst.server.app.use('*', cors(corsConfig));\n }\n }\n\n // --- DevTools SPA (single SPA for all specs, spec-aware via WebSocket) ---\n if (options.devtools) {\n mountDevToolsSpa(mainApp, logger);\n }\n\n // --- Internal API (multi-spec: aggregated + per-spec routes) ---\n if (instances.length > 0) {\n mountMultiSpecInternalApi(mainApp, instances);\n }\n\n // --- Spec metadata (computed early for the connected event) ---\n const specsInfo = instances.map((inst) => inst.info);\n\n // --- Shared WebSocket Hub (multi-spec aware: broadcast interception + command routing) ---\n const wsHub = createMultiSpecWebSocketHub(instances, specsInfo);\n\n // --- WebSocket Route (/_ws) ---\n const { injectWebSocket } = await mountWebSocketRoute(mainApp, wsHub, logger);\n\n // --- X-Spec-Id dispatch middleware ---\n const instanceMap = new Map(instances.map((inst) => [inst.id, inst]));\n mainApp.use('*', createDispatchMiddleware(instanceMap));\n\n // ========================================================================\n // Lifecycle\n // ========================================================================\n\n let serverInstance: NodeServer | null = null;\n let boundPort = 0;\n\n /**\n * Start a Node.js HTTP server and wait for it to bind.\n *\n * @returns The actual bound port (handles ephemeral port 0).\n */\n async function startServerOnPort(\n fetchHandler: Hono['fetch'],\n port: number,\n ): Promise<{ server: NodeServer; actualPort: number }> {\n let createAdaptorServer: typeof import('@hono/node-server').createAdaptorServer;\n try {\n const nodeServer = await import('@hono/node-server');\n createAdaptorServer = nodeServer.createAdaptorServer;\n } catch {\n throw new Error('@hono/node-server is required. Install with: npm install @hono/node-server');\n }\n\n const server = createAdaptorServer({ fetch: fetchHandler }) as NodeServer;\n\n // Attach listeners BEFORE calling listen() to avoid a race condition\n // where the 'listening' event fires before the handler is registered.\n const actualPort = await new Promise<number>((resolve, reject) => {\n const onListening = () => {\n server.removeListener('error', onError);\n const addr = server.address();\n resolve(typeof addr === 'object' && addr ? addr.port : port);\n };\n\n const onError = (err: NodeJS.ErrnoException) => {\n server.removeListener('listening', onListening);\n server.close(() => {});\n if (err.code === 'EADDRINUSE') {\n reject(new Error(`[vite-plugin-open-api-server] Port ${port} is already in use.`));\n } else {\n reject(new Error(`[vite-plugin-open-api-server] Server error: ${err.message}`));\n }\n };\n\n server.once('listening', onListening);\n server.once('error', onError);\n server.listen(port);\n });\n\n return { server, actualPort };\n }\n\n return {\n app: mainApp,\n instances,\n specsInfo,\n wsHub,\n\n get port(): number {\n return boundPort;\n },\n\n async start(): Promise<void> {\n if (serverInstance) {\n throw new Error('[vite-plugin-open-api-server] Server already running. Call stop() first.');\n }\n\n const { server, actualPort } = await startServerOnPort(mainApp.fetch, options.port);\n serverInstance = server;\n boundPort = actualPort;\n\n // Inject WebSocket support into the Node.js HTTP server.\n // This hooks into the server's 'upgrade' event for WebSocket handshakes.\n if (injectWebSocket) {\n injectWebSocket(serverInstance);\n }\n\n logger.info(`[vite-plugin-open-api-server] Server started on http://localhost:${actualPort}`);\n },\n\n async stop(): Promise<void> {\n const server = serverInstance;\n if (server) {\n try {\n // Remove all clients from the hub's tracking set so broadcasts\n // during teardown are no-ops. Does not close WS connections —\n // closeAllConnections() handles the network layer below.\n wsHub.clear();\n\n // Forcibly destroy all open connections (including WebSocket clients)\n // so server.close() resolves promptly instead of waiting for idle drain.\n if (typeof server.closeAllConnections === 'function') {\n server.closeAllConnections();\n }\n await new Promise<void>((resolve, reject) => {\n server.close((err?: Error) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n logger.info('[vite-plugin-open-api-server] Server stopped');\n } catch (err) {\n logger.error?.('[vite-plugin-open-api-server] Error closing server:', err);\n throw err;\n } finally {\n serverInstance = null;\n boundPort = 0;\n }\n }\n },\n };\n}\n","/**\n * Vite Plugin Implementation\n *\n * What: Main Vite plugin for OpenAPI mock server (multi-spec)\n * How: Uses orchestrator to create N spec instances, configures multi-proxy\n * Why: Integrates multiple OpenAPI mock servers seamlessly into Vite dev workflow\n *\n * @module plugin\n */\n\nimport { createRequire } from 'node:module';\nimport type { Plugin, ViteDevServer } from 'vite';\nimport { extractBannerInfo, printBanner, printError } from './banner.js';\nimport { createPerSpecFileWatchers, type FileWatcher } from './hot-reload.js';\nimport { configureMultiProxy, DEVTOOLS_PROXY_PATH } from './multi-proxy.js';\nimport { createOrchestrator, type OrchestratorResult } from './orchestrator.js';\nimport { type OpenApiServerOptions, resolveOptions } from './types.js';\n\n/**\n * Virtual module ID for the DevTools tab registration script.\n *\n * This script is served as a Vite module (not inline HTML) so that bare\n * import specifiers like `@vue/devtools-api` are resolved through Vite's\n * module pipeline. Inline `<script type=\"module\">` blocks in HTML are\n * executed directly by the browser, which cannot resolve bare specifiers.\n */\nconst VIRTUAL_DEVTOOLS_TAB_ID = 'virtual:open-api-devtools-tab';\nconst RESOLVED_VIRTUAL_DEVTOOLS_TAB_ID = `\\0${VIRTUAL_DEVTOOLS_TAB_ID}`;\n\n/**\n * Create the OpenAPI Server Vite plugin\n *\n * This plugin starts mock servers based on OpenAPI specifications\n * and configures Vite to proxy API requests to them. Supports\n * multiple specs via the orchestrator pattern.\n *\n * @example\n * ```typescript\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import vue from '@vitejs/plugin-vue';\n * import { openApiServer } from '@websublime/vite-plugin-open-api-server';\n *\n * export default defineConfig({\n * plugins: [\n * vue(),\n * openApiServer({\n * specs: [\n * { spec: './openapi/petstore.yaml', proxyPath: '/api/pets' },\n * { spec: './openapi/inventory.yaml', proxyPath: '/api/inventory' },\n * ],\n * port: 4000,\n * }),\n * ],\n * });\n * ```\n *\n * @param options - Plugin configuration options\n * @returns Vite plugin\n */\nexport function openApiServer(options: OpenApiServerOptions): Plugin {\n const resolvedOptions = resolveOptions(options);\n\n let orchestrator: OrchestratorResult | null = null;\n let fileWatchers: FileWatcher[] = [];\n let cwd: string = process.cwd();\n\n return {\n name: 'vite-plugin-open-api-server',\n apply: 'serve',\n\n /**\n * Ensure @vue/devtools-api is available for the DevTools tab module\n *\n * The virtual module imports from '@vue/devtools-api', which Vite needs\n * to pre-bundle so it can be resolved at runtime in the browser, even\n * though the host app may not have it as a direct dependency.\n */\n config() {\n if (!resolvedOptions.devtools || !resolvedOptions.enabled) {\n return;\n }\n\n // Only add to optimizeDeps if the package is actually resolvable\n // to avoid Vite warnings when the consumer hasn't installed it\n const require = createRequire(import.meta.url);\n try {\n require.resolve('@vue/devtools-api');\n } catch {\n return;\n }\n\n return {\n optimizeDeps: {\n include: ['@vue/devtools-api'],\n },\n };\n },\n\n /**\n * Resolve the virtual module for DevTools tab registration\n */\n resolveId(id: string) {\n if (id === VIRTUAL_DEVTOOLS_TAB_ID) {\n return RESOLVED_VIRTUAL_DEVTOOLS_TAB_ID;\n }\n },\n\n /**\n * Load the virtual module that registers the custom Vue DevTools tab\n *\n * This code is served as a proper Vite module, allowing bare import\n * specifiers to be resolved through Vite's dependency pre-bundling.\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_DEVTOOLS_TAB_ID) {\n return `\nimport { addCustomTab } from '@vue/devtools-api';\n\ntry {\n // Route through Vite's proxy so it works in all environments\n const iframeSrc = window.location.origin + '${DEVTOOLS_PROXY_PATH}/';\n\n addCustomTab({\n name: 'vite-plugin-open-api-server',\n title: 'OpenAPI Server',\n icon: 'https://api.iconify.design/carbon:api-1.svg?width=24&height=24&color=%2394a3b8',\n view: {\n type: 'iframe',\n src: iframeSrc,\n },\n category: 'app',\n });\n} catch (e) {\n // @vue/devtools-api not available - expected when the package is not installed\n}\n`;\n }\n },\n\n /**\n * Configure the Vite dev server\n *\n * This hook is called when the dev server is created.\n * We use it to:\n * 1. Create and start the multi-spec orchestrator\n * 2. Configure Vite's multi-proxy for all specs\n * 3. Set up per-spec file watchers for hot reload\n * 4. Print startup banner\n */\n async configureServer(viteServer: ViteDevServer): Promise<void> {\n cwd = viteServer.config.root;\n\n if (!resolvedOptions.enabled) {\n return;\n }\n\n try {\n // Create multi-spec orchestrator (processes all specs, loads handlers/seeds)\n orchestrator = await createOrchestrator(resolvedOptions, viteServer, cwd);\n\n // Start the shared HTTP server\n await orchestrator.start();\n\n // Configure Vite proxies for all specs\n configureMultiProxy(viteServer, orchestrator.instances, orchestrator.port);\n\n // Set up per-spec file watchers for hot reload\n fileWatchers = await createPerSpecFileWatchers(\n orchestrator.instances,\n viteServer,\n cwd,\n resolvedOptions,\n );\n\n // Print startup banner (v0.x single-spec banner, shows first spec only)\n // TODO: Replace with printMultiSpecBanner() in Epic 5 (Task 5.1)\n if (!resolvedOptions.silent && orchestrator.instances.length > 0) {\n const firstInstance = orchestrator.instances[0];\n const bannerInfo = extractBannerInfo(\n firstInstance.server.registry,\n {\n info: {\n title: firstInstance.server.document.info?.title ?? 'OpenAPI Server',\n version: firstInstance.server.document.info?.version ?? '1.0.0',\n },\n },\n // Handler/seed counts are not tracked per-instance yet.\n // Multi-spec banner (Epic 5, Task 5.1) will display proper per-spec counts.\n 0,\n 0,\n resolvedOptions,\n );\n printBanner(bannerInfo, resolvedOptions);\n }\n } catch (error) {\n await teardown();\n printError('Failed to start OpenAPI mock server', error, resolvedOptions);\n throw error;\n }\n },\n\n /**\n * Inject Vue DevTools custom tab registration script\n *\n * When devtools is enabled, this injects a script tag that loads the\n * virtual module for custom tab registration. Using a virtual module\n * (instead of an inline script) ensures that bare import specifiers\n * like `@vue/devtools-api` are resolved through Vite's module pipeline.\n */\n transformIndexHtml() {\n if (!resolvedOptions.devtools || !resolvedOptions.enabled) {\n return;\n }\n\n return [\n {\n tag: 'script',\n attrs: { type: 'module', src: `/@id/${VIRTUAL_DEVTOOLS_TAB_ID}` },\n injectTo: 'head' as const,\n },\n ];\n },\n\n /**\n * Clean up when Vite server closes\n *\n * NOTE: closeBundle() is called by Vite when the dev server shuts down\n * (e.g., Ctrl+C). This is the same lifecycle hook used in v0.x.\n * While configureServer's viteServer.httpServer?.on('close', ...) is\n * an alternative, closeBundle() is more reliable across Vite versions\n * and is the established pattern in this codebase.\n */\n async closeBundle(): Promise<void> {\n await teardown();\n },\n };\n\n /**\n * Tear down all plugin resources: close file watchers and stop the orchestrator.\n *\n * Shared by `closeBundle` (normal shutdown) and the error path in\n * `configureServer` (partial-init cleanup). Uses `Promise.allSettled`\n * and try/catch so failures in one resource do not prevent cleanup\n * of the others.\n */\n async function teardown(): Promise<void> {\n await Promise.allSettled(fileWatchers.map((w) => w.close()));\n fileWatchers = [];\n\n if (orchestrator) {\n try {\n await orchestrator.stop();\n } catch {\n // Swallow stop errors — nothing actionable at shutdown\n }\n orchestrator = null;\n }\n }\n}\n","/**\n * Vue DevTools Integration\n *\n * What: Provides a function to register OpenAPI Server in Vue DevTools\n * How: Uses @vue/devtools-api to add a custom tab with iframe to DevTools SPA\n * Why: Enables debugging and inspection of the mock API server within Vue DevTools\n *\n * @module devtools\n */\n\nimport type { App } from 'vue';\n\n/**\n * Options for registering the DevTools plugin\n */\nexport interface RegisterDevToolsOptions {\n /**\n * The port where the OpenAPI server is running\n * @default 4000\n */\n port?: number;\n\n /**\n * The host where the OpenAPI server is running\n * @default 'localhost' (or derived from window.location.hostname if in browser)\n */\n host?: string;\n\n /**\n * The protocol to use for the DevTools URL\n * @default 'http' (or derived from window.location.protocol if in browser)\n */\n protocol?: 'http' | 'https';\n\n /**\n * Enable or disable DevTools registration\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Custom label for the DevTools tab\n * @default 'OpenAPI Server'\n */\n label?: string;\n}\n\n/**\n * Register OpenAPI Server in Vue DevTools\n *\n * This function should be called in your Vue application's main entry point\n * to add a custom tab to Vue DevTools. The tab contains an iframe that loads\n * the OpenAPI Server DevTools SPA.\n *\n * @example\n * ```typescript\n * // In your main.ts or main.js\n * import { createApp } from 'vue';\n * import { registerDevTools } from '@websublime/vite-plugin-open-api-server';\n * import App from './App.vue';\n *\n * const app = createApp(App);\n *\n * // Register OpenAPI Server DevTools\n * if (import.meta.env.DEV) {\n * await registerDevTools(app);\n * }\n *\n * app.mount('#app');\n * ```\n *\n * @param app - Vue application instance\n * @param options - Configuration options\n */\nexport async function registerDevTools(\n app: App,\n options: RegisterDevToolsOptions = {},\n): Promise<void> {\n const { enabled = true, label = 'OpenAPI Server', port, host, protocol } = options;\n\n // Validate app parameter\n if (!app || typeof app !== 'object') {\n // biome-ignore lint/suspicious/noConsole: Intentional warning for invalid app instance\n console.warn('[OpenAPI DevTools] Invalid Vue app instance provided');\n return;\n }\n\n // Only register if enabled\n if (!enabled) {\n return;\n }\n\n // Check if running in browser environment\n if (typeof window === 'undefined') {\n return;\n }\n\n // Lazy import to avoid SSR issues\n try {\n const { addCustomTab } = await import('@vue/devtools-api');\n\n // Get the DevTools URL\n const devtoolsUrl = getDevToolsUrl(port, host, protocol);\n\n // Add custom tab with iframe to Vue DevTools\n addCustomTab({\n name: 'vite-plugin-open-api-server',\n title: label,\n icon: 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%234f46e5%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z%22/%3E%3Cpolyline points=%223.29 7 12 12 20.71 7%22/%3E%3Cline x1=%2212%22 y1=%2222%22 x2=%2212%22 y2=%2212%22/%3E%3C/svg%3E',\n view: {\n type: 'iframe',\n src: devtoolsUrl,\n },\n category: 'app',\n });\n } catch (error) {\n // Log warning but don't crash the app\n // DevTools integration is optional, so the app should continue working\n // biome-ignore lint/suspicious/noConsole: Intentional warning for registration failure\n console.warn('[OpenAPI DevTools] Failed to register with Vue DevTools:', error);\n }\n}\n\n/**\n * Get the DevTools URL for the given configuration\n *\n * When running in a browser, protocol and host are automatically derived from\n * window.location if not explicitly provided.\n *\n * @param port - Server port (default: 4000, matching OpenApiServerOptions.port)\n * @param host - Server host (default: 'localhost' or window.location.hostname)\n * @param protocol - Protocol to use (default: 'http' or window.location.protocol)\n * @returns DevTools SPA URL\n */\nexport function getDevToolsUrl(port = 4000, host?: string, protocol?: 'http' | 'https'): string {\n // Derive defaults from browser environment if available\n const actualProtocol =\n protocol ||\n (typeof window !== 'undefined'\n ? (window.location.protocol.replace(':', '') as 'http' | 'https')\n : 'http');\n const actualHost =\n host || (typeof window !== 'undefined' ? window.location.hostname : 'localhost');\n\n return `${actualProtocol}://${actualHost}:${port}/_devtools/`;\n}\n"]}
1
+ {"version":3,"sources":["../src/banner.ts","../src/utils.ts","../src/handlers.ts","../src/seeds.ts","../src/hot-reload.ts","../src/multi-proxy.ts","../package.json","../src/multi-internal-api.ts","../src/multi-command.ts","../src/multi-ws.ts","../src/types.ts","../src/proxy-path.ts","../src/spec-id.ts","../src/orchestrator.ts","../src/plugin.ts","../src/devtools.ts"],"names":["path","fg","PACKAGE_VERSION","id","executeSeeds","existsSync","Hono","require"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Startup Banner\n *\n * What: Prints a colorful startup banner with server information\n * How: Uses picocolors for ANSI color output\n * Why: Provides clear feedback about server status and configuration\n *\n * @module banner\n */\n\nimport type { EndpointRegistry } from '@websublime/vite-plugin-open-api-core';\nimport pc from 'picocolors';\nimport type { ResolvedOptions } from './types.js';\n\n/**\n * Banner configuration\n */\nexport interface BannerInfo {\n /** Server port */\n port: number;\n /** Proxy path in Vite */\n proxyPath: string;\n /** OpenAPI spec title */\n title: string;\n /** OpenAPI spec version */\n version: string;\n /** Number of endpoints */\n endpointCount: number;\n /** Number of loaded handlers */\n handlerCount: number;\n /** Number of loaded seeds */\n seedCount: number;\n /** DevTools enabled */\n devtools: boolean;\n}\n\n/**\n * Print the startup banner\n *\n * @param info - Banner information\n * @param options - Resolved plugin options\n */\nexport function printBanner(info: BannerInfo, options: ResolvedOptions): void {\n if (options.silent) {\n return;\n }\n\n const logger = options.logger ?? console;\n const log = (msg: string) => logger.info(msg);\n\n // Box drawing characters\n const BOX = {\n topLeft: '╭',\n topRight: '╮',\n bottomLeft: '╰',\n bottomRight: '╯',\n horizontal: '─',\n vertical: '│',\n };\n\n const width = 56;\n const horizontalLine = BOX.horizontal.repeat(width - 2);\n\n log('');\n log(pc.cyan(`${BOX.topLeft}${horizontalLine}${BOX.topRight}`));\n log(\n pc.cyan(BOX.vertical) + centerText('🚀 OpenAPI Mock Server', width - 2) + pc.cyan(BOX.vertical),\n );\n log(pc.cyan(`${BOX.bottomLeft}${horizontalLine}${BOX.bottomRight}`));\n log('');\n\n // API Info\n log(\n ` ${pc.bold(pc.white('API:'))} ${pc.green(info.title)} ${pc.dim(`v${info.version}`)}`,\n );\n log(` ${pc.bold(pc.white('Server:'))} ${pc.cyan(`http://localhost:${info.port}`)}`);\n log(\n ` ${pc.bold(pc.white('Proxy:'))} ${pc.yellow(info.proxyPath)} ${pc.dim('→')} ${pc.dim(`localhost:${info.port}`)}`,\n );\n log('');\n\n // Stats\n const stats = [\n { label: 'Endpoints', value: info.endpointCount, color: pc.blue },\n { label: 'Handlers', value: info.handlerCount, color: pc.green },\n { label: 'Seeds', value: info.seedCount, color: pc.magenta },\n ];\n\n const statsLine = stats\n .map((s) => `${pc.dim(`${s.label}:`)} ${s.color(String(s.value))}`)\n .join(pc.dim(' │ '));\n log(` ${statsLine}`);\n log('');\n\n // DevTools\n if (info.devtools) {\n log(\n ` ${pc.bold(pc.white('DevTools:'))} ${pc.cyan(`http://localhost:${info.port}/_devtools`)}`,\n );\n log(` ${pc.bold(pc.white('API Info:'))} ${pc.cyan(`http://localhost:${info.port}/_api`)}`);\n log('');\n }\n\n // Footer\n log(pc.dim(' Press Ctrl+C to stop the server'));\n log('');\n}\n\n/**\n * Center text within a given width\n *\n * @param text - Text to center\n * @param width - Total width\n * @returns Centered text with padding\n */\n// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes require control characters\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[0-9;]*m/g;\n\nfunction centerText(text: string, width: number): string {\n // Account for ANSI codes - get visible length\n const visibleLength = text.replace(ANSI_ESCAPE_REGEX, '').length;\n const padding = Math.max(0, width - visibleLength);\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + text + ' '.repeat(rightPad);\n}\n\n/**\n * Extract banner info from server registry and document\n *\n * Note: This is the v0.x single-spec banner. It will be redesigned for\n * multi-spec display in Task 1.7 (vite-qq9.7). Currently only shows the\n * first spec's information.\n *\n * @param registry - Endpoint registry\n * @param document - OpenAPI document\n * @param handlerCount - Number of loaded handlers\n * @param seedCount - Number of loaded seed schemas\n * @param options - Resolved options (must contain at least one spec)\n * @returns Banner info\n */\nexport function extractBannerInfo(\n registry: EndpointRegistry,\n document: { info: { title: string; version: string } },\n handlerCount: number,\n seedCount: number,\n options: ResolvedOptions,\n): BannerInfo {\n return {\n port: options.port,\n proxyPath: options.specs[0]?.proxyPath || '(pending resolution)',\n title: document.info.title,\n version: document.info.version,\n endpointCount: registry.endpoints.size,\n handlerCount,\n seedCount,\n devtools: options.devtools,\n };\n}\n\n/**\n * Print a hot reload notification\n *\n * @param type - Type of reload ('handlers' | 'seeds')\n * @param count - Number of reloaded items\n * @param options - Resolved options\n */\nexport function printReloadNotification(\n type: 'handlers' | 'seeds',\n count: number,\n options: ResolvedOptions,\n): void {\n if (options.silent) {\n return;\n }\n\n const logger = options.logger ?? console;\n const icon = type === 'handlers' ? '🔄' : '🌱';\n const label = type === 'handlers' ? 'Handlers' : 'Seeds';\n const color = type === 'handlers' ? pc.green : pc.magenta;\n\n logger.info(` ${icon} ${color(label)} reloaded: ${pc.bold(String(count))} ${type}`);\n}\n\n/**\n * Print an error message\n *\n * @param message - Error message\n * @param error - Optional error object\n * @param options - Resolved options\n */\nexport function printError(message: string, error: unknown, options: ResolvedOptions): void {\n const logger = options.logger ?? console;\n logger.error(`${pc.red('✖')} ${pc.bold(pc.red('Error:'))} ${message}`);\n if (error instanceof Error) {\n logger.error(pc.dim(` ${error.message}`));\n }\n}\n\n/**\n * Print a warning message\n *\n * @param message - Warning message\n * @param options - Resolved options\n */\nexport function printWarning(message: string, options: ResolvedOptions): void {\n if (options.silent) {\n return;\n }\n\n const logger = options.logger ?? console;\n logger.warn(`${pc.yellow('⚠')} ${pc.yellow('Warning:')} ${message}`);\n}\n","/**\n * Filesystem Utilities\n *\n * What: Shared utility functions for filesystem operations\n * How: Uses Node.js fs/promises module with error handling\n * Why: Provides reusable utilities for handler and seed loading\n *\n * @module utils\n */\n\n/**\n * Check if a directory exists\n *\n * @param dirPath - Path to check\n * @returns Promise resolving to true if directory exists\n */\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n const fs = await import('node:fs/promises');\n const stats = await fs.stat(dirPath);\n return stats.isDirectory();\n } catch {\n return false;\n }\n}\n","/**\n * Handler Loading\n *\n * What: Loads handler files from a directory using glob patterns\n * How: Uses Vite's ssrLoadModule to transform and load TypeScript files\n * Why: Enables users to define custom handlers for operationIds in TypeScript\n *\n * @module handlers\n */\n\nimport path from 'node:path';\nimport type { HandlerDefinition, HandlerFn, Logger } from '@websublime/vite-plugin-open-api-core';\nimport fg from 'fast-glob';\nimport type { ViteDevServer } from 'vite';\nimport { directoryExists } from './utils.js';\n\n/**\n * Result of loading handlers\n */\nexport interface LoadHandlersResult {\n /** Map of operationId to handler function */\n handlers: Map<string, HandlerFn>;\n /** Number of handler files loaded */\n fileCount: number;\n /** List of loaded file paths (relative) */\n files: string[];\n}\n\n/**\n * Load handlers from a directory\n *\n * Searches for handler files matching the pattern `*.handlers.{ts,js,mjs}`\n * in the specified directory. Each file should export an object with\n * operationId keys and handler functions as values.\n *\n * Uses Vite's ssrLoadModule to transform TypeScript files on-the-fly.\n *\n * @example\n * ```typescript\n * // mocks/handlers/pets.handlers.ts\n * import { defineHandlers } from '@websublime/vite-plugin-open-api-core';\n *\n * export default defineHandlers({\n * getPetById: async ({ req, store }) => {\n * const pet = store.get('Pet', req.params.petId);\n * return pet ?? { status: 404, data: { message: 'Pet not found' } };\n * },\n * });\n * ```\n *\n * @param handlersDir - Directory to search for handler files\n * @param viteServer - Vite dev server instance for ssrLoadModule\n * @param cwd - Current working directory (defaults to process.cwd())\n * @param logger - Optional logger for warnings/errors\n * @returns Promise resolving to loaded handlers\n */\nexport async function loadHandlers(\n handlersDir: string,\n viteServer: ViteDevServer,\n cwd: string = process.cwd(),\n logger: Logger = console,\n): Promise<LoadHandlersResult> {\n const handlers = new Map<string, HandlerFn>();\n const absoluteDir = path.resolve(cwd, handlersDir);\n\n // Check if directory exists\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return {\n handlers,\n fileCount: 0,\n files: [],\n };\n }\n\n // Find handler files (supports TypeScript via Vite's transform)\n const pattern = '**/*.handlers.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: false,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n // Load each file using Vite's ssrLoadModule\n for (const file of files) {\n const absolutePath = path.join(absoluteDir, file);\n const fileHandlers = await loadHandlerFile(absolutePath, viteServer, logger);\n\n // Merge handlers\n for (const [operationId, handler] of Object.entries(fileHandlers)) {\n if (handlers.has(operationId)) {\n logger.warn(\n `[vite-plugin-open-api-server] Duplicate handler for operationId \"${operationId}\" in ${file}. Using last definition.`,\n );\n }\n handlers.set(operationId, handler);\n }\n }\n\n return {\n handlers,\n fileCount: files.length,\n files,\n };\n}\n\n/**\n * Load a single handler file using Vite's ssrLoadModule\n *\n * @param filePath - Absolute path to the handler file\n * @param viteServer - Vite dev server instance\n * @param logger - Logger for warnings/errors\n * @returns Promise resolving to handler definition object\n */\nasync function loadHandlerFile(\n filePath: string,\n viteServer: ViteDevServer,\n logger: Logger,\n): Promise<HandlerDefinition> {\n try {\n // Invalidate module cache for hot reload\n const moduleNode = viteServer.moduleGraph.getModuleById(filePath);\n if (moduleNode) {\n viteServer.moduleGraph.invalidateModule(moduleNode);\n }\n\n // Use Vite's ssrLoadModule to transform and load the file\n // This handles TypeScript, ESM, and other transforms automatically\n const module = await viteServer.ssrLoadModule(filePath);\n\n // Support both default export and named export\n const handlers = module.default ?? module.handlers ?? module;\n\n // Validate handlers object\n if (!handlers || typeof handlers !== 'object') {\n logger.warn(\n `[vite-plugin-open-api-server] Invalid handler file ${filePath}: expected object export`,\n );\n return {};\n }\n\n // Filter to only handler functions\n const validHandlers: HandlerDefinition = {};\n for (const [key, value] of Object.entries(handlers)) {\n if (typeof value === 'function') {\n validHandlers[key] = value as HandlerFn;\n }\n }\n\n return validHandlers;\n } catch (error) {\n logger.error(\n `[vite-plugin-open-api-server] Failed to load handler file ${filePath}:`,\n error instanceof Error ? error.message : error,\n );\n return {};\n }\n}\n\n/**\n * Get list of handler files in a directory\n *\n * Useful for file watching setup.\n *\n * @param handlersDir - Directory to search\n * @param cwd - Current working directory\n * @returns Promise resolving to list of absolute file paths\n */\nexport async function getHandlerFiles(\n handlersDir: string,\n cwd: string = process.cwd(),\n): Promise<string[]> {\n const absoluteDir = path.resolve(cwd, handlersDir);\n\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return [];\n }\n\n const pattern = '**/*.handlers.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: true,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n return files;\n}\n","/**\n * Seed Loading and Utilities\n *\n * What: Loads seed files from a directory and provides seed data utilities\n * How: Uses Vite's ssrLoadModule to transform and load TypeScript files\n * Why: Enables users to define seed data for schemas in TypeScript\n *\n * @module seeds\n */\n\nimport path from 'node:path';\nimport type {\n AnySeedFn,\n Logger,\n SeedDefinition,\n Store,\n} from '@websublime/vite-plugin-open-api-core';\nimport fg from 'fast-glob';\nimport type { ViteDevServer } from 'vite';\nimport { directoryExists } from './utils.js';\n\n/**\n * Result of loading seeds\n */\nexport interface LoadSeedsResult {\n /** Map of schema name to seed function */\n seeds: Map<string, AnySeedFn>;\n /** Number of seed files loaded */\n fileCount: number;\n /** List of loaded file paths (relative) */\n files: string[];\n}\n\n/**\n * Load seeds from a directory\n *\n * Searches for seed files matching the pattern `*.seeds.{ts,js,mjs}`\n * in the specified directory. Each file should export an object with\n * schema name keys and seed functions as values.\n *\n * Uses Vite's ssrLoadModule to transform TypeScript files on-the-fly.\n *\n * @example\n * ```typescript\n * // mocks/seeds/pets.seeds.ts\n * import { defineSeeds } from '@websublime/vite-plugin-open-api-core';\n *\n * export default defineSeeds({\n * Pet: ({ seed, faker }) => {\n * return seed.count(10, () => ({\n * id: faker.number.int({ min: 1, max: 1000 }),\n * name: faker.animal.dog(),\n * status: faker.helpers.arrayElement(['available', 'pending', 'sold']),\n * }));\n * },\n * });\n * ```\n *\n * @param seedsDir - Directory to search for seed files\n * @param viteServer - Vite dev server instance for ssrLoadModule\n * @param cwd - Current working directory (defaults to process.cwd())\n * @param logger - Optional logger for warnings/errors\n * @returns Promise resolving to loaded seeds\n */\nexport async function loadSeeds(\n seedsDir: string,\n viteServer: ViteDevServer,\n cwd: string = process.cwd(),\n logger: Logger = console,\n): Promise<LoadSeedsResult> {\n const seeds = new Map<string, AnySeedFn>();\n const absoluteDir = path.resolve(cwd, seedsDir);\n\n // Check if directory exists\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return {\n seeds,\n fileCount: 0,\n files: [],\n };\n }\n\n // Find seed files (supports TypeScript via Vite's transform)\n const pattern = '**/*.seeds.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: false,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n // Load each file using Vite's ssrLoadModule\n for (const file of files) {\n const absolutePath = path.join(absoluteDir, file);\n const fileSeeds = await loadSeedFile(absolutePath, viteServer, logger);\n\n // Merge seeds\n for (const [schemaName, seedFn] of Object.entries(fileSeeds)) {\n if (seeds.has(schemaName)) {\n logger.warn(\n `[vite-plugin-open-api-server] Duplicate seed for schema \"${schemaName}\" in ${file}. Using last definition.`,\n );\n }\n seeds.set(schemaName, seedFn);\n }\n }\n\n return {\n seeds,\n fileCount: files.length,\n files,\n };\n}\n\n/**\n * Load a single seed file using Vite's ssrLoadModule\n *\n * @param filePath - Absolute path to the seed file\n * @param viteServer - Vite dev server instance\n * @param logger - Logger for warnings/errors\n * @returns Promise resolving to seed definition object\n */\nasync function loadSeedFile(\n filePath: string,\n viteServer: ViteDevServer,\n logger: Logger,\n): Promise<SeedDefinition> {\n try {\n // Invalidate module cache for hot reload\n const moduleNode = viteServer.moduleGraph.getModuleById(filePath);\n if (moduleNode) {\n viteServer.moduleGraph.invalidateModule(moduleNode);\n }\n\n // Use Vite's ssrLoadModule to transform and load the file\n // This handles TypeScript, ESM, and other transforms automatically\n const module = await viteServer.ssrLoadModule(filePath);\n\n // Support both default export and named export\n const seeds = module.default ?? module.seeds ?? module;\n\n // Validate seeds object\n if (!seeds || typeof seeds !== 'object') {\n logger.warn(\n `[vite-plugin-open-api-server] Invalid seed file ${filePath}: expected object export`,\n );\n return {};\n }\n\n // Filter to only seed functions\n const validSeeds: SeedDefinition = {};\n for (const [key, value] of Object.entries(seeds)) {\n if (typeof value === 'function') {\n validSeeds[key] = value as AnySeedFn;\n }\n }\n\n return validSeeds;\n } catch (error) {\n logger.error(\n `[vite-plugin-open-api-server] Failed to load seed file ${filePath}:`,\n error instanceof Error ? error.message : error,\n );\n return {};\n }\n}\n\n/**\n * Get list of seed files in a directory\n *\n * Useful for file watching setup.\n *\n * @param seedsDir - Directory to search\n * @param cwd - Current working directory\n * @returns Promise resolving to list of absolute file paths\n */\nexport async function getSeedFiles(\n seedsDir: string,\n cwd: string = process.cwd(),\n): Promise<string[]> {\n const absoluteDir = path.resolve(cwd, seedsDir);\n\n const dirExists = await directoryExists(absoluteDir);\n if (!dirExists) {\n return [];\n }\n\n const pattern = '**/*.seeds.{ts,js,mjs}';\n const files = await fg(pattern, {\n cwd: absoluteDir,\n absolute: true,\n onlyFiles: true,\n ignore: ['node_modules/**', 'dist/**'],\n });\n\n return files;\n}\n\n/**\n * Build a seed data Map from the store's current contents.\n *\n * After `executeSeeds()` populates the store, this function reads back\n * the materialized data so it can be passed to `server.updateSeeds()`.\n * The route builder's seed map needs static `Map<string, unknown[]>`\n * data (not seed functions), which is exactly what the store contains\n * after execution.\n *\n * @param store - Store populated by executeSeeds()\n * @returns Map of schema name to array of items\n */\nexport function buildSeedMapFromStore(store: Store): Map<string, unknown[]> {\n const seedMap = new Map<string, unknown[]>();\n for (const schemaName of store.getSchemas()) {\n const items = store.list(schemaName);\n if (items.length > 0) {\n seedMap.set(schemaName, items);\n }\n }\n return seedMap;\n}\n","/**\n * Hot Reload\n *\n * What: File watcher for hot reloading handlers and seeds with per-spec isolation\n * How: Uses chokidar to watch for file changes, one watcher per spec instance\n * Why: Enables rapid development iteration without server restart; per-spec\n * isolation ensures handler/seed changes in one spec don't affect others\n *\n * @module hot-reload\n */\n\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { executeSeeds, type Logger } from '@websublime/vite-plugin-open-api-core';\nimport type { FSWatcher } from 'chokidar';\nimport type { ViteDevServer } from 'vite';\nimport { printError, printReloadNotification } from './banner.js';\nimport { loadHandlers } from './handlers.js';\nimport type { SpecInstance } from './orchestrator.js';\nimport { buildSeedMapFromStore, loadSeeds } from './seeds.js';\nimport type { ResolvedOptions } from './types.js';\n\n// Segment-boundary patterns: match \"node_modules\" or \"dist\" as a directory\n// segment, not as a substring (avoids false positives like \"distribution/\").\nconst nodeModulesRe = /(^|[\\\\/])node_modules([\\\\/]|$)/;\nconst distRe = /(^|[\\\\/])dist([\\\\/]|$)/;\n\n/**\n * File watcher configuration\n */\nexport interface FileWatcherOptions {\n /** Directory containing handler files */\n handlersDir?: string;\n /** Directory containing seed files */\n seedsDir?: string;\n /** Callback when a handler file changes */\n onHandlerChange?: (filePath: string) => Promise<void> | void;\n /** Callback when a seed file changes */\n onSeedChange?: (filePath: string) => Promise<void> | void;\n /** Current working directory */\n cwd?: string;\n /** Logger for error messages */\n logger?: Logger;\n}\n\n/**\n * File watcher instance\n */\nexport interface FileWatcher {\n /** Close the watcher and release resources */\n close(): Promise<void>;\n /** Check if watcher is active */\n readonly isWatching: boolean;\n /** Promise that resolves when all watchers are ready */\n readonly ready: Promise<void>;\n}\n\n/**\n * Create a file watcher for handlers and seeds\n *\n * Watches for changes to handler and seed files and invokes\n * callbacks when changes are detected. Supports add, change,\n * and unlink events.\n *\n * @example\n * ```typescript\n * const watcher = await createFileWatcher({\n * handlersDir: './mocks/handlers',\n * seedsDir: './mocks/seeds',\n * onHandlerChange: async (file) => {\n * console.log('Handler changed:', file);\n * const handlers = await loadHandlers('./mocks/handlers');\n * server.updateHandlers(handlers.handlers);\n * },\n * onSeedChange: async (file) => {\n * console.log('Seed changed:', file);\n * const seeds = await loadSeeds('./mocks/seeds');\n * // Re-execute seeds...\n * },\n * });\n *\n * // Later, clean up\n * await watcher.close();\n * ```\n *\n * @param options - Watcher configuration\n * @returns Promise resolving to file watcher instance\n */\nexport async function createFileWatcher(options: FileWatcherOptions): Promise<FileWatcher> {\n const {\n handlersDir,\n seedsDir,\n onHandlerChange,\n onSeedChange,\n cwd = process.cwd(),\n logger = console,\n } = options;\n\n // Dynamic import chokidar to avoid bundling issues\n const { watch } = await import('chokidar');\n\n const watchers: FSWatcher[] = [];\n const readyPromises: Promise<void>[] = [];\n let isWatching = true;\n\n // File extension filters — chokidar v4+/v5 removed glob support,\n // so we watch the directory and filter via the `ignored` callback.\n const handlerRe = /\\.handlers\\.(ts|js|mjs)$/;\n const seedRe = /\\.seeds\\.(ts|js|mjs)$/;\n\n /**\n * Wrapper to safely invoke async callbacks and log errors\n * Prevents unhandled promise rejections from file watcher events\n */\n const safeInvoke = (\n callback: (filePath: string) => Promise<void> | void,\n filePath: string,\n context: string,\n ): void => {\n Promise.resolve()\n .then(() => callback(filePath))\n .catch((error) => {\n logger.error(\n `[vite-plugin-open-api-server] ${context} callback error for ${filePath}:`,\n error,\n );\n });\n };\n\n /**\n * Build an `ignored` function for chokidar that accepts only files\n * matching the given pattern and skips node_modules/dist directories.\n */\n const buildIgnored = (pattern: RegExp) => {\n return (filePath: string, stats?: { isFile(): boolean }): boolean => {\n // Always ignore node_modules and dist directories\n if (nodeModulesRe.test(filePath) || distRe.test(filePath)) {\n return true;\n }\n // When stats is unavailable (chokidar's initial pass), allow\n // traversal so subdirectories are not accidentally skipped.\n if (!stats) {\n return false;\n }\n // Allow confirmed directories to be traversed so chokidar\n // descends into sub-folders even though they won't match the\n // file-extension pattern.\n if (!stats.isFile()) {\n return false;\n }\n // Ignore files that don't match the expected pattern\n return !pattern.test(filePath);\n };\n };\n\n try {\n // Watch handlers directory\n if (handlersDir && onHandlerChange) {\n const absoluteHandlersDir = path.resolve(cwd, handlersDir);\n if (!existsSync(absoluteHandlersDir)) {\n logger.warn(\n `[vite-plugin-open-api-server] Handlers directory does not exist, skipping watcher: ${absoluteHandlersDir}`,\n );\n } else {\n const handlerWatcher = watch(absoluteHandlersDir, {\n ignoreInitial: true,\n ignored: buildIgnored(handlerRe),\n persistent: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n handlerWatcher.on('add', (file) => {\n safeInvoke(onHandlerChange, file, 'Handler add');\n });\n\n handlerWatcher.on('change', (file) => {\n safeInvoke(onHandlerChange, file, 'Handler change');\n });\n\n handlerWatcher.on('unlink', (file) => {\n safeInvoke(onHandlerChange, file, 'Handler unlink');\n });\n\n handlerWatcher.on('error', (error) => {\n logger.error('[vite-plugin-open-api-server] Handler watcher error:', error);\n });\n\n // Track ready promise for this watcher\n readyPromises.push(\n new Promise<void>((resolve) => {\n handlerWatcher.on('ready', () => resolve());\n }),\n );\n\n watchers.push(handlerWatcher);\n }\n }\n\n // Watch seeds directory\n if (seedsDir && onSeedChange) {\n const absoluteSeedsDir = path.resolve(cwd, seedsDir);\n if (!existsSync(absoluteSeedsDir)) {\n logger.warn(\n `[vite-plugin-open-api-server] Seeds directory does not exist, skipping watcher: ${absoluteSeedsDir}`,\n );\n } else {\n const seedWatcher = watch(absoluteSeedsDir, {\n ignoreInitial: true,\n ignored: buildIgnored(seedRe),\n persistent: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n seedWatcher.on('add', (file) => {\n safeInvoke(onSeedChange, file, 'Seed add');\n });\n\n seedWatcher.on('change', (file) => {\n safeInvoke(onSeedChange, file, 'Seed change');\n });\n\n seedWatcher.on('unlink', (file) => {\n safeInvoke(onSeedChange, file, 'Seed unlink');\n });\n\n seedWatcher.on('error', (error) => {\n logger.error('[vite-plugin-open-api-server] Seed watcher error:', error);\n });\n\n // Track ready promise for this watcher\n readyPromises.push(\n new Promise<void>((resolve) => {\n seedWatcher.on('ready', () => resolve());\n }),\n );\n\n watchers.push(seedWatcher);\n }\n }\n } catch (error) {\n // Clean up any already-created FSWatchers before re-throwing\n await Promise.allSettled(watchers.map((w) => w.close()));\n throw error;\n }\n\n // Create combined ready promise\n const readyPromise = Promise.all(readyPromises).then(() => {});\n\n return {\n async close(): Promise<void> {\n isWatching = false;\n await Promise.allSettled(watchers.map((w) => w.close()));\n },\n get isWatching(): boolean {\n return isWatching;\n },\n get ready(): Promise<void> {\n return readyPromise;\n },\n };\n}\n\n/**\n * Debounced function with cancel support\n */\nexport interface DebouncedFunction<T extends (...args: unknown[]) => unknown> {\n (...args: Parameters<T>): void;\n /** Cancel any pending debounce timer and queued execution */\n cancel(): void;\n}\n\n/**\n * Debounce a function with async execution guard\n *\n * Useful for preventing multiple rapid reloads when\n * multiple files change at once (e.g., during save all).\n *\n * This implementation prevents overlapping async executions:\n * - If the function is already running, the call is queued\n * - When the running function completes, it executes with the latest args\n * - Multiple calls during execution are coalesced into one\n *\n * @param fn - Function to debounce (can be sync or async)\n * @param delay - Debounce delay in milliseconds\n * @returns Debounced function with cancel() method\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number,\n): DebouncedFunction<T> {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let isRunning = false;\n let pendingArgs: Parameters<T> | null = null;\n let cancelled = false;\n\n const execute = async (...args: Parameters<T>): Promise<void> => {\n if (cancelled || isRunning) {\n if (isRunning && !cancelled) {\n // Queue the latest args for execution after current run completes\n pendingArgs = args;\n }\n return;\n }\n\n isRunning = true;\n try {\n // Wrap in try-catch to handle sync throws, then await for async rejections\n // This prevents both sync errors and async rejections from propagating\n try {\n await fn(...args);\n } catch {\n // Silently catch errors - the caller is responsible for error handling\n // This prevents unhandled rejections from breaking the debounce chain\n }\n } finally {\n isRunning = false;\n\n // If there were calls during execution, run with the latest args\n if (pendingArgs !== null && !cancelled) {\n const nextArgs = pendingArgs;\n pendingArgs = null;\n // Use setTimeout to avoid deep recursion\n setTimeout(() => execute(...nextArgs), 0);\n }\n }\n };\n\n const debouncedFn = (...args: Parameters<T>): void => {\n if (cancelled) return;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n timeoutId = null;\n execute(...args);\n }, delay);\n };\n\n debouncedFn.cancel = (): void => {\n cancelled = true;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n pendingArgs = null;\n };\n\n return debouncedFn;\n}\n\n// =============================================================================\n// Per-Spec Hot Reload\n// =============================================================================\n\n/**\n * Create file watchers for all spec instances\n *\n * Each spec gets independent watchers for its handlers and seeds directories.\n * Changes to one spec's files only trigger reload for that spec instance.\n *\n * @param instances - All spec instances to watch\n * @param vite - Vite dev server (for ssrLoadModule / module invalidation)\n * @param cwd - Project root directory\n * @param options - Resolved plugin options\n * @returns Promise resolving to array of file watchers (one per spec)\n */\nexport async function createPerSpecFileWatchers(\n instances: SpecInstance[],\n vite: ViteDevServer,\n cwd: string,\n options: ResolvedOptions,\n): Promise<FileWatcher[]> {\n const watchers: FileWatcher[] = [];\n const allDebouncedFns: DebouncedFunction<(...args: unknown[]) => unknown>[] = [];\n\n try {\n for (const instance of instances) {\n const debouncedHandlerReload = debounce(\n () => reloadSpecHandlers(instance, vite, cwd, options),\n 100,\n );\n const debouncedSeedReload = debounce(\n () => reloadSpecSeeds(instance, vite, cwd, options),\n 100,\n );\n allDebouncedFns.push(debouncedHandlerReload, debouncedSeedReload);\n\n const innerWatcher = await createFileWatcher({\n handlersDir: instance.config.handlersDir,\n seedsDir: instance.config.seedsDir,\n cwd,\n logger: options.logger,\n onHandlerChange: debouncedHandlerReload,\n onSeedChange: debouncedSeedReload,\n });\n\n // Wrap each FileWatcher so close() also cancels its debounced timers,\n // preventing post-teardown execution of reload functions.\n watchers.push({\n async close(): Promise<void> {\n debouncedHandlerReload.cancel();\n debouncedSeedReload.cancel();\n await innerWatcher.close();\n },\n get isWatching(): boolean {\n return innerWatcher.isWatching;\n },\n get ready(): Promise<void> {\n return innerWatcher.ready;\n },\n });\n }\n } catch (error) {\n // Cancel all debounced timers before closing watchers\n for (const fn of allDebouncedFns) fn.cancel();\n await Promise.allSettled(watchers.map((w) => w.close()));\n throw error;\n }\n\n return watchers;\n}\n\n/**\n * Reload handlers for a specific spec instance\n *\n * Loads fresh handlers from disk via Vite's ssrLoadModule, updates\n * the spec's server, broadcasts a WebSocket event, and logs the result.\n *\n * @param instance - The spec instance to reload handlers for\n * @param vite - Vite dev server\n * @param cwd - Project root directory\n * @param options - Resolved plugin options\n */\nexport async function reloadSpecHandlers(\n instance: SpecInstance,\n vite: ViteDevServer,\n cwd: string,\n options: ResolvedOptions,\n): Promise<void> {\n try {\n const logger = options.logger ?? console;\n const handlersResult = await loadHandlers(instance.config.handlersDir, vite, cwd, logger);\n\n // updateHandlers() broadcasts 'handlers:updated' internally — no explicit broadcast needed.\n // In Epic 3 (Task 3.1), the broadcast wrapper will add specId automatically.\n instance.server.updateHandlers(handlersResult.handlers);\n\n printReloadNotification('handlers', handlersResult.handlers.size, options);\n } catch (error) {\n printError(`Failed to reload handlers for spec \"${instance.id}\"`, error, options);\n }\n}\n\n/**\n * Reload seeds for a specific spec instance\n *\n * Loads fresh seeds from disk, clears the spec's store, re-executes\n * seeds, and syncs the route builder's seed map via `updateSeeds()`.\n * Broadcasts a WebSocket event and logs the result.\n *\n * Note: This operation is not fully atomic — there's a brief window between\n * clearing the store and repopulating it where requests may see empty data.\n * For development tooling, this tradeoff is acceptable.\n *\n * @param instance - The spec instance to reload seeds for\n * @param vite - Vite dev server\n * @param cwd - Project root directory\n * @param options - Resolved plugin options\n */\nexport async function reloadSpecSeeds(\n instance: SpecInstance,\n vite: ViteDevServer,\n cwd: string,\n options: ResolvedOptions,\n): Promise<void> {\n try {\n // Load seeds first (before clearing) to minimize the window where store is empty.\n const logger = options.logger ?? console;\n const seedsResult = await loadSeeds(instance.config.seedsDir, vite, cwd, logger);\n\n instance.server.store.clearAll();\n\n if (seedsResult.seeds.size > 0) {\n try {\n await executeSeeds(seedsResult.seeds, instance.server.store, instance.server.document);\n } catch (execError) {\n // Store was already cleared — warn that it's now empty due to seed execution failure.\n // Sync an empty seed map so the route builder doesn't serve stale data.\n instance.server.updateSeeds(new Map());\n printError(\n `Seeds loaded but executeSeeds failed for spec \"${instance.id}\"; store is now empty`,\n execError,\n options,\n );\n return;\n }\n }\n\n // Sync the route builder's seed map from the now-populated store.\n // updateSeeds() handles: in-place map mutation, registry hasSeed flags,\n // WebSocket broadcast, and logging.\n const seedMap = buildSeedMapFromStore(instance.server.store);\n instance.server.updateSeeds(seedMap);\n\n if (seedMap.size > 0) {\n printReloadNotification('seeds', seedMap.size, options);\n }\n } catch (error) {\n printError(`Failed to reload seeds for spec \"${instance.id}\"`, error, options);\n }\n}\n","/**\n * Multi-Path Proxy Configuration\n *\n * What: Configures Vite proxy for multiple OpenAPI spec instances\n * How: Generates one proxy entry per spec with path rewriting and X-Spec-Id header,\n * plus shared service proxies for DevTools, Internal API, and WebSocket\n * Why: Enables each spec's API requests to be routed through Vite to the shared server\n *\n * @module multi-proxy\n */\n\nimport type { ProxyOptions, ViteDevServer } from 'vite';\n\nimport type { SpecInstance } from './orchestrator.js';\n\n/**\n * Shared service proxy path prefixes.\n *\n * These constants are the single source of truth for the reserved proxy paths\n * used by the DevTools iframe, internal API, and WebSocket connections.\n * Both `configureMultiProxy()` and the virtual DevTools tab module in\n * `plugin.ts` reference these to prevent divergence.\n */\nexport const DEVTOOLS_PROXY_PATH = '/_devtools';\nexport const API_PROXY_PATH = '/_api';\nexport const WS_PROXY_PATH = '/_ws';\n\n/**\n * Ensure `vite.config.server.proxy` exists and return a mutable reference.\n *\n * Returns `null` when `vite.config.server` is falsy, which can happen if\n * the function is called outside the normal Vite plugin lifecycle (e.g.,\n * a custom integration). Callers should early-return on `null`.\n *\n * @internal\n */\nfunction getProxyConfig(vite: ViteDevServer): Record<string, ProxyOptions> | null {\n if (!vite.config.server) {\n return null;\n }\n\n vite.config.server.proxy ??= {};\n return vite.config.server.proxy as Record<string, ProxyOptions>;\n}\n\n/**\n * Configure Vite proxy for multiple spec instances and shared services.\n *\n * Generates:\n * 1. **Per-spec proxy entries** — one per spec, with path rewriting (prefix\n * stripping) and an `X-Spec-Id` header so the shared Hono server can\n * route to the correct spec instance.\n * 2. **Shared service proxies** — spec-agnostic entries for `/_devtools`,\n * `/_api`, and `/_ws` that forward to the same server without path\n * rewriting or spec headers.\n *\n * Uses `startsWith`/`slice` for path rewriting instead of the regex approach\n * described in the tech spec (Section 5.7). Literal prefix matching is safer\n * because it correctly handles regex metacharacters in proxy paths (e.g.,\n * `/api.v3` matches literally, not as `/api<any>v3`).\n *\n * @param vite - Vite dev server instance\n * @param instances - Resolved spec instances from the orchestrator\n * @param port - Shared server port\n */\nexport function configureMultiProxy(\n vite: ViteDevServer,\n instances: SpecInstance[],\n port: number,\n): void {\n const proxyConfig = getProxyConfig(vite);\n if (!proxyConfig) {\n return;\n }\n\n const httpTarget = `http://localhost:${port}`;\n\n // ── Per-spec proxy entries ──────────────────────────────────────────────\n\n for (const instance of instances) {\n const prefix = instance.config.proxyPath;\n\n proxyConfig[prefix] = {\n target: httpTarget,\n changeOrigin: true,\n rewrite: (path: string) => {\n // Guard against prefix collisions: only rewrite when the path equals\n // the prefix exactly or continues with a '/' or '?' segment boundary.\n // e.g. prefix '/api' must NOT rewrite '/api2/users'.\n if (path !== prefix && !path.startsWith(`${prefix}/`) && !path.startsWith(`${prefix}?`))\n return path;\n const rest = path.slice(prefix.length);\n if (rest === '' || rest === '/') return '/';\n if (rest.startsWith('?')) return `/${rest}`;\n return rest;\n },\n headers: { 'x-spec-id': instance.id },\n };\n }\n\n // ── Shared service proxies ─────────────────────────────────────────────\n // Placed after per-spec entries so they overwrite (last-writer-wins on\n // object keys) any per-spec entry that happens to use a reserved path.\n // In practice validateUniqueProxyPaths() guards against such collisions\n // before this function is reached.\n\n proxyConfig[DEVTOOLS_PROXY_PATH] = {\n target: httpTarget,\n changeOrigin: true,\n };\n\n proxyConfig[API_PROXY_PATH] = {\n target: httpTarget,\n changeOrigin: true,\n };\n\n proxyConfig[WS_PROXY_PATH] = {\n target: `ws://localhost:${port}`,\n changeOrigin: true,\n ws: true,\n };\n}\n","{\n \"name\": \"@websublime/vite-plugin-open-api-server\",\n \"version\": \"0.24.0-next.13\",\n \"description\": \"Vite plugin for OpenAPI mock server with DevTools integration\",\n \"keywords\": [\n \"vite\",\n \"plugin\",\n \"openapi\",\n \"mock\",\n \"server\",\n \"devtools\"\n ],\n \"license\": \"MIT\",\n \"author\": \"Websublime\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"main\": \"./dist/index.js\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/websublime/vite-open-api-server.git\",\n \"directory\": \"packages/server\"\n },\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"copy:devtools-spa\": \"node scripts/copy-devtools-spa.mjs\",\n \"build\": \"tsup && pnpm run copy:devtools-spa\"\n },\n \"dependencies\": {\n \"picocolors\": \"^1.1.1\",\n \"@vue/devtools-api\": \"^8.0.6\",\n \"fast-glob\": \"^3.3.3\",\n \"chokidar\": \"^5.0.0\",\n \"@websublime/vite-plugin-open-api-core\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"@websublime/vite-plugin-open-api-devtools\": \"workspace:*\",\n \"typescript\": \"^5.9.0\",\n \"@hono/node-ws\": \"^1.3.0\",\n \"@types/node\": \"^20.17.10\",\n \"@scalar/openapi-types\": \"^0.5.3\",\n \"vite\": \"^7.0.0\",\n \"vue\": \"^3.5.27\",\n \"hono\": \"^4.11.4\",\n \"tsup\": \"^8.5.0\",\n \"@hono/node-server\": \"^1.14.3\"\n },\n \"peerDependencies\": {\n \"@hono/node-server\": \"^1.14.0\",\n \"vite\": \"^5.0.0 || ^6.0.0 || ^7.0.0\",\n \"vue\": \"^3.0.0\",\n \"@hono/node-ws\": \"^1.3.0\",\n \"hono\": \"^4.11.4\"\n },\n \"peerDependenciesMeta\": {\n \"vue\": {\n \"optional\": true\n },\n \"@hono/node-ws\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"private\": false,\n \"type\": \"module\",\n \"types\": \"./dist/index.d.ts\",\n \"module\": \"./dist/index.js\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n }\n}","/**\n * Multi-Spec Internal API\n *\n * What: HTTP API routes for multi-spec DevTools and management\n * How: Aggregated routes across all specs + per-spec routes via :specId param\n * Why: Enables DevTools and external tools to query/manage individual spec instances\n *\n * TODO: Task 5.4.7/5.4.8 will add integration tests for these routes\n * TODO: Export response types when DevTools client (Epic 4) consumes them\n * TODO: Write routes (POST/DELETE store, POST/DELETE simulations, DELETE timeline)\n * are deferred — mutations use WebSocket commands (task 3.2.4). Add HTTP write\n * routes if needed by external tooling.\n *\n * @module multi-internal-api\n */\n\nimport { Hono } from 'hono';\nimport packageJson from '../package.json' with { type: 'json' };\nimport type { SpecInstance } from './orchestrator.js';\n\n/** Hono environment with per-spec middleware variables */\ntype SpecEnv = { Variables: { specInstance: SpecInstance } };\n\n/**\n * Package version from package.json\n */\nconst PACKAGE_VERSION = packageJson.version;\n\n/**\n * Mount multi-spec internal API routes on the main Hono app.\n *\n * Aggregated routes:\n * GET /_api/specs - List all specs with metadata\n * GET /_api/registry - Aggregated registry across all specs\n * GET /_api/health - Aggregated health check\n *\n * Per-spec routes (resolved via middleware):\n * GET /_api/specs/:specId/registry - Registry for one spec\n * GET /_api/specs/:specId/store - List schemas for one spec\n * GET /_api/specs/:specId/store/:schema - Store data for one spec\n * GET /_api/specs/:specId/document - OpenAPI document for one spec\n * GET /_api/specs/:specId/simulations - Simulations for one spec\n * GET /_api/specs/:specId/timeline - Timeline for one spec\n *\n * @param app - Main Hono application\n * @param instances - All resolved spec instances\n */\nexport function mountMultiSpecInternalApi(app: Hono, instances: SpecInstance[]): void {\n const seen = new Set<string>();\n for (const inst of instances) {\n if (seen.has(inst.id)) {\n throw new Error(\n `[vite-plugin-open-api-server] Duplicate specId \"${inst.id}\" in instances array`,\n );\n }\n seen.add(inst.id);\n }\n const instanceMap = new Map(instances.map((i) => [i.id, i]));\n\n // ========================================================================\n // Aggregated Routes\n // ========================================================================\n\n /**\n * GET /_api/specs\n * List all spec instances with metadata\n */\n app.get('/_api/specs', (c) => {\n const specs = instances.map((i) => ({\n id: i.id,\n title: i.info.title,\n version: i.info.version,\n proxyPath: i.config.proxyPath,\n color: i.info.color,\n endpoints: i.server.registry.endpoints.size,\n schemas: i.server.store.getSchemas().length,\n simulations: i.server.simulationManager.count(),\n }));\n return c.json({ specs, count: specs.length });\n });\n\n /**\n * GET /_api/registry\n * Aggregated registry across all specs\n */\n app.get('/_api/registry', (c) => {\n const registries = instances.map((i) => ({\n specId: i.id,\n specTitle: i.info.title,\n specColor: i.info.color,\n endpoints: Array.from(i.server.registry.endpoints.entries()).map(([key, entry]) => ({\n ...entry,\n key,\n })),\n stats: i.server.registry.stats,\n }));\n\n const totalEndpoints = registries.reduce((sum, r) => sum + r.endpoints.length, 0);\n\n return c.json({\n specs: registries,\n totalEndpoints,\n totalSpecs: registries.length,\n });\n });\n\n /**\n * GET /_api/health\n * Aggregated health check with PACKAGE_VERSION\n */\n app.get('/_api/health', (c) => {\n const specs = instances.map((i) => ({\n id: i.id,\n endpoints: i.server.registry.endpoints.size,\n schemas: i.server.store.getSchemas().length,\n simulations: i.server.simulationManager.count(),\n }));\n\n return c.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n version: PACKAGE_VERSION,\n totalSpecs: instances.length,\n totalEndpoints: specs.reduce((s, i) => s + i.endpoints, 0),\n specs,\n });\n });\n\n // ========================================================================\n // Per-Spec Routes (typed sub-app with middleware)\n // ========================================================================\n\n const specApi = new Hono<SpecEnv>();\n\n /**\n * Middleware: resolve spec instance from :specId param.\n * Returns 404 for unknown specId. Sets resolved instance on context\n * for downstream route handlers.\n */\n specApi.use('/:specId/*', async (c, next) => {\n const specId = c.req.param('specId');\n const instance = instanceMap.get(specId);\n if (!instance) {\n return c.json({ error: `Unknown spec: ${specId}` }, 404);\n }\n c.set('specInstance', instance);\n await next();\n });\n\n /**\n * GET /_api/specs/:specId/registry\n * Registry for one spec\n */\n specApi.get('/:specId/registry', (c) => {\n const instance = c.get('specInstance');\n\n return c.json({\n specId: instance.id,\n endpoints: Array.from(instance.server.registry.endpoints.entries()).map(([key, entry]) => ({\n ...entry,\n key,\n })),\n stats: instance.server.registry.stats,\n });\n });\n\n /**\n * GET /_api/specs/:specId/store\n * List schemas for one spec\n */\n specApi.get('/:specId/store', (c) => {\n const instance = c.get('specInstance');\n\n const schemas = instance.server.store.getSchemas().map((schema) => ({\n name: schema,\n count: instance.server.store.getCount(schema),\n idField: instance.server.store.getIdField(schema),\n }));\n return c.json({ specId: instance.id, schemas });\n });\n\n /**\n * GET /_api/specs/:specId/store/:schema\n * Store data for one spec. Supports optional `limit` and `offset` query params.\n *\n * Default limit = min(total, 1000). Store data is typically small so most\n * requests return all items. Capped at 1000 per request in all cases.\n */\n specApi.get('/:specId/store/:schema', (c) => {\n const instance = c.get('specInstance');\n\n const schema = c.req.param('schema');\n const allItems = instance.server.store.list(schema);\n const total = allItems.length;\n\n const rawOffset = Number(c.req.query('offset'));\n const offset = Number.isFinite(rawOffset) ? Math.max(Math.floor(rawOffset), 0) : 0;\n\n const rawLimit = Number(c.req.query('limit'));\n const limit = Number.isFinite(rawLimit)\n ? Math.min(Math.max(Math.floor(rawLimit), 0), 1000)\n : Math.min(total, 1000);\n\n const items = limit === 0 ? [] : allItems.slice(offset, offset + limit);\n return c.json({\n specId: instance.id,\n schema,\n idField: instance.server.store.getIdField(schema),\n items,\n count: items.length,\n total,\n offset,\n limit,\n });\n });\n\n /**\n * GET /_api/specs/:specId/document\n * OpenAPI document for one spec\n */\n specApi.get('/:specId/document', (c) => {\n const instance = c.get('specInstance');\n return c.json(instance.server.document);\n });\n\n /**\n * GET /_api/specs/:specId/simulations\n * Simulations for one spec\n */\n specApi.get('/:specId/simulations', (c) => {\n const instance = c.get('specInstance');\n\n return c.json({\n specId: instance.id,\n simulations: instance.server.simulationManager.list(),\n count: instance.server.simulationManager.count(),\n });\n });\n\n /**\n * GET /_api/specs/:specId/timeline\n * Timeline for one spec.\n *\n * Default limit = 100 (most recent entries) because timeline can grow\n * unbounded during a dev session. Capped at 1000 per request.\n */\n specApi.get('/:specId/timeline', (c) => {\n const instance = c.get('specInstance');\n\n const parsed = Number(c.req.query('limit'));\n const limit = Number.isFinite(parsed) ? Math.min(Math.max(Math.floor(parsed), 0), 1000) : 100;\n const timeline = instance.server.getTimeline();\n const entries = limit === 0 ? [] : timeline.slice(-limit);\n return c.json({\n specId: instance.id,\n entries,\n count: entries.length,\n total: timeline.length,\n limit,\n });\n });\n\n // Mount per-spec sub-app under /_api/specs\n app.route('/_api/specs', specApi);\n}\n","/**\n * Multi-Spec Command Handler\n *\n * What: Routes WebSocket commands to the correct spec instance\n * How: Global commands aggregate across specs; spec-scoped commands delegate to instances\n * Why: Enables DevTools to interact with multiple spec instances through a single WebSocket\n *\n * @module multi-command\n */\n\nimport type {\n SpecInfo,\n WebSocketClient,\n WebSocketHub,\n} from '@websublime/vite-plugin-open-api-core';\nimport type { SpecInstance } from './orchestrator.js';\n\n/**\n * Dependencies for the multi-spec command handler\n */\nexport interface MultiCommandHandlerDeps {\n /** Shared WebSocket hub (the multi-spec hub) */\n hub: WebSocketHub;\n\n /** All spec instances */\n instances: SpecInstance[];\n\n /** Spec metadata array */\n specsInfo: SpecInfo[];\n\n /** Server version string */\n serverVersion: string;\n}\n\n/**\n * Spec-scoped command types that require a `specId` parameter\n */\nconst SPEC_SCOPED_COMMANDS = new Set([\n 'get:store',\n 'set:store',\n 'clear:store',\n 'set:simulation',\n 'clear:simulation',\n 'reseed',\n]);\n\n/** Parsed command shape from client */\ninterface ParsedCommand {\n type: string;\n data?: { specId?: string; [key: string]: unknown };\n}\n\n/**\n * Send an error response to a client\n */\nfunction sendError(\n hub: WebSocketHub,\n client: WebSocketClient,\n command: string,\n message: string,\n): void {\n // biome-ignore lint/suspicious/noExplicitAny: error event data shape compatible with ServerEvent\n hub.sendTo(client, { type: 'error', data: { command, message } } as any);\n}\n\n/**\n * Resolve a spec instance from a specId, sending an error if not found.\n * Returns the instance or undefined if invalid.\n *\n * Dual-use contract:\n * - Falsy specId → returns undefined without error. Aggregated handlers\n * (handleGetRegistry, handleGetTimeline, handleClearTimeline) rely on this\n * to iterate all specs when no specId is provided.\n * - Truthy specId not in map → sends an error to the client and returns undefined.\n * - Spec-scoped handlers (handleSpecScoped) perform their own specId-required\n * validation before calling this function.\n */\nfunction resolveInstance(\n specId: string | undefined,\n instanceMap: Map<string, SpecInstance>,\n hub: WebSocketHub,\n client: WebSocketClient,\n commandType: string,\n): SpecInstance | undefined {\n if (!specId) return undefined;\n const instance = instanceMap.get(specId);\n if (!instance) {\n sendError(hub, client, commandType, `Unknown spec: ${specId}`);\n }\n return instance;\n}\n\n/**\n * Handle get:specs — return enhanced connected event\n */\nfunction handleGetSpecs(\n hub: WebSocketHub,\n client: WebSocketClient,\n specsInfo: SpecInfo[],\n serverVersion: string,\n): void {\n // biome-ignore lint/suspicious/noExplicitAny: MultiSpecServerEvent connected data extends ServerEvent\n hub.sendTo(client, { type: 'connected', data: { serverVersion, specs: specsInfo } } as any);\n}\n\n/**\n * Handle get:registry — single spec (by specId) or all specs.\n *\n * Constructs the registry response directly (with specId) rather than\n * delegating to per-spec hubs, for consistency with other handlers.\n */\nfunction handleGetRegistry(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instances: SpecInstance[],\n instanceMap: Map<string, SpecInstance>,\n): void {\n const sendRegistry = (instance: SpecInstance, id: string) => {\n const registryEvent = {\n type: 'registry',\n data: {\n specId: id,\n endpoints: Array.from(instance.server.registry.endpoints.entries()).map(([key, entry]) => ({\n ...entry,\n key,\n })),\n stats: { ...instance.server.registry.stats },\n },\n };\n // biome-ignore lint/suspicious/noExplicitAny: registry data with specId extends ServerEvent\n hub.sendTo(client, registryEvent as any);\n };\n\n const specId = cmd.data?.specId;\n if (specId) {\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n sendRegistry(instance, specId);\n } else {\n for (const instance of instances) {\n sendRegistry(instance, instance.id);\n }\n }\n}\n\n/**\n * Handle get:timeline — single spec or all specs\n */\nfunction handleGetTimeline(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instances: SpecInstance[],\n instanceMap: Map<string, SpecInstance>,\n): void {\n const specId = cmd.data?.specId;\n const rawLimit = Number(cmd.data?.limit);\n const limit = Number.isFinite(rawLimit) ? Math.min(Math.max(Math.floor(rawLimit), 0), 1000) : 100;\n\n const sendTimeline = (instance: SpecInstance, id: string) => {\n const timeline = instance.server.getTimeline();\n const entries = limit === 0 ? [] : timeline.slice(-limit);\n const timelineEvent = {\n type: 'timeline',\n data: {\n specId: id,\n entries,\n count: entries.length,\n total: timeline.length,\n },\n };\n // biome-ignore lint/suspicious/noExplicitAny: timeline data with specId extends ServerEvent\n hub.sendTo(client, timelineEvent as any);\n };\n\n if (specId) {\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n sendTimeline(instance, specId);\n } else {\n for (const instance of instances) {\n sendTimeline(instance, instance.id);\n }\n }\n}\n\n/**\n * Handle clear:timeline — single spec or all specs\n */\nfunction handleClearTimeline(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instances: SpecInstance[],\n instanceMap: Map<string, SpecInstance>,\n): void {\n const specId = cmd.data?.specId;\n\n const clearAndNotify = (instance: SpecInstance, id: string) => {\n const count = instance.server.clearTimeline();\n // biome-ignore lint/suspicious/noExplicitAny: cleared data with specId\n hub.sendTo(client, { type: 'timeline:cleared', data: { specId: id, count } } as any);\n };\n\n if (specId) {\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n clearAndNotify(instance, specId);\n } else {\n for (const instance of instances) {\n clearAndNotify(instance, instance.id);\n }\n }\n}\n\n/**\n * Handle spec-scoped commands — delegate to the correct instance's command handler\n */\nfunction handleSpecScoped(\n cmd: ParsedCommand,\n hub: WebSocketHub,\n client: WebSocketClient,\n instanceMap: Map<string, SpecInstance>,\n): void {\n const specId = cmd.data?.specId;\n if (!specId) {\n sendError(hub, client, cmd.type, 'specId is required for this command');\n return;\n }\n\n const instance = resolveInstance(specId, instanceMap, hub, client, cmd.type);\n if (!instance) return;\n\n // Forward to the instance's command handler, stripping specId\n // (core command handler doesn't know about specId)\n const { specId: _, ...coreData } = cmd.data ?? {};\n const coreCommand =\n Object.keys(coreData).length > 0 ? { type: cmd.type, data: coreData } : { type: cmd.type };\n\n instance.server.wsHub.handleMessage(client, JSON.stringify(coreCommand));\n}\n\n/**\n * Create a multi-spec command handler that routes commands to the correct spec instance.\n *\n * Command routing:\n * - `get:specs` — returns enhanced connected event with all specs metadata\n * - `get:registry` — aggregates across all specs (no specId) or single spec (with specId)\n * - `get:timeline` / `clear:timeline` — global (all specs) or single spec\n * - Spec-scoped commands (`get:store`, `set:store`, `clear:store`, `set:simulation`,\n * `clear:simulation`, `reseed`) — require specId, delegate to instance's command handler\n *\n * @param deps - Dependencies for command routing\n * @returns Command handler function compatible with `hub.setCommandHandler()`\n */\nexport function createMultiSpecCommandHandler(\n deps: MultiCommandHandlerDeps,\n): (client: WebSocketClient, command: unknown) => void {\n const { hub, instances, specsInfo, serverVersion } = deps;\n const instanceMap = new Map(instances.map((i) => [i.id, i]));\n\n return (client: WebSocketClient, command: unknown) => {\n if (!command || typeof command !== 'object' || !('type' in command)) {\n return;\n }\n const cmd = command as ParsedCommand;\n if (typeof cmd.type !== 'string') {\n return;\n }\n\n switch (cmd.type) {\n case 'get:specs':\n handleGetSpecs(hub, client, specsInfo, serverVersion);\n break;\n case 'get:registry':\n handleGetRegistry(cmd, hub, client, instances, instanceMap);\n break;\n case 'get:timeline':\n handleGetTimeline(cmd, hub, client, instances, instanceMap);\n break;\n case 'clear:timeline':\n handleClearTimeline(cmd, hub, client, instances, instanceMap);\n break;\n default:\n if (SPEC_SCOPED_COMMANDS.has(cmd.type)) {\n handleSpecScoped(cmd, hub, client, instanceMap);\n } else {\n sendError(hub, client, cmd.type, `Unknown command type: ${cmd.type}`);\n }\n break;\n }\n };\n}\n","/**\n * Multi-Spec WebSocket Hub\n *\n * What: Creates a single WebSocket hub for all spec instances\n * How: Wraps the core hub with broadcast interception and enhanced connected event\n * Why: Enables spec-aware real-time communication with DevTools\n *\n * @module multi-ws\n */\n\nimport {\n createWebSocketHub,\n type SpecInfo,\n type WebSocketClient,\n type WebSocketHub,\n} from '@websublime/vite-plugin-open-api-core';\nimport packageJson from '../package.json' with { type: 'json' };\nimport { createMultiSpecCommandHandler } from './multi-command.js';\nimport type { SpecInstance } from './orchestrator.js';\n\n/**\n * Package version from package.json\n */\nconst PACKAGE_VERSION = packageJson.version;\n\n/**\n * Command types that exist only in multi-spec mode and are NOT in\n * the core hub's CLIENT_COMMAND_TYPES. These need special handling\n * because the core hub rejects unknown command types.\n */\nconst MULTI_SPEC_ONLY_COMMANDS = new Set(['get:specs']);\n\n/**\n * Create a multi-spec aware WebSocket hub.\n *\n * Strategy:\n * - Single WebSocket hub for all connections (`autoConnect: false`)\n * - `addClient()` is overridden to send an enhanced `connected` event with\n * `specs` metadata and `PACKAGE_VERSION`\n * - Each core server's `wsHub.broadcast()` is intercepted to add `specId`\n * to event data before broadcasting on the shared hub\n * - Client commands are routed to the correct spec instance via the\n * multi-spec command handler\n *\n * @param instances - All resolved spec instances\n * @param specsInfo - Spec metadata array (for the `connected` event)\n * @returns Shared WebSocket hub with multi-spec support\n */\nexport function createMultiSpecWebSocketHub(\n instances: SpecInstance[],\n specsInfo: SpecInfo[],\n): WebSocketHub {\n // autoConnect: false prevents the hub from sending its own 'connected'\n // event in addClient(). We send an enhanced version instead.\n const hub = createWebSocketHub({ autoConnect: false });\n\n // --- Override addClient to send enhanced connected event ---\n const originalAddClient = hub.addClient.bind(hub);\n hub.addClient = (ws: WebSocketClient) => {\n originalAddClient(ws);\n\n // Send multi-spec enhanced connected event\n hub.sendTo(ws, {\n type: 'connected',\n // biome-ignore lint/suspicious/noExplicitAny: MultiSpecServerEvent extends ServerEvent with specs[]\n data: { serverVersion: PACKAGE_VERSION, specs: specsInfo } as any,\n });\n };\n\n // --- Wire each core server's broadcasts to add specId ---\n for (const instance of instances) {\n instance.server.wsHub.broadcast = (event) => {\n // Add specId to the event data and broadcast on the shared hub\n // biome-ignore lint/suspicious/noExplicitAny: enriching ServerEvent with specId at runtime\n const enriched = { type: event.type, data: { ...(event as any).data, specId: instance.id } };\n // biome-ignore lint/suspicious/noExplicitAny: enriched event compatible with ServerEvent\n hub.broadcast(enriched as any);\n };\n\n // Also intercept sendTo for direct responses that go through the core hub\n instance.server.wsHub.sendTo = (client, event) => {\n // Add specId to direct responses too\n // biome-ignore lint/suspicious/noExplicitAny: enriching ServerEvent with specId at runtime\n const enriched = { type: event.type, data: { ...(event as any).data, specId: instance.id } };\n // biome-ignore lint/suspicious/noExplicitAny: enriched event compatible with ServerEvent\n return hub.sendTo(client, enriched as any);\n };\n }\n\n // --- Set up multi-spec command handler ---\n const commandHandler = createMultiSpecCommandHandler({\n hub,\n instances,\n specsInfo,\n serverVersion: PACKAGE_VERSION,\n });\n\n hub.setCommandHandler(commandHandler);\n\n // --- Override handleMessage to accept multi-spec-only commands ---\n // The core hub's handleMessage validates command types against CLIENT_COMMAND_TYPES,\n // which doesn't include multi-spec commands like 'get:specs'. We intercept these\n // before the core validation and route them directly to the command handler.\n const originalHandleMessage = hub.handleMessage.bind(hub);\n hub.handleMessage = (client: WebSocketClient, message: string | unknown) => {\n try {\n const parsed = typeof message === 'string' ? JSON.parse(message) : message;\n if (parsed && typeof parsed === 'object' && 'type' in parsed) {\n const cmd = parsed as { type: string };\n if (MULTI_SPEC_ONLY_COMMANDS.has(cmd.type)) {\n commandHandler(client, cmd as never);\n return;\n }\n }\n } catch {\n // Fall through to core handleMessage which handles parse errors\n }\n originalHandleMessage(client, message);\n };\n\n return hub;\n}\n","/**\n * Vite Plugin Types\n *\n * What: Type definitions for the OpenAPI server Vite plugin\n * How: Defines configuration options, resolved types, and validation errors\n * Why: Provides type safety and documentation for plugin consumers\n *\n * @module types\n */\n\nimport type { Logger } from '@websublime/vite-plugin-open-api-core';\n\n// =============================================================================\n// Validation Error Codes (Appendix B)\n// =============================================================================\n\n/**\n * Error codes for configuration validation errors.\n *\n * Used across Tasks 1.2–1.4 for typed error handling.\n * Matches TECHNICAL-SPECIFICATION-V2.md Appendix B.\n */\nexport type ValidationErrorCode =\n | 'SPEC_ID_MISSING'\n | 'SPEC_ID_DUPLICATE'\n | 'PROXY_PATH_MISSING'\n | 'PROXY_PATH_TOO_BROAD'\n | 'PROXY_PATH_DUPLICATE'\n | 'PROXY_PATH_OVERLAP'\n | 'PROXY_PATH_PREFIX_COLLISION'\n | 'SPEC_NOT_FOUND'\n | 'SPECS_EMPTY';\n\n/**\n * Typed validation error for configuration issues.\n *\n * Thrown by resolveOptions() and validation functions in spec-id.ts\n * and proxy-path.ts. Consumers can catch and inspect the `code` field\n * for programmatic error handling.\n *\n * @example\n * ```typescript\n * try {\n * resolveOptions({ specs: [] });\n * } catch (error) {\n * if (error instanceof ValidationError && error.code === 'SPECS_EMPTY') {\n * // handle empty specs\n * }\n * }\n * ```\n */\nexport class ValidationError extends Error {\n readonly code: ValidationErrorCode;\n\n constructor(code: ValidationErrorCode, message: string) {\n super(message);\n this.name = 'ValidationError';\n this.code = code;\n }\n}\n\n// =============================================================================\n// Shared Type Aliases\n// =============================================================================\n\n/**\n * How a proxy path was determined.\n *\n * - `'explicit'` — set directly in SpecConfig.proxyPath\n * - `'auto'` — auto-derived from the OpenAPI document's servers[0].url\n *\n * Used by both DeriveProxyPathResult and ResolvedSpecConfig to ensure\n * the two sources of this value stay in sync.\n */\nexport type ProxyPathSource = 'auto' | 'explicit';\n\n// =============================================================================\n// User-Facing Configuration Types\n// =============================================================================\n\n/**\n * Configuration for a single OpenAPI spec instance\n *\n * @example\n * ```typescript\n * const petstore: SpecConfig = {\n * spec: './openapi/petstore.yaml',\n * id: 'petstore',\n * proxyPath: '/api/v3',\n * handlersDir: './mocks/petstore/handlers',\n * seedsDir: './mocks/petstore/seeds',\n * idFields: { Pet: 'petId' },\n * };\n * ```\n */\nexport interface SpecConfig {\n /**\n * Path to OpenAPI spec file (required)\n *\n * Supports: file paths, URLs, YAML, JSON\n *\n * @example './openapi/petstore.yaml'\n * @example 'https://petstore3.swagger.io/api/v3/openapi.json'\n */\n spec: string;\n\n /**\n * Unique identifier for this spec instance\n *\n * Used for routing, DevTools grouping, logging, default directory names.\n * If omitted, auto-derived from spec's info.title (slugified).\n *\n * @example 'petstore'\n */\n id?: string;\n\n /**\n * Base path for request proxy\n *\n * If omitted, auto-derived from spec's servers[0].url.\n * Must be unique across all specs.\n *\n * @example '/api/v3'\n */\n proxyPath?: string;\n\n /**\n * Directory containing handler files for this spec\n * @default './mocks/{specId}/handlers'\n */\n handlersDir?: string;\n\n /**\n * Directory containing seed files for this spec\n * @default './mocks/{specId}/seeds'\n */\n seedsDir?: string;\n\n /**\n * ID field configuration per schema for this spec\n * @default {} (uses 'id' for all schemas)\n */\n idFields?: Record<string, string>;\n}\n\n/**\n * Plugin configuration options\n *\n * @example\n * ```typescript\n * import { openApiServer } from '@websublime/vite-plugin-open-api-server';\n *\n * export default defineConfig({\n * plugins: [\n * openApiServer({\n * specs: [\n * { spec: './openapi/petstore.yaml' },\n * { spec: './openapi/inventory.yaml', id: 'inventory' },\n * ],\n * port: 4000,\n * }),\n * ],\n * });\n * ```\n */\nexport interface OpenApiServerOptions {\n /**\n * Array of OpenAPI spec configurations (required)\n * Each entry runs as an isolated instance.\n */\n specs: SpecConfig[];\n\n /**\n * Server port — all spec instances share this port\n * @default 4000\n */\n port?: number;\n\n /**\n * Enable/disable plugin\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Maximum timeline events per spec\n * @default 500\n */\n timelineLimit?: number;\n\n /**\n * Enable DevTools integration\n * @default true\n */\n devtools?: boolean;\n\n /**\n * Enable CORS\n * @default true\n */\n cors?: boolean;\n\n /**\n * CORS origin configuration\n * @default '*'\n */\n corsOrigin?: string | string[];\n\n /**\n * Custom logger instance\n */\n logger?: Logger;\n\n /**\n * Suppress startup banner\n * @default false\n */\n silent?: boolean;\n}\n\n// =============================================================================\n// Internal Resolved Types\n// =============================================================================\n\n/**\n * Resolved spec config with all defaults applied\n *\n * Exported for advanced use cases (e.g., custom orchestrators or\n * test utilities that need to inspect resolved configuration).\n */\nexport interface ResolvedSpecConfig {\n spec: string;\n /** Empty string until orchestrator resolution; guaranteed non-empty after `createOrchestrator()` */\n id: string;\n /** Empty string until orchestrator resolution; guaranteed non-empty after `createOrchestrator()` */\n proxyPath: string;\n /**\n * How proxyPath was determined — used for banner display.\n *\n * Written back by the orchestrator after document processing.\n * Used by the startup banner to display `(auto-derived)` vs\n * `(explicit)` next to each proxy path.\n */\n proxyPathSource: ProxyPathSource;\n handlersDir: string;\n seedsDir: string;\n idFields: Record<string, string>;\n}\n\n/**\n * Resolved options with defaults applied\n *\n * Exported for advanced use cases (e.g., custom orchestrators or\n * test utilities that need to inspect resolved configuration).\n */\nexport interface ResolvedOptions {\n specs: ResolvedSpecConfig[];\n port: number;\n enabled: boolean;\n timelineLimit: number;\n devtools: boolean;\n cors: boolean;\n corsOrigin: string | string[];\n silent: boolean;\n logger?: Logger;\n}\n\n// =============================================================================\n// Option Resolution\n// =============================================================================\n\n/**\n * Validate that specs array is non-empty and each entry has a valid spec field.\n *\n * @param specs - Array of spec configurations to validate\n * @throws {ValidationError} SPECS_EMPTY if specs array is missing or empty\n * @throws {ValidationError} SPEC_NOT_FOUND if a spec entry has empty spec field\n */\nexport function validateSpecs(specs: SpecConfig[]): void {\n if (!specs || !Array.isArray(specs) || specs.length === 0) {\n throw new ValidationError(\n 'SPECS_EMPTY',\n 'specs is required and must be a non-empty array of SpecConfig',\n );\n }\n\n for (let i = 0; i < specs.length; i++) {\n const spec = specs[i];\n if (!spec || typeof spec !== 'object') {\n throw new ValidationError(\n 'SPEC_NOT_FOUND',\n `specs[${i}]: must be a SpecConfig object, got ${spec === null ? 'null' : typeof spec}`,\n );\n }\n if (!spec.spec || typeof spec.spec !== 'string' || spec.spec.trim() === '') {\n const identifier = spec.id ? ` (id: \"${spec.id}\")` : '';\n throw new ValidationError(\n 'SPEC_NOT_FOUND',\n `specs[${i}]${identifier}: spec field is required and must be a non-empty string (path or URL to OpenAPI spec)`,\n );\n }\n }\n}\n\n/**\n * Resolve options with defaults.\n *\n * Note: spec ID and proxyPath resolution requires processing the OpenAPI document\n * first, so they are resolved later in the orchestrator.\n * This function only resolves static defaults.\n *\n * @param options - User-provided options\n * @returns Resolved options with all defaults applied\n */\nexport function resolveOptions(options: OpenApiServerOptions): ResolvedOptions {\n validateSpecs(options.specs);\n\n return {\n specs: options.specs.map((s) => ({\n spec: s.spec,\n // Placeholder — populated by orchestrator after document processing\n id: s.id ?? '',\n // Placeholder — populated by orchestrator after document processing\n proxyPath: s.proxyPath ?? '',\n // Preliminary — overwritten by deriveProxyPath() during orchestration\n proxyPathSource: s.proxyPath?.trim() ? 'explicit' : 'auto',\n handlersDir: s.handlersDir ?? '',\n seedsDir: s.seedsDir ?? '',\n idFields: s.idFields ?? {},\n })),\n port: options.port ?? 4000,\n enabled: options.enabled ?? true,\n timelineLimit: options.timelineLimit ?? 500,\n devtools: options.devtools ?? true,\n cors: options.cors ?? true,\n corsOrigin: options.corsOrigin ?? '*',\n silent: options.silent ?? false,\n logger: options.logger,\n };\n}\n","/**\n * Proxy Path Auto-Detection\n *\n * What: Functions to derive and validate proxy paths for spec instances\n * How: Extracts path from explicit config or auto-derives from servers[0].url\n * Why: Each spec instance needs a unique, non-overlapping proxy path for\n * Vite proxy configuration and request routing\n *\n * @module proxy-path\n */\n\nimport type { OpenAPIV3_1 } from '@scalar/openapi-types';\n\nimport { API_PROXY_PATH, DEVTOOLS_PROXY_PATH, WS_PROXY_PATH } from './multi-proxy.js';\nimport type { ProxyPathSource } from './types.js';\nimport { ValidationError } from './types.js';\n\n/**\n * Reserved proxy path prefixes used by shared services.\n *\n * User-defined `proxyPath` values must not collide with these.\n */\nconst RESERVED_PROXY_PATHS: readonly string[] = [\n DEVTOOLS_PROXY_PATH,\n API_PROXY_PATH,\n WS_PROXY_PATH,\n];\n\n// =============================================================================\n// Result Types\n// =============================================================================\n\n/**\n * Result of proxy path derivation\n *\n * Includes the normalized path and how it was determined,\n * so the startup banner can display \"(auto-derived)\" vs \"(explicit)\".\n */\nexport interface DeriveProxyPathResult {\n /** Normalized proxy path (e.g., \"/api/v3\") */\n proxyPath: string;\n /** How the path was determined */\n proxyPathSource: ProxyPathSource;\n}\n\n// =============================================================================\n// deriveProxyPath()\n// =============================================================================\n\n/**\n * Derive the proxy path from config or OpenAPI document's servers field\n *\n * Priority:\n * 1. Explicit proxyPath from config (if non-empty after trimming)\n * 2. Path portion of servers[0].url\n *\n * Full URLs (e.g., \"https://api.example.com/api/v3\") have their path\n * extracted via the URL constructor. Relative paths (e.g., \"/api/v3\")\n * are used directly.\n *\n * @param explicitPath - proxyPath from SpecConfig (may be empty)\n * @param document - Processed OpenAPI document\n * @param specId - Spec ID for error messages\n * @returns Normalized proxy path with source indication\n * @throws {ValidationError} PROXY_PATH_MISSING if path cannot be derived\n * @throws {ValidationError} PROXY_PATH_TOO_BROAD if path resolves to \"/\" (e.g., \"/\", \".\", \"..\")\n *\n * @example\n * // Explicit path\n * deriveProxyPath('/api/v3', document, 'petstore')\n * // → { proxyPath: '/api/v3', proxyPathSource: 'explicit' }\n *\n * @example\n * // Auto-derived from servers[0].url = \"https://api.example.com/api/v3\"\n * deriveProxyPath('', document, 'petstore')\n * // → { proxyPath: '/api/v3', proxyPathSource: 'auto' }\n */\nexport function deriveProxyPath(\n explicitPath: string,\n document: OpenAPIV3_1.Document,\n specId: string,\n): DeriveProxyPathResult {\n if (explicitPath.trim()) {\n return {\n proxyPath: normalizeProxyPath(explicitPath.trim(), specId),\n proxyPathSource: 'explicit',\n };\n }\n\n const servers = document.servers;\n const serverUrl = servers?.[0]?.url?.trim();\n if (!serverUrl) {\n throw new ValidationError(\n 'PROXY_PATH_MISSING',\n `[${specId}] Cannot derive proxyPath: no servers defined in the OpenAPI document. ` +\n 'Set an explicit proxyPath in the spec configuration.',\n );\n }\n\n let path: string;\n let parsedUrl: URL | undefined;\n\n try {\n parsedUrl = new URL(serverUrl);\n } catch {\n // Not a full URL — treat as relative path\n }\n\n if (parsedUrl) {\n try {\n // Decode percent-encoded characters (e.g., URL constructor encodes\n // OpenAPI template variable braces: /{version} → /%7Bversion%7D)\n path = decodeURIComponent(parsedUrl.pathname);\n } catch {\n // Malformed percent-encoding — fall back to the raw pathname\n path = parsedUrl.pathname;\n }\n } else {\n path = serverUrl;\n }\n\n return {\n proxyPath: normalizeProxyPath(path, specId),\n proxyPathSource: 'auto',\n };\n}\n\n// =============================================================================\n// normalizeProxyPath()\n// =============================================================================\n\n/**\n * Normalize and validate a proxy path\n *\n * Rules:\n * - Strip query strings and fragments\n * - Ensure leading slash\n * - Collapse consecutive slashes\n * - Resolve dot segments (\".\" and \"..\" per RFC 3986 §5.2.4)\n * - Remove trailing slash\n * - Reject \"/\" as too broad (would capture all requests, including dot-segments that resolve to \"/\")\n *\n * @param path - Raw path string to normalize\n * @param specId - Spec ID for error messages\n * @returns Normalized path (e.g., \"/api/v3\")\n * @throws {ValidationError} PROXY_PATH_TOO_BROAD if path resolves to \"/\" (e.g., \"/\", \".\", \"..\")\n *\n * @example\n * normalizeProxyPath('api/v3', 'petstore') → '/api/v3'\n * normalizeProxyPath('/api/v3/', 'petstore') → '/api/v3'\n */\nexport function normalizeProxyPath(path: string, specId: string): string {\n // Trim leading/trailing whitespace (e.g., \" /api/v3 \" → \"/api/v3\")\n path = path.trim();\n\n // Strip query string and fragment (e.g., \"/api/v3?debug=true#section\" → \"/api/v3\")\n const queryIdx = path.indexOf('?');\n const hashIdx = path.indexOf('#');\n const cutIdx = Math.min(\n queryIdx >= 0 ? queryIdx : path.length,\n hashIdx >= 0 ? hashIdx : path.length,\n );\n let normalized = path.slice(0, cutIdx);\n\n // Ensure leading slash\n normalized = normalized.startsWith('/') ? normalized : `/${normalized}`;\n\n // Collapse consecutive slashes (e.g., \"//api//v3\" → \"/api/v3\")\n normalized = normalized.replace(/\\/{2,}/g, '/');\n\n // Resolve dot segments per RFC 3986 §5.2.4 (e.g., \"/api/../v3\" → \"/v3\")\n // HTTP clients canonicalize these, so proxy paths must match the resolved form\n const segments = normalized.split('/');\n const resolved: string[] = [];\n for (const segment of segments) {\n if (segment === '.') {\n continue;\n }\n if (segment === '..') {\n // Don't pop beyond root\n if (resolved.length > 1) {\n resolved.pop();\n }\n continue;\n }\n resolved.push(segment);\n }\n normalized = resolved.join('/') || '/';\n\n // Remove trailing slash (but not if path is just \"/\")\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n if (normalized === '/') {\n throw new ValidationError(\n 'PROXY_PATH_TOO_BROAD',\n `[${specId}] proxyPath \"/\" is too broad — it would capture all requests. ` +\n 'Set a more specific proxyPath (e.g., \"/api/v1\").',\n );\n }\n\n return normalized;\n}\n\n// =============================================================================\n// validateUniqueProxyPaths()\n// =============================================================================\n\n/**\n * Validate proxy paths are unique and non-overlapping\n *\n * Checks for:\n * 1. Duplicate paths — two specs with the same proxyPath\n * 2. Overlapping paths — one path is a prefix of another at a segment boundary\n * (e.g., \"/api\" and \"/api/v1\") which would cause routing ambiguity\n * 3. String-prefix collisions — one path is a raw string prefix of another\n * without a segment boundary (e.g., \"/api\" and \"/api2\"). Vite's internal\n * proxy matching uses plain `url.startsWith(context)` with no segment\n * awareness, so \"/api\" would incorrectly capture \"/api2/users\" requests.\n *\n * @remarks\n * Entries with an empty or falsy `proxyPath` are silently skipped. These\n * represent specs whose proxy path has not yet been resolved (e.g., during\n * early option resolution before the OpenAPI document is processed). Callers\n * should expect unresolved entries to be excluded from uniqueness checks\n * rather than triggering false-positive errors.\n *\n * @param specs - Array of spec entries with id and proxyPath.\n * Entries with empty/falsy proxyPath are skipped (unresolved).\n * @throws {ValidationError} PROXY_PATH_DUPLICATE if duplicate paths found\n * @throws {ValidationError} PROXY_PATH_OVERLAP if overlapping paths found (segment boundary)\n * @throws {ValidationError} PROXY_PATH_PREFIX_COLLISION if one path is a raw string prefix\n * of another without a segment boundary (e.g., \"/api\" and \"/api2\")\n *\n * @example\n * // Throws PROXY_PATH_DUPLICATE\n * validateUniqueProxyPaths([\n * { id: 'petstore', proxyPath: '/api/v3' },\n * { id: 'inventory', proxyPath: '/api/v3' },\n * ]);\n *\n * @example\n * // Throws PROXY_PATH_OVERLAP\n * validateUniqueProxyPaths([\n * { id: 'petstore', proxyPath: '/api' },\n * { id: 'inventory', proxyPath: '/api/v1' },\n * ]);\n *\n * @example\n * // Throws PROXY_PATH_PREFIX_COLLISION\n * validateUniqueProxyPaths([\n * { id: 'petstore', proxyPath: '/api' },\n * { id: 'inventory', proxyPath: '/api2' },\n * ]);\n */\nexport function validateUniqueProxyPaths(specs: Array<{ id: string; proxyPath: string }>): void {\n const paths = new Map<string, string>();\n\n for (const spec of specs) {\n // Skip entries with empty/whitespace-only proxyPath — they haven't been resolved yet\n const path = spec.proxyPath?.trim();\n if (!path) {\n continue;\n }\n\n validateNotReservedPath(path, spec.id);\n\n if (paths.has(path)) {\n throw new ValidationError(\n 'PROXY_PATH_DUPLICATE',\n `Duplicate proxyPath \"${path}\" used by specs \"${paths.get(path)}\" ` +\n `and \"${spec.id}\". Each spec must have a unique proxyPath.`,\n );\n }\n paths.set(path, spec.id);\n }\n\n validateNoPrefixOverlaps(paths);\n}\n\n/**\n * Throw if the given path collides with a reserved shared-service prefix\n * (e.g. `/_devtools`, `/_api`, `/_ws`).\n */\nfunction validateNotReservedPath(path: string, specId: string): void {\n for (const reserved of RESERVED_PROXY_PATHS) {\n if (path === reserved || path.startsWith(`${reserved}/`) || reserved.startsWith(path)) {\n throw new ValidationError(\n 'PROXY_PATH_OVERLAP',\n `[${specId}] proxyPath \"${path}\" collides with reserved path \"${reserved}\" ` +\n 'used by the shared DevTools/API/WebSocket service.',\n );\n }\n }\n}\n\n/**\n * Detect segment-boundary overlaps (`/api` vs `/api/v1`) and raw\n * string-prefix collisions (`/api` vs `/api2`) among validated proxy paths.\n *\n * Vite's proxy matching uses `url.startsWith(context)` with no segment\n * awareness, so `/api` would incorrectly capture `/api2/*` requests.\n */\nfunction validateNoPrefixOverlaps(paths: Map<string, string>): void {\n const sortedPaths = Array.from(paths.entries()).sort(([a], [b]) => a.length - b.length);\n for (let i = 0; i < sortedPaths.length; i++) {\n for (let j = i + 1; j < sortedPaths.length; j++) {\n const [shorter, shorterId] = sortedPaths[i];\n const [longer, longerId] = sortedPaths[j];\n\n // Segment-boundary overlap: \"/api\" is a parent of \"/api/v1\"\n if (longer.startsWith(`${shorter}/`)) {\n throw new ValidationError(\n 'PROXY_PATH_OVERLAP',\n `Overlapping proxyPaths: \"${shorter}\" (${shorterId}) is a prefix of ` +\n `\"${longer}\" (${longerId}). This would cause routing ambiguity.`,\n );\n }\n\n // Raw string-prefix collision: \"/api\" is a string prefix of \"/api2\".\n if (longer.startsWith(shorter)) {\n throw new ValidationError(\n 'PROXY_PATH_PREFIX_COLLISION',\n `Proxy path prefix collision: \"${shorter}\" (${shorterId}) is a string prefix of ` +\n `\"${longer}\" (${longerId}). Vite's proxy uses startsWith matching, so ` +\n `\"${shorter}\" would incorrectly capture requests meant for \"${longer}\".`,\n );\n }\n }\n }\n}\n","/**\n * Spec ID Derivation\n *\n * What: Functions to derive and validate spec identifiers\n * How: Slugifies explicit IDs or auto-derives from OpenAPI info.title\n * Why: Each spec instance needs a unique, URL-safe identifier for routing,\n * DevTools grouping, logging, and default directory names\n *\n * @module spec-id\n */\n\nimport type { OpenAPIV3_1 } from '@scalar/openapi-types';\n\nimport { ValidationError } from './types.js';\n\n/**\n * Slugify a string for use as a spec identifier\n *\n * Rules:\n * - Lowercase\n * - Replace spaces and special chars with hyphens\n * - Remove consecutive hyphens\n * - Trim leading/trailing hyphens\n *\n * @example\n * slugify(\"Swagger Petstore\") → \"swagger-petstore\"\n * slugify(\"Billing API v2\") → \"billing-api-v2\"\n * slugify(\"café\") → \"cafe\"\n */\nexport function slugify(input: string): string {\n return input\n .normalize('NFD')\n .replace(/\\p{M}/gu, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\n/**\n * Derive a spec ID from the processed OpenAPI document\n *\n * Priority:\n * 1. Explicit id from config (if non-empty)\n * 2. Slugified info.title from the processed document\n *\n * @param explicitId - ID from SpecConfig.id (may be empty)\n * @param document - Processed OpenAPI document\n * @returns Stable, URL-safe spec identifier\n * @throws {ValidationError} SPEC_ID_MISSING if no ID can be derived (missing title and no explicit id)\n */\nexport function deriveSpecId(explicitId: string, document: OpenAPIV3_1.Document): string {\n if (explicitId.trim()) {\n const id = slugify(explicitId);\n if (!id) {\n throw new ValidationError(\n 'SPEC_ID_MISSING',\n `Cannot derive spec ID: explicit id \"${explicitId}\" produces an empty slug. ` +\n 'Please provide an id containing ASCII letters or numbers.',\n );\n }\n return id;\n }\n\n const title = document.info?.title;\n if (!title || !title.trim()) {\n throw new ValidationError(\n 'SPEC_ID_MISSING',\n 'Cannot derive spec ID: info.title is missing from the OpenAPI document. ' +\n 'Please set an explicit id in the spec configuration.',\n );\n }\n\n const id = slugify(title);\n if (!id) {\n throw new ValidationError(\n 'SPEC_ID_MISSING',\n `Cannot derive spec ID: info.title \"${title}\" produces an empty slug. ` +\n 'Please set an explicit id in the spec configuration.',\n );\n }\n\n return id;\n}\n\n/**\n * Validate spec IDs are unique across all specs\n *\n * Collects all duplicated IDs and reports them in a single error.\n *\n * @param ids - Array of resolved spec IDs\n * @throws {ValidationError} SPEC_ID_DUPLICATE if duplicate IDs found\n */\nexport function validateUniqueIds(ids: string[]): void {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of ids) {\n if (seen.has(id)) {\n duplicates.add(id);\n }\n seen.add(id);\n }\n if (duplicates.size > 0) {\n const list = [...duplicates].join(', ');\n throw new ValidationError(\n 'SPEC_ID_DUPLICATE',\n `Duplicate spec IDs: ${list}. Each spec must have a unique ID. ` +\n 'Set explicit ids in spec configuration to resolve.',\n );\n }\n}\n","/**\n * Multi-Spec Orchestrator\n *\n * What: Central orchestrator that creates N spec instances and mounts them on a single Hono app\n * How: Three phases — process specs, validate uniqueness, build main Hono app with dispatch middleware\n * Why: Enables multiple OpenAPI specs to run on a single server with isolated stores and handlers\n *\n * @module orchestrator\n */\n\nimport { existsSync } from 'node:fs';\nimport type { Server as NodeServer } from 'node:http';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n createOpenApiServer,\n executeSeeds,\n type Logger,\n mountDevToolsRoutes,\n type OpenApiServer,\n type SpecInfo,\n type WebSocketHub,\n} from '@websublime/vite-plugin-open-api-core';\nimport { type Context, Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport type { ViteDevServer } from 'vite';\nimport { loadHandlers } from './handlers.js';\nimport { mountMultiSpecInternalApi } from './multi-internal-api.js';\nimport { createMultiSpecWebSocketHub } from './multi-ws.js';\nimport { deriveProxyPath, validateUniqueProxyPaths } from './proxy-path.js';\nimport { buildSeedMapFromStore, loadSeeds } from './seeds.js';\nimport { deriveSpecId, slugify, validateUniqueIds } from './spec-id.js';\nimport type { ResolvedOptions, ResolvedSpecConfig } from './types.js';\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/**\n * Deterministic color palette for spec identification in DevTools.\n *\n * Colors are assigned by index: spec 0 gets green, spec 1 gets blue, etc.\n * Wraps around for >8 specs.\n */\nexport const SPEC_COLORS: readonly string[] = [\n '#4ade80', // green\n '#60a5fa', // blue\n '#f472b6', // pink\n '#facc15', // yellow\n '#a78bfa', // purple\n '#fb923c', // orange\n '#2dd4bf', // teal\n '#f87171', // red\n];\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Resolved spec instance with all runtime data.\n *\n * Created during Phase 1 of orchestration. Each instance owns\n * an isolated core `OpenApiServer` with its own store, registry,\n * handlers, seeds, and timeline.\n */\nexport interface SpecInstance {\n /** Unique spec identifier (explicit or auto-derived from info.title) */\n id: string;\n\n /** Spec metadata for DevTools display and WebSocket protocol */\n info: SpecInfo;\n\n /** Core server instance (isolated Hono app, store, registry, etc.) */\n server: OpenApiServer;\n\n /** Resolved configuration for this spec */\n config: ResolvedSpecConfig;\n}\n\n/**\n * Orchestrator result — returned by `createOrchestrator()`.\n *\n * Provides access to the main Hono app (all specs mounted),\n * individual spec instances, aggregated metadata, and lifecycle methods.\n */\nexport interface OrchestratorResult {\n /**\n * Main Hono app with all specs mounted via X-Spec-Id dispatch.\n *\n * **Note**: Consumers using this property directly must have `hono`\n * as a dependency. The `start()`/`stop()` lifecycle methods do not\n * require direct interaction with this Hono instance.\n */\n app: Hono;\n\n /** All spec instances (in config order) */\n instances: SpecInstance[];\n\n /** Spec metadata array for WebSocket `connected` event */\n specsInfo: SpecInfo[];\n\n /**\n * Shared WebSocket hub for the orchestrator.\n *\n * Created via `createMultiSpecWebSocketHub()` with:\n * - `autoConnect: false` to suppress default connected events\n * - Enhanced `addClient()` that sends specs metadata\n * - Broadcast interception that adds `specId` to all events\n * - Multi-spec command handler for spec-scoped routing\n */\n wsHub: WebSocketHub;\n\n /** Start the shared HTTP server on the configured port */\n start(): Promise<void>;\n\n /** Stop the HTTP server and clean up resources */\n stop(): Promise<void>;\n\n /** Actual bound port after start() resolves (0 before start or after stop) */\n readonly port: number;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/**\n * Resolved values produced by `processSpec` for a single spec.\n *\n * Returned instead of mutating the input `ResolvedSpecConfig` so that\n * the caller (`createOrchestrator`) decides how to propagate the values.\n */\ninterface ProcessedSpec {\n instance: SpecInstance;\n resolvedConfig: {\n id: string;\n proxyPath: string;\n proxyPathSource: 'auto' | 'explicit';\n handlersDir: string;\n seedsDir: string;\n };\n}\n\n/**\n * Process a single spec configuration into a resolved SpecInstance.\n *\n * Loads handlers and seeds, creates the core OpenApiServer, derives the\n * spec ID and proxy path, and builds the SpecInfo metadata.\n *\n * Does **not** mutate `specConfig`. Returns resolved values separately\n * so the caller can assign them back.\n */\nasync function processSpec(\n specConfig: ResolvedSpecConfig,\n index: number,\n options: ResolvedOptions,\n vite: ViteDevServer,\n cwd: string,\n logger: Logger,\n): Promise<ProcessedSpec> {\n // ---- Step 1: Create core server to parse the OpenAPI document ----\n // Pass empty handlers and seeds — they will be loaded from the correct\n // directory once the spec ID is finalized (step 3).\n const server = await createOpenApiServer({\n spec: specConfig.spec,\n port: options.port,\n idFields: specConfig.idFields,\n handlers: new Map(),\n seeds: new Map(),\n timelineLimit: options.timelineLimit,\n cors: false, // CORS handled at main app level\n devtools: false, // DevTools mounted at main app level\n logger,\n });\n\n // ---- Step 2: Derive spec ID and resolve directories ----\n // Now that the document is parsed, we can derive the final spec ID\n // and compute the correct default directory paths.\n // deriveSpecId() always returns a slugified string, so no need to re-slugify.\n const id = deriveSpecId(specConfig.id, server.document);\n const handlersDir = specConfig.handlersDir || `./mocks/${id}/handlers`;\n const seedsDir = specConfig.seedsDir || `./mocks/${id}/seeds`;\n\n // ---- Step 3: Load handlers and seeds from the correct directories ----\n const handlersResult = await loadHandlers(handlersDir, vite, cwd, logger);\n const seedsResult = await loadSeeds(seedsDir, vite, cwd, logger);\n\n // Register loaded handlers on the server (silent: suppress broadcast/log during initial setup)\n if (handlersResult.handlers.size > 0) {\n server.updateHandlers(handlersResult.handlers, { silent: true });\n }\n\n // Execute seed functions to populate the store, then sync route builder\n if (seedsResult.seeds.size > 0) {\n await executeSeeds(seedsResult.seeds, server.store, server.document);\n\n // Sync the route builder's seed map from the now-populated store.\n // executeSeeds() only writes to the store — the route builder's seed map\n // (used for the seed response priority path) is a separate reference that\n // must be updated explicitly via updateSeeds().\n const seedMap = buildSeedMapFromStore(server.store);\n server.updateSeeds(seedMap);\n }\n\n // Derive proxy path (from explicit config or servers[0].url)\n const { proxyPath, proxyPathSource } = deriveProxyPath(specConfig.proxyPath, server.document, id);\n\n // Build SpecInfo metadata for DevTools and WebSocket protocol\n const info: SpecInfo = {\n id,\n title: server.document.info?.title ?? id,\n version: server.document.info?.version ?? 'unknown',\n proxyPath,\n color: SPEC_COLORS[index % SPEC_COLORS.length],\n endpointCount: server.registry.endpoints.size,\n schemaCount: server.store.getSchemas().length,\n };\n\n return {\n instance: { id, info, server, config: specConfig },\n resolvedConfig: { id, proxyPath, proxyPathSource, handlersDir, seedsDir },\n };\n}\n\n// =============================================================================\n// Phase 3 Helpers (extracted for cognitive complexity)\n// =============================================================================\n\n/** CORS configuration used by both mainApp and sub-instance middleware */\ninterface CorsConfig {\n origin: string | string[];\n allowMethods: string[];\n allowHeaders: string[];\n exposeHeaders: string[];\n maxAge: number;\n credentials: boolean;\n}\n\n/**\n * Build the CORS configuration from resolved options.\n *\n * Normalizes `['*']` to `'*'` (Hono's array branch uses `.includes(origin)`\n * which never matches browser-sent origins against the literal `'*'`).\n */\nfunction buildCorsConfig(options: ResolvedOptions): CorsConfig {\n const isWildcardOrigin =\n options.corsOrigin === '*' ||\n (Array.isArray(options.corsOrigin) && options.corsOrigin.includes('*'));\n\n const effectiveCorsOrigin: string | string[] = isWildcardOrigin ? '*' : options.corsOrigin;\n\n return {\n origin: effectiveCorsOrigin,\n allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],\n allowHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'X-Spec-Id'],\n exposeHeaders: ['Content-Length', 'X-Request-Id'],\n maxAge: 86400,\n credentials: !isWildcardOrigin,\n };\n}\n\n/**\n * Mount the DevTools SPA on the main Hono app.\n *\n * Resolves the SPA directory relative to this file's location.\n * Logs a warning if the built SPA is not found.\n */\nfunction mountDevToolsSpa(mainApp: Hono, logger: Logger): void {\n const pluginDir = dirname(fileURLToPath(import.meta.url));\n const spaDir = join(pluginDir, 'devtools-spa');\n const devtoolsSpaDir = existsSync(spaDir) ? spaDir : undefined;\n\n if (!devtoolsSpaDir) {\n logger.warn?.(\n '[vite-plugin-open-api-server] DevTools SPA not found at',\n spaDir,\n '- serving placeholder. Run \"pnpm build\" to include the SPA.',\n );\n }\n\n mountDevToolsRoutes(mainApp, {\n spaDir: devtoolsSpaDir,\n logger,\n });\n}\n\n/**\n * Result of WebSocket route setup.\n *\n * Contains the injection function that must be called on `start()` to\n * hook the Node.js HTTP server's `upgrade` event for WS handshakes.\n */\ninterface WebSocketRouteResult {\n // biome-ignore lint/suspicious/noExplicitAny: @hono/node-ws types expect node http.Server but we store generically\n injectWebSocket: ((server: any) => void) | null;\n}\n\n/**\n * Mount the `/_ws` WebSocket route on the main Hono app.\n *\n * Attempts to dynamically import `@hono/node-ws`. On success, registers\n * the upgrade middleware and returns the `injectWebSocket` function for\n * use during `start()`. On failure (optional peer not installed), mounts\n * a 501 placeholder.\n */\nasync function mountWebSocketRoute(\n mainApp: Hono,\n wsHub: WebSocketHub,\n logger: Logger,\n): Promise<WebSocketRouteResult> {\n // Isolate the dynamic import so only module-not-found errors produce\n // the 501 fallback. Runtime errors from createNodeWebSocket or route\n // registration are real bugs and must propagate.\n let nodeWsModule: typeof import('@hono/node-ws');\n try {\n nodeWsModule = await import('@hono/node-ws');\n } catch (err: unknown) {\n const isModuleNotFound =\n err instanceof Error &&\n ('code' in err\n ? (err as NodeJS.ErrnoException).code === 'ERR_MODULE_NOT_FOUND'\n : err.message.includes('@hono/node-ws'));\n\n if (!isModuleNotFound) {\n throw err;\n }\n\n // @hono/node-ws not available — serve 501 placeholder\n mainApp.get('/_ws', (c) => {\n return c.json(\n {\n message: 'WebSocket endpoint - use ws:// protocol',\n note: 'Install @hono/node-ws to enable WebSocket support',\n },\n 501,\n );\n });\n\n logger.debug?.(\n '[vite-plugin-open-api-server] @hono/node-ws not available, WebSocket upgrade disabled',\n );\n return { injectWebSocket: null };\n }\n\n // Module loaded — wire up the WebSocket route. Errors here (e.g., from\n // createNodeWebSocket or mainApp.get) are bugs and must propagate.\n const nodeWs = nodeWsModule.createNodeWebSocket({ app: mainApp });\n\n mainApp.get(\n '/_ws',\n nodeWs.upgradeWebSocket(() => ({\n onOpen(_event, ws) {\n wsHub.addClient(ws);\n },\n onMessage(event, ws) {\n wsHub.handleMessage(ws, event.data);\n },\n onClose(_event, ws) {\n wsHub.removeClient(ws);\n },\n })),\n );\n\n logger.debug?.('[vite-plugin-open-api-server] WebSocket upgrade enabled at /_ws');\n return { injectWebSocket: nodeWs.injectWebSocket };\n}\n\n/**\n * Create the X-Spec-Id dispatch middleware.\n *\n * Uses slugify() to normalize the incoming header so it matches the\n * instanceMap keys produced by deriveSpecId().\n *\n * **Note**: Dispatched requests bypass `mainApp` response middleware\n * because `instance.server.app.fetch()` returns a raw `Response`.\n * Shared response concerns (e.g., CORS) are applied per-instance.\n */\nfunction createDispatchMiddleware(\n instanceMap: Map<string, SpecInstance>,\n): (c: Context, next: () => Promise<void>) => Promise<Response | undefined> {\n return async (c: Context, next: () => Promise<void>): Promise<Response | undefined> => {\n const rawSpecId = c.req.header('x-spec-id');\n if (!rawSpecId) {\n await next();\n return;\n }\n\n const specId = slugify(rawSpecId.trim());\n if (!specId) {\n await next();\n return;\n }\n\n const instance = instanceMap.get(specId);\n if (!instance) {\n return c.json({ error: `Unknown spec: ${specId}` }, 404);\n }\n\n return instance.server.app.fetch(c.req.raw);\n };\n}\n\n// =============================================================================\n// Orchestrator Factory\n// =============================================================================\n\n/**\n * Create the multi-spec orchestrator.\n *\n * Flow:\n * 1. **Phase 1 — Process specs**: For each spec config, load handlers/seeds,\n * create a core `OpenApiServer` instance, derive ID and proxy path.\n * 2. **Phase 2 — Validate uniqueness**: Ensure all spec IDs and proxy paths\n * are unique and non-overlapping.\n * 3. **Phase 3 — Build main app**: Create a single Hono app with CORS,\n * DevTools, Internal API, and X-Spec-Id dispatch middleware.\n *\n * **Note**: This function populates the resolved values (id, proxyPath,\n * proxyPathSource, handlersDir, seedsDir) on each `options.specs[i]` object.\n * Since `instances[i].config` is the same object reference, consumers should\n * access resolved values through `instances[i].config` (the authoritative view).\n *\n * @param options - Resolved plugin options (from `resolveOptions()`)\n * @param vite - Vite dev server instance (for ssrLoadModule)\n * @param cwd - Project root directory\n * @returns Orchestrator result with app, instances, and lifecycle methods\n */\nexport async function createOrchestrator(\n options: ResolvedOptions,\n vite: ViteDevServer,\n cwd: string,\n): Promise<OrchestratorResult> {\n const logger = options.logger ?? console;\n\n // ========================================================================\n // Phase 1: Process each spec — load handlers/seeds, create core instances\n // ========================================================================\n\n const instances: SpecInstance[] = [];\n for (let i = 0; i < options.specs.length; i++) {\n const { instance, resolvedConfig } = await processSpec(\n options.specs[i],\n i,\n options,\n vite,\n cwd,\n logger,\n );\n\n // Populate the resolved values on the shared spec config object.\n // `instance.config` and `options.specs[i]` are the same reference,\n // so these writes are visible through both. This is intentional:\n // downstream consumers (banner, file watcher, plugin.ts) access\n // the final values via `instance.config`.\n instance.config.id = resolvedConfig.id;\n instance.config.proxyPath = resolvedConfig.proxyPath;\n instance.config.proxyPathSource = resolvedConfig.proxyPathSource;\n instance.config.handlersDir = resolvedConfig.handlersDir;\n instance.config.seedsDir = resolvedConfig.seedsDir;\n\n instances.push(instance);\n }\n\n // ========================================================================\n // Phase 2: Validate uniqueness of IDs and proxy paths\n // ========================================================================\n\n validateUniqueIds(instances.map((inst) => inst.id));\n validateUniqueProxyPaths(\n instances.map((inst) => ({\n id: inst.id,\n proxyPath: inst.config.proxyPath,\n })),\n );\n\n // ========================================================================\n // Phase 3: Build main Hono app\n // ========================================================================\n\n const mainApp = new Hono();\n\n // --- CORS ---\n const corsConfig = buildCorsConfig(options);\n if (options.cors) {\n // mainApp CORS covers shared services (/_devtools, /_api).\n mainApp.use('*', cors(corsConfig));\n // Sub-instance CORS covers dispatched requests (app.fetch() bypasses mainApp middleware).\n for (const inst of instances) {\n inst.server.app.use('*', cors(corsConfig));\n }\n }\n\n // --- DevTools SPA (single SPA for all specs, spec-aware via WebSocket) ---\n if (options.devtools) {\n mountDevToolsSpa(mainApp, logger);\n }\n\n // --- Internal API (multi-spec: aggregated + per-spec routes) ---\n if (instances.length > 0) {\n mountMultiSpecInternalApi(mainApp, instances);\n }\n\n // --- Spec metadata (computed early for the connected event) ---\n const specsInfo = instances.map((inst) => inst.info);\n\n // --- Shared WebSocket Hub (multi-spec aware: broadcast interception + command routing) ---\n const wsHub = createMultiSpecWebSocketHub(instances, specsInfo);\n\n // --- WebSocket Route (/_ws) ---\n const { injectWebSocket } = await mountWebSocketRoute(mainApp, wsHub, logger);\n\n // --- X-Spec-Id dispatch middleware ---\n const instanceMap = new Map(instances.map((inst) => [inst.id, inst]));\n mainApp.use('*', createDispatchMiddleware(instanceMap));\n\n // ========================================================================\n // Lifecycle\n // ========================================================================\n\n let serverInstance: NodeServer | null = null;\n let boundPort = 0;\n\n /**\n * Start a Node.js HTTP server and wait for it to bind.\n *\n * @returns The actual bound port (handles ephemeral port 0).\n */\n async function startServerOnPort(\n fetchHandler: Hono['fetch'],\n port: number,\n ): Promise<{ server: NodeServer; actualPort: number }> {\n let createAdaptorServer: typeof import('@hono/node-server').createAdaptorServer;\n try {\n const nodeServer = await import('@hono/node-server');\n createAdaptorServer = nodeServer.createAdaptorServer;\n } catch {\n throw new Error('@hono/node-server is required. Install with: npm install @hono/node-server');\n }\n\n const server = createAdaptorServer({ fetch: fetchHandler }) as NodeServer;\n\n // Attach listeners BEFORE calling listen() to avoid a race condition\n // where the 'listening' event fires before the handler is registered.\n const actualPort = await new Promise<number>((resolve, reject) => {\n const onListening = () => {\n server.removeListener('error', onError);\n const addr = server.address();\n resolve(typeof addr === 'object' && addr ? addr.port : port);\n };\n\n const onError = (err: NodeJS.ErrnoException) => {\n server.removeListener('listening', onListening);\n server.close(() => {});\n if (err.code === 'EADDRINUSE') {\n reject(new Error(`[vite-plugin-open-api-server] Port ${port} is already in use.`));\n } else {\n reject(new Error(`[vite-plugin-open-api-server] Server error: ${err.message}`));\n }\n };\n\n server.once('listening', onListening);\n server.once('error', onError);\n server.listen(port);\n });\n\n return { server, actualPort };\n }\n\n return {\n app: mainApp,\n instances,\n specsInfo,\n wsHub,\n\n get port(): number {\n return boundPort;\n },\n\n async start(): Promise<void> {\n if (serverInstance) {\n throw new Error('[vite-plugin-open-api-server] Server already running. Call stop() first.');\n }\n\n const { server, actualPort } = await startServerOnPort(mainApp.fetch, options.port);\n serverInstance = server;\n boundPort = actualPort;\n\n // Inject WebSocket support into the Node.js HTTP server.\n // This hooks into the server's 'upgrade' event for WebSocket handshakes.\n if (injectWebSocket) {\n injectWebSocket(serverInstance);\n }\n\n logger.info(`[vite-plugin-open-api-server] Server started on http://localhost:${actualPort}`);\n },\n\n async stop(): Promise<void> {\n const server = serverInstance;\n if (server) {\n try {\n // Remove all clients from the hub's tracking set so broadcasts\n // during teardown are no-ops. Does not close WS connections —\n // closeAllConnections() handles the network layer below.\n wsHub.clear();\n\n // Forcibly destroy all open connections (including WebSocket clients)\n // so server.close() resolves promptly instead of waiting for idle drain.\n if (typeof server.closeAllConnections === 'function') {\n server.closeAllConnections();\n }\n await new Promise<void>((resolve, reject) => {\n server.close((err?: Error) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n logger.info('[vite-plugin-open-api-server] Server stopped');\n } catch (err) {\n logger.error?.('[vite-plugin-open-api-server] Error closing server:', err);\n throw err;\n } finally {\n serverInstance = null;\n boundPort = 0;\n }\n }\n },\n };\n}\n","/**\n * Vite Plugin Implementation\n *\n * What: Main Vite plugin for OpenAPI mock server (multi-spec)\n * How: Uses orchestrator to create N spec instances, configures multi-proxy\n * Why: Integrates multiple OpenAPI mock servers seamlessly into Vite dev workflow\n *\n * @module plugin\n */\n\nimport { createRequire } from 'node:module';\nimport type { Plugin, ViteDevServer } from 'vite';\nimport { extractBannerInfo, printBanner, printError } from './banner.js';\nimport { createPerSpecFileWatchers, type FileWatcher } from './hot-reload.js';\nimport { configureMultiProxy, DEVTOOLS_PROXY_PATH } from './multi-proxy.js';\nimport { createOrchestrator, type OrchestratorResult } from './orchestrator.js';\nimport { type OpenApiServerOptions, resolveOptions } from './types.js';\n\n/**\n * Virtual module ID for the DevTools tab registration script.\n *\n * This script is served as a Vite module (not inline HTML) so that bare\n * import specifiers like `@vue/devtools-api` are resolved through Vite's\n * module pipeline. Inline `<script type=\"module\">` blocks in HTML are\n * executed directly by the browser, which cannot resolve bare specifiers.\n */\nconst VIRTUAL_DEVTOOLS_TAB_ID = 'virtual:open-api-devtools-tab';\nconst RESOLVED_VIRTUAL_DEVTOOLS_TAB_ID = `\\0${VIRTUAL_DEVTOOLS_TAB_ID}`;\n\n/**\n * Create the OpenAPI Server Vite plugin\n *\n * This plugin starts mock servers based on OpenAPI specifications\n * and configures Vite to proxy API requests to them. Supports\n * multiple specs via the orchestrator pattern.\n *\n * @example\n * ```typescript\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import vue from '@vitejs/plugin-vue';\n * import { openApiServer } from '@websublime/vite-plugin-open-api-server';\n *\n * export default defineConfig({\n * plugins: [\n * vue(),\n * openApiServer({\n * specs: [\n * { spec: './openapi/petstore.yaml', proxyPath: '/api/pets' },\n * { spec: './openapi/inventory.yaml', proxyPath: '/api/inventory' },\n * ],\n * port: 4000,\n * }),\n * ],\n * });\n * ```\n *\n * @param options - Plugin configuration options\n * @returns Vite plugin\n */\nexport function openApiServer(options: OpenApiServerOptions): Plugin {\n const resolvedOptions = resolveOptions(options);\n\n let orchestrator: OrchestratorResult | null = null;\n let fileWatchers: FileWatcher[] = [];\n let cwd: string = process.cwd();\n\n return {\n name: 'vite-plugin-open-api-server',\n apply: 'serve',\n\n /**\n * Ensure @vue/devtools-api is available for the DevTools tab module\n *\n * The virtual module imports from '@vue/devtools-api', which Vite needs\n * to pre-bundle so it can be resolved at runtime in the browser, even\n * though the host app may not have it as a direct dependency.\n */\n config() {\n if (!resolvedOptions.devtools || !resolvedOptions.enabled) {\n return;\n }\n\n // Only add to optimizeDeps if the package is actually resolvable\n // to avoid Vite warnings when the consumer hasn't installed it\n const require = createRequire(import.meta.url);\n try {\n require.resolve('@vue/devtools-api');\n } catch {\n return;\n }\n\n return {\n optimizeDeps: {\n include: ['@vue/devtools-api'],\n },\n };\n },\n\n /**\n * Resolve the virtual module for DevTools tab registration\n */\n resolveId(id: string) {\n if (id === VIRTUAL_DEVTOOLS_TAB_ID) {\n return RESOLVED_VIRTUAL_DEVTOOLS_TAB_ID;\n }\n },\n\n /**\n * Load the virtual module that registers the custom Vue DevTools tab\n *\n * This code is served as a proper Vite module, allowing bare import\n * specifiers to be resolved through Vite's dependency pre-bundling.\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_DEVTOOLS_TAB_ID) {\n return `\nimport { addCustomTab } from '@vue/devtools-api';\n\ntry {\n // Route through Vite's proxy so it works in all environments\n const iframeSrc = window.location.origin + '${DEVTOOLS_PROXY_PATH}/';\n\n addCustomTab({\n name: 'vite-plugin-open-api-server',\n title: 'OpenAPI Server',\n icon: 'https://api.iconify.design/carbon:api-1.svg?width=24&height=24&color=%2394a3b8',\n view: {\n type: 'iframe',\n src: iframeSrc,\n },\n category: 'app',\n });\n} catch (e) {\n // @vue/devtools-api not available - expected when the package is not installed\n}\n`;\n }\n },\n\n /**\n * Configure the Vite dev server\n *\n * This hook is called when the dev server is created.\n * We use it to:\n * 1. Create and start the multi-spec orchestrator\n * 2. Configure Vite's multi-proxy for all specs\n * 3. Set up per-spec file watchers for hot reload\n * 4. Print startup banner\n */\n async configureServer(viteServer: ViteDevServer): Promise<void> {\n cwd = viteServer.config.root;\n\n if (!resolvedOptions.enabled) {\n return;\n }\n\n try {\n // Create multi-spec orchestrator (processes all specs, loads handlers/seeds)\n orchestrator = await createOrchestrator(resolvedOptions, viteServer, cwd);\n\n // Start the shared HTTP server\n await orchestrator.start();\n\n // Configure Vite proxies for all specs\n configureMultiProxy(viteServer, orchestrator.instances, orchestrator.port);\n\n // Set up per-spec file watchers for hot reload\n fileWatchers = await createPerSpecFileWatchers(\n orchestrator.instances,\n viteServer,\n cwd,\n resolvedOptions,\n );\n\n // Print startup banner (v0.x single-spec banner, shows first spec only)\n // TODO: Replace with printMultiSpecBanner() in Epic 5 (Task 5.1)\n if (!resolvedOptions.silent && orchestrator.instances.length > 0) {\n const firstInstance = orchestrator.instances[0];\n const bannerInfo = extractBannerInfo(\n firstInstance.server.registry,\n {\n info: {\n title: firstInstance.server.document.info?.title ?? 'OpenAPI Server',\n version: firstInstance.server.document.info?.version ?? '1.0.0',\n },\n },\n // Handler/seed counts are not tracked per-instance yet.\n // Multi-spec banner (Epic 5, Task 5.1) will display proper per-spec counts.\n 0,\n 0,\n resolvedOptions,\n );\n printBanner(bannerInfo, resolvedOptions);\n }\n } catch (error) {\n await teardown();\n printError('Failed to start OpenAPI mock server', error, resolvedOptions);\n throw error;\n }\n },\n\n /**\n * Inject Vue DevTools custom tab registration script\n *\n * When devtools is enabled, this injects a script tag that loads the\n * virtual module for custom tab registration. Using a virtual module\n * (instead of an inline script) ensures that bare import specifiers\n * like `@vue/devtools-api` are resolved through Vite's module pipeline.\n */\n transformIndexHtml() {\n if (!resolvedOptions.devtools || !resolvedOptions.enabled) {\n return;\n }\n\n return [\n {\n tag: 'script',\n attrs: { type: 'module', src: `/@id/${VIRTUAL_DEVTOOLS_TAB_ID}` },\n injectTo: 'head' as const,\n },\n ];\n },\n\n /**\n * Clean up when Vite server closes\n *\n * NOTE: closeBundle() is called by Vite when the dev server shuts down\n * (e.g., Ctrl+C). This is the same lifecycle hook used in v0.x.\n * While configureServer's viteServer.httpServer?.on('close', ...) is\n * an alternative, closeBundle() is more reliable across Vite versions\n * and is the established pattern in this codebase.\n */\n async closeBundle(): Promise<void> {\n await teardown();\n },\n };\n\n /**\n * Tear down all plugin resources: close file watchers and stop the orchestrator.\n *\n * Shared by `closeBundle` (normal shutdown) and the error path in\n * `configureServer` (partial-init cleanup). Uses `Promise.allSettled`\n * and try/catch so failures in one resource do not prevent cleanup\n * of the others.\n */\n async function teardown(): Promise<void> {\n await Promise.allSettled(fileWatchers.map((w) => w.close()));\n fileWatchers = [];\n\n if (orchestrator) {\n try {\n await orchestrator.stop();\n } catch {\n // Swallow stop errors — nothing actionable at shutdown\n }\n orchestrator = null;\n }\n }\n}\n","/**\n * Vue DevTools Integration\n *\n * What: Provides a function to register OpenAPI Server in Vue DevTools\n * How: Uses @vue/devtools-api to add a custom tab with iframe to DevTools SPA\n * Why: Enables debugging and inspection of the mock API server within Vue DevTools\n *\n * @module devtools\n */\n\nimport type { App } from 'vue';\n\n/**\n * Options for registering the DevTools plugin\n */\nexport interface RegisterDevToolsOptions {\n /**\n * The port where the OpenAPI server is running\n * @default 4000\n */\n port?: number;\n\n /**\n * The host where the OpenAPI server is running\n * @default 'localhost' (or derived from window.location.hostname if in browser)\n */\n host?: string;\n\n /**\n * The protocol to use for the DevTools URL\n * @default 'http' (or derived from window.location.protocol if in browser)\n */\n protocol?: 'http' | 'https';\n\n /**\n * Enable or disable DevTools registration\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Custom label for the DevTools tab\n * @default 'OpenAPI Server'\n */\n label?: string;\n}\n\n/**\n * Register OpenAPI Server in Vue DevTools\n *\n * This function should be called in your Vue application's main entry point\n * to add a custom tab to Vue DevTools. The tab contains an iframe that loads\n * the OpenAPI Server DevTools SPA.\n *\n * @example\n * ```typescript\n * // In your main.ts or main.js\n * import { createApp } from 'vue';\n * import { registerDevTools } from '@websublime/vite-plugin-open-api-server';\n * import App from './App.vue';\n *\n * const app = createApp(App);\n *\n * // Register OpenAPI Server DevTools\n * if (import.meta.env.DEV) {\n * await registerDevTools(app);\n * }\n *\n * app.mount('#app');\n * ```\n *\n * @param app - Vue application instance\n * @param options - Configuration options\n */\nexport async function registerDevTools(\n app: App,\n options: RegisterDevToolsOptions = {},\n): Promise<void> {\n const { enabled = true, label = 'OpenAPI Server', port, host, protocol } = options;\n\n // Validate app parameter\n if (!app || typeof app !== 'object') {\n // biome-ignore lint/suspicious/noConsole: Intentional warning for invalid app instance\n console.warn('[OpenAPI DevTools] Invalid Vue app instance provided');\n return;\n }\n\n // Only register if enabled\n if (!enabled) {\n return;\n }\n\n // Check if running in browser environment\n if (typeof window === 'undefined') {\n return;\n }\n\n // Lazy import to avoid SSR issues\n try {\n const { addCustomTab } = await import('@vue/devtools-api');\n\n // Get the DevTools URL\n const devtoolsUrl = getDevToolsUrl(port, host, protocol);\n\n // Add custom tab with iframe to Vue DevTools\n addCustomTab({\n name: 'vite-plugin-open-api-server',\n title: label,\n icon: 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22%234f46e5%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22%3E%3Cpath d=%22M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z%22/%3E%3Cpolyline points=%223.29 7 12 12 20.71 7%22/%3E%3Cline x1=%2212%22 y1=%2222%22 x2=%2212%22 y2=%2212%22/%3E%3C/svg%3E',\n view: {\n type: 'iframe',\n src: devtoolsUrl,\n },\n category: 'app',\n });\n } catch (error) {\n // Log warning but don't crash the app\n // DevTools integration is optional, so the app should continue working\n // biome-ignore lint/suspicious/noConsole: Intentional warning for registration failure\n console.warn('[OpenAPI DevTools] Failed to register with Vue DevTools:', error);\n }\n}\n\n/**\n * Get the DevTools URL for the given configuration\n *\n * When running in a browser, protocol and host are automatically derived from\n * window.location if not explicitly provided.\n *\n * @param port - Server port (default: 4000, matching OpenApiServerOptions.port)\n * @param host - Server host (default: 'localhost' or window.location.hostname)\n * @param protocol - Protocol to use (default: 'http' or window.location.protocol)\n * @returns DevTools SPA URL\n */\nexport function getDevToolsUrl(port = 4000, host?: string, protocol?: 'http' | 'https'): string {\n // Derive defaults from browser environment if available\n const actualProtocol =\n protocol ||\n (typeof window !== 'undefined'\n ? (window.location.protocol.replace(':', '') as 'http' | 'https')\n : 'http');\n const actualHost =\n host || (typeof window !== 'undefined' ? window.location.hostname : 'localhost');\n\n return `${actualProtocol}://${actualHost}:${port}/_devtools/`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websublime/vite-plugin-open-api-server",
3
- "version": "0.24.0-next.13",
3
+ "version": "0.24.0-next.14",
4
4
  "description": "Vite plugin for OpenAPI mock server with DevTools integration",
5
5
  "keywords": [
6
6
  "vite",
@@ -25,34 +25,34 @@
25
25
  "dependencies": {
26
26
  "picocolors": "^1.1.1",
27
27
  "@vue/devtools-api": "^8.0.6",
28
- "fast-glob": "^3.3.3",
29
28
  "chokidar": "^5.0.0",
30
- "@websublime/vite-plugin-open-api-core": "0.14.0-next.14"
29
+ "fast-glob": "^3.3.3",
30
+ "@websublime/vite-plugin-open-api-core": "0.14.0-next.15"
31
31
  },
32
32
  "devDependencies": {
33
- "typescript": "^5.9.0",
34
33
  "@hono/node-ws": "^1.3.0",
35
34
  "@types/node": "^20.17.10",
36
- "@scalar/openapi-types": "^0.5.3",
37
- "vite": "^7.0.0",
38
- "vue": "^3.5.27",
39
- "hono": "^4.11.4",
40
35
  "tsup": "^8.5.0",
41
36
  "@hono/node-server": "^1.14.3",
37
+ "typescript": "^5.9.0",
38
+ "vite": "^7.0.0",
39
+ "hono": "^4.11.4",
40
+ "@scalar/openapi-types": "^0.5.3",
41
+ "vue": "^3.5.27",
42
42
  "@websublime/vite-plugin-open-api-devtools": "0.8.5"
43
43
  },
44
44
  "peerDependencies": {
45
- "@hono/node-server": "^1.14.0",
45
+ "@hono/node-ws": "^1.3.0",
46
+ "hono": "^4.11.4",
46
47
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
47
48
  "vue": "^3.0.0",
48
- "@hono/node-ws": "^1.3.0",
49
- "hono": "^4.11.4"
49
+ "@hono/node-server": "^1.14.0"
50
50
  },
51
51
  "peerDependenciesMeta": {
52
- "vue": {
52
+ "@hono/node-ws": {
53
53
  "optional": true
54
54
  },
55
- "@hono/node-ws": {
55
+ "vue": {
56
56
  "optional": true
57
57
  }
58
58
  },
@@ -70,9 +70,10 @@
70
70
  }
71
71
  },
72
72
  "scripts": {
73
- "dev": "tsup --watch",
74
- "typecheck": "tsc --noEmit",
75
73
  "copy:devtools-spa": "node scripts/copy-devtools-spa.mjs",
76
- "build": "tsup && pnpm run copy:devtools-spa"
74
+ "test": "vitest run",
75
+ "build": "tsup && pnpm run copy:devtools-spa",
76
+ "typecheck": "tsc --noEmit",
77
+ "dev": "tsup --watch"
77
78
  }
78
79
  }