@tdi2/vite-plugin-di Overview
@tdi2/vite-plugin-di Overview
Section titled “@tdi2/vite-plugin-di Overview”Build-Time DI Transformation
Section titled “Build-Time DI Transformation”The Vite plugin that transforms your TDI2 code at build time, providing automatic interface resolution, component transformation, and development debugging tools.
🎯 Plugin Features
- Interface Resolution - Automatic service discovery from TypeScript interfaces
- Component Transformation - Convert service props to useService hooks
- Hot Reload - Development-friendly automatic retransformation
- Debug Tools - Development endpoints and verbose logging
🔧 Technical Background: See ADR-001: AST Transformation and ADR-004: Build-Time DI for the design rationale.
Installation
Section titled “Installation”# npmnpm install @tdi2/vite-plugin-di @tdi2/di-core
# bunbun add @tdi2/vite-plugin-di @tdi2/di-core
# pnpmpnpm add @tdi2/vite-plugin-di @tdi2/di-coreBasic Configuration
Section titled “Basic Configuration”Minimal Setup
Section titled “Minimal Setup”import { defineConfig } from 'vite';import react from '@vitejs/plugin-react';import { diEnhancedPlugin } from '@tdi2/vite-plugin-di';
export default defineConfig({ plugins: [ diEnhancedPlugin(), // Zero config setup! react(), ],});Development Configuration
Section titled “Development Configuration”export default defineConfig({ plugins: [ diEnhancedPlugin({ // Enable all features for development enableInterfaceResolution: true, enableFunctionalDI: true, verbose: true, generateDebugFiles: true, }), react(), ],});Production Configuration
Section titled “Production Configuration”export default defineConfig({ plugins: [ diEnhancedPlugin({ // Optimized for production enableInterfaceResolution: true, enableFunctionalDI: true, verbose: false, generateDebugFiles: false, reuseExistingConfig: true, }), react(), ],});How It Works
Section titled “How It Works”1. Interface Resolution
Section titled “1. Interface Resolution”The plugin scans your codebase and automatically maps interfaces to implementations:
// Your codeexport interface ProductServiceInterface { loadProducts(): Promise<void>;}
@Service()export class ProductService implements ProductServiceInterface { // Implementation...}Generated mapping:
// .tdi2/di-config.ts (auto-generated)export const DI_CONFIG = { services: [ { interface: 'ProductServiceInterface', implementation: 'ProductService', token: 'ProductService' } ]};2. Component Transformation
Section titled “2. Component Transformation”Components with service props are automatically transformed:
Your code:
function ProductList({ productService }: { productService: Inject<ProductServiceInterface>;}) { const { products, loading } = productService.state; return <div>{/* JSX */}</div>;}Generated code:
function ProductList() { // TDI2-GENERATED: Service injection const productService = useService<ProductServiceInterface>('ProductService'); const productServiceSnap = useSnapshot(productService.state); const { products, loading } = productServiceSnap;
return <div>{/* Your JSX unchanged */}</div>;}Configuration Options
Section titled “Configuration Options”Core Options
Section titled “Core Options”interface DIPluginOptions { /** Source directory to scan */ srcDir?: string; // default: './src'
/** Output directory for generated files */ outputDir?: string; // default: './src/.tdi2'
/** Enable verbose logging */ verbose?: boolean; // default: false
/** Enable hot reload during development */ watch?: boolean; // default: true
/** Enable functional component transformation */ enableFunctionalDI?: boolean; // default: true
/** Enable interface-to-implementation resolution */ enableInterfaceResolution?: boolean; // default: true}Advanced Options
Section titled “Advanced Options”interface DIPluginOptions { /** Generate debug files for inspection */ generateDebugFiles?: boolean; // default: false
/** Reuse existing configurations */ reuseExistingConfig?: boolean; // default: true
/** Clean old configuration files */ cleanOldConfigs?: boolean; // default: true
/** Number of configurations to keep */ keepConfigCount?: number; // default: 3}Development Features
Section titled “Development Features”Debug Endpoints
Section titled “Debug Endpoints”During development, access these URLs for debugging:
# General debug informationhttp://localhost:5173/_di_debug
# Interface mappingshttp://localhost:5173/_di_interfaces
# Configuration managementhttp://localhost:5173/_di_configs
# Performance statisticshttp://localhost:5173/_di_performanceForce Regeneration
Section titled “Force Regeneration”# Via APIcurl -X POST http://localhost:5173/_di_regenerate
# Via CLI (if available)npm run di:regenerateDebug File Generation
Section titled “Debug File Generation”Enable debug file generation to inspect transformations:
diEnhancedPlugin({ generateDebugFiles: true, verbose: true})This creates files in .tdi2/debug/ showing:
- Original component code
- Transformed component code
- Interface mappings
- Service registrations
Presets
Section titled “Presets”Use predefined configurations for common scenarios:
import { diEnhancedPlugin, createDIPluginPresets } from '@tdi2/vite-plugin-di';
const presets = createDIPluginPresets();
export default defineConfig({ plugins: [ // Choose appropriate preset process.env.NODE_ENV === 'development' ? diEnhancedPlugin(presets.development.options) : diEnhancedPlugin(presets.production.options),
react(), ],});Available presets:
development- Verbose logging, hot reload, debug filesproduction- Minimal logging, optimized buildstesting- Fast rebuilds, no debug outputdebugging- Maximum verbosity for troubleshooting
Examples
Section titled “Examples”Interface-Based Resolution
Section titled “Interface-Based Resolution”// No manual token mapping needed!export interface CartServiceInterface { addItem(product: Product): void;}
@Service()export class CartService implements CartServiceInterface { constructor( @Inject() private storage: StorageService, // Auto-resolved @Inject() private analytics?: AnalyticsService // Optional ) {}}Multiple Implementations
Section titled “Multiple Implementations”// Primary implementation@Service()@Primary()export class DatabaseUserRepository implements UserRepositoryInterface {}
// Alternative implementation@Service()@Qualifier('cache')export class CacheUserRepository implements UserRepositoryInterface {}
@Service()export class UserService { constructor( @Inject() private repo: UserRepositoryInterface, // → DatabaseUserRepository @Inject() @Qualifier('cache') private cache: UserRepositoryInterface // → CacheUserRepository ) {}}Generic Interfaces
Section titled “Generic Interfaces”export interface Repository<T> { findById(id: string): Promise<T>; save(entity: T): Promise<void>;}
@Service()export class ProductRepository implements Repository<Product> { // Implementation...}
// Automatic resolution with generics!@Service()export class ProductService { constructor(@Inject() private repo: Repository<Product>) {} // ↑ Automatically resolves to ProductRepository}Performance
Section titled “Performance”Build-Time Benefits
Section titled “Build-Time Benefits”- Zero Runtime Overhead - All DI resolution happens at build time
- Tree Shaking - Only used services included in bundles
- Code Generation - No runtime reflection or metadata
- Parallel Processing - Concurrent file processing for large codebases
Development Performance
Section titled “Development Performance”- Intelligent Caching - Avoid unnecessary regeneration
- Hot Reload - Automatic retransformation on changes
- Incremental Updates - Only rebuild changed components
Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”Service Not Found
Section titled “Service Not Found”# Check interface mappingscurl http://localhost:5173/_di_interfaces
# Force regenerationcurl -X POST http://localhost:5173/_di_regenerateInterface Resolution Failing
Section titled “Interface Resolution Failing”// Ensure proper implementation@Service()export class MyService implements MyServiceInterface { // Must implement interface methods}Hot Reload Not Working
Section titled “Hot Reload Not Working”diEnhancedPlugin({ watch: true, // Enable file watching verbose: true // See what's happening})Debug Mode
Section titled “Debug Mode”Enable maximum debugging for troubleshooting:
diEnhancedPlugin({ verbose: true, generateDebugFiles: true, // Force fresh start reuseExistingConfig: false, cleanOldConfigs: true})Integration Examples
Section titled “Integration Examples”With TypeScript
Section titled “With TypeScript”{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": false, "target": "ES2020" }}With Testing
Section titled “With Testing”export default defineConfig({ plugins: [ diEnhancedPlugin(presets.testing.options), react(), ], test: { environment: 'jsdom', },});With Monorepos
Section titled “With Monorepos”export default defineConfig({ plugins: [ diEnhancedPlugin({ srcDir: './src', outputDir: './src/.tdi2', // Scan shared packages too advanced: { fileExtensions: ['.ts', '.tsx'], searchPaths: ['../../packages/*/src'] } }), react(), ],});Next Steps
Section titled “Next Steps”Essential Reading
Section titled “Essential Reading”- DI Core Package - Core framework features
- Testing Guide - Test with build-time DI
Setup Guides
Section titled “Setup Guides”- Quick Start - Complete setup tutorial
- Service Patterns - Design robust services
Examples
Section titled “Examples”- Complete E-Commerce App - Working implementation
- Build Configuration Examples - Various setup configurations
- Debug Output Examples - See transformations in action
The Vite plugin handles all the complexity of dependency injection transformation. Your code stays clean and readable while the plugin generates optimized production code.