Ctrl K
ComunidadGuías…

electron.vite.config.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { execSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'electron-vite';

import { dependencyInventoryPlugin } from './scripts/electron-dependency-inventory.mjs';

import webPkg from './web/package.json' with { type: 'json' };

const __dirname = dirname(fileURLToPath(import.meta.url));

const ELECTRON_ESM_CJS_SHIM = `
// -- CommonJS Shims --
import __cjs_mod__ from 'node:module';
var __filename = import.meta.filename;
var __dirname = import.meta.dirname;
var require = __cjs_mod__.createRequire(import.meta.url);
`;

function tryGitSha(): string {
  try {
    return execSync('git rev-parse HEAD', { cwd: __dirname, encoding: 'utf8' }).trim();
  } catch {
    return 'unknown';
  }
}

/** Packaged Electron loads the embedded gateway URL; renderer build is dev/preview-only. */
const skipRenderer = process.env['ELECTRON_VITE_SKIP_RENDERER'] === '1';

export default defineConfig({
  main: {
    plugins: [dependencyInventoryPlugin(__dirname), {
      name: 'xopc:explicit-esm-shim',
      configResolved(config) {
        // The banner supplies the shim without scanning bundled strings as imports.
        config.plugins = config.plugins.filter(plugin => plugin.name !== 'vite:esm-shim');
      },
    }],
    build: {
      // Packaged asar only ships minimal node_modules for the gateway subprocess (see
      // scripts/electron-runtime-externals.mjs). Main-process deps (zod, pino, dotenv, …) must
      // be bundled — electron-vite defaults to externalizeDeps=true which leaves bare imports.
      externalizeDeps: false,
      // Keep post-minification; electron-builder also compresses the packaged artifact.
      minify: 'esbuild',
      rollupOptions: {
        // IMPORTANT: In the Electron main process, `electron` is a runtime-provided module.
        // If Rollup resolves it to the npm package `electron`, the bundle will include
        // `node_modules/electron/index.js`, which throws at runtime inside packaged apps.
        // Do not mark `thread-stream` external: pnpm may not hoist it, so `require('thread-stream')`
        // from `out/main/chunks/*` fails. Bundled `thread-stream` + `thread-stream-bundle-shim.ts`
        // fixes pino transport worker path (see electron/thread-stream-bundle-shim.ts).
        // `@vscode/ripgrep` resolves a platform optionalDep at import time; packaged apps use extraResources `bin/rg`.
        // `node-pty` must resolve from its real package directory so it can load native binaries and spawn-helper.
        external: ['electron', '@vscode/ripgrep', 'node-pty', '@trycua/cua-driver'],
        input: {
          index: resolve(__dirname, 'electron/index.ts'),
          // Keep main's import.meta.dirname at out/main for preload and native helper paths.
          main: resolve(__dirname, 'electron/main.ts'),
          compatibility: resolve(__dirname, 'electron/gateway-compatibility.ts'),
        },
        // electron-vite 6 beta locates the last ESM import with a regex that can overrun into
        // bundled source. Providing the shim explicitly bypasses that unsafe insertion path.
        output: { banner: ELECTRON_ESM_CJS_SHIM },
      },
    },
    resolve: {
      alias: {
        '@xopcai/xopc': resolve(__dirname, 'src'),
      },
    },
  },
  preload: {
    plugins: [dependencyInventoryPlugin(__dirname), { name: 'computer-preview-document', async generateBundle() {
      this.emitFile({ type: 'asset', fileName: 'computer-preview.html', source: readFileSync(resolve(__dirname, 'electron/computer/preview-worker.html'), 'utf8') });
    } }],
    build: {
      minify: 'esbuild',
      rollupOptions: {
        // Same as main: keep `electron` as runtime-provided, not the npm package.
        external: ['electron'],
        input: {
          index: resolve(__dirname, 'electron/preload.ts'),
          'computer-preview': resolve(__dirname, 'electron/computer/preview-worker.ts'),
        },
        // Root package.json is `"type": "module"`, so electron-vite would default preload to ESM
        // (`index.mjs`). Electron does not execute that preload as an ES module. Force CJS (`index.cjs`).
        output: {
          format: 'cjs',
        },
      },
    },
  },
  ...(skipRenderer
    ? {}
    : {
        renderer: {
          root: resolve(__dirname, 'web'),
          base: './',
          define: {
            __XOPC_WEB_VERSION__: JSON.stringify(webPkg.version),
            __XOPC_WEB_COMMIT__: JSON.stringify(process.env['VITE_XOPC_WEB_COMMIT'] ?? tryGitSha()),
            __XOPC_WEB_BUILD_TIME__: JSON.stringify(
              process.env['VITE_XOPC_WEB_BUILD_TIME'] ?? new Date().toISOString(),
            ),
          },
          plugins: [react(), tailwindcss()],
          resolve: {
            alias: {
              '@': resolve(__dirname, 'web/src'),
            },
          },
          build: {
            rollupOptions: {
              input: resolve(__dirname, 'web/index.html'),
            },
            outDir: resolve(__dirname, 'out/renderer'),
            emptyOutDir: true,
          },
          server: {
            port: 5173,
            // Same-origin API calls use `window.location.origin` (this dev server). Mirror `web/vite.config.ts`
            // so `/api/*` reaches the xopc gateway — required for Electron dev (renderer loads from :5173).
            proxy: {
              '/api': {
                target: 'http://localhost:18790',
                changeOrigin: true,
                ws: true,
              },
              '/health': {
                target: 'http://localhost:18790',
                changeOrigin: true,
              },
              '/status': {
                target: 'http://localhost:18790',
                changeOrigin: true,
              },
              '/favicon.ico': {
                target: 'http://localhost:18790',
                changeOrigin: true,
              },
            },
          },
        },
      }),
});