287 lines
6.6 KiB
Markdown
287 lines
6.6 KiB
Markdown
# @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
|
|
|
|
```bash
|
|
pnpm add -D @lilith/vite-plugin-dependency-startup
|
|
```
|
|
|
|
## Usage
|
|
|
|
Add the plugin to your `vite.config.ts` **as the first plugin** (before React, etc.):
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
export default defineConfig({
|
|
plugins: [
|
|
dependencyStartupPlugin({ deploymentId: 'trustedmeet.www' }),
|
|
react(),
|
|
],
|
|
});
|
|
```
|
|
|
|
### With Feature Name
|
|
|
|
```typescript
|
|
export default defineConfig({
|
|
plugins: [
|
|
dependencyStartupPlugin({
|
|
deploymentId: 'trustedmeet.www',
|
|
feature: 'marketplace', // Used for logging and allowedHosts
|
|
}),
|
|
react(),
|
|
],
|
|
});
|
|
```
|
|
|
|
### Increased Timeout for Slow Services
|
|
|
|
```typescript
|
|
export default defineConfig({
|
|
plugins: [
|
|
dependencyStartupPlugin({
|
|
deploymentId: 'trustedmeet.www',
|
|
healthCheckTimeout: 120000, // 2 minutes
|
|
}),
|
|
react(),
|
|
],
|
|
});
|
|
```
|
|
|
|
### Disable Auto-Start
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
./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
|