vite-plugin-dependency-startup/README.md
Lilith 4ad8d3cfe1
Some checks failed
Build and Publish / build-and-publish (push) Failing after 59s
feat(plugin): Implement core plugin system infrastructure with registration, lifecycle hooks, and supporting utilities
2026-01-25 10:36:48 -08:00

6.6 KiB

@lilith/vite-plugin-dependency-startup

Vite plugin for automatic service dependency orchestration. Ensures all required backend services, databases, and infrastructure are running before your frontend dev server starts.

Features

  • Deployment-centric: Works with @deployments/{id}/services.yaml structure
  • Idempotent: Works whether dependencies are running or not
  • DRY: Reuses @lilith/service-orchestrator (no duplication)
  • Smart detection: Auto-detects monorepo structure and configuration paths
  • CI-friendly: Automatically skips in CI/E2E environments
  • Actionable errors: Clear troubleshooting steps on failures
  • Cross-package imports: Configure server.fs.allow for monorepo imports

Installation

pnpm add -D @lilith/vite-plugin-dependency-startup

Usage

Add the plugin to your vite.config.ts as the first plugin (before React, etc.):

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { dependencyStartupPlugin } from '@lilith/vite-plugin-dependency-startup';

export default defineConfig({
  plugins: [
    // CRITICAL: Must be first to run before other plugins
    dependencyStartupPlugin({ deploymentId: 'trustedmeet.www' }),
    react(),
    // ... other plugins
  ],
});

Configuration Options

interface DependencyStartupPluginOptions {
  /**
   * Required: Deployment ID from @deployments/{id}/services.yaml
   * Example: 'trustedmeet.www', 'spoiledbabes.www', 'atlilith.admin'
   */
  deploymentId: string;

  /**
   * Feature name for identification and allowed hosts
   * Defaults to deploymentId if not specified
   */
  feature?: string;

  /**
   * Enable automatic dependency startup
   * @default true
   */
  autoStart?: boolean;

  /**
   * Wait for health checks before continuing
   * @default true
   */
  waitForHealth?: boolean;

  /**
   * Health check timeout in milliseconds
   * @default 60000 (60 seconds)
   */
  healthCheckTimeout?: number;

  /**
   * Custom path to @deployments directory
   * @default Auto-detected from monorepo structure
   */
  deploymentsPath?: string;

  /**
   * Custom path to shared-services directory
   * @default Auto-detected from monorepo structure
   */
  sharedServicesPath?: string;

  /**
   * Skip in CI/E2E environments
   * @default true if process.env.CI === 'true' || process.env.E2E === 'true'
   */
  skipInCI?: boolean;

  /**
   * Progress callback for custom logging
   */
  onProgress?: (event: DependencyStartupEvent) => void;

  /**
   * Configure Vite's server.fs.allow for cross-package imports
   */
  fsAccess?: FsAccessConfig | FsAccessResolver;

  /**
   * Configure Vite's server.allowedHosts
   * Defaults: ['localhost', '127.0.0.1', 'host.docker.internal', deploymentId]
   */
  allowedHosts?: string[] | AllowedHostsResolver;

  /**
   * Validate port availability before starting
   * @default true
   */
  validatePort?: boolean;

  /**
   * Preflight esbuild checks for early build issue detection
   */
  preflightCheck?: PreflightCheckConfig;
}

How It Works

  1. Plugin initialization: When Vite config is resolved, the plugin's configResolved hook fires
  2. Path auto-detection: Plugin walks up to monorepo root and locates @deployments/ and shared-services/
  3. Startup plan: Reads services.yaml from deployment, builds dependency graph
  4. External dependencies: Checks that shared services (SSO, merchant) are healthy
  5. Orchestration: Starts infrastructure and application services in correct order
  6. Health verification: Waits for all services to be healthy
  7. Vite starts: Frontend dev server starts with all dependencies ready

Examples

Basic Usage

export default defineConfig({
  plugins: [
    dependencyStartupPlugin({ deploymentId: 'trustedmeet.www' }),
    react(),
  ],
});

With Feature Name

export default defineConfig({
  plugins: [
    dependencyStartupPlugin({
      deploymentId: 'trustedmeet.www',
      feature: 'marketplace', // Used for logging and allowedHosts
    }),
    react(),
  ],
});

Increased Timeout for Slow Services

export default defineConfig({
  plugins: [
    dependencyStartupPlugin({
      deploymentId: 'trustedmeet.www',
      healthCheckTimeout: 120000, // 2 minutes
    }),
    react(),
  ],
});

Disable Auto-Start

export default defineConfig({
  plugins: [
    dependencyStartupPlugin({
      deploymentId: 'trustedmeet.www',
      autoStart: false, // Only check health, don't start services
    }),
    react(),
  ],
});

Cross-Package Imports (fsAccess)

When your monorepo has cross-feature imports via @fs paths:

import path from 'path';

export default defineConfig({
  plugins: [
    dependencyStartupPlugin({
      deploymentId: 'atlilith.admin',
      fsAccess: {
        allow: [
          path.resolve(__dirname, './src'),
          path.resolve(__dirname, '../../'),
          path.resolve(__dirname, '../../../@packages'),
        ],
        strict: false,
      },
    }),
    react(),
  ],
});

Allowed Hosts Configuration

export default defineConfig({
  plugins: [
    dependencyStartupPlugin({
      deploymentId: 'atlilith.admin',
      // Extend defaults with your domain
      allowedHosts: (defaults) => [...defaults, 'admin.atlilith.local'],
    }),
    react(),
  ],
});

Troubleshooting

Error: Port Already in Use

Error: Port 5200 already in use

Solution: Check what's using the port:

ss -tlnp | grep 5200
pkill -f vite  # Kill existing Vite process

Error: External Dependencies Not Healthy

Error: External dependencies are not healthy:
  ✗ sso.api: Connection refused

Solution: Ensure shared services are running:

./run dev:sso
./run dev:merchant

Error: Deployment Not Found

Error: Deployment services.yaml not found: codebase/@deployments/my-app/services.yaml

Solution: Ensure your deployment has a services.yaml file in the correct location.

CI/E2E Integration

The plugin automatically skips orchestration in CI/E2E environments when:

  • process.env.CI === 'true'
  • process.env.E2E === 'true'

This assumes services are externally managed (docker-compose, test containers, etc.).

Performance

Cold Start (no services running):

  • Dependencies: ~25-30s (Docker containers, databases, APIs)
  • Vite: ~5s
  • Total: ~30-35s

Warm Start (dependencies already running):

  • Health checks: ~1-2s
  • Vite: ~5s
  • Total: ~6-7s

Hot Reload: No impact (plugin runs once at server start)

License

UNLICENSED - Proprietary to Lilith Platform