@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.d.ts +56 -9
- package/dist/index.js +289 -222
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
206
|
-
const
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|