@websublime/vite-plugin-open-api-server 0.24.0-next.6 → 0.24.0-next.7

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
@@ -1,10 +1,10 @@
1
1
  import { createRequire } from 'module';
2
- import { mountInternalApi, executeSeeds, createOpenApiServer, mountDevToolsRoutes, createWebSocketHub } from '@websublime/vite-plugin-open-api-core';
3
- export { defineHandlers, defineSeeds } from '@websublime/vite-plugin-open-api-core';
4
2
  import pc from 'picocolors';
5
- import path2, { dirname, join } from 'path';
6
- import fg from 'fast-glob';
7
3
  import { existsSync } from 'fs';
4
+ import path, { dirname, join } from 'path';
5
+ import { executeSeeds, mountInternalApi, createOpenApiServer, mountDevToolsRoutes, createWebSocketHub } from '@websublime/vite-plugin-open-api-core';
6
+ export { defineHandlers, defineSeeds } from '@websublime/vite-plugin-open-api-core';
7
+ import fg from 'fast-glob';
8
8
  import { fileURLToPath } from 'url';
9
9
  import { Hono } from 'hono';
10
10
  import { cors } from 'hono/cors';
@@ -111,7 +111,7 @@ async function directoryExists(dirPath) {
111
111
  // src/handlers.ts
112
112
  async function loadHandlers(handlersDir, viteServer, cwd = process.cwd(), logger = console) {
113
113
  const handlers = /* @__PURE__ */ new Map();
114
- const absoluteDir = path2.resolve(cwd, handlersDir);
114
+ const absoluteDir = path.resolve(cwd, handlersDir);
115
115
  const dirExists = await directoryExists(absoluteDir);
116
116
  if (!dirExists) {
117
117
  return {
@@ -128,7 +128,7 @@ async function loadHandlers(handlersDir, viteServer, cwd = process.cwd(), logger
128
128
  ignore: ["node_modules/**", "dist/**"]
129
129
  });
130
130
  for (const file of files) {
131
- const absolutePath = path2.join(absoluteDir, file);
131
+ const absolutePath = path.join(absoluteDir, file);
132
132
  const fileHandlers = await loadHandlerFile(absolutePath, viteServer, logger);
133
133
  for (const [operationId, handler] of Object.entries(fileHandlers)) {
134
134
  if (handlers.has(operationId)) {
@@ -175,7 +175,7 @@ async function loadHandlerFile(filePath, viteServer, logger) {
175
175
  }
176
176
  }
177
177
  async function getHandlerFiles(handlersDir, cwd = process.cwd()) {
178
- const absoluteDir = path2.resolve(cwd, handlersDir);
178
+ const absoluteDir = path.resolve(cwd, handlersDir);
179
179
  const dirExists = await directoryExists(absoluteDir);
180
180
  if (!dirExists) {
181
181
  return [];
@@ -189,6 +189,90 @@ async function getHandlerFiles(handlersDir, cwd = process.cwd()) {
189
189
  });
190
190
  return files;
191
191
  }
192
+ async function loadSeeds(seedsDir, viteServer, cwd = process.cwd(), logger = console) {
193
+ const seeds = /* @__PURE__ */ new Map();
194
+ const absoluteDir = path.resolve(cwd, seedsDir);
195
+ const dirExists = await directoryExists(absoluteDir);
196
+ if (!dirExists) {
197
+ return {
198
+ seeds,
199
+ fileCount: 0,
200
+ files: []
201
+ };
202
+ }
203
+ const pattern = "**/*.seeds.{ts,js,mjs}";
204
+ const files = await fg(pattern, {
205
+ cwd: absoluteDir,
206
+ absolute: false,
207
+ onlyFiles: true,
208
+ ignore: ["node_modules/**", "dist/**"]
209
+ });
210
+ for (const file of files) {
211
+ const absolutePath = path.join(absoluteDir, file);
212
+ const fileSeeds = await loadSeedFile(absolutePath, viteServer, logger);
213
+ for (const [schemaName, seedFn] of Object.entries(fileSeeds)) {
214
+ if (seeds.has(schemaName)) {
215
+ logger.warn(
216
+ `[vite-plugin-open-api-server] Duplicate seed for schema "${schemaName}" in ${file}. Using last definition.`
217
+ );
218
+ }
219
+ seeds.set(schemaName, seedFn);
220
+ }
221
+ }
222
+ return {
223
+ seeds,
224
+ fileCount: files.length,
225
+ files
226
+ };
227
+ }
228
+ async function loadSeedFile(filePath, viteServer, logger) {
229
+ try {
230
+ const moduleNode = viteServer.moduleGraph.getModuleById(filePath);
231
+ if (moduleNode) {
232
+ viteServer.moduleGraph.invalidateModule(moduleNode);
233
+ }
234
+ const module = await viteServer.ssrLoadModule(filePath);
235
+ const seeds = module.default ?? module.seeds ?? module;
236
+ if (!seeds || typeof seeds !== "object") {
237
+ logger.warn(
238
+ `[vite-plugin-open-api-server] Invalid seed file ${filePath}: expected object export`
239
+ );
240
+ return {};
241
+ }
242
+ const validSeeds = {};
243
+ for (const [key, value] of Object.entries(seeds)) {
244
+ if (typeof value === "function") {
245
+ validSeeds[key] = value;
246
+ }
247
+ }
248
+ return validSeeds;
249
+ } catch (error) {
250
+ logger.error(
251
+ `[vite-plugin-open-api-server] Failed to load seed file ${filePath}:`,
252
+ error instanceof Error ? error.message : error
253
+ );
254
+ return {};
255
+ }
256
+ }
257
+ async function getSeedFiles(seedsDir, cwd = process.cwd()) {
258
+ const absoluteDir = path.resolve(cwd, seedsDir);
259
+ const dirExists = await directoryExists(absoluteDir);
260
+ if (!dirExists) {
261
+ return [];
262
+ }
263
+ const pattern = "**/*.seeds.{ts,js,mjs}";
264
+ const files = await fg(pattern, {
265
+ cwd: absoluteDir,
266
+ absolute: true,
267
+ onlyFiles: true,
268
+ ignore: ["node_modules/**", "dist/**"]
269
+ });
270
+ return files;
271
+ }
272
+
273
+ // src/hot-reload.ts
274
+ var nodeModulesRe = /(^|[\\/])node_modules([\\/]|$)/;
275
+ var distRe = /(^|[\\/])dist([\\/]|$)/;
192
276
  async function createFileWatcher(options) {
193
277
  const {
194
278
  handlersDir,
@@ -202,8 +286,8 @@ async function createFileWatcher(options) {
202
286
  const watchers = [];
203
287
  const readyPromises = [];
204
288
  let isWatching = true;
205
- const handlerPattern = "**/*.handlers.{ts,js,mjs}";
206
- const seedPattern = "**/*.seeds.{ts,js,mjs}";
289
+ const handlerRe = /\.handlers\.(ts|js|mjs)$/;
290
+ const seedRe = /\.seeds\.(ts|js|mjs)$/;
207
291
  const safeInvoke = (callback, filePath, context) => {
208
292
  Promise.resolve().then(() => callback(filePath)).catch((error) => {
209
293
  logger.error(
@@ -212,80 +296,103 @@ async function createFileWatcher(options) {
212
296
  );
213
297
  });
214
298
  };
215
- if (handlersDir && onHandlerChange) {
216
- const absoluteHandlersDir = path2.resolve(cwd, handlersDir);
217
- const handlerWatcher = watch(handlerPattern, {
218
- cwd: absoluteHandlersDir,
219
- ignoreInitial: true,
220
- ignored: ["**/node_modules/**", "**/dist/**"],
221
- persistent: true,
222
- awaitWriteFinish: {
223
- stabilityThreshold: 100,
224
- pollInterval: 50
299
+ const buildIgnored = (pattern) => {
300
+ return (filePath, stats) => {
301
+ if (nodeModulesRe.test(filePath) || distRe.test(filePath)) {
302
+ return true;
225
303
  }
226
- });
227
- handlerWatcher.on("add", (file) => {
228
- const absolutePath = path2.join(absoluteHandlersDir, file);
229
- safeInvoke(onHandlerChange, absolutePath, "Handler add");
230
- });
231
- handlerWatcher.on("change", (file) => {
232
- const absolutePath = path2.join(absoluteHandlersDir, file);
233
- safeInvoke(onHandlerChange, absolutePath, "Handler change");
234
- });
235
- handlerWatcher.on("unlink", (file) => {
236
- const absolutePath = path2.join(absoluteHandlersDir, file);
237
- safeInvoke(onHandlerChange, absolutePath, "Handler unlink");
238
- });
239
- handlerWatcher.on("error", (error) => {
240
- logger.error("[vite-plugin-open-api-server] Handler watcher error:", error);
241
- });
242
- readyPromises.push(
243
- new Promise((resolve) => {
244
- handlerWatcher.on("ready", () => resolve());
245
- })
246
- );
247
- watchers.push(handlerWatcher);
248
- }
249
- if (seedsDir && onSeedChange) {
250
- const absoluteSeedsDir = path2.resolve(cwd, seedsDir);
251
- const seedWatcher = watch(seedPattern, {
252
- cwd: absoluteSeedsDir,
253
- ignoreInitial: true,
254
- ignored: ["**/node_modules/**", "**/dist/**"],
255
- persistent: true,
256
- awaitWriteFinish: {
257
- stabilityThreshold: 100,
258
- pollInterval: 50
304
+ if (!stats) {
305
+ return false;
259
306
  }
260
- });
261
- seedWatcher.on("add", (file) => {
262
- const absolutePath = path2.join(absoluteSeedsDir, file);
263
- safeInvoke(onSeedChange, absolutePath, "Seed add");
264
- });
265
- seedWatcher.on("change", (file) => {
266
- const absolutePath = path2.join(absoluteSeedsDir, file);
267
- safeInvoke(onSeedChange, absolutePath, "Seed change");
268
- });
269
- seedWatcher.on("unlink", (file) => {
270
- const absolutePath = path2.join(absoluteSeedsDir, file);
271
- safeInvoke(onSeedChange, absolutePath, "Seed unlink");
272
- });
273
- seedWatcher.on("error", (error) => {
274
- logger.error("[vite-plugin-open-api-server] Seed watcher error:", error);
275
- });
276
- readyPromises.push(
277
- new Promise((resolve) => {
278
- seedWatcher.on("ready", () => resolve());
279
- })
280
- );
281
- watchers.push(seedWatcher);
307
+ if (!stats.isFile()) {
308
+ return false;
309
+ }
310
+ return !pattern.test(filePath);
311
+ };
312
+ };
313
+ try {
314
+ if (handlersDir && onHandlerChange) {
315
+ const absoluteHandlersDir = path.resolve(cwd, handlersDir);
316
+ if (!existsSync(absoluteHandlersDir)) {
317
+ logger.warn(
318
+ `[vite-plugin-open-api-server] Handlers directory does not exist, skipping watcher: ${absoluteHandlersDir}`
319
+ );
320
+ } else {
321
+ const handlerWatcher = watch(absoluteHandlersDir, {
322
+ ignoreInitial: true,
323
+ ignored: buildIgnored(handlerRe),
324
+ persistent: true,
325
+ awaitWriteFinish: {
326
+ stabilityThreshold: 100,
327
+ pollInterval: 50
328
+ }
329
+ });
330
+ handlerWatcher.on("add", (file) => {
331
+ safeInvoke(onHandlerChange, file, "Handler add");
332
+ });
333
+ handlerWatcher.on("change", (file) => {
334
+ safeInvoke(onHandlerChange, file, "Handler change");
335
+ });
336
+ handlerWatcher.on("unlink", (file) => {
337
+ safeInvoke(onHandlerChange, file, "Handler unlink");
338
+ });
339
+ handlerWatcher.on("error", (error) => {
340
+ logger.error("[vite-plugin-open-api-server] Handler watcher error:", error);
341
+ });
342
+ readyPromises.push(
343
+ new Promise((resolve) => {
344
+ handlerWatcher.on("ready", () => resolve());
345
+ })
346
+ );
347
+ watchers.push(handlerWatcher);
348
+ }
349
+ }
350
+ if (seedsDir && onSeedChange) {
351
+ const absoluteSeedsDir = path.resolve(cwd, seedsDir);
352
+ if (!existsSync(absoluteSeedsDir)) {
353
+ logger.warn(
354
+ `[vite-plugin-open-api-server] Seeds directory does not exist, skipping watcher: ${absoluteSeedsDir}`
355
+ );
356
+ } else {
357
+ const seedWatcher = watch(absoluteSeedsDir, {
358
+ ignoreInitial: true,
359
+ ignored: buildIgnored(seedRe),
360
+ persistent: true,
361
+ awaitWriteFinish: {
362
+ stabilityThreshold: 100,
363
+ pollInterval: 50
364
+ }
365
+ });
366
+ seedWatcher.on("add", (file) => {
367
+ safeInvoke(onSeedChange, file, "Seed add");
368
+ });
369
+ seedWatcher.on("change", (file) => {
370
+ safeInvoke(onSeedChange, file, "Seed change");
371
+ });
372
+ seedWatcher.on("unlink", (file) => {
373
+ safeInvoke(onSeedChange, file, "Seed unlink");
374
+ });
375
+ seedWatcher.on("error", (error) => {
376
+ logger.error("[vite-plugin-open-api-server] Seed watcher error:", error);
377
+ });
378
+ readyPromises.push(
379
+ new Promise((resolve) => {
380
+ seedWatcher.on("ready", () => resolve());
381
+ })
382
+ );
383
+ watchers.push(seedWatcher);
384
+ }
385
+ }
386
+ } catch (error) {
387
+ await Promise.allSettled(watchers.map((w) => w.close()));
388
+ throw error;
282
389
  }
283
390
  const readyPromise = Promise.all(readyPromises).then(() => {
284
391
  });
285
392
  return {
286
393
  async close() {
287
394
  isWatching = false;
288
- await Promise.all(watchers.map((w) => w.close()));
395
+ await Promise.allSettled(watchers.map((w) => w.close()));
289
396
  },
290
397
  get isWatching() {
291
398
  return isWatching;
@@ -299,9 +406,12 @@ function debounce(fn, delay) {
299
406
  let timeoutId = null;
300
407
  let isRunning = false;
301
408
  let pendingArgs = null;
409
+ let cancelled = false;
302
410
  const execute = async (...args) => {
303
- if (isRunning) {
304
- pendingArgs = args;
411
+ if (cancelled || isRunning) {
412
+ if (isRunning && !cancelled) {
413
+ pendingArgs = args;
414
+ }
305
415
  return;
306
416
  }
307
417
  isRunning = true;
@@ -312,14 +422,15 @@ function debounce(fn, delay) {
312
422
  }
313
423
  } finally {
314
424
  isRunning = false;
315
- if (pendingArgs !== null) {
425
+ if (pendingArgs !== null && !cancelled) {
316
426
  const nextArgs = pendingArgs;
317
427
  pendingArgs = null;
318
428
  setTimeout(() => execute(...nextArgs), 0);
319
429
  }
320
430
  }
321
431
  };
322
- return (...args) => {
432
+ const debouncedFn = (...args) => {
433
+ if (cancelled) return;
323
434
  if (timeoutId !== null) {
324
435
  clearTimeout(timeoutId);
325
436
  }
@@ -328,6 +439,97 @@ function debounce(fn, delay) {
328
439
  execute(...args);
329
440
  }, delay);
330
441
  };
442
+ debouncedFn.cancel = () => {
443
+ cancelled = true;
444
+ if (timeoutId !== null) {
445
+ clearTimeout(timeoutId);
446
+ timeoutId = null;
447
+ }
448
+ pendingArgs = null;
449
+ };
450
+ return debouncedFn;
451
+ }
452
+ async function createPerSpecFileWatchers(instances, vite, cwd, options) {
453
+ const watchers = [];
454
+ const allDebouncedFns = [];
455
+ try {
456
+ for (const instance of instances) {
457
+ const debouncedHandlerReload = debounce(
458
+ () => reloadSpecHandlers(instance, vite, cwd, options),
459
+ 100
460
+ );
461
+ const debouncedSeedReload = debounce(
462
+ () => reloadSpecSeeds(instance, vite, cwd, options),
463
+ 100
464
+ );
465
+ allDebouncedFns.push(debouncedHandlerReload, debouncedSeedReload);
466
+ const innerWatcher = await createFileWatcher({
467
+ handlersDir: instance.config.handlersDir,
468
+ seedsDir: instance.config.seedsDir,
469
+ cwd,
470
+ logger: options.logger,
471
+ onHandlerChange: debouncedHandlerReload,
472
+ onSeedChange: debouncedSeedReload
473
+ });
474
+ watchers.push({
475
+ async close() {
476
+ debouncedHandlerReload.cancel();
477
+ debouncedSeedReload.cancel();
478
+ await innerWatcher.close();
479
+ },
480
+ get isWatching() {
481
+ return innerWatcher.isWatching;
482
+ },
483
+ get ready() {
484
+ return innerWatcher.ready;
485
+ }
486
+ });
487
+ }
488
+ } catch (error) {
489
+ for (const fn of allDebouncedFns) fn.cancel();
490
+ await Promise.allSettled(watchers.map((w) => w.close()));
491
+ throw error;
492
+ }
493
+ return watchers;
494
+ }
495
+ async function reloadSpecHandlers(instance, vite, cwd, options) {
496
+ try {
497
+ const logger = options.logger ?? console;
498
+ const handlersResult = await loadHandlers(instance.config.handlersDir, vite, cwd, logger);
499
+ instance.server.updateHandlers(handlersResult.handlers);
500
+ printReloadNotification("handlers", handlersResult.handlers.size, options);
501
+ } catch (error) {
502
+ printError(`Failed to reload handlers for spec "${instance.id}"`, error, options);
503
+ }
504
+ }
505
+ async function reloadSpecSeeds(instance, vite, cwd, options) {
506
+ try {
507
+ const logger = options.logger ?? console;
508
+ const seedsResult = await loadSeeds(instance.config.seedsDir, vite, cwd, logger);
509
+ let broadcastCount = seedsResult.seeds.size;
510
+ instance.server.store.clearAll();
511
+ if (seedsResult.seeds.size > 0) {
512
+ try {
513
+ await executeSeeds(seedsResult.seeds, instance.server.store, instance.server.document);
514
+ } catch (execError) {
515
+ broadcastCount = 0;
516
+ printError(
517
+ `Seeds loaded but executeSeeds failed for spec "${instance.id}"; store is now empty`,
518
+ execError,
519
+ options
520
+ );
521
+ }
522
+ }
523
+ instance.server.wsHub.broadcast({
524
+ type: "seeds:updated",
525
+ data: { count: broadcastCount }
526
+ });
527
+ if (broadcastCount > 0) {
528
+ printReloadNotification("seeds", broadcastCount, options);
529
+ }
530
+ } catch (error) {
531
+ printError(`Failed to reload seeds for spec "${instance.id}"`, error, options);
532
+ }
331
533
  }
332
534
 
333
535
  // src/multi-proxy.ts
@@ -380,7 +582,7 @@ function configureMultiProxy(vite, instances, port) {
380
582
 
381
583
  // package.json
382
584
  var package_default = {
383
- version: "0.24.0-next.5"};
585
+ version: "0.24.0-next.6"};
384
586
 
385
587
  // src/types.ts
386
588
  var ValidationError = class extends Error {
@@ -568,86 +770,6 @@ function validateNoPrefixOverlaps(paths) {
568
770
  }
569
771
  }
570
772
  }
571
- async function loadSeeds(seedsDir, viteServer, cwd = process.cwd(), logger = console) {
572
- const seeds = /* @__PURE__ */ new Map();
573
- const absoluteDir = path2.resolve(cwd, seedsDir);
574
- const dirExists = await directoryExists(absoluteDir);
575
- if (!dirExists) {
576
- return {
577
- seeds,
578
- fileCount: 0,
579
- files: []
580
- };
581
- }
582
- const pattern = "**/*.seeds.{ts,js,mjs}";
583
- const files = await fg(pattern, {
584
- cwd: absoluteDir,
585
- absolute: false,
586
- onlyFiles: true,
587
- ignore: ["node_modules/**", "dist/**"]
588
- });
589
- for (const file of files) {
590
- const absolutePath = path2.join(absoluteDir, file);
591
- const fileSeeds = await loadSeedFile(absolutePath, viteServer, logger);
592
- for (const [schemaName, seedFn] of Object.entries(fileSeeds)) {
593
- if (seeds.has(schemaName)) {
594
- logger.warn(
595
- `[vite-plugin-open-api-server] Duplicate seed for schema "${schemaName}" in ${file}. Using last definition.`
596
- );
597
- }
598
- seeds.set(schemaName, seedFn);
599
- }
600
- }
601
- return {
602
- seeds,
603
- fileCount: files.length,
604
- files
605
- };
606
- }
607
- async function loadSeedFile(filePath, viteServer, logger) {
608
- try {
609
- const moduleNode = viteServer.moduleGraph.getModuleById(filePath);
610
- if (moduleNode) {
611
- viteServer.moduleGraph.invalidateModule(moduleNode);
612
- }
613
- const module = await viteServer.ssrLoadModule(filePath);
614
- const seeds = module.default ?? module.seeds ?? module;
615
- if (!seeds || typeof seeds !== "object") {
616
- logger.warn(
617
- `[vite-plugin-open-api-server] Invalid seed file ${filePath}: expected object export`
618
- );
619
- return {};
620
- }
621
- const validSeeds = {};
622
- for (const [key, value] of Object.entries(seeds)) {
623
- if (typeof value === "function") {
624
- validSeeds[key] = value;
625
- }
626
- }
627
- return validSeeds;
628
- } catch (error) {
629
- logger.error(
630
- `[vite-plugin-open-api-server] Failed to load seed file ${filePath}:`,
631
- error instanceof Error ? error.message : error
632
- );
633
- return {};
634
- }
635
- }
636
- async function getSeedFiles(seedsDir, cwd = process.cwd()) {
637
- const absoluteDir = path2.resolve(cwd, seedsDir);
638
- const dirExists = await directoryExists(absoluteDir);
639
- if (!dirExists) {
640
- return [];
641
- }
642
- const pattern = "**/*.seeds.{ts,js,mjs}";
643
- const files = await fg(pattern, {
644
- cwd: absoluteDir,
645
- absolute: true,
646
- onlyFiles: true,
647
- ignore: ["node_modules/**", "dist/**"]
648
- });
649
- return files;
650
- }
651
773
 
652
774
  // src/spec-id.ts
653
775
  function slugify(input) {
@@ -1102,7 +1224,12 @@ try {
1102
1224
  orchestrator = await createOrchestrator(resolvedOptions, viteServer, cwd);
1103
1225
  await orchestrator.start();
1104
1226
  configureMultiProxy(viteServer, orchestrator.instances, orchestrator.port);
1105
- fileWatchers = await setupPerSpecFileWatching(orchestrator, viteServer, cwd);
1227
+ fileWatchers = await createPerSpecFileWatchers(
1228
+ orchestrator.instances,
1229
+ viteServer,
1230
+ cwd,
1231
+ resolvedOptions
1232
+ );
1106
1233
  if (!resolvedOptions.silent && orchestrator.instances.length > 0) {
1107
1234
  const firstInstance = orchestrator.instances[0];
1108
1235
  const bannerInfo = extractBannerInfo(
@@ -1171,66 +1298,6 @@ try {
1171
1298
  orchestrator = null;
1172
1299
  }
1173
1300
  }
1174
- async function setupPerSpecFileWatching(orch, viteServer, projectCwd) {
1175
- const watchers = [];
1176
- try {
1177
- for (const instance of orch.instances) {
1178
- const specServer = instance.server;
1179
- const specConfig = instance.config;
1180
- const debouncedHandlerReload = debounce(
1181
- () => reloadSpecHandlers(specServer, specConfig.handlersDir, viteServer, projectCwd),
1182
- 100
1183
- );
1184
- const debouncedSeedReload = debounce(
1185
- () => reloadSpecSeeds(specServer, specConfig.seedsDir, viteServer, projectCwd),
1186
- 100
1187
- );
1188
- const watcher = await createFileWatcher({
1189
- handlersDir: specConfig.handlersDir,
1190
- seedsDir: specConfig.seedsDir,
1191
- cwd: projectCwd,
1192
- onHandlerChange: debouncedHandlerReload,
1193
- onSeedChange: debouncedSeedReload
1194
- });
1195
- watchers.push(watcher);
1196
- }
1197
- } catch (error) {
1198
- await Promise.allSettled(watchers.map((w) => w.close()));
1199
- throw error;
1200
- }
1201
- return watchers;
1202
- }
1203
- async function reloadSpecHandlers(server, handlersDir, viteServer, projectCwd) {
1204
- try {
1205
- const logger = resolvedOptions.logger ?? console;
1206
- const handlersResult = await loadHandlers(handlersDir, viteServer, projectCwd, logger);
1207
- server.updateHandlers(handlersResult.handlers);
1208
- server.wsHub.broadcast({
1209
- type: "handlers:updated",
1210
- data: { count: handlersResult.handlers.size }
1211
- });
1212
- printReloadNotification("handlers", handlersResult.handlers.size, resolvedOptions);
1213
- } catch (error) {
1214
- printError("Failed to reload handlers", error, resolvedOptions);
1215
- }
1216
- }
1217
- async function reloadSpecSeeds(server, seedsDir, viteServer, projectCwd) {
1218
- try {
1219
- const logger = resolvedOptions.logger ?? console;
1220
- const seedsResult = await loadSeeds(seedsDir, viteServer, projectCwd, logger);
1221
- server.store.clearAll();
1222
- if (seedsResult.seeds.size > 0) {
1223
- await executeSeeds(seedsResult.seeds, server.store, server.document);
1224
- }
1225
- server.wsHub.broadcast({
1226
- type: "seeds:updated",
1227
- data: { count: seedsResult.seeds.size }
1228
- });
1229
- printReloadNotification("seeds", seedsResult.seeds.size, resolvedOptions);
1230
- } catch (error) {
1231
- printError("Failed to reload seeds", error, resolvedOptions);
1232
- }
1233
- }
1234
1301
  }
1235
1302
 
1236
1303
  // src/devtools.ts
@@ -1269,6 +1336,6 @@ function getDevToolsUrl(port = 4e3, host, protocol) {
1269
1336
  return `${actualProtocol}://${actualHost}:${port}/_devtools/`;
1270
1337
  }
1271
1338
 
1272
- export { API_PROXY_PATH, DEVTOOLS_PROXY_PATH, SPEC_COLORS, ValidationError, WS_PROXY_PATH, configureMultiProxy, createFileWatcher, createOrchestrator, debounce, deriveProxyPath, deriveSpecId, getDevToolsUrl, getHandlerFiles, getSeedFiles, loadHandlers, loadSeeds, normalizeProxyPath, openApiServer, registerDevTools, resolveOptions, slugify, validateSpecs, validateUniqueIds, validateUniqueProxyPaths };
1339
+ export { API_PROXY_PATH, DEVTOOLS_PROXY_PATH, SPEC_COLORS, ValidationError, 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 };
1273
1340
  //# sourceMappingURL=index.js.map
1274
1341
  //# sourceMappingURL=index.js.map