From c064b0b40d62666838037359822e180b05badcda Mon Sep 17 00:00:00 2001 From: padreug Date: Wed, 17 Sep 2025 20:23:32 +0200 Subject: [PATCH] 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. --- CLAUDE.md | 165 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 147 insertions(+), 18 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 9d106b1..185930d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 { - // 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 { + // Restore connections, refresh data when app becomes visible + await this.checkConnectionHealth() + await this.refreshData() + } + + private async onPause(): Promise { + // 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 + } + } + } } } ```