Add module development checklist and critical requirements to CLAUDE.md

- Introduced a comprehensive module development checklist to ensure consistency and quality in module implementation.
- Added critical service and module installation requirements, emphasizing proper service initialization, dependency management, and configuration usage.
- Included common mistakes to avoid during module development to guide developers in best practices.

These updates enhance the documentation for module development, promoting better adherence to standards and improving overall code quality.
This commit is contained in:
padreug 2025-09-17 20:23:32 +02:00
parent 453bb53282
commit c064b0b40d

165
CLAUDE.md
View file

@ -342,6 +342,46 @@ const onSubmit = form.handleSubmit(async (values) => {
4. **API Isolation**: Module-specific API calls must be in the module's services folder
5. **Dependency Injection**: Cross-module communication only through DI container
### **📋 MODULE DEVELOPMENT CHECKLIST**
Before considering any module complete, verify ALL items:
**Service Implementation:**
- [ ] Service extends `BaseService`
- [ ] Has `metadata` with `name`, `version`, `dependencies`
- [ ] Dependencies listed in metadata match actual usage
- [ ] No manual `injectService()` calls in `onInitialize()`
- [ ] Registers with VisibilityService if has real-time features
- [ ] Implements `onResume()` and `onPause()` if using VisibilityService
- [ ] Uses module config, not direct config imports
**Module Plugin:**
- [ ] Depends on `'base'` module
- [ ] Creates service instances
- [ ] Registers services in DI container BEFORE initialization
- [ ] Calls `service.initialize()` with `waitForDependencies: true`
- [ ] Registers components AFTER service initialization
**Configuration:**
- [ ] Module added to `app.config.ts`
- [ ] Has `enabled` flag
- [ ] Has `config` object with necessary settings
- [ ] Uses `appConfig.modules.[moduleName].config` in services
**Forms (if applicable):**
- [ ] Uses Shadcn/UI form components
- [ ] Uses vee-validate with Zod schema
- [ ] Has proper validation messages
- [ ] Disables submit button until form is valid
- [ ] Uses `form.handleSubmit()` for submission
**Testing Checklist:**
- [ ] Service initializes without errors
- [ ] Dependencies are properly injected
- [ ] VisibilityService callbacks work (test by switching tabs)
- [ ] Configuration is properly loaded
- [ ] Module can be disabled via config
**Required Module Structure:**
```
src/modules/[module-name]/
@ -357,58 +397,147 @@ src/modules/[module-name]/
```
**Service Implementation Pattern:**
**⚠️ CRITICAL SERVICE REQUIREMENTS - MUST FOLLOW EXACTLY:**
```typescript
// Always extend BaseService for services
// ✅ CORRECT: Proper BaseService implementation
export class MyModuleService extends BaseService {
// 1. REQUIRED: Declare metadata with dependencies
protected readonly metadata = {
name: 'MyModuleService',
version: '1.0.0',
dependencies: [] // List service dependencies
dependencies: ['PaymentService', 'AuthService'] // List ALL service dependencies by name
}
// 2. REQUIRED: DO NOT manually inject services in onInitialize
protected async onInitialize(): Promise<void> {
// Service-specific initialization
// ❌ WRONG: Manual injection
// this.paymentService = injectService(SERVICE_TOKENS.PAYMENT_SERVICE)
// ✅ CORRECT: BaseService auto-injects based on metadata.dependencies
// this.paymentService is already available here!
// 3. REQUIRED: Register with VisibilityService if you have ANY real-time features
if (this.hasRealTimeFeatures()) {
this.visibilityService.registerService(
this.metadata.name,
this.onResume.bind(this),
this.onPause.bind(this)
)
}
// 4. Initialize your module-specific logic
await this.loadInitialData()
}
// 5. REQUIRED: Implement visibility handlers for connection management
private async onResume(): Promise<void> {
// Restore connections, refresh data when app becomes visible
await this.checkConnectionHealth()
await this.refreshData()
}
private async onPause(): Promise<void> {
// Pause expensive operations for battery efficiency
this.pausePolling()
}
private hasRealTimeFeatures(): boolean {
// Return true if your service uses WebSockets, polling, or real-time updates
return true
}
}
// API services for LNbits integration
export class MyModuleAPI extends BaseService {
private baseUrl: string
constructor() {
super()
const config = appConfig.modules.myModule.config
this.baseUrl = config.apiConfig.baseUrl
// ❌ WRONG: Direct config import
// import { config } from '@/lib/config'
// ✅ CORRECT: Use module configuration
const moduleConfig = appConfig.modules.myModule.config
this.baseUrl = moduleConfig.apiConfig.baseUrl
}
// API methods here
}
```
**❌ COMMON MISTAKES TO AVOID:**
1. **Manual service injection** in onInitialize - BaseService handles this
2. **Direct config imports** - Always use module configuration
3. **Missing metadata.dependencies** - Breaks automatic dependency injection
4. **No VisibilityService integration** - Causes connection issues on mobile
5. **Not using proper initialization options** - Miss dependency waiting
**Module Plugin Pattern:**
**⚠️ CRITICAL MODULE INSTALLATION REQUIREMENTS:**
```typescript
export const myModule: ModulePlugin = {
name: 'my-module',
version: '1.0.0',
dependencies: ['base'], // Always depend on base
dependencies: ['base'], // ALWAYS depend on 'base' for core infrastructure
async install(app: App, options?: { config?: MyModuleConfig }) {
// 1. Create service instances
// 1. REQUIRED: Create service instances
const myService = new MyModuleService()
const myAPI = new MyModuleAPI()
// 2. Register in DI container
// 2. REQUIRED: Register in DI container BEFORE initialization
container.provide(SERVICE_TOKENS.MY_SERVICE, myService)
container.provide(SERVICE_TOKENS.MY_API, myAPI)
// 3. Initialize services
// 3. CRITICAL: Initialize services with proper options
await myService.initialize({
waitForDependencies: true,
maxRetries: 3
waitForDependencies: true, // REQUIRED: Wait for dependencies
maxRetries: 3, // RECOMMENDED: Retry on failure
timeout: 5000 // OPTIONAL: Timeout for initialization
})
// 4. Register components if needed
// Initialize API service if it needs initialization
if (myAPI.initialize) {
await myAPI.initialize({
waitForDependencies: true,
maxRetries: 3
})
}
// 4. Register components AFTER services are initialized
app.component('MyComponent', MyComponent)
// 5. OPTIONAL: Export for testing/debugging
return {
service: myService,
api: myAPI
}
}
}
```
**MODULE CONFIGURATION IN app.config.ts:**
```typescript
// REQUIRED: Add module configuration
export default {
modules: {
'my-module': {
enabled: true,
config: {
apiConfig: {
baseUrl: import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000'
},
// Module-specific configuration
features: {
realTimeUpdates: true,
offlineSupport: false
}
}
}
}
}
```