@websublime/vite-plugin-open-api-server 0.24.0-next.1 → 0.24.0-next.11
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.d.ts +443 -23
- package/dist/index.js +1166 -302
- package/dist/index.js.map +1 -1
- package/package.json +23 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Plugin, ViteDevServer } from 'vite';
|
|
2
|
-
import { Logger, HandlerFn, AnySeedFn } from '@websublime/vite-plugin-open-api-core';
|
|
2
|
+
import { Logger, SpecInfo, OpenApiServer, WebSocketHub, HandlerFn, AnySeedFn } from '@websublime/vite-plugin-open-api-core';
|
|
3
3
|
export { HandlerContext, HandlerDefinition, HandlerFn, HandlerReturn, SecurityContext, SeedContext, SeedDefinition, SeedFn, SeedHelper, defineHandlers, defineSeeds } from '@websublime/vite-plugin-open-api-core';
|
|
4
|
+
import { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
5
|
+
import { Hono } from 'hono';
|
|
4
6
|
import { App } from 'vue';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -19,7 +21,7 @@ import { App } from 'vue';
|
|
|
19
21
|
* Used across Tasks 1.2–1.4 for typed error handling.
|
|
20
22
|
* Matches TECHNICAL-SPECIFICATION-V2.md Appendix B.
|
|
21
23
|
*/
|
|
22
|
-
type ValidationErrorCode = 'SPEC_ID_MISSING' | 'SPEC_ID_DUPLICATE' | 'PROXY_PATH_MISSING' | 'PROXY_PATH_TOO_BROAD' | 'PROXY_PATH_DUPLICATE' | 'PROXY_PATH_OVERLAP' | 'SPEC_NOT_FOUND' | 'SPECS_EMPTY';
|
|
24
|
+
type ValidationErrorCode = 'SPEC_ID_MISSING' | 'SPEC_ID_DUPLICATE' | 'PROXY_PATH_MISSING' | 'PROXY_PATH_TOO_BROAD' | 'PROXY_PATH_DUPLICATE' | 'PROXY_PATH_OVERLAP' | 'PROXY_PATH_PREFIX_COLLISION' | 'SPEC_NOT_FOUND' | 'SPECS_EMPTY';
|
|
23
25
|
/**
|
|
24
26
|
* Typed validation error for configuration issues.
|
|
25
27
|
*
|
|
@@ -42,6 +44,16 @@ declare class ValidationError extends Error {
|
|
|
42
44
|
readonly code: ValidationErrorCode;
|
|
43
45
|
constructor(code: ValidationErrorCode, message: string);
|
|
44
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* How a proxy path was determined.
|
|
49
|
+
*
|
|
50
|
+
* - `'explicit'` — set directly in SpecConfig.proxyPath
|
|
51
|
+
* - `'auto'` — auto-derived from the OpenAPI document's servers[0].url
|
|
52
|
+
*
|
|
53
|
+
* Used by both DeriveProxyPathResult and ResolvedSpecConfig to ensure
|
|
54
|
+
* the two sources of this value stay in sync.
|
|
55
|
+
*/
|
|
56
|
+
type ProxyPathSource = 'auto' | 'explicit';
|
|
45
57
|
/**
|
|
46
58
|
* Configuration for a single OpenAPI spec instance
|
|
47
59
|
*
|
|
@@ -175,18 +187,18 @@ interface OpenApiServerOptions {
|
|
|
175
187
|
*/
|
|
176
188
|
interface ResolvedSpecConfig {
|
|
177
189
|
spec: string;
|
|
178
|
-
/**
|
|
190
|
+
/** Empty string until orchestrator resolution; guaranteed non-empty after `createOrchestrator()` */
|
|
179
191
|
id: string;
|
|
180
|
-
/**
|
|
192
|
+
/** Empty string until orchestrator resolution; guaranteed non-empty after `createOrchestrator()` */
|
|
181
193
|
proxyPath: string;
|
|
182
194
|
/**
|
|
183
195
|
* How proxyPath was determined — used for banner display.
|
|
184
196
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
197
|
+
* Written back by the orchestrator after document processing.
|
|
198
|
+
* Used by the startup banner to display `(auto-derived)` vs
|
|
199
|
+
* `(explicit)` next to each proxy path.
|
|
188
200
|
*/
|
|
189
|
-
proxyPathSource:
|
|
201
|
+
proxyPathSource: ProxyPathSource;
|
|
190
202
|
handlersDir: string;
|
|
191
203
|
seedsDir: string;
|
|
192
204
|
idFields: Record<string, string>;
|
|
@@ -208,19 +220,380 @@ interface ResolvedOptions {
|
|
|
208
220
|
silent: boolean;
|
|
209
221
|
logger?: Logger;
|
|
210
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Validate that specs array is non-empty and each entry has a valid spec field.
|
|
225
|
+
*
|
|
226
|
+
* @param specs - Array of spec configurations to validate
|
|
227
|
+
* @throws {ValidationError} SPECS_EMPTY if specs array is missing or empty
|
|
228
|
+
* @throws {ValidationError} SPEC_NOT_FOUND if a spec entry has empty spec field
|
|
229
|
+
*/
|
|
230
|
+
declare function validateSpecs(specs: SpecConfig[]): void;
|
|
231
|
+
/**
|
|
232
|
+
* Resolve options with defaults.
|
|
233
|
+
*
|
|
234
|
+
* Note: spec ID and proxyPath resolution requires processing the OpenAPI document
|
|
235
|
+
* first, so they are resolved later in the orchestrator.
|
|
236
|
+
* This function only resolves static defaults.
|
|
237
|
+
*
|
|
238
|
+
* @param options - User-provided options
|
|
239
|
+
* @returns Resolved options with all defaults applied
|
|
240
|
+
*/
|
|
241
|
+
declare function resolveOptions(options: OpenApiServerOptions): ResolvedOptions;
|
|
211
242
|
|
|
212
243
|
/**
|
|
213
244
|
* Vite Plugin Implementation
|
|
214
245
|
*
|
|
215
|
-
* What: Main Vite plugin for OpenAPI mock server
|
|
216
|
-
* How: Uses
|
|
217
|
-
* Why: Integrates OpenAPI mock
|
|
246
|
+
* What: Main Vite plugin for OpenAPI mock server (multi-spec)
|
|
247
|
+
* How: Uses orchestrator to create N spec instances, configures multi-proxy
|
|
248
|
+
* Why: Integrates multiple OpenAPI mock servers seamlessly into Vite dev workflow
|
|
218
249
|
*
|
|
219
250
|
* @module plugin
|
|
220
251
|
*/
|
|
221
252
|
|
|
253
|
+
/**
|
|
254
|
+
* Create the OpenAPI Server Vite plugin
|
|
255
|
+
*
|
|
256
|
+
* This plugin starts mock servers based on OpenAPI specifications
|
|
257
|
+
* and configures Vite to proxy API requests to them. Supports
|
|
258
|
+
* multiple specs via the orchestrator pattern.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* // vite.config.ts
|
|
263
|
+
* import { defineConfig } from 'vite';
|
|
264
|
+
* import vue from '@vitejs/plugin-vue';
|
|
265
|
+
* import { openApiServer } from '@websublime/vite-plugin-open-api-server';
|
|
266
|
+
*
|
|
267
|
+
* export default defineConfig({
|
|
268
|
+
* plugins: [
|
|
269
|
+
* vue(),
|
|
270
|
+
* openApiServer({
|
|
271
|
+
* specs: [
|
|
272
|
+
* { spec: './openapi/petstore.yaml', proxyPath: '/api/pets' },
|
|
273
|
+
* { spec: './openapi/inventory.yaml', proxyPath: '/api/inventory' },
|
|
274
|
+
* ],
|
|
275
|
+
* port: 4000,
|
|
276
|
+
* }),
|
|
277
|
+
* ],
|
|
278
|
+
* });
|
|
279
|
+
* ```
|
|
280
|
+
*
|
|
281
|
+
* @param options - Plugin configuration options
|
|
282
|
+
* @returns Vite plugin
|
|
283
|
+
*/
|
|
222
284
|
declare function openApiServer(options: OpenApiServerOptions): Plugin;
|
|
223
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Spec ID Derivation
|
|
288
|
+
*
|
|
289
|
+
* What: Functions to derive and validate spec identifiers
|
|
290
|
+
* How: Slugifies explicit IDs or auto-derives from OpenAPI info.title
|
|
291
|
+
* Why: Each spec instance needs a unique, URL-safe identifier for routing,
|
|
292
|
+
* DevTools grouping, logging, and default directory names
|
|
293
|
+
*
|
|
294
|
+
* @module spec-id
|
|
295
|
+
*/
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Slugify a string for use as a spec identifier
|
|
299
|
+
*
|
|
300
|
+
* Rules:
|
|
301
|
+
* - Lowercase
|
|
302
|
+
* - Replace spaces and special chars with hyphens
|
|
303
|
+
* - Remove consecutive hyphens
|
|
304
|
+
* - Trim leading/trailing hyphens
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* slugify("Swagger Petstore") → "swagger-petstore"
|
|
308
|
+
* slugify("Billing API v2") → "billing-api-v2"
|
|
309
|
+
* slugify("café") → "cafe"
|
|
310
|
+
*/
|
|
311
|
+
declare function slugify(input: string): string;
|
|
312
|
+
/**
|
|
313
|
+
* Derive a spec ID from the processed OpenAPI document
|
|
314
|
+
*
|
|
315
|
+
* Priority:
|
|
316
|
+
* 1. Explicit id from config (if non-empty)
|
|
317
|
+
* 2. Slugified info.title from the processed document
|
|
318
|
+
*
|
|
319
|
+
* @param explicitId - ID from SpecConfig.id (may be empty)
|
|
320
|
+
* @param document - Processed OpenAPI document
|
|
321
|
+
* @returns Stable, URL-safe spec identifier
|
|
322
|
+
* @throws {ValidationError} SPEC_ID_MISSING if no ID can be derived (missing title and no explicit id)
|
|
323
|
+
*/
|
|
324
|
+
declare function deriveSpecId(explicitId: string, document: OpenAPIV3_1.Document): string;
|
|
325
|
+
/**
|
|
326
|
+
* Validate spec IDs are unique across all specs
|
|
327
|
+
*
|
|
328
|
+
* Collects all duplicated IDs and reports them in a single error.
|
|
329
|
+
*
|
|
330
|
+
* @param ids - Array of resolved spec IDs
|
|
331
|
+
* @throws {ValidationError} SPEC_ID_DUPLICATE if duplicate IDs found
|
|
332
|
+
*/
|
|
333
|
+
declare function validateUniqueIds(ids: string[]): void;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Proxy Path Auto-Detection
|
|
337
|
+
*
|
|
338
|
+
* What: Functions to derive and validate proxy paths for spec instances
|
|
339
|
+
* How: Extracts path from explicit config or auto-derives from servers[0].url
|
|
340
|
+
* Why: Each spec instance needs a unique, non-overlapping proxy path for
|
|
341
|
+
* Vite proxy configuration and request routing
|
|
342
|
+
*
|
|
343
|
+
* @module proxy-path
|
|
344
|
+
*/
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Result of proxy path derivation
|
|
348
|
+
*
|
|
349
|
+
* Includes the normalized path and how it was determined,
|
|
350
|
+
* so the startup banner can display "(auto-derived)" vs "(explicit)".
|
|
351
|
+
*/
|
|
352
|
+
interface DeriveProxyPathResult {
|
|
353
|
+
/** Normalized proxy path (e.g., "/api/v3") */
|
|
354
|
+
proxyPath: string;
|
|
355
|
+
/** How the path was determined */
|
|
356
|
+
proxyPathSource: ProxyPathSource;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Derive the proxy path from config or OpenAPI document's servers field
|
|
360
|
+
*
|
|
361
|
+
* Priority:
|
|
362
|
+
* 1. Explicit proxyPath from config (if non-empty after trimming)
|
|
363
|
+
* 2. Path portion of servers[0].url
|
|
364
|
+
*
|
|
365
|
+
* Full URLs (e.g., "https://api.example.com/api/v3") have their path
|
|
366
|
+
* extracted via the URL constructor. Relative paths (e.g., "/api/v3")
|
|
367
|
+
* are used directly.
|
|
368
|
+
*
|
|
369
|
+
* @param explicitPath - proxyPath from SpecConfig (may be empty)
|
|
370
|
+
* @param document - Processed OpenAPI document
|
|
371
|
+
* @param specId - Spec ID for error messages
|
|
372
|
+
* @returns Normalized proxy path with source indication
|
|
373
|
+
* @throws {ValidationError} PROXY_PATH_MISSING if path cannot be derived
|
|
374
|
+
* @throws {ValidationError} PROXY_PATH_TOO_BROAD if path resolves to "/" (e.g., "/", ".", "..")
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* // Explicit path
|
|
378
|
+
* deriveProxyPath('/api/v3', document, 'petstore')
|
|
379
|
+
* // → { proxyPath: '/api/v3', proxyPathSource: 'explicit' }
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* // Auto-derived from servers[0].url = "https://api.example.com/api/v3"
|
|
383
|
+
* deriveProxyPath('', document, 'petstore')
|
|
384
|
+
* // → { proxyPath: '/api/v3', proxyPathSource: 'auto' }
|
|
385
|
+
*/
|
|
386
|
+
declare function deriveProxyPath(explicitPath: string, document: OpenAPIV3_1.Document, specId: string): DeriveProxyPathResult;
|
|
387
|
+
/**
|
|
388
|
+
* Normalize and validate a proxy path
|
|
389
|
+
*
|
|
390
|
+
* Rules:
|
|
391
|
+
* - Strip query strings and fragments
|
|
392
|
+
* - Ensure leading slash
|
|
393
|
+
* - Collapse consecutive slashes
|
|
394
|
+
* - Resolve dot segments ("." and ".." per RFC 3986 §5.2.4)
|
|
395
|
+
* - Remove trailing slash
|
|
396
|
+
* - Reject "/" as too broad (would capture all requests, including dot-segments that resolve to "/")
|
|
397
|
+
*
|
|
398
|
+
* @param path - Raw path string to normalize
|
|
399
|
+
* @param specId - Spec ID for error messages
|
|
400
|
+
* @returns Normalized path (e.g., "/api/v3")
|
|
401
|
+
* @throws {ValidationError} PROXY_PATH_TOO_BROAD if path resolves to "/" (e.g., "/", ".", "..")
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* normalizeProxyPath('api/v3', 'petstore') → '/api/v3'
|
|
405
|
+
* normalizeProxyPath('/api/v3/', 'petstore') → '/api/v3'
|
|
406
|
+
*/
|
|
407
|
+
declare function normalizeProxyPath(path: string, specId: string): string;
|
|
408
|
+
/**
|
|
409
|
+
* Validate proxy paths are unique and non-overlapping
|
|
410
|
+
*
|
|
411
|
+
* Checks for:
|
|
412
|
+
* 1. Duplicate paths — two specs with the same proxyPath
|
|
413
|
+
* 2. Overlapping paths — one path is a prefix of another at a segment boundary
|
|
414
|
+
* (e.g., "/api" and "/api/v1") which would cause routing ambiguity
|
|
415
|
+
* 3. String-prefix collisions — one path is a raw string prefix of another
|
|
416
|
+
* without a segment boundary (e.g., "/api" and "/api2"). Vite's internal
|
|
417
|
+
* proxy matching uses plain `url.startsWith(context)` with no segment
|
|
418
|
+
* awareness, so "/api" would incorrectly capture "/api2/users" requests.
|
|
419
|
+
*
|
|
420
|
+
* @remarks
|
|
421
|
+
* Entries with an empty or falsy `proxyPath` are silently skipped. These
|
|
422
|
+
* represent specs whose proxy path has not yet been resolved (e.g., during
|
|
423
|
+
* early option resolution before the OpenAPI document is processed). Callers
|
|
424
|
+
* should expect unresolved entries to be excluded from uniqueness checks
|
|
425
|
+
* rather than triggering false-positive errors.
|
|
426
|
+
*
|
|
427
|
+
* @param specs - Array of spec entries with id and proxyPath.
|
|
428
|
+
* Entries with empty/falsy proxyPath are skipped (unresolved).
|
|
429
|
+
* @throws {ValidationError} PROXY_PATH_DUPLICATE if duplicate paths found
|
|
430
|
+
* @throws {ValidationError} PROXY_PATH_OVERLAP if overlapping paths found (segment boundary)
|
|
431
|
+
* @throws {ValidationError} PROXY_PATH_PREFIX_COLLISION if one path is a raw string prefix
|
|
432
|
+
* of another without a segment boundary (e.g., "/api" and "/api2")
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* // Throws PROXY_PATH_DUPLICATE
|
|
436
|
+
* validateUniqueProxyPaths([
|
|
437
|
+
* { id: 'petstore', proxyPath: '/api/v3' },
|
|
438
|
+
* { id: 'inventory', proxyPath: '/api/v3' },
|
|
439
|
+
* ]);
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* // Throws PROXY_PATH_OVERLAP
|
|
443
|
+
* validateUniqueProxyPaths([
|
|
444
|
+
* { id: 'petstore', proxyPath: '/api' },
|
|
445
|
+
* { id: 'inventory', proxyPath: '/api/v1' },
|
|
446
|
+
* ]);
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* // Throws PROXY_PATH_PREFIX_COLLISION
|
|
450
|
+
* validateUniqueProxyPaths([
|
|
451
|
+
* { id: 'petstore', proxyPath: '/api' },
|
|
452
|
+
* { id: 'inventory', proxyPath: '/api2' },
|
|
453
|
+
* ]);
|
|
454
|
+
*/
|
|
455
|
+
declare function validateUniqueProxyPaths(specs: Array<{
|
|
456
|
+
id: string;
|
|
457
|
+
proxyPath: string;
|
|
458
|
+
}>): void;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Multi-Spec Orchestrator
|
|
462
|
+
*
|
|
463
|
+
* What: Central orchestrator that creates N spec instances and mounts them on a single Hono app
|
|
464
|
+
* How: Three phases — process specs, validate uniqueness, build main Hono app with dispatch middleware
|
|
465
|
+
* Why: Enables multiple OpenAPI specs to run on a single server with isolated stores and handlers
|
|
466
|
+
*
|
|
467
|
+
* @module orchestrator
|
|
468
|
+
*/
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Deterministic color palette for spec identification in DevTools.
|
|
472
|
+
*
|
|
473
|
+
* Colors are assigned by index: spec 0 gets green, spec 1 gets blue, etc.
|
|
474
|
+
* Wraps around for >8 specs.
|
|
475
|
+
*/
|
|
476
|
+
declare const SPEC_COLORS: readonly string[];
|
|
477
|
+
/**
|
|
478
|
+
* Resolved spec instance with all runtime data.
|
|
479
|
+
*
|
|
480
|
+
* Created during Phase 1 of orchestration. Each instance owns
|
|
481
|
+
* an isolated core `OpenApiServer` with its own store, registry,
|
|
482
|
+
* handlers, seeds, and timeline.
|
|
483
|
+
*/
|
|
484
|
+
interface SpecInstance {
|
|
485
|
+
/** Unique spec identifier (explicit or auto-derived from info.title) */
|
|
486
|
+
id: string;
|
|
487
|
+
/** Spec metadata for DevTools display and WebSocket protocol */
|
|
488
|
+
info: SpecInfo;
|
|
489
|
+
/** Core server instance (isolated Hono app, store, registry, etc.) */
|
|
490
|
+
server: OpenApiServer;
|
|
491
|
+
/** Resolved configuration for this spec */
|
|
492
|
+
config: ResolvedSpecConfig;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Orchestrator result — returned by `createOrchestrator()`.
|
|
496
|
+
*
|
|
497
|
+
* Provides access to the main Hono app (all specs mounted),
|
|
498
|
+
* individual spec instances, aggregated metadata, and lifecycle methods.
|
|
499
|
+
*/
|
|
500
|
+
interface OrchestratorResult {
|
|
501
|
+
/**
|
|
502
|
+
* Main Hono app with all specs mounted via X-Spec-Id dispatch.
|
|
503
|
+
*
|
|
504
|
+
* **Note**: Consumers using this property directly must have `hono`
|
|
505
|
+
* as a dependency. The `start()`/`stop()` lifecycle methods do not
|
|
506
|
+
* require direct interaction with this Hono instance.
|
|
507
|
+
*/
|
|
508
|
+
app: Hono;
|
|
509
|
+
/** All spec instances (in config order) */
|
|
510
|
+
instances: SpecInstance[];
|
|
511
|
+
/** Spec metadata array for WebSocket `connected` event */
|
|
512
|
+
specsInfo: SpecInfo[];
|
|
513
|
+
/**
|
|
514
|
+
* Shared WebSocket hub for the orchestrator.
|
|
515
|
+
*
|
|
516
|
+
* Created via `createMultiSpecWebSocketHub()` with:
|
|
517
|
+
* - `autoConnect: false` to suppress default connected events
|
|
518
|
+
* - Enhanced `addClient()` that sends specs metadata
|
|
519
|
+
* - Broadcast interception that adds `specId` to all events
|
|
520
|
+
* - Multi-spec command handler for spec-scoped routing
|
|
521
|
+
*/
|
|
522
|
+
wsHub: WebSocketHub;
|
|
523
|
+
/** Start the shared HTTP server on the configured port */
|
|
524
|
+
start(): Promise<void>;
|
|
525
|
+
/** Stop the HTTP server and clean up resources */
|
|
526
|
+
stop(): Promise<void>;
|
|
527
|
+
/** Actual bound port after start() resolves (0 before start or after stop) */
|
|
528
|
+
readonly port: number;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Create the multi-spec orchestrator.
|
|
532
|
+
*
|
|
533
|
+
* Flow:
|
|
534
|
+
* 1. **Phase 1 — Process specs**: For each spec config, load handlers/seeds,
|
|
535
|
+
* create a core `OpenApiServer` instance, derive ID and proxy path.
|
|
536
|
+
* 2. **Phase 2 — Validate uniqueness**: Ensure all spec IDs and proxy paths
|
|
537
|
+
* are unique and non-overlapping.
|
|
538
|
+
* 3. **Phase 3 — Build main app**: Create a single Hono app with CORS,
|
|
539
|
+
* DevTools, Internal API, and X-Spec-Id dispatch middleware.
|
|
540
|
+
*
|
|
541
|
+
* **Note**: This function populates the resolved values (id, proxyPath,
|
|
542
|
+
* proxyPathSource, handlersDir, seedsDir) on each `options.specs[i]` object.
|
|
543
|
+
* Since `instances[i].config` is the same object reference, consumers should
|
|
544
|
+
* access resolved values through `instances[i].config` (the authoritative view).
|
|
545
|
+
*
|
|
546
|
+
* @param options - Resolved plugin options (from `resolveOptions()`)
|
|
547
|
+
* @param vite - Vite dev server instance (for ssrLoadModule)
|
|
548
|
+
* @param cwd - Project root directory
|
|
549
|
+
* @returns Orchestrator result with app, instances, and lifecycle methods
|
|
550
|
+
*/
|
|
551
|
+
declare function createOrchestrator(options: ResolvedOptions, vite: ViteDevServer, cwd: string): Promise<OrchestratorResult>;
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Multi-Path Proxy Configuration
|
|
555
|
+
*
|
|
556
|
+
* What: Configures Vite proxy for multiple OpenAPI spec instances
|
|
557
|
+
* How: Generates one proxy entry per spec with path rewriting and X-Spec-Id header,
|
|
558
|
+
* plus shared service proxies for DevTools, Internal API, and WebSocket
|
|
559
|
+
* Why: Enables each spec's API requests to be routed through Vite to the shared server
|
|
560
|
+
*
|
|
561
|
+
* @module multi-proxy
|
|
562
|
+
*/
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Shared service proxy path prefixes.
|
|
566
|
+
*
|
|
567
|
+
* These constants are the single source of truth for the reserved proxy paths
|
|
568
|
+
* used by the DevTools iframe, internal API, and WebSocket connections.
|
|
569
|
+
* Both `configureMultiProxy()` and the virtual DevTools tab module in
|
|
570
|
+
* `plugin.ts` reference these to prevent divergence.
|
|
571
|
+
*/
|
|
572
|
+
declare const DEVTOOLS_PROXY_PATH = "/_devtools";
|
|
573
|
+
declare const API_PROXY_PATH = "/_api";
|
|
574
|
+
declare const WS_PROXY_PATH = "/_ws";
|
|
575
|
+
/**
|
|
576
|
+
* Configure Vite proxy for multiple spec instances and shared services.
|
|
577
|
+
*
|
|
578
|
+
* Generates:
|
|
579
|
+
* 1. **Per-spec proxy entries** — one per spec, with path rewriting (prefix
|
|
580
|
+
* stripping) and an `X-Spec-Id` header so the shared Hono server can
|
|
581
|
+
* route to the correct spec instance.
|
|
582
|
+
* 2. **Shared service proxies** — spec-agnostic entries for `/_devtools`,
|
|
583
|
+
* `/_api`, and `/_ws` that forward to the same server without path
|
|
584
|
+
* rewriting or spec headers.
|
|
585
|
+
*
|
|
586
|
+
* Uses `startsWith`/`slice` for path rewriting instead of the regex approach
|
|
587
|
+
* described in the tech spec (Section 5.7). Literal prefix matching is safer
|
|
588
|
+
* because it correctly handles regex metacharacters in proxy paths (e.g.,
|
|
589
|
+
* `/api.v3` matches literally, not as `/api<any>v3`).
|
|
590
|
+
*
|
|
591
|
+
* @param vite - Vite dev server instance
|
|
592
|
+
* @param instances - Resolved spec instances from the orchestrator
|
|
593
|
+
* @param port - Shared server port
|
|
594
|
+
*/
|
|
595
|
+
declare function configureMultiProxy(vite: ViteDevServer, instances: SpecInstance[], port: number): void;
|
|
596
|
+
|
|
224
597
|
/**
|
|
225
598
|
* Handler Loading
|
|
226
599
|
*
|
|
@@ -349,14 +722,12 @@ declare function getSeedFiles(seedsDir: string, cwd?: string): Promise<string[]>
|
|
|
349
722
|
/**
|
|
350
723
|
* Hot Reload
|
|
351
724
|
*
|
|
352
|
-
* What: File watcher for hot reloading handlers and seeds
|
|
353
|
-
* How: Uses chokidar to watch for file changes
|
|
354
|
-
* Why: Enables rapid development iteration without server restart
|
|
725
|
+
* What: File watcher for hot reloading handlers and seeds with per-spec isolation
|
|
726
|
+
* How: Uses chokidar to watch for file changes, one watcher per spec instance
|
|
727
|
+
* Why: Enables rapid development iteration without server restart; per-spec
|
|
728
|
+
* isolation ensures handler/seed changes in one spec don't affect others
|
|
355
729
|
*
|
|
356
730
|
* @module hot-reload
|
|
357
|
-
*
|
|
358
|
-
* TODO: Full implementation in Task 3.3
|
|
359
|
-
* This module provides placeholder/basic functionality for Task 3.1
|
|
360
731
|
*/
|
|
361
732
|
|
|
362
733
|
/**
|
|
@@ -419,6 +790,14 @@ interface FileWatcher {
|
|
|
419
790
|
* @returns Promise resolving to file watcher instance
|
|
420
791
|
*/
|
|
421
792
|
declare function createFileWatcher(options: FileWatcherOptions): Promise<FileWatcher>;
|
|
793
|
+
/**
|
|
794
|
+
* Debounced function with cancel support
|
|
795
|
+
*/
|
|
796
|
+
interface DebouncedFunction<T extends (...args: unknown[]) => unknown> {
|
|
797
|
+
(...args: Parameters<T>): void;
|
|
798
|
+
/** Cancel any pending debounce timer and queued execution */
|
|
799
|
+
cancel(): void;
|
|
800
|
+
}
|
|
422
801
|
/**
|
|
423
802
|
* Debounce a function with async execution guard
|
|
424
803
|
*
|
|
@@ -432,9 +811,50 @@ declare function createFileWatcher(options: FileWatcherOptions): Promise<FileWat
|
|
|
432
811
|
*
|
|
433
812
|
* @param fn - Function to debounce (can be sync or async)
|
|
434
813
|
* @param delay - Debounce delay in milliseconds
|
|
435
|
-
* @returns Debounced function
|
|
814
|
+
* @returns Debounced function with cancel() method
|
|
436
815
|
*/
|
|
437
|
-
declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number):
|
|
816
|
+
declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): DebouncedFunction<T>;
|
|
817
|
+
/**
|
|
818
|
+
* Create file watchers for all spec instances
|
|
819
|
+
*
|
|
820
|
+
* Each spec gets independent watchers for its handlers and seeds directories.
|
|
821
|
+
* Changes to one spec's files only trigger reload for that spec instance.
|
|
822
|
+
*
|
|
823
|
+
* @param instances - All spec instances to watch
|
|
824
|
+
* @param vite - Vite dev server (for ssrLoadModule / module invalidation)
|
|
825
|
+
* @param cwd - Project root directory
|
|
826
|
+
* @param options - Resolved plugin options
|
|
827
|
+
* @returns Promise resolving to array of file watchers (one per spec)
|
|
828
|
+
*/
|
|
829
|
+
declare function createPerSpecFileWatchers(instances: SpecInstance[], vite: ViteDevServer, cwd: string, options: ResolvedOptions): Promise<FileWatcher[]>;
|
|
830
|
+
/**
|
|
831
|
+
* Reload handlers for a specific spec instance
|
|
832
|
+
*
|
|
833
|
+
* Loads fresh handlers from disk via Vite's ssrLoadModule, updates
|
|
834
|
+
* the spec's server, broadcasts a WebSocket event, and logs the result.
|
|
835
|
+
*
|
|
836
|
+
* @param instance - The spec instance to reload handlers for
|
|
837
|
+
* @param vite - Vite dev server
|
|
838
|
+
* @param cwd - Project root directory
|
|
839
|
+
* @param options - Resolved plugin options
|
|
840
|
+
*/
|
|
841
|
+
declare function reloadSpecHandlers(instance: SpecInstance, vite: ViteDevServer, cwd: string, options: ResolvedOptions): Promise<void>;
|
|
842
|
+
/**
|
|
843
|
+
* Reload seeds for a specific spec instance
|
|
844
|
+
*
|
|
845
|
+
* Loads fresh seeds from disk, clears the spec's store, and re-executes
|
|
846
|
+
* seeds. Broadcasts a WebSocket event and logs the result.
|
|
847
|
+
*
|
|
848
|
+
* Note: This operation is not fully atomic — there's a brief window between
|
|
849
|
+
* clearing the store and repopulating it where requests may see empty data.
|
|
850
|
+
* For development tooling, this tradeoff is acceptable.
|
|
851
|
+
*
|
|
852
|
+
* @param instance - The spec instance to reload seeds for
|
|
853
|
+
* @param vite - Vite dev server
|
|
854
|
+
* @param cwd - Project root directory
|
|
855
|
+
* @param options - Resolved plugin options
|
|
856
|
+
*/
|
|
857
|
+
declare function reloadSpecSeeds(instance: SpecInstance, vite: ViteDevServer, cwd: string, options: ResolvedOptions): Promise<void>;
|
|
438
858
|
|
|
439
859
|
/**
|
|
440
860
|
* Vue DevTools Integration
|
|
@@ -452,7 +872,7 @@ declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, dela
|
|
|
452
872
|
interface RegisterDevToolsOptions {
|
|
453
873
|
/**
|
|
454
874
|
* The port where the OpenAPI server is running
|
|
455
|
-
* @default
|
|
875
|
+
* @default 4000
|
|
456
876
|
*/
|
|
457
877
|
port?: number;
|
|
458
878
|
/**
|
|
@@ -494,7 +914,7 @@ interface RegisterDevToolsOptions {
|
|
|
494
914
|
*
|
|
495
915
|
* // Register OpenAPI Server DevTools
|
|
496
916
|
* if (import.meta.env.DEV) {
|
|
497
|
-
* await registerDevTools(app
|
|
917
|
+
* await registerDevTools(app);
|
|
498
918
|
* }
|
|
499
919
|
*
|
|
500
920
|
* app.mount('#app');
|
|
@@ -510,11 +930,11 @@ declare function registerDevTools(app: App, options?: RegisterDevToolsOptions):
|
|
|
510
930
|
* When running in a browser, protocol and host are automatically derived from
|
|
511
931
|
* window.location if not explicitly provided.
|
|
512
932
|
*
|
|
513
|
-
* @param port - Server port (default:
|
|
933
|
+
* @param port - Server port (default: 4000, matching OpenApiServerOptions.port)
|
|
514
934
|
* @param host - Server host (default: 'localhost' or window.location.hostname)
|
|
515
935
|
* @param protocol - Protocol to use (default: 'http' or window.location.protocol)
|
|
516
936
|
* @returns DevTools SPA URL
|
|
517
937
|
*/
|
|
518
938
|
declare function getDevToolsUrl(port?: number, host?: string, protocol?: 'http' | 'https'): string;
|
|
519
939
|
|
|
520
|
-
export { type FileWatcher, type FileWatcherOptions, type LoadHandlersResult, type LoadSeedsResult, type OpenApiServerOptions, type RegisterDevToolsOptions, type ResolvedOptions, type ResolvedSpecConfig, type SpecConfig, ValidationError, type ValidationErrorCode, createFileWatcher, debounce, getDevToolsUrl, getHandlerFiles, getSeedFiles, loadHandlers, loadSeeds, openApiServer, registerDevTools };
|
|
940
|
+
export { API_PROXY_PATH, DEVTOOLS_PROXY_PATH, type DebouncedFunction, type DeriveProxyPathResult, type FileWatcher, type FileWatcherOptions, type LoadHandlersResult, type LoadSeedsResult, type OpenApiServerOptions, type OrchestratorResult, type ProxyPathSource, type RegisterDevToolsOptions, type ResolvedOptions, type ResolvedSpecConfig, SPEC_COLORS, type SpecConfig, type SpecInstance, ValidationError, type ValidationErrorCode, WS_PROXY_PATH, configureMultiProxy, createFileWatcher, createOrchestrator, createPerSpecFileWatchers, debounce, deriveProxyPath, deriveSpecId, getDevToolsUrl, getHandlerFiles, getSeedFiles, loadHandlers, loadSeeds, normalizeProxyPath, openApiServer, registerDevTools, reloadSpecHandlers, reloadSpecSeeds, resolveOptions, slugify, validateSpecs, validateUniqueIds, validateUniqueProxyPaths };
|