All files / src/plugin vitek-dev.ts

2.77% Statements 1/36
0% Branches 0/26
12.5% Functions 1/8
2.85% Lines 1/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91                          27x                                                                                                                                                          
/**
 * vitek:dev — configureServer, middleware, watcher
 */
 
import * as path from 'path';
import * as fs from 'fs';
import { createViteDevServerMiddleware } from '../adapters/vite/dev-server.js';
import { createViteLogger } from '../adapters/vite/logger.js';
import { API_BASE_PATH, getSocketBasePath } from '../shared/constants.js';
import type { Plugin } from 'vite';
import type { PluginContext } from './context.js';
 
export function createDevPlugin(ctx: PluginContext): Plugin {
  return {
    name: 'vitek:dev',
 
    async configureServer(server) {
      if (!ctx.root) return;
      const fullApiDir = path.resolve(ctx.root, ctx.apiDirOption);
 
      if (!fs.existsSync(fullApiDir)) {
        server.config.logger.warn(
          `[vitek] API directory not found: ${fullApiDir}`
        );
        return;
      }
 
      const logger = createViteLogger(server.config.logger, ctx.options.logging);
      const socketsEnabled = ctx.options.sockets !== false;
      const socketBasePath = getSocketBasePath(
        ctx.options.apiBasePath,
        typeof ctx.options.sockets === 'object' ? ctx.options.sockets?.path : undefined
      );
      const beforeApiRequest = (ctx.options.plugins ?? [])
        .filter((p): p is typeof p & { beforeApiRequest: NonNullable<typeof p.beforeApiRequest> } => !!p.beforeApiRequest)
        .map((p) => (hookCtx: { req: import('http').IncomingMessage; res: import('http').ServerResponse; path: string; method: string }, next: () => void) =>
          p.beforeApiRequest!({ ...hookCtx, next })
        );
      const afterTypesGenerated = (ctx.options.plugins ?? [])
        .map((p) => p.afterTypesGenerated)
        .filter((h): h is NonNullable<typeof h> => !!h);
      const { ready, middleware, cleanup, setupSockets } = createViteDevServerMiddleware({
        root: ctx.root,
        apiDir: fullApiDir,
        logger,
        viteServer: server,
        enableValidation: ctx.options.enableValidation || false,
        openApi: ctx.options.openApi,
        sockets: socketsEnabled,
        socketBasePath,
        apiBasePath: ctx.options.apiBasePath ?? API_BASE_PATH,
        onGenerationError: ctx.options.onGenerationError,
        beforeApiRequest,
        afterTypesGenerated,
        cors: ctx.options.cors,
        trustProxy: ctx.options.trustProxy,
        maxBodySize: ctx.options.maxBodySize,
        onError: ctx.options.onError,
      });
 
      ctx.cleanupFn = cleanup;
 
      server.middlewares.use(middleware);
 
      await ready;
 
      if (socketsEnabled && server.httpServer) {
        setupSockets(server.httpServer);
      }
 
      logger.info('Vitek plugin initialized');
 
      const port = server.config.server?.port ?? 5173;
      const apiPath = ctx.options.apiBasePath ?? API_BASE_PATH;
      const originalPrintUrls = server.printUrls?.bind(server);
      if (typeof originalPrintUrls === 'function') {
        server.printUrls = () => {
          originalPrintUrls();
          const host = 'localhost';
          const apiUrl = `http://${host}:${port}${apiPath}`;
          server.config.logger.info(`  ➜  API:     ${apiUrl}`);
          if (socketsEnabled) {
            const wsUrl = `ws://${host}:${port}${socketBasePath}`;
            server.config.logger.info(`  ➜  WS:      ${wsUrl}`);
          }
        };
      }
    },
  };
}