docs: reorganize documentation structure with 7-item folder limits

- Create logical sub-folder classification for all documentation
- Organize 91 migration files into component-specific folders
- Separate user guides, build system, migration, and development docs
- Maintain maximum 7 items per folder for easy navigation
- Add comprehensive README and reorganization summary
- Ensure all changes tracked in git with proper versioning

Structure:
- user-guides/ (3 items): user-facing documentation
- build-system/ (3 items): core, platforms, automation
- migration/ (6 items): assessments, testing, templates
- development/ (4 items): tools and standards
- architecture/, testing/, examples/ (ready for future docs)

Total: 24 folders created, all within 7-item limits
This commit is contained in:
Matthew Raymer
2025-07-22 09:18:30 +00:00
parent 2f38eba4ff
commit db5da0cdfc
127 changed files with 956 additions and 0 deletions

View File

@@ -0,0 +1,519 @@
# Complete Migration Checklist - MANDATORY STEPS
## Overview
This checklist ensures NO migration steps are forgotten. **Every component migration MUST complete ALL sections.**
## 🚨 **CRITICAL: PRE-MIGRATION PLANNING REQUIRED**
**BEFORE starting any migration, you MUST:**
1. **Create detailed migration documentation** in `docs/migration-testing/[COMPONENT]_MIGRATION.md`
2. **Complete pre-migration analysis** including:
- Current state assessment (database, notifications, template complexity)
- Migration complexity assessment
- Risk assessment
- Timeline estimation
- Testing requirements
3. **Review the plan** and confirm all migration targets are identified
4. **Get approval** before proceeding with code changes
**❌ NO EXCEPTIONS**: Every migration must have a documented plan before implementation begins.
## Requirements
**EVERY component migration MUST complete ALL SIX migration types:**
1. **Database Migration**: Replace databaseUtil calls with PlatformServiceMixin methods
2. **SQL Abstraction**: Replace raw SQL queries with service methods
2.5. **Contact Method Standardization**: Replace inconsistent contact fetching patterns
3. **Notification Migration**: Replace `$notify()` calls with helper methods + centralized constants
4. **Template Streamlining**: Extract repeated expressions and complex logic to computed properties
5. **Component Extraction**: Extract reusable UI patterns into separate components
**❌ INCOMPLETE**: Any migration missing one of these steps
**✅ COMPLETE**: All five patterns implemented with code quality review
## ⏱️ **TIME TRACKING REQUIREMENT**: All migrations must be timed and performance recorded
## 🎯 **USER CONTROL COMMANDS**: For seamless migration workflow
### **Control Handoff Commands**
Use these commands to maintain control between migrations:
```bash
# When ready to continue
"move to the next file" - Start next component migration
"migrate [ComponentName]" - Target specific component
"check migration status" - Run validation script
"pause migrations" - Focus on other tasks
```
### **Migration Workflow Commands**
```bash
# Time tracking
./scripts/time-migration.sh [Component] start
./scripts/time-migration.sh [Component] end
# Status checking
bash scripts/validate-notification-completeness.sh
./scripts/daily-migration-summary.sh
# Quality assurance
npm run lint [file]
git add [file] && git commit -m "[message]"
```
### **User Control Flow**
1. **Review** completed migrations
2. **Test** components manually
3. **Review** commit messages before committing
4. **Plan** next migration batch
5. **Choose** when to continue
6. **Maintain** project control
### **Commit Message Control**
**CRITICAL**: User must review and approve all commit messages before committing:
```bash
# AI provides commit message preview for copy/paste
git add [files]
# AI shows: "Ready to commit with message: [preview]"
# User copies, pastes, and modifies as needed
git commit -m "[user-approved-message]"
```
**Process**:
1. AI stages files: `git add [files]`
2. AI provides commit message preview
3. User reviews, modifies, and commits manually
4. User maintains full control over commit history
## ⚠️ CRITICAL: Enhanced Triple Migration Pattern
### 🔑 The Complete Pattern (ALL 5 REQUIRED)
1. **Database Migration**: Replace legacy `databaseUtil` calls with `PlatformServiceMixin` methods
2. **SQL Abstraction**: Replace raw SQL queries with service methods
3. **Notification Migration**: Replace `$notify()` calls with helper methods + centralized constants
4. **Template Streamlining**: Extract repeated expressions and complex logic to computed properties
5. **Component Extraction**: Extract reusable UI patterns into separate components
**❌ INCOMPLETE**: Any migration missing one of these steps
**✅ COMPLETE**: All five patterns implemented with code quality review
## Pre-Migration Assessment
### [ ] 0. Pre-Migration Feature Audit & Planning
- [ ] **MANDATORY**: Create detailed feature audit using `docs/migration-templates/PRE_MIGRATION_AUDIT_TEMPLATE.md`
- [ ] **MANDATORY**: Create comprehensive migration plan in `docs/migration-testing/[COMPONENT]_MIGRATION.md`
- [ ] **MANDATORY**: Complete pre-migration analysis (database, notifications, template complexity)
- [ ] **MANDATORY**: Assess migration complexity and estimate timeline
- [ ] **MANDATORY**: Identify all migration targets and potential risks
- [ ] **MANDATORY**: Review plan and get approval before proceeding with code changes
- [ ] Document all database operations with line numbers
- [ ] Document all notification patterns with line numbers
- [ ] Document all template complexity patterns with line numbers
- [ ] Create verification checklist for post-migration testing
- [ ] Assess migration complexity and time requirements
### [ ] 1. Start Time Tracking
- [ ] **MANDATORY**: Run `./scripts/time-migration.sh [ComponentName.vue] start`
- [ ] Record start time in terminal output
- [ ] Keep terminal open for entire migration process
### [ ] 2. Component Complexity Assessment (REVISED ESTIMATES)
- [ ] **Simple** (8-12 min): Dialog components, minimal DB operations, few notifications
- [ ] **Medium** (15-25 min): Standard views, moderate DB usage, multiple notifications
- [ ] **Complex** (25-35 min): Large views, extensive DB operations, many notifications
- [ ] Document complexity level for performance tracking
- [ ] **Note**: Estimates revised based on 48% acceleration from actual performance data
### Date Time Context
- [ ] Always use system date command to establish accurate time context
- [ ] Use time log to track project progress
- [ ] Use historical time durations to improve estimates
### Acceleration Factors (48% Faster Than Original Estimates)
- [ ] **Established Patterns**: Consistent migration workflow reduces decision time
- [ ] **Enhanced Tooling**: PlatformServiceMixin eliminates boilerplate
- [ ] **Notification Infrastructure**: Centralized constants speed up message extraction
- [ ] **Documentation**: Comprehensive templates reduce planning overhead
- [ ] **Validation Scripts**: Automated checking catches issues early
- [ ] **Experience**: Familiarity with common patterns improves efficiency
- [ ] **Mixin Enhancement**: Added utility methods eliminate databaseUtil dependencies
### [ ] 3. Identify Legacy Patterns
- [ ] Count `databaseUtil` imports and calls
- [ ] Count raw SQL queries (`SELECT`, `INSERT`, `UPDATE`, `DELETE`)
- [ ] Count `$notify()` calls
- [ ] Count `logConsoleAndDb()` calls
- [ ] Identify template complexity patterns (repeated expressions, long class strings)
- [ ] Document total issues found
### [ ] 4. Verify PlatformServiceMixin Setup
- [ ] Component already imports `PlatformServiceMixin`
- [ ] Component already has `mixins: [PlatformServiceMixin]`
- [ ] If missing, add mixin first
## Phase 1: Database Migration
### [ ] 5. Replace Database Utility Calls
- [ ] Remove `import * as databaseUtil from "../db/databaseUtil"`
- [ ] Replace `databaseUtil.retrieveSettingsForActiveAccount()``this.$accountSettings()`
- [ ] Replace `databaseUtil.mapQueryResultToValues()``this.$mapQueryResultToValues()`
- [ ] Replace other `databaseUtil.*` calls with mixin equivalents
### [ ] 6. Replace Logging Calls
- [ ] Remove `import { logConsoleAndDb } from "../db/index"`
- [ ] Replace `logConsoleAndDb()``this.$logAndConsole()`
## Phase 2: SQL Abstraction Migration
### [ ] 7. Replace Raw Contact Operations
- [ ] `SELECT * FROM contacts WHERE did = ?``this.$getContact(did)`
- [ ] `DELETE FROM contacts WHERE did = ?``this.$deleteContact(did)`
- [ ] `UPDATE contacts SET x = ? WHERE did = ?``this.$updateContact(did, changes)`
- [ ] `INSERT INTO contacts``this.$insertContact(contact)`
### [ ] 8. Replace Other Raw SQL
- [ ] `SELECT * FROM settings``this.$accountSettings()`
- [ ] `UPDATE settings``this.$saveSettings(changes)`
- [ ] Generic queries → appropriate service methods
- [ ] **NO RAW SQL ALLOWED**: All database operations through service layer
## Phase 2.5: Contact Method Standardization
### [ ] 9. Standardize Contact Fetching Methods
- [ ] **CRITICAL**: Replace `this.$getAllContacts()``this.$contacts()`
- [ ] **REASON**: Eliminate inconsistent contact fetching patterns
- [ ] **BENEFIT**: All components use same contact data source
- [ ] **VALIDATION**: Search for `$getAllContacts` and replace with `$contacts`
- [ ] **CONSISTENCY**: All contact operations use unified approach
### [ ] 10. Verify Contact Method Consistency
- [ ] **NO** `$getAllContacts()` calls remain in component
- [ ] **ALL** contact fetching uses `$contacts()` method
- [ ] **CONSISTENT** contact data across component lifecycle
- [ ] **VALIDATED**: Component uses standardized contact API
## Phase 3: Notification Migration
### [ ] 11. Add Notification Infrastructure
- [ ] Add import: `import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify"`
- [ ] Add property: `notify!: ReturnType<typeof createNotifyHelpers>;`
- [ ] Add initialization: `created() { this.notify = createNotifyHelpers(this.$notify); }`
### [ ] 12. Add Notification Constants to Central File
- [ ] **CRITICAL**: Add constants to `src/constants/notifications.ts` (NOT local constants)
- [ ] Use naming pattern: `NOTIFY_[COMPONENT]_[ACTION]` (e.g., `NOTIFY_OFFER_SETTINGS_ERROR`)
- [ ] Import constants: `import { NOTIFY_X, NOTIFY_Y } from "@/constants/notifications"`
- [ ] **NO LOCAL CONSTANTS**: All notification text must be centralized
### [ ] 13. Replace Notification Calls
- [ ] **Warning**: `this.$notify({type: "warning"})``this.notify.warning(CONSTANT.message, TIMEOUTS.LONG)`
- [ ] **Error**: `this.$notify({type: "danger"})``this.notify.error(CONSTANT.message, TIMEOUTS.LONG)`
- [ ] **Success**: `this.$notify({type: "success"})``this.notify.success(CONSTANT.message, TIMEOUTS.STANDARD)`
- [ ] **Toast**: `this.$notify({type: "toast"})``this.notify.toast(title, message, TIMEOUTS.SHORT)`
- [ ] **Confirm**: `this.$notify({type: "confirm"})``this.notify.confirm(message, onYes)`
- [ ] **Standard patterns**: Use `this.notify.confirmationSubmitted()`, `this.notify.sent()`, etc.
### [ ] 13.1. 🚨 CRITICAL: Replace ALL Hardcoded Timeout Values
- [ ] **Replace hardcoded timeouts**: `3000`, `5000`, `1000`, `2000` → timeout constants
- [ ] **Add timeout constants**: `COMPONENT_TIMEOUT_SHORT = 1000`, `COMPONENT_TIMEOUT_MEDIUM = 2000`, `COMPONENT_TIMEOUT_STANDARD = 3000`, `COMPONENT_TIMEOUT_LONG = 5000`
- [ ] **Import timeout constants**: Import from `@/constants/notifications`
- [ ] **Validation command**: `grep -n "notify\.[a-z]*(" [file] | grep -E "[0-9]{3,4}"`
### [ ] 13.2. 🚨 CRITICAL: Remove ALL Unused Notification Imports
- [ ] **Check each import**: Verify every imported `NOTIFY_*` constant is actually used
- [ ] **Remove unused imports**: Delete any `NOTIFY_*` constants not referenced in component
- [ ] **Validation command**: `grep -n "import.*NOTIFY_" [file]` then verify usage
- [ ] **Clean imports**: Only import notification constants that are actually used
### [ ] 13.3. 🚨 CRITICAL: Replace ALL Literal Strings with Constants
- [ ] **No literal strings**: All static notification messages must use constants
- [ ] **Add constants**: Create `NOTIFY_*` constants for ALL static messages
- [ ] **Replace literals**: `"The contact DID is missing."``NOTIFY_CONTACT_MISSING_DID.message`
- [ ] **Validation command**: `grep -n "notify\.[a-z]*(" [file] | grep -v "NOTIFY_\|message"`
### [ ] 13.4. 🚨 CRITICAL: Remove Legacy Wrapper Functions
- [ ] **Remove legacy functions**: Delete `danger()`, `success()`, `warning()`, `info()` wrapper functions
- [ ] **Direct usage**: Use `this.notify.error()` instead of `this.danger()`
- [ ] **Why remove**: Maintains consistency with centralized notification system
- [ ] **Validation command**: `grep -n "danger\|success\|warning\|info.*(" [file] | grep -v "notify\."`
### [ ] 14. Constants vs Literal Strings
- [ ] **Use constants** for static, reusable messages
- [ ] **Use literal strings** for dynamic messages with variables
- [ ] **Extract literals from complex modals** - Even raw `$notify` calls should use constants for text
- [ ] **Document decision** for each notification call
## Phase 4: Template Streamlining
### [ ] 15. Identify Template Complexity Patterns
- [ ] **Repeated CSS Classes**: Long Tailwind strings used multiple times
- [ ] **Complex Configuration Objects**: Multi-line objects in template
- [ ] **Repeated Function Calls**: Same logic executed multiple times
- [ ] **Complex Conditional Logic**: Nested ternary or complex boolean expressions
### [ ] 16. Extract to Computed Properties
- [ ] **CSS Class Groups**: Extract repeated styling to computed properties
- [ ] **Configuration Objects**: Move router configs, form configs to computed
- [ ] **Conditional Logic**: Extract complex `v-if` conditions to computed properties
- [ ] **Dynamic Values**: Convert repeated calculations to cached computed properties
### [ ] 16.1. 🚨 CRITICAL: Extract ALL Long Class Attributes
- [ ] **Find long classes**: Search for `class="[^"]{50,}"` (50+ character class strings)
- [ ] **Extract to computed**: Replace with `:class="computedPropertyName"`
- [ ] **Name descriptively**: Use names like `nameWarningClasses`, `buttonPrimaryClasses`
- [ ] **Validation command**: `grep -n "class=\"[^\"]\{50,\}" [file]`
- [ ] **Benefits**: Improves readability, enables reusability, makes testing easier
### [ ] 17. Document Computed Properties
- [ ] **JSDoc Comments**: Add comprehensive comments for all computed properties
- [ ] **Purpose Documentation**: Explain what template complexity each property solves
- [ ] **Organized Sections**: Group related computed properties with section headers
- [ ] **Descriptive Names**: Use clear, descriptive names for computed properties
## Phase 5: Component Extraction
### [ ] 18. Identify Reusable UI Patterns
- [ ] **Repeated Form Elements**: Similar input fields, buttons, or form sections
- [ ] **Common Layout Patterns**: Repeated card layouts, list items, or modal structures
- [ ] **Shared UI Components**: Elements that appear in multiple places with similar structure
- [ ] **Complex Template Sections**: Large template blocks that could be simplified
- [ ] **Validation Patterns**: Repeated validation logic or error display patterns
### [ ] 19. Extract Reusable Components
- [ ] **Create New Component Files**: Extract patterns to `src/components/` directory
- [ ] **Define Clear Props Interface**: Create TypeScript interfaces for component props
- [ ] **Add Event Emissions**: Define events for parent-child communication
- [ ] **Include JSDoc Documentation**: Document component purpose and usage
- [ ] **Follow Naming Conventions**: Use descriptive, consistent component names
### [ ] 20. Component Extraction Patterns
#### 20.1 Form Element Extraction
- [ ] **Input Groups**: Extract repeated input field patterns with labels and validation
- [ ] **Button Groups**: Extract common button combinations (Save/Cancel, etc.)
- [ ] **Form Sections**: Extract logical form groupings (personal info, settings, etc.)
#### 20.2 Layout Component Extraction
- [ ] **Card Components**: Extract repeated card layouts with headers and content
- [ ] **List Item Components**: Extract repeated list item patterns
- [ ] **Modal Components**: Extract common modal structures and behaviors
#### 20.3 Validation Component Extraction
- [ ] **Error Display Components**: Extract error message display patterns
- [ ] **Validation Wrapper Components**: Extract form validation wrapper patterns
- [ ] **Status Indicator Components**: Extract loading, success, error status patterns
### [ ] 21. Update Parent Components
- [ ] **Import New Components**: Add imports for extracted components
- [ ] **Replace Template Code**: Replace extracted patterns with component usage
- [ ] **Pass Required Props**: Provide all necessary data and configuration
- [ ] **Handle Events**: Implement event handlers for component interactions
- [ ] **Update TypeScript**: Add component types to component registration
### [ ] 22. Component Quality Standards
- [ ] **Single Responsibility**: Each extracted component has one clear purpose
- [ ] **Reusability**: Component can be used in multiple contexts
- [ ] **Props Interface**: Clear, well-documented props with proper types
- [ ] **Event Handling**: Appropriate events for parent communication
- [ ] **Documentation**: JSDoc comments explaining usage and examples
### [ ] 23. Validation of Component Extraction
- [ ] **No Template Duplication**: Extracted patterns don't appear elsewhere
- [ ] **Proper Component Registration**: All components properly imported and registered
- [ ] **Event Handling Works**: Parent components receive and handle events correctly
- [ ] **Props Validation**: All required props are provided with correct types
- [ ] **Styling Consistency**: Extracted components maintain visual consistency
## Phase 6: Code Quality Review
### [ ] 24. Template Quality Assessment
- [ ] **Readability**: Template is easy to scan and understand
- [ ] **Maintainability**: Styling changes can be made in one place
- [ ] **Performance**: Computed properties cache expensive operations
- [ ] **Consistency**: Similar patterns use similar solutions
### [ ] 25. Component Architecture Review
- [ ] **Single Responsibility**: Component has clear, focused purpose
- [ ] **Props Interface**: Clear, well-documented component props
- [ ] **Event Emissions**: Appropriate event handling and emission
- [ ] **State Management**: Component state is minimal and well-organized
### [ ] 26. Code Organization Review
- [ ] **Import Organization**: Imports are grouped logically (Vue, constants, services)
- [ ] **Method Organization**: Methods are grouped by purpose with section headers
- [ ] **Property Organization**: Data properties are documented and organized
- [ ] **Comment Quality**: All complex logic has explanatory comments
## Validation Phase
### [ ] 27. Run Validation Script
- [ ] Execute: `scripts/validate-migration.sh`
- [ ] **MUST show**: "Technically Compliant" (not "Mixed Pattern")
- [ ] **Zero** legacy patterns detected
### [ ] 28. Run Linting
- [ ] Execute: `npm run lint-fix`
- [ ] **Zero errors** introduced
- [ ] **TypeScript compiles** without errors
### [ ] 29. Manual Code Review
- [ ] **NO** `databaseUtil` imports or calls
- [ ] **NO** raw SQL queries (`SELECT`, `INSERT`, `UPDATE`, `DELETE`)
- [ ] **NO** `$notify()` calls with object syntax
- [ ] **NO** `logConsoleAndDb()` calls
- [ ] **NO** local notification constants
- [ ] **ALL** database operations through service methods
- [ ] **ALL** notifications through helper methods with centralized constants
- [ ] **ALL** complex template logic extracted to computed properties
- [ ] **ALL** reusable UI patterns extracted to components
### [ ] 29.1. 🚨 CRITICAL: Validate All Omission Fixes
- [ ] **NO** hardcoded timeout values (`1000`, `2000`, `3000`, `5000`)
- [ ] **NO** unused notification imports (all `NOTIFY_*` imports are used)
- [ ] **NO** literal strings in notification calls (all use constants)
- [ ] **NO** legacy wrapper functions (`danger()`, `success()`, etc.)
- [ ] **NO** long class attributes (50+ characters) in template
- [ ] **NO** duplicated template patterns (all extracted to components)
- [ ] **ALL** timeout values use constants
- [ ] **ALL** notification messages use centralized constants
- [ ] **ALL** class styling extracted to computed properties
- [ ] **ALL** reusable UI patterns extracted to components
## ⏱️ Time Tracking & Commit Phase
### [ ] 30. End Time Tracking
- [ ] **MANDATORY**: Run `./scripts/time-migration.sh [ComponentName.vue] end`
- [ ] Record total duration from terminal output
- [ ] Note any blockers or issues that impacted timing
- [ ] **MANDATORY**: Verify all features from pre-migration audit are working
### [ ] 31. Commit with Time Data
- [ ] **MANDATORY**: Include time data in commit message
- [ ] Use template: `Complete [ComponentName] Enhanced Triple Migration Pattern (X minutes)`
- [ ] Include complexity level and any issues encountered
- [ ] Document specific changes made in each phase
### [ ] 32. Performance Analysis
- [ ] Compare actual time vs. revised estimated time for complexity level
- [ ] Note if component was faster/slower than expected (target: within 20% of estimate)
- [ ] Document any efficiency improvements discovered
- [ ] **Revised Baseline**: Simple (8-12 min), Medium (15-25 min), Complex (25-35 min)
- [ ] **Acceleration Target**: Maintain 48% improvement over original estimates
## Documentation Phase
### [ ] 33. Update Migration Documentation
- [ ] Create `docs/migration-testing/[COMPONENT]_MIGRATION.md`
- [ ] Document all changes made (database, SQL, notifications, template, component extraction)
- [ ] Include before/after examples for template streamlining and component extraction
- [ ] Note validation results and timing data
- [ ] Provide a guide to finding the components in the user interface
- [ ] Include code quality review notes
### [ ] 34. Update Testing Tracker
- [ ] Update `docs/migration-testing/HUMAN_TESTING_TRACKER.md`
- [ ] Mark component as "Ready for Testing"
- [ ] Include notes about migration completed with template streamlining and component extraction
- [ ] Record actual migration time for future estimates
## Human Testing Phase
### [ ] 35. Test All Functionality
- [ ] **Core functionality** works correctly
- [ ] **Database operations** function properly
- [ ] **Notifications** display correctly with proper timing
- [ ] **Error scenarios** handled gracefully
- [ ] **Template rendering** performs smoothly with computed properties
- [ ] **Extracted components** work correctly and maintain functionality
- [ ] **Cross-platform** compatibility (web/mobile)
### [ ] 36. Confirm Testing Complete
- [ ] User confirms component works correctly
- [ ] Update testing tracker with results
- [ ] Mark as "Human Tested" in validation script
## Final Validation
### [ ] 37. Comprehensive Check
- [ ] Component shows as "Technically Compliant" in validation
- [ ] All manual testing passed
- [ ] Zero legacy patterns remain
- [ ] Template streamlining complete
- [ ] Component extraction complete
- [ ] Code quality review passed
- [ ] Documentation complete
- [ ] Time tracking data recorded
- [ ] Ready for production
## ⏱️ **Time Tracking Performance Targets**
### **Expected Durations by Complexity**
- **Simple Components**: 15-20 minutes
- **Medium Components**: 30-45 minutes
- **Complex Components**: 45-60 minutes
### **Quality Gates**
- [ ] Start time logged with script
- [ ] End time logged with script
- [ ] Duration recorded in commit message
- [ ] Performance compared to expected range
- [ ] Issues affecting timing documented
### **Efficiency Tracking**
- [ ] Batch similar components for efficiency
- [ ] Use proven patterns to reduce time
- [ ] Note any new patterns or shortcuts discovered
- [ ] Update time estimates based on actual performance
## Wait for human confirmation before proceeding to next file unless directly overridden.
## 🚨 FAILURE CONDITIONS
**❌ INCOMPLETE MIGRATION** if ANY of these remain:
- `databaseUtil` imports or calls
- Raw SQL queries (`SELECT`, `INSERT`, `UPDATE`, `DELETE`)
- `$notify()` calls with object syntax
- `logConsoleAndDb()` calls
- Local notification constants
- Complex template logic not extracted to computed properties
- **Missing time tracking data in commit**
**❌ INCOMPLETE TIME TRACKING** if ANY of these are missing:
- Start time not logged
- End time not logged
- Duration not recorded in commit message
- Complexity level not assessed
- Performance not compared to targets
## 🎯 **SUCCESS CRITERIA**
**✅ COMPLETE MIGRATION** requires ALL of these:
- All four migration phases completed
- Zero legacy patterns detected
- All validation scripts pass
- Time tracking data recorded
- Commit includes performance metrics
- Documentation updated
- Ready for human testing
**Expected Project Completion**: 2-3 weeks (69 remaining components × 20 minutes average = 23 hours = 3 days focused work)
## Templates and References
- **Migration Template**: `docs/migration-templates/component-migration.md`
- **Notification Constants**: `src/constants/notifications.ts`
- **PlatformServiceMixin**: `src/utils/PlatformServiceMixin.ts`
- **Notification Helpers**: `src/utils/notify.ts`
- **Validation Script**: `scripts/validate-migration.sh`
---
**⚠️ WARNING**: This checklist exists because steps were previously forgotten. DO NOT skip any items. The enhanced triple migration pattern (Database + SQL + Notifications + Template Streamlining) is MANDATORY for all component migrations.
**Author**: Matthew Raymer
**Date**: 2024-07-07
**Purpose**: Prevent migration oversight by cementing ALL requirements including template quality
**Updated**: Enhanced with template streamlining and code quality review phases

View File

@@ -0,0 +1,159 @@
# Pre-Migration Feature Audit Template
## Overview
This template provides a systematic approach to audit all features in a component before migration to ensure no functionality is lost and provide a verification checklist.
## Component Information
- **Component Name**: [ComponentName.vue]
- **Location**: [src/path/to/Component.vue]
- **Total Lines**: [XXX lines]
- **Audit Date**: [YYYY-MM-DD]
- **Auditor**: Matthew Raymer
## 📊 Migration Scope Analysis
### Database Operations Audit
- [ ] **Total Database Operations**: [X operations]
- [ ] **Legacy databaseUtil imports**: [X imports]
- [ ] **PlatformServiceFactory calls**: [X calls]
- [ ] **Raw SQL queries**: [X queries]
### Notification Operations Audit
- [ ] **Total Notification Calls**: [X calls]
- [ ] **Direct $notify calls**: [X calls]
- [ ] **Legacy notification patterns**: [X patterns]
### Template Complexity Audit
- [ ] **Complex template expressions**: [X expressions]
- [ ] **Repeated CSS classes**: [X repetitions]
- [ ] **Configuration objects**: [X objects]
## 🔍 Feature-by-Feature Audit
### 1. Database Features
#### Feature: [Feature Name]
- **Location**: Lines [XXX-XXX]
- **Type**: [SELECT/INSERT/UPDATE/DELETE/COUNT/etc.]
- **Current Implementation**:
```typescript
// Current code snippet
```
- **Migration Target**: `this.$methodName()`
- **Verification**: [ ] Functionality preserved after migration
#### Feature: [Feature Name]
- **Location**: Lines [XXX-XXX]
- **Type**: [Type]
- **Current Implementation**:
```typescript
// Current code snippet
```
- **Migration Target**: `this.$methodName()`
- **Verification**: [ ] Functionality preserved after migration
### 2. Notification Features
#### Feature: [Feature Name]
- **Location**: Lines [XXX-XXX]
- **Type**: [success/error/warning/info/toast/confirm]
- **Current Implementation**:
```typescript
// Current code snippet
```
- **Migration Target**: `this.notify.methodName()`
- **Verification**: [ ] Functionality preserved after migration
### 3. Template Features
#### Feature: [Feature Name]
- **Location**: Lines [XXX-XXX]
- **Type**: [computed/method/expression/class]
- **Current Implementation**:
```vue
<!-- Current template snippet -->
```
- **Migration Target**: Extract to computed property/method
- **Verification**: [ ] Functionality preserved after migration
## 🎯 Migration Checklist Totals
### Database Migration Requirements
- [ ] **Replace databaseUtil imports**: [X imports] → PlatformServiceMixin
- [ ] **Replace PlatformServiceFactory calls**: [X calls] → mixin methods
- [ ] **Replace raw SQL queries**: [X queries] → service methods
- [ ] **Update error handling**: [X patterns] → mixin error handling
### Notification Migration Requirements
- [ ] **Add notification helpers**: Import createNotifyHelpers
- [ ] **Replace direct $notify calls**: [X calls] → helper methods
- [ ] **Add notification constants**: [X constants] → src/constants/notifications.ts
- [ ] **Update notification patterns**: [X patterns] → standardized helpers
### Template Streamlining Requirements
- [ ] **Extract repeated classes**: [X repetitions] → computed properties
- [ ] **Extract complex expressions**: [X expressions] → computed properties
- [ ] **Extract configuration objects**: [X objects] → computed properties
- [ ] **Simplify template logic**: [X patterns] → methods/computed
## 📋 Post-Migration Verification Checklist
### ✅ Database Functionality Verification
- [ ] All database operations work correctly
- [ ] Error handling functions properly
- [ ] Performance is maintained or improved
- [ ] Data integrity is preserved
### ✅ Notification Functionality Verification
- [ ] All notification types display correctly
- [ ] Notification timing works as expected
- [ ] User feedback is appropriate
- [ ] Error notifications are informative
### ✅ Template Functionality Verification
- [ ] All UI elements render correctly
- [ ] Interactive elements function properly
- [ ] Responsive design is maintained
- [ ] Accessibility is preserved
### ✅ Integration Verification
- [ ] Component integrates properly with parent components
- [ ] Router navigation works correctly
- [ ] Props and events function as expected
- [ ] Cross-platform compatibility maintained
## 🚀 Migration Readiness Assessment
### Pre-Migration Requirements
- [ ] **Feature audit completed**: All features documented with line numbers
- [ ] **Migration targets identified**: Each feature has clear migration path
- [ ] **Test scenarios planned**: Verification steps documented
- [ ] **Backup created**: Original component backed up
### Complexity Assessment
- [ ] **Simple** (15-20 min): Few database operations, minimal notifications
- [ ] **Medium** (30-45 min): Multiple database operations, several notifications
- [ ] **Complex** (45-60 min): Extensive database usage, many notifications, complex templates
### Dependencies Assessment
- [ ] **No blocking dependencies**: Component can be migrated independently
- [ ] **Parent dependencies identified**: Known impacts on parent components
- [ ] **Child dependencies identified**: Known impacts on child components
## 📝 Notes and Special Considerations
### Special Migration Considerations
[Document any unusual patterns, complex logic, or special requirements]
### Risk Assessment
[Document any potential risks or challenges for this migration]
### Testing Strategy
[Document specific testing approach for this component]
---
**Template Version**: 1.0
**Created**: 2025-01-08
**Author**: Matthew Raymer
**Status**: Ready for use

View File

@@ -0,0 +1,150 @@
# TimeSafari Migration Process Overview
## 🎯 Purpose
This document provides a high-level overview of the complete migration process for TimeSafari components, preventing oversight and ensuring systematic completion.
## 📋 The Complete Migration Pattern
### Triple Migration Requirement
**ALL components must complete ALL three migration types:**
1. **🗃️ Database Migration**: Replace legacy `databaseUtil` calls
2. **🔗 SQL Abstraction**: Replace raw SQL with service methods
3. **🔔 Notification Migration**: Replace `$notify()` with helper methods
### Why All Three Are Required
| Migration Type | Purpose | Risk of Skipping |
|----------------|---------|------------------|
| Database | Modern API access | Inconsistent database patterns |
| SQL Abstraction | Service layer separation | Exposed SQL in components |
| Notification | Consistent UX patterns | Inconsistent user messaging |
## 🛠️ Tools and Resources
### Documentation
- **Primary Checklist**: `docs/migration-templates/COMPLETE_MIGRATION_CHECKLIST.md`
- **Quick Reference**: `docs/migration-templates/component-migration.md`
- **Testing Tracker**: `docs/migration-testing/HUMAN_TESTING_TRACKER.md`
### Validation Scripts
- **Overall Status**: `scripts/validate-migration.sh`
- **Notification Completeness**: `scripts/validate-notification-completeness.sh`
- **Linting**: `npm run lint-fix`
### Source References
- **PlatformServiceMixin**: `src/utils/PlatformServiceMixin.ts`
- **Notification Helpers**: `src/utils/notify.ts`
- **Notification Constants**: `src/constants/notifications.ts`
## 🔄 Standard Workflow
### 1. Pre-Migration Assessment
```bash
# Run validation to identify issues
scripts/validate-migration.sh
scripts/validate-notification-completeness.sh
```
### 2. Execute Triple Migration
**Follow `COMPLETE_MIGRATION_CHECKLIST.md` exactly**
- Phase 1: Database Migration
- Phase 2: SQL Abstraction
- Phase 3: Notification Migration
### 3. Validation Loop
```bash
# After each phase, validate progress
scripts/validate-migration.sh
scripts/validate-notification-completeness.sh
npm run lint-fix
```
### 4. Human Testing
- Component functional testing
- Cross-platform validation
- Error scenario testing
### 5. Documentation
- Update testing tracker
- Create migration documentation
- Mark as complete
## 🚨 Common Oversights
### ❌ Incomplete Patterns
1. **Partial Database Migration**: Mixin imported but legacy calls remain
2. **Missing SQL Abstraction**: Database migrated but raw SQL remains
3. **Forgotten Notifications**: Database/SQL done but `$notify()` calls remain
### ✅ Success Indicators
1. **Zero Legacy Patterns**: No `databaseUtil`, raw SQL, or `$notify()` calls
2. **Validation Clean**: All scripts pass without issues
3. **Functional Testing**: All features work correctly
4. **Documentation Complete**: Migration recorded and tracked
## 🎯 Current Status
### Migration Statistics
Run these commands for current status:
```bash
scripts/validate-migration.sh | grep "Migration percentage"
scripts/validate-notification-completeness.sh | grep "Summary"
```
### Priority Focus
1. **Mixed Pattern Files**: Components with partial migrations
2. **Notification Incomplete**: Components with `$notify()` calls
3. **New Components**: Ensure they follow modern patterns
## 🔧 Troubleshooting
### Component Shows "Mixed Pattern"
```bash
# Check what patterns remain
grep -n "databaseUtil\|logConsoleAndDb\|this\.\$notify" src/path/to/component.vue
```
### Notification Validation Fails
```bash
# Check notification setup
grep -n "createNotifyHelpers\|notify!:\|this\.notify =" src/path/to/component.vue
```
### TypeScript Errors
```bash
# Check compilation
npx tsc --noEmit
npm run lint-fix
```
## 📚 Learning From This Process
### Key Lesson: Systematic Validation
The creation of this process was triggered by forgetting notification migration in DIDView.vue, demonstrating that:
1. **Checklists prevent oversights**
2. **Validation scripts catch mistakes**
3. **Documentation cements requirements**
4. **Multiple validation layers ensure completeness**
### Prevention Strategy
- **Always use the complete checklist**
- **Run all validation scripts**
- **Document every migration**
- **Update tracking systematically**
## 🚀 Next Steps
1. **Complete current mixed patterns** using the established process
2. **Validate all "technically compliant" components** for notification completeness
3. **Establish this as standard process** for all future migrations
4. **Create automated CI checks** to prevent regression
---
**Remember**: This process exists to prevent the exact oversight that occurred with DIDView.vue notification migration. Follow it completely to ensure systematic migration success.
**Author**: Matthew Raymer
**Date**: 2024-01-XX
**Purpose**: Prevent migration oversights through systematic process

View File

@@ -0,0 +1,436 @@
# PlatformServiceMixin Best Practices Guide
## Overview
This guide establishes best practices for using PlatformServiceMixin in TimeSafari components to ensure consistent, maintainable, and secure code.
## Core Principles
### 1. **Single Source of Truth**
- Always use PlatformServiceMixin for database operations
- Never mix legacy patterns with mixin patterns in the same component
- Use mixin caching to avoid redundant database queries
### 2. **Component Context Awareness**
- Always include component name in error logging
- Use `this.$options.name` for consistent component identification
- Implement proper error boundaries with context
### 3. **Progressive Enhancement**
- Start with basic mixin methods (`$db`, `$exec`, `$one`)
- Use specialized methods when available (`$getAllContacts`, `$settings`)
- Leverage caching for frequently accessed data
## Implementation Patterns
### Database Operations
#### ✅ **Preferred Pattern: Use Specialized Methods**
```typescript
// Best: Use high-level specialized methods
const contacts = await this.$getAllContacts();
const settings = await this.$settings();
const userSettings = await this.$accountSettings(did);
```
#### ✅ **Good Pattern: Use Mapped Query Methods**
```typescript
// Good: Use query methods with automatic mapping
const results = await this.$query<Contact>(
"SELECT * FROM contacts WHERE registered = ?",
[true]
);
```
#### ⚠️ **Acceptable Pattern: Use Raw Database Methods**
```typescript
// Acceptable: Use raw methods when specialized methods don't exist
const result = await this.$db("SELECT COUNT(*) as count FROM logs");
const count = result?.values?.[0]?.[0] || 0;
```
#### ❌ **Anti-Pattern: Direct Platform Service**
```typescript
// Anti-pattern: Avoid direct PlatformService usage
const platformService = PlatformServiceFactory.getInstance();
const result = await platformService.dbQuery(sql, params);
```
### Settings Management
#### ✅ **Best Practice: Use Mixin Methods**
```typescript
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
async loadSettings() {
// ✅ Use cached settings retrieval
const settings = await this.$settings();
return settings;
}
async saveUserPreferences(changes: Partial<Settings>) {
// ✅ Use specialized save method
await this.$saveSettings(changes);
await this.$log("User preferences saved");
}
async loadAccountSettings(did: string) {
// ✅ Use account-specific settings
const accountSettings = await this.$accountSettings(did);
return accountSettings;
}
}
```
#### ❌ **Anti-Pattern: Legacy Settings Access**
```typescript
// Anti-pattern: Avoid legacy databaseUtil methods
import * as databaseUtil from "../db/databaseUtil";
async loadSettings() {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
return settings;
}
```
### Error Handling
#### ✅ **Best Practice: Component-Aware Error Handling**
```typescript
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
async performOperation() {
try {
const result = await this.$getAllContacts();
await this.$log("Operation completed successfully");
return result;
} catch (error) {
// ✅ Include component context in error logging
await this.$logError(`[${this.$options.name}] Operation failed: ${error}`);
// ✅ Provide user-friendly error handling
this.$notify({
group: "alert",
type: "danger",
title: "Operation Failed",
text: "Unable to load contacts. Please try again.",
});
throw error; // Re-throw for upstream handling
}
}
}
```
#### ❌ **Anti-Pattern: Generic Error Handling**
```typescript
// Anti-pattern: Generic error handling without context
try {
// operation
} catch (error) {
console.error("Error:", error);
throw error;
}
```
### Logging
#### ✅ **Best Practice: Structured Logging**
```typescript
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
async performDatabaseOperation() {
// ✅ Log operation start with context
await this.$log(`[${this.$options.name}] Starting database operation`);
try {
const result = await this.$getAllContacts();
// ✅ Log successful completion
await this.$log(`[${this.$options.name}] Database operation completed, found ${result.length} contacts`);
return result;
} catch (error) {
// ✅ Log errors with full context
await this.$logError(`[${this.$options.name}] Database operation failed: ${error}`);
throw error;
}
}
// ✅ Use appropriate log levels
async validateInput(input: string) {
if (!input) {
await this.$log(`[${this.$options.name}] Input validation failed: empty input`, 'warn');
return false;
}
return true;
}
}
```
### Caching Strategies
#### ✅ **Best Practice: Smart Caching Usage**
```typescript
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
async loadContactsWithCaching() {
// ✅ Use cached contacts (automatically managed by mixin)
const contacts = await this.$contacts();
// ✅ Force refresh when needed
if (this.needsFreshData) {
const freshContacts = await this.$refreshContacts();
return freshContacts;
}
return contacts;
}
async updateContactAndRefresh(did: string, changes: Partial<Contact>) {
// ✅ Update contact and invalidate cache
await this.$updateContact(did, changes);
// ✅ Clear cache to ensure fresh data on next access
this.$clearAllCaches();
await this.$log(`[${this.$options.name}] Contact updated and cache cleared`);
}
}
```
## Security Best Practices
### Input Validation
#### ✅ **Always Validate Database Inputs**
```typescript
async saveContact(contact: Partial<Contact>) {
// ✅ Validate required fields
if (!contact.did || !contact.name) {
await this.$logError(`[${this.$options.name}] Invalid contact data: missing required fields`);
throw new Error('Contact must have DID and name');
}
// ✅ Sanitize inputs
const sanitizedContact = {
...contact,
name: contact.name.trim(),
// Remove any potential XSS vectors
notes: contact.notes?.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
};
return await this.$insertContact(sanitizedContact);
}
```
### Error Information Disclosure
#### ✅ **Safe Error Handling**
```typescript
async performSensitiveOperation(did: string) {
try {
// Sensitive operation
const result = await this.$accountSettings(did);
return result;
} catch (error) {
// ✅ Log full error for debugging
await this.$logError(`[${this.$options.name}] Sensitive operation failed: ${error}`);
// ✅ Return generic error to user
throw new Error('Unable to complete operation. Please try again.');
}
}
```
### SQL Injection Prevention
#### ✅ **Always Use Parameterized Queries**
```typescript
// ✅ Safe: Parameterized query
async findContactsByName(searchTerm: string) {
return await this.$query<Contact>(
"SELECT * FROM contacts WHERE name LIKE ?",
[`%${searchTerm}%`]
);
}
// ❌ Dangerous: String concatenation
async findContactsByNameUnsafe(searchTerm: string) {
return await this.$query<Contact>(
`SELECT * FROM contacts WHERE name LIKE '%${searchTerm}%'`
);
}
```
## Performance Optimization
### Database Query Optimization
#### ✅ **Efficient Query Patterns**
```typescript
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
async loadOptimizedData() {
// ✅ Use transactions for multiple operations
return await this.$withTransaction(async () => {
const contacts = await this.$getAllContacts();
const settings = await this.$settings();
return { contacts, settings };
});
}
async loadDataWithPagination(offset: number, limit: number) {
// ✅ Use LIMIT and OFFSET for large datasets
return await this.$query<Contact>(
"SELECT * FROM contacts ORDER BY name LIMIT ? OFFSET ?",
[limit, offset]
);
}
}
```
### Memory Management
#### ✅ **Proper Cache Management**
```typescript
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
beforeDestroy() {
// ✅ Clear component caches on destroy
this.$clearAllCaches();
}
async handleLargeDataset() {
try {
// Process large dataset
const largeResult = await this.$query("SELECT * FROM large_table");
// ✅ Process in chunks to avoid memory issues
const chunkSize = 100;
for (let i = 0; i < largeResult.length; i += chunkSize) {
const chunk = largeResult.slice(i, i + chunkSize);
await this.processChunk(chunk);
}
} finally {
// ✅ Clear caches after processing large datasets
this.$clearAllCaches();
}
}
}
```
## Testing Strategies
### Unit Testing
#### ✅ **Mock Mixin Methods**
```typescript
// test/MyComponent.spec.ts
import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';
import { PlatformServiceMixin } from '@/utils/PlatformServiceMixin';
describe('MyComponent', () => {
let wrapper;
beforeEach(() => {
// ✅ Mock mixin methods
const mockMixin = {
...PlatformServiceMixin,
methods: {
...PlatformServiceMixin.methods,
$getAllContacts: jest.fn().mockResolvedValue([]),
$settings: jest.fn().mockResolvedValue({}),
$log: jest.fn().mockResolvedValue(undefined),
$logError: jest.fn().mockResolvedValue(undefined),
}
};
wrapper = mount(MyComponent, {
mixins: [mockMixin]
});
});
it('should load contacts on mount', async () => {
await wrapper.vm.loadContacts();
expect(wrapper.vm.$getAllContacts).toHaveBeenCalled();
});
});
```
### Integration Testing
#### ✅ **Test Real Database Operations**
```typescript
// test/integration/ContactsView.spec.ts
import { createLocalVue, mount } from '@vue/test-utils';
import ContactsView from '@/views/ContactsView.vue';
import { PlatformServiceMixin } from '@/utils/PlatformServiceMixin';
describe('ContactsView Integration', () => {
it('should perform real database operations', async () => {
const wrapper = mount(ContactsView, {
mixins: [PlatformServiceMixin]
});
// ✅ Test real mixin functionality
const contacts = await wrapper.vm.$getAllContacts();
expect(Array.isArray(contacts)).toBe(true);
});
});
```
## Migration Checklist
When migrating components to PlatformServiceMixin:
### Pre-Migration
- [ ] Identify all database operations in the component
- [ ] List all logging operations
- [ ] Check for error handling patterns
- [ ] Note any specialized database queries
### During Migration
- [ ] Add PlatformServiceMixin to mixins array
- [ ] Replace all database operations with mixin methods
- [ ] Update logging to use mixin logging methods
- [ ] Add component context to error messages
- [ ] Replace settings operations with mixin methods
- [ ] Update error handling to use structured patterns
### Post-Migration
- [ ] Remove all legacy imports (databaseUtil, logConsoleAndDb)
- [ ] Test all component functionality
- [ ] Verify TypeScript compilation
- [ ] Check for any remaining anti-patterns
- [ ] Update component tests if needed
- [ ] Run migration validation script
## Troubleshooting Common Issues
### Issue: TypeScript errors after migration
**Solution**: Ensure proper type definitions and mixin interface implementation
### Issue: Methods not available on `this`
**Solution**: Verify PlatformServiceMixin is properly included in mixins array
### Issue: Caching not working as expected
**Solution**: Check cache TTL settings and clear cache when needed
### Issue: Database operations failing
**Solution**: Verify PlatformService is properly initialized and check error logs
### Issue: Performance degradation
**Solution**: Review query efficiency and cache usage patterns
## Version History
- **v1.0** - Initial best practices documentation
- **v1.1** - Added security and performance sections
- **v1.2** - Enhanced testing strategies and troubleshooting

View File

@@ -0,0 +1,936 @@
# Component Migration Template
## Overview
This template provides step-by-step instructions for migrating Vue components from legacy patterns to PlatformServiceMixin.
## Before Migration Checklist
- [ ] Component uses `import * as databaseUtil`
- [ ] Component uses `import { logConsoleAndDb }`
- [ ] Component has direct `PlatformServiceFactory.getInstance()` calls
- [ ] Component has manual error handling for database operations
- [ ] Component has verbose SQL result processing
## Step-by-Step Migration
### Step 1: Update Imports
```typescript
// ❌ BEFORE - Legacy imports
import * as databaseUtil from "../db/databaseUtil";
import { logConsoleAndDb } from "../db/databaseUtil";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
// ✅ AFTER - Clean imports
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { Contact } from "@/db/tables/contacts";
import { Settings } from "@/db/tables/settings";
```
### Step 2: Add Mixin to Component
```typescript
// ❌ BEFORE - No mixin
@Component({
components: { /* ... */ }
})
export default class MyComponent extends Vue {
// ...
}
// ✅ AFTER - With mixin
@Component({
components: { /* ... */ }
})
export default class MyComponent extends Vue {
mixins: [PlatformServiceMixin],
// ...
}
```
### Step 3: Replace Database Operations
```typescript
// ❌ BEFORE - Legacy database access
async loadContacts() {
try {
const platformService = PlatformServiceFactory.getInstance();
const result = await platformService.dbQuery("SELECT * FROM contacts");
const contacts = databaseUtil.mapQueryResultToValues(result);
await logConsoleAndDb("Contacts loaded successfully");
return contacts;
} catch (error) {
await logConsoleAndDb("Error loading contacts: " + error, true);
throw error;
}
}
// ✅ AFTER - Mixin methods
async loadContacts() {
try {
const contacts = await this.$getAllContacts();
await this.$log("Contacts loaded successfully");
return contacts;
} catch (error) {
await this.$logError(`[${this.$options.name}] Error loading contacts: ${error}`);
throw error;
}
}
```
### Step 4: Replace Settings Operations
```typescript
// ❌ BEFORE - Legacy settings access
async loadSettings() {
const settingsRow = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = settingsRow || {};
return settings;
}
async saveSettings(changes: Partial<Settings>) {
await databaseUtil.updateDefaultSettings(changes);
await logConsoleAndDb("Settings saved");
}
// ✅ AFTER - Mixin methods
async loadSettings() {
return await this.$settings();
}
async saveSettings(changes: Partial<Settings>) {
await this.$saveSettings(changes);
await this.$log("Settings saved");
}
```
### Step 5: Replace Logging Operations
```typescript
// ❌ BEFORE - Legacy logging
try {
// operation
} catch (error) {
console.error("Error occurred:", error);
await logConsoleAndDb("Error: " + error, true);
}
// ✅ AFTER - Mixin logging
try {
// operation
} catch (error) {
await this.$logError(`[${this.$options.name}] Error: ${error}`);
}
```
## Common Migration Patterns
### Pattern 1: Database Query + Result Processing
```typescript
// ❌ BEFORE
const platformService = PlatformServiceFactory.getInstance();
const result = await platformService.dbQuery(sql, params);
const processed = databaseUtil.mapQueryResultToValues(result);
// ✅ AFTER
const processed = await this.$query(sql, params);
```
### Pattern 2: Settings Retrieval
```typescript
// ❌ BEFORE
const settingsRow = await databaseUtil.retrieveSettingsForActiveAccount();
const value = settingsRow?.[field] || defaultValue;
// ✅ AFTER
const settings = await this.$settings();
const value = settings[field] || defaultValue;
```
### Pattern 3: Contact Operations
```typescript
// ❌ BEFORE
const platformService = PlatformServiceFactory.getInstance();
const contacts = await platformService.dbQuery("SELECT * FROM contacts");
const mappedContacts = databaseUtil.mapQueryResultToValues(contacts);
// ✅ AFTER
const contacts = await this.$getAllContacts();
```
### Pattern 4: Error Handling
```typescript
// ❌ BEFORE
try {
// operation
} catch (error) {
console.error("[MyComponent] Error:", error);
await databaseUtil.logToDb("Error: " + error, "error");
}
// ✅ AFTER
try {
// operation
} catch (error) {
await this.$logError(`[${this.$options.name}] Error: ${error}`);
}
```
## Notification Migration (Additional Step)
If component uses `this.$notify()` calls, also migrate to notification helpers:
### Import and Setup
```typescript
// Add imports
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import {
NOTIFY_CONTACT_LOADING_ISSUE,
NOTIFY_FEED_LOADING_ISSUE,
// Add other constants as needed
} from "@/constants/notifications";
// Add property
notify!: ReturnType<typeof createNotifyHelpers>;
// Initialize in created()
created() {
this.notify = createNotifyHelpers(this.$notify);
}
```
### Replace Notification Calls
```typescript
// ❌ BEFORE
this.$notify({
group: "alert",
type: "warning",
title: "Warning",
text: "Something went wrong"
}, 5000);
// ✅ AFTER - Use constants for reusable messages
this.notify.warning(NOTIFY_CONTACT_LOADING_ISSUE.message, TIMEOUTS.LONG);
// ✅ AFTER - Literal strings for dynamic content
this.notify.error(userMessage || "Fallback error message", TIMEOUTS.LONG);
```
### Common Notification Patterns
- Warning: `this.notify.warning(NOTIFY_CONSTANT.message, TIMEOUTS.LONG)`
- Error: `this.notify.error(NOTIFY_CONSTANT.message, TIMEOUTS.LONG)`
- Success: `this.notify.success(NOTIFY_CONSTANT.message, TIMEOUTS.STANDARD)`
- Toast: `this.notify.toast(title, message, TIMEOUTS.SHORT)`
- Confirm: `this.notify.confirm(message, onYes)`
- Standard patterns: `this.notify.confirmationSubmitted()`, `this.notify.sent()`, etc.
### Notification Constants Guidelines
- **Use constants** for static, reusable messages (defined in `src/constants/notifications.ts`)
- **Use literal strings** for dynamic messages with variables
- **Add new constants** to `notifications.ts` for new reusable messages
#### Extract Literals from Complex Modals
**IMPORTANT**: Even when complex modals must remain as raw `$notify` calls due to advanced features (custom buttons, nested callbacks, `promptToStopAsking`, etc.), **always extract literal strings to constants**:
```typescript
// ❌ BAD - Literals in complex modal
this.$notify({
group: "modal",
type: "confirm",
title: "Are you nearby with cameras?",
text: "If so, we'll use those with QR codes to share.",
yesText: "we are nearby with cameras",
noText: "we will share another way",
onNo: () => { /* complex callback */ }
});
// ✅ GOOD - Constants used even in complex modal
export const NOTIFY_CAMERA_SHARE_METHOD = {
title: "Are you nearby with cameras?",
text: "If so, we'll use those with QR codes to share.",
yesText: "we are nearby with cameras",
noText: "we will share another way",
};
this.$notify({
group: "modal",
type: "confirm",
title: NOTIFY_CAMERA_SHARE_METHOD.title,
text: NOTIFY_CAMERA_SHARE_METHOD.text,
yesText: NOTIFY_CAMERA_SHARE_METHOD.yesText,
noText: NOTIFY_CAMERA_SHARE_METHOD.noText,
onNo: () => { /* complex callback preserved */ }
});
```
This approach provides:
- **Consistency**: All user-facing text centralized
- **Maintainability**: Easy to update messages
- **Localization**: Ready for future i18n support
- **Testability**: Constants can be imported in tests
## Critical Migration Omissions to Avoid
### 1. Remove Unused Notification Imports
**❌ COMMON MISTAKE**: Importing notification constants that aren't actually used
```typescript
// ❌ BAD - Unused imports
import {
NOTIFY_CONTACT_ADDED, // Not used
NOTIFY_CONTACT_ADDED_SUCCESS, // Not used
NOTIFY_CONTACT_ERROR, // Actually used
NOTIFY_CONTACT_EXISTS, // Actually used
} from "@/constants/notifications";
// ✅ GOOD - Only import what's used
import {
NOTIFY_CONTACT_ERROR,
NOTIFY_CONTACT_EXISTS,
} from "@/constants/notifications";
```
**How to check**: Use IDE "Find Usages" or grep to verify each imported constant is actually used in the file.
### 2. Replace ALL Hardcoded Timeout Values
**❌ COMMON MISTAKE**: Converting `$notify()` calls but leaving hardcoded timeout values
```typescript
// ❌ BAD - Hardcoded timeout values
this.notify.error(NOTIFY_CONTACT_ERROR.message, 5000);
this.notify.success(NOTIFY_CONTACT_ADDED.message, 3000);
this.notify.warning(NOTIFY_CONTACT_EXISTS.message, 5000);
this.notify.toast(NOTIFY_URL_COPIED.message, 2000);
// ✅ GOOD - Use timeout constants
this.notify.error(NOTIFY_CONTACT_ERROR.message, QR_TIMEOUT_LONG);
this.notify.success(NOTIFY_CONTACT_ADDED.message, QR_TIMEOUT_STANDARD);
this.notify.warning(NOTIFY_CONTACT_EXISTS.message, QR_TIMEOUT_LONG);
this.notify.toast(NOTIFY_URL_COPIED.message, QR_TIMEOUT_MEDIUM);
```
**Add timeout constants to your constants file**:
```typescript
// Add to src/constants/notifications.ts
export const QR_TIMEOUT_SHORT = 1000; // Short operations
export const QR_TIMEOUT_MEDIUM = 2000; // Medium operations
export const QR_TIMEOUT_STANDARD = 3000; // Standard success messages
export const QR_TIMEOUT_LONG = 5000; // Error messages and warnings
```
### 3. Remove Legacy Wrapper Functions
**❌ COMMON MISTAKE**: Keeping legacy notification wrapper functions that are inconsistent with the new system
```typescript
// ❌ BAD - Legacy wrapper function
danger(message: string, title: string = "Error", timeout = 5000) {
this.notify.error(message, timeout);
}
// Usage (inconsistent with rest of system)
this.danger(result.error as string, "Error Setting Visibility");
// ✅ GOOD - Direct usage of notification system
this.notify.error(result.error as string, QR_TIMEOUT_LONG);
```
**Why remove legacy wrappers**:
- Creates inconsistency in the codebase
- Adds unnecessary abstraction layer
- Often have unused parameters (like `title` above)
- Bypasses the centralized notification system benefits
### 4. Extract Long Class Attributes to Computed Properties
**❌ COMMON MISTAKE**: Leaving long class strings in template instead of extracting to computed properties
```typescript
// ❌ BAD - Long class strings in template
<template>
<div class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 my-4">
<button class="inline-block text-md uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md">
Set Name
</button>
</div>
</template>
// ✅ GOOD - Extract to computed properties
<template>
<div :class="nameWarningClasses">
<button :class="setNameButtonClasses">
Set Name
</button>
</div>
</template>
// Class methods
get nameWarningClasses(): string {
return "bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 my-4";
}
get setNameButtonClasses(): string {
return "inline-block text-md uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md";
}
```
**Benefits of extracting long classes**:
- Improves template readability
- Enables reusability of styles
- Makes testing easier
- Allows for dynamic class computation
### 5. Ensure ALL Literal Strings Use Constants
**❌ COMMON MISTAKE**: Converting `$notify()` calls to helpers but not replacing literal strings with constants
```typescript
// ❌ BAD - Literal strings in notification calls
this.notify.error("This QR code does not contain valid contact information.");
this.notify.warning("The contact DID is missing.");
this.notify.success("Registration submitted...");
// ✅ GOOD - Use constants for all static messages
this.notify.error(NOTIFY_QR_INVALID_QR_CODE.message);
this.notify.warning(NOTIFY_QR_MISSING_DID.message);
this.notify.success(NOTIFY_QR_REGISTRATION_SUBMITTED.message);
```
**Add constants for ALL static messages**:
```typescript
// Add to src/constants/notifications.ts
export const NOTIFY_QR_INVALID_QR_CODE = {
message: "This QR code does not contain valid contact information.",
};
export const NOTIFY_QR_MISSING_DID = {
message: "The contact DID is missing.",
};
export const NOTIFY_QR_REGISTRATION_SUBMITTED = {
message: "Registration submitted...",
};
```
### 6. Validation Checklist for Omissions
**Before marking migration complete, verify these items**:
```bash
# Check for unused imports
grep -n "import.*NOTIFY_" src/views/YourComponent.vue
# Then verify each imported constant is actually used in the file
# Check for hardcoded timeouts
grep -n "notify\.[a-z]*(" src/views/YourComponent.vue | grep -E "[0-9]{3,4}"
# Check for legacy wrapper functions
grep -n "danger\|success\|warning\|info.*(" src/views/YourComponent.vue | grep -v "notify\."
# Check for long class attributes (>50 chars)
grep -n "class=\"[^\"]\{50,\}" src/views/YourComponent.vue
# Check for literal strings in notifications
grep -n "notify\.[a-z]*(" src/views/YourComponent.vue | grep -v "NOTIFY_\|message"
```
### 7. Post-Migration Cleanup Commands
**Run these commands after migration to catch omissions**:
```bash
# Check TypeScript compilation
npm run lint-fix
# Run validation scripts
scripts/validate-migration.sh
scripts/validate-notification-completeness.sh
# Check for any remaining databaseUtil references
grep -r "databaseUtil" src/views/YourComponent.vue
# Check for any remaining $notify calls
grep -r "\$notify(" src/views/YourComponent.vue
```
## Template Logic Streamlining
### Move Complex Template Logic to Class
When migrating components, look for opportunities to simplify template expressions by moving logic into computed properties or methods:
#### Pattern 1: Repeated Function Calls
```typescript
// ❌ BEFORE - Template with repeated function calls
<template>
<div>{{ formatName(user.firstName, user.lastName, user.title) }}</div>
<div>{{ formatName(contact.firstName, contact.lastName, contact.title) }}</div>
</template>
// ✅ AFTER - Computed properties for repeated logic
<template>
<div>{{ userDisplayName }}</div>
<div>{{ contactDisplayName }}</div>
</template>
// Class methods
get userDisplayName() {
return this.formatName(this.user?.firstName, this.user?.lastName, this.user?.title);
}
get contactDisplayName() {
return this.formatName(this.contact?.firstName, this.contact?.lastName, this.contact?.title);
}
```
#### Pattern 2: Complex Conditional Logic
```typescript
// ❌ BEFORE - Complex template conditions
<template>
<div v-if="profile?.locLat && profile?.locLon && profile?.showLocation">
<l-map :center="[profile.locLat, profile.locLon]" :zoom="12">
<!-- map content -->
</l-map>
</div>
</template>
// ✅ AFTER - Computed properties for clarity
<template>
<div v-if="shouldShowMap">
<l-map :center="mapCenter" :zoom="mapZoom">
<!-- map content -->
</l-map>
</div>
</template>
// Class methods
get shouldShowMap() {
return this.profile?.locLat && this.profile?.locLon && this.profile?.showLocation;
}
get mapCenter() {
return [this.profile?.locLat, this.profile?.locLon];
}
get mapZoom() {
return 12;
}
```
#### Pattern 3: Repeated Configuration Objects
```typescript
// ❌ BEFORE - Repeated inline objects
<template>
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
layer-type="base"
name="OpenStreetMap"
/>
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
layer-type="base"
name="OpenStreetMap"
/>
</template>
// ✅ AFTER - Computed property for configuration
<template>
<l-tile-layer
:url="tileLayerUrl"
layer-type="base"
name="OpenStreetMap"
/>
<l-tile-layer
:url="tileLayerUrl"
layer-type="base"
name="OpenStreetMap"
/>
</template>
// Class methods
get tileLayerUrl() {
return "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
}
```
#### Pattern 4: Array/Object Construction in Template
```typescript
// ❌ BEFORE - Complex array construction in template
<template>
<component :coords="[item.lat || 0, item.lng || 0]" />
</template>
// ✅ AFTER - Computed property for complex data
<template>
<component :coords="itemCoordinates" />
</template>
// Class methods
get itemCoordinates() {
return [this.item?.lat || 0, this.item?.lng || 0];
}
```
### Benefits of Logic Streamlining
1. **Improved Readability**: Template becomes cleaner and easier to understand
2. **Better Performance**: Vue caches computed properties, avoiding recalculation
3. **Easier Testing**: Logic can be unit tested independently
4. **Reduced Duplication**: Common expressions defined once
5. **Type Safety**: TypeScript can better validate computed property return types
### Guidelines for Logic Streamlining
- **Move to computed properties**: Expressions used multiple times or complex calculations
- **Keep in template**: Simple property access (`user.name`) or single-use expressions
- **Document computed properties**: Add JSDoc comments explaining purpose and return types
- **Use descriptive names**: `userDisplayName` instead of `getName()`
## Component Extraction Patterns
### When to Extract Components
Extract components when you identify:
- **Repeated UI patterns** used in multiple places
- **Complex template sections** that could be simplified
- **Form elements** with similar structure and behavior
- **Layout patterns** that appear consistently
- **Validation patterns** with repeated logic
### Component Extraction Examples
#### Form Input Extraction
```typescript
// Before: Repeated form input pattern
<template>
<div class="form-group">
<label class="form-label">Name</label>
<input class="form-input" v-model="name" />
<div class="error-message" v-if="nameError">{{ nameError }}</div>
</div>
<div class="form-group">
<label class="form-label">Email</label>
<input class="form-input" v-model="email" />
<div class="error-message" v-if="emailError">{{ emailError }}</div>
</div>
</template>
// After: Extracted FormInput component
<template>
<FormInput
label="Name"
v-model="name"
:error="nameError"
/>
<FormInput
label="Email"
v-model="email"
:error="emailError"
/>
</template>
// New FormInput.vue component
<template>
<div class="form-group">
<label class="form-label">{{ label }}</label>
<input
class="form-input"
:value="value"
@input="$emit('input', $event.target.value)"
/>
<div class="error-message" v-if="error">{{ error }}</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator";
/**
* Reusable form input component with label and error handling
*/
@Component
export default class FormInput extends Vue {
@Prop({ required: true }) label!: string;
@Prop({ required: true }) value!: string;
@Prop() error?: string;
}
</script>
```
#### Button Group Extraction
```typescript
// Before: Repeated button patterns
<template>
<div class="button-group">
<button class="btn btn-primary" @click="save">Save</button>
<button class="btn btn-secondary" @click="cancel">Cancel</button>
</div>
</template>
// After: Extracted ButtonGroup component
<template>
<ButtonGroup
:primary-action="{ text: 'Save', handler: save }"
:secondary-action="{ text: 'Cancel', handler: cancel }"
/>
</template>
// New ButtonGroup.vue component
<template>
<div class="button-group">
<button
class="btn btn-primary"
@click="primaryAction.handler"
>
{{ primaryAction.text }}
</button>
<button
class="btn btn-secondary"
@click="secondaryAction.handler"
>
{{ secondaryAction.text }}
</button>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator";
interface ButtonAction {
text: string;
handler: () => void;
}
/**
* Reusable button group component for common action patterns
*/
@Component
export default class ButtonGroup extends Vue {
@Prop({ required: true }) primaryAction!: ButtonAction;
@Prop({ required: true }) secondaryAction!: ButtonAction;
}
</script>
```
### Component Quality Standards
#### Single Responsibility
- Each extracted component should have one clear purpose
- Component name should clearly indicate its function
- Props should be focused and relevant to the component's purpose
#### Reusability
- Component should work in multiple contexts
- Props should be flexible enough for different use cases
- Events should provide appropriate communication with parent
#### Type Safety
- All props should have proper TypeScript interfaces
- Event emissions should be properly typed
- Component should compile without type errors
#### Documentation
- JSDoc comments explaining component purpose
- Usage examples in comments
- Clear prop descriptions and types
### Validation Checklist
After component extraction:
- [ ] **No template duplication**: Extracted patterns don't appear elsewhere
- [ ] **Proper component registration**: All components properly imported and registered
- [ ] **Event handling works**: Parent components receive and handle events correctly
- [ ] **Props validation**: All required props are provided with correct types
- [ ] **Styling consistency**: Extracted components maintain visual consistency
- [ ] **Functionality preserved**: All original functionality works with extracted components
## After Migration Checklist
⚠️ **CRITICAL**: Use `docs/migration-templates/COMPLETE_MIGRATION_CHECKLIST.md` for comprehensive validation
### Phase 1: Database Migration
- [ ] All `databaseUtil` imports removed
- [ ] All `logConsoleAndDb` imports removed
- [ ] All direct `PlatformServiceFactory.getInstance()` calls removed
- [ ] Component includes `PlatformServiceMixin` in mixins array
- [ ] Database operations use mixin methods (`$db`, `$query`, `$getAllContacts`, etc.)
- [ ] Settings operations use mixin methods (`$settings`, `$saveSettings`)
- [ ] Logging uses mixin methods (`$log`, `$logError`, `$logAndConsole`)
### Phase 2: SQL Abstraction (if applicable)
- [ ] All raw SQL queries replaced with service methods
- [ ] Contact operations use `$getContact()`, `$deleteContact()`, `$updateContact()`
- [ ] Settings operations use `$accountSettings()`, `$saveSettings()`
- [ ] **NO raw SQL queries remain** (`SELECT`, `INSERT`, `UPDATE`, `DELETE`)
### Phase 3: Notification Migration (if applicable)
- [ ] `createNotifyHelpers` imported and initialized
- [ ] `notify!` property declared and created in `created()`
- [ ] **All `this.$notify()` calls replaced with helper methods**
- [ ] **Hardcoded timeouts replaced with `TIMEOUTS` constants**
- [ ] **Static messages use notification constants from `@/constants/notifications`**
- [ ] **Dynamic messages use literal strings appropriately**
- [ ] **Unused notification constants removed from imports but these can mean that notifications have been overlooked**
- [ ] **Legacy wrapper functions removed (e.g., `danger()`, `success()`, etc.)**
### Phase 4: Template Streamlining (if applicable)
- [ ] **All long class attributes (50+ characters) extracted to computed properties**
- [ ] **Complex conditional logic moved to computed properties**
- [ ] **Repeated expressions extracted to computed properties**
- [ ] **Configuration objects moved to computed properties**
- [ ] **All computed properties have JSDoc documentation**
### Phase 5: Component Extraction (if applicable)
- [ ] **Reusable UI patterns identified and extracted to separate components**
- [ ] **Form elements extracted to reusable components**
- [ ] **Layout patterns extracted to reusable components**
- [ ] **Validation patterns extracted to reusable components**
- [ ] **All extracted components have clear props interfaces**
- [ ] **All extracted components have proper event handling**
- [ ] **All extracted components have JSDoc documentation**
- [ ] **Parent components properly import and use extracted components**
### Final Validation
- [ ] Error handling includes component name context
- [ ] Component compiles without TypeScript errors
- [ ] Component functionality works as expected
- [ ] `scripts/validate-migration.sh` shows "Technically Compliant"
- [ ] `scripts/validate-notification-completeness.sh` shows as complete
### Validation Commands
```bash
# Check overall migration status
scripts/validate-migration.sh
# Check notification migration completeness
scripts/validate-notification-completeness.sh
# Check for compilation errors
npm run lint-fix
```
## Testing Migration
1. **Compile Check**: `npm run build` should complete without errors
2. **Runtime Check**: Component should load and function normally
3. **Logging Check**: Verify logs appear in console and database
4. **Error Handling Check**: Verify errors are properly logged and handled
## Troubleshooting
### Common Issues
1. **Missing Mixin Methods**: Ensure component properly extends PlatformServiceMixin
2. **TypeScript Errors**: Check that all types are properly imported
3. **Runtime Errors**: Verify all async operations are properly awaited
4. **Missing Context**: Add component name to error messages for better debugging
### Performance Considerations
- Mixin methods include caching for frequently accessed data
- Database operations are queued and optimized
- Error logging includes proper context and formatting
## Phase 4: Testing and Validation
### 4.1 Multi-Platform Testing Requirements
**ALL MIGRATIONS MUST BE TESTED ON ALL SUPPORTED PLATFORMS:**
#### Web Platform Testing (Required)
- [ ] Test in Chrome/Chromium (primary browser)
- [ ] Test in Firefox (secondary browser)
- [ ] Test in Safari (if applicable)
- [ ] Verify PWA functionality works correctly
- [ ] Test responsive design on different screen sizes
#### Desktop Platform Testing (Required)
- [ ] Test Electron app functionality
- [ ] Verify desktop-specific features work
- [ ] Test file system access (if applicable)
- [ ] Verify native desktop integrations
#### Mobile Platform Testing (Required)
- [ ] Test iOS app via Capacitor
- [ ] Test Android app via Capacitor
- [ ] Verify mobile-specific features (camera, contacts, etc.)
- [ ] Test deep linking functionality
- [ ] Verify push notifications work
### 4.2 Functional Testing Per Platform
For each platform, test these core scenarios:
#### Database Operations
- [ ] Create/Read/Update/Delete operations work
- [ ] Data persistence across app restarts
- [ ] Database migration handling (if applicable)
#### Logging and Error Handling
- [ ] Errors are logged correctly to console
- [ ] Errors are stored in database logs
- [ ] Error messages display appropriately to users
- [ ] Network errors are handled gracefully
#### User Interface
- [ ] All buttons and interactions work
- [ ] Loading states display correctly
- [ ] Error states display appropriately
- [ ] Responsive design works on platform
### 4.3 Platform-Specific Testing Notes
#### Web Platform
- Test offline/online scenarios
- Verify IndexedDB storage works
- Test service worker functionality
- Check browser developer tools for errors
#### Desktop Platform
- Test native menu integrations
- Verify file system permissions
- Test auto-updater functionality
- Check Electron developer tools
#### Mobile Platform
- Test device permissions (camera, storage, etc.)
- Verify app store compliance
- Test background/foreground transitions
- Check native debugging tools
### 4.4 Sign-Off Requirements
**MIGRATION IS NOT COMPLETE UNTIL ALL PLATFORMS ARE TESTED AND SIGNED OFF:**
```markdown
## Testing Sign-Off Checklist
### Web Platform ✅/❌
- [ ] Chrome: Tested by [Name] on [Date]
- [ ] Firefox: Tested by [Name] on [Date]
- [ ] Safari: Tested by [Name] on [Date]
- [ ] Notes: [Any platform-specific issues or observations]
### Desktop Platform ✅/❌
- [ ] Windows: Tested by [Name] on [Date]
- [ ] macOS: Tested by [Name] on [Date]
- [ ] Linux: Tested by [Name] on [Date]
- [ ] Notes: [Any platform-specific issues or observations]
### Mobile Platform ✅/❌
- [ ] iOS: Tested by [Name] on [Date]
- [ ] Android: Tested by [Name] on [Date]
- [ ] Notes: [Any platform-specific issues or observations]
### Final Sign-Off
- [ ] All platforms tested and working
- [ ] No regressions identified
- [ ] Performance is acceptable
- [ ] Migration completed by: [Name] on [Date]
```

View File

@@ -0,0 +1,307 @@
# ESLint Rules for PlatformServiceMixin Migration
## Overview
Custom ESLint rules to enforce PlatformServiceMixin patterns and prevent regression to legacy patterns.
## Rules Configuration
Add to `.eslintrc.js`:
```javascript
module.exports = {
// ... existing config
rules: {
// ... existing rules
// Custom rules for PlatformServiceMixin migration
'timesafari/no-direct-database-util': 'error',
'timesafari/no-legacy-logging': 'error',
'timesafari/require-mixin-for-database': 'error',
'timesafari/no-direct-platform-service': 'warn',
'timesafari/prefer-mixin-methods': 'warn',
},
// Custom rules plugin
plugins: ['timesafari'],
}
```
## Custom Rules Implementation
Create `eslint-plugin-timesafari/index.js`:
```javascript
module.exports = {
rules: {
'no-direct-database-util': {
meta: {
type: 'problem',
docs: {
description: 'Disallow direct imports from databaseUtil',
category: 'Migration',
recommended: true,
},
schema: [],
},
create(context) {
return {
ImportDeclaration(node) {
if (node.source.value.includes('databaseUtil')) {
context.report({
node,
message: 'Direct databaseUtil imports are deprecated. Use PlatformServiceMixin instead.',
});
}
},
};
},
},
'no-legacy-logging': {
meta: {
type: 'problem',
docs: {
description: 'Disallow legacy logging methods',
category: 'Migration',
recommended: true,
},
schema: [],
},
create(context) {
return {
ImportDeclaration(node) {
if (node.specifiers.some(spec => spec.imported?.name === 'logConsoleAndDb')) {
context.report({
node,
message: 'logConsoleAndDb is deprecated. Use PlatformServiceMixin $log methods instead.',
});
}
},
CallExpression(node) {
if (node.callee.name === 'logConsoleAndDb') {
context.report({
node,
message: 'logConsoleAndDb is deprecated. Use this.$logAndConsole() instead.',
});
}
},
};
},
},
'require-mixin-for-database': {
meta: {
type: 'suggestion',
docs: {
description: 'Require PlatformServiceMixin for components using database operations',
category: 'Migration',
recommended: true,
},
schema: [],
},
create(context) {
let hasDbOperations = false;
let hasMixin = false;
return {
CallExpression(node) {
// Check for database operations
if (node.callee.property &&
['dbQuery', 'dbExec', 'dbGetOneRow'].includes(node.callee.property.name)) {
hasDbOperations = true;
}
},
Property(node) {
// Check for mixin usage
if (node.key.name === 'mixins' &&
node.value.elements?.some(el => el.name === 'PlatformServiceMixin')) {
hasMixin = true;
}
},
'Program:exit'() {
if (hasDbOperations && !hasMixin) {
context.report({
node: context.getSourceCode().ast,
message: 'Components using database operations should include PlatformServiceMixin.',
});
}
},
};
},
},
'no-direct-platform-service': {
meta: {
type: 'suggestion',
docs: {
description: 'Discourage direct PlatformServiceFactory usage',
category: 'Migration',
recommended: false,
},
schema: [],
},
create(context) {
return {
CallExpression(node) {
if (node.callee.object?.name === 'PlatformServiceFactory' &&
node.callee.property?.name === 'getInstance') {
context.report({
node,
message: 'Consider using PlatformServiceMixin methods instead of direct PlatformServiceFactory.',
});
}
},
};
},
},
'prefer-mixin-methods': {
meta: {
type: 'suggestion',
docs: {
description: 'Prefer mixin convenience methods over direct database calls',
category: 'Migration',
recommended: false,
},
schema: [],
},
create(context) {
return {
CallExpression(node) {
// Check for patterns that could use mixin methods
if (node.callee.property?.name === 'dbQuery') {
const arg = node.arguments[0];
if (arg && arg.type === 'Literal') {
const sql = arg.value.toLowerCase();
if (sql.includes('select * from contacts')) {
context.report({
node,
message: 'Consider using this.$getAllContacts() instead of direct SQL.',
});
}
if (sql.includes('select * from settings')) {
context.report({
node,
message: 'Consider using this.$settings() instead of direct SQL.',
});
}
}
}
},
};
},
},
},
};
```
## Pre-commit Hook
Create `.pre-commit-config.yaml`:
```yaml
repos:
- repo: local
hooks:
- id: eslint-migration-check
name: ESLint Migration Check
entry: npx eslint --ext .vue --rule 'timesafari/no-direct-database-util: error'
language: system
files: \.vue$
- id: no-legacy-logging
name: No Legacy Logging
entry: bash -c 'if grep -r "logConsoleAndDb" src/ --include="*.vue" --include="*.ts"; then echo "Found legacy logging imports"; exit 1; fi'
language: system
pass_filenames: false
```
## Migration Validation Script
Create `scripts/validate-migration.sh`:
```bash
#!/bin/bash
echo "🔍 Validating PlatformServiceMixin migration..."
# Check for legacy patterns
echo "Checking for legacy databaseUtil imports..."
LEGACY_DB_IMPORTS=$(grep -r "import.*databaseUtil" src/ --include="*.vue" --include="*.ts" | wc -l)
echo "Found $LEGACY_DB_IMPORTS legacy databaseUtil imports"
echo "Checking for legacy logging imports..."
LEGACY_LOG_IMPORTS=$(grep -r "logConsoleAndDb" src/ --include="*.vue" --include="*.ts" | wc -l)
echo "Found $LEGACY_LOG_IMPORTS legacy logging imports"
# Check for mixin usage
echo "Checking for PlatformServiceMixin usage..."
MIXIN_USAGE=$(grep -r "PlatformServiceMixin" src/ --include="*.vue" | wc -l)
echo "Found $MIXIN_USAGE files using PlatformServiceMixin"
# Check for direct PlatformService usage
echo "Checking for direct PlatformService usage..."
DIRECT_PLATFORM=$(grep -r "PlatformServiceFactory.getInstance" src/ --include="*.vue" --include="*.ts" | wc -l)
echo "Found $DIRECT_PLATFORM direct PlatformService usages"
# Summary
echo ""
echo "📊 Migration Status Summary:"
echo "- Legacy databaseUtil imports: $LEGACY_DB_IMPORTS (should be 0)"
echo "- Legacy logging imports: $LEGACY_LOG_IMPORTS (should be 0)"
echo "- Mixin usage: $MIXIN_USAGE (should be high)"
echo "- Direct PlatformService usage: $DIRECT_PLATFORM (should be low)"
# Set exit code based on legacy usage
if [ $LEGACY_DB_IMPORTS -gt 0 ] || [ $LEGACY_LOG_IMPORTS -gt 0 ]; then
echo "❌ Migration validation failed - legacy patterns found"
exit 1
else
echo "✅ Migration validation passed - no legacy patterns found"
exit 0
fi
```
## Usage
1. **Install ESLint rules**:
```bash
npm install --save-dev eslint-plugin-timesafari
```
2. **Run validation**:
```bash
npm run lint
./scripts/validate-migration.sh
```
3. **Fix issues automatically**:
```bash
npm run lint -- --fix
```
## IDE Integration
### VS Code Settings
Add to `.vscode/settings.json`:
```json
{
"eslint.validate": [
"javascript",
"typescript",
"vue"
],
"eslint.options": {
"extensions": [".js", ".ts", ".vue"]
}
}
```
### WebStorm Settings
1. Go to Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint
2. Enable ESLint
3. Set configuration file to `.eslintrc.js`
4. Add `.vue` to file extensions