Finalize Dexie-to-SQLite migration prep: docs, circular dep removal, SQL helpers, tests
- Removed all vestigial Dexie/USE_DEXIE_DB references from code and docs - Centralized DB logic in PlatformServiceMixin; resolved logger/databaseUtil circular dependency - Modularized SQL helpers (`$generateInsertStatement`, `$generateUpdateStatement`) and added unit tests - Created/updated migration tracking docs and helper script for cross-machine progress - Confirmed all lint/type checks and tests pass; ready for systematic file migration
This commit is contained in:
418
doc/platformservicemixin-completion-plan.md
Normal file
418
doc/platformservicemixin-completion-plan.md
Normal file
@@ -0,0 +1,418 @@
|
||||
# PlatformServiceMixin Completion Plan: 2-Day Sprint
|
||||
|
||||
## Overview
|
||||
|
||||
This document outlines the complete plan to finish PlatformServiceMixin implementation and migrate all 52 remaining files from databaseUtil imports to PlatformServiceMixin usage within 2 days.
|
||||
|
||||
## Current Status
|
||||
|
||||
### ✅ **PlatformServiceMixin - 95% Complete**
|
||||
- **Core functionality**: ✅ Implemented
|
||||
- **Caching system**: ✅ Implemented
|
||||
- **Database methods**: ✅ Implemented
|
||||
- **Utility methods**: ✅ Implemented
|
||||
- **Type definitions**: ✅ Implemented
|
||||
|
||||
### ⚠️ **Remaining Issues**
|
||||
1. **Single circular dependency**: `memoryLogs` import from databaseUtil
|
||||
2. **Missing utility functions**: `generateInsertStatement`, `generateUpdateStatement`
|
||||
3. **52 files** still importing databaseUtil
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **DAY 1: Complete PlatformServiceMixin (4-6 hours)**
|
||||
|
||||
### **Phase 1: Remove Circular Dependency (30 minutes)**
|
||||
|
||||
#### **Step 1.1: Create Self-Contained memoryLogs**
|
||||
```typescript
|
||||
// In PlatformServiceMixin.ts - Replace line 50:
|
||||
// Remove: import { memoryLogs } from "@/db/databaseUtil";
|
||||
|
||||
// Add self-contained implementation:
|
||||
const _memoryLogs: string[] = [];
|
||||
|
||||
// Update $memoryLogs computed property:
|
||||
$memoryLogs(): string[] {
|
||||
return _memoryLogs;
|
||||
},
|
||||
|
||||
// Add method to append to memory logs:
|
||||
$appendToMemoryLogs(message: string): void {
|
||||
_memoryLogs.push(`${new Date().toISOString()}: ${message}`);
|
||||
// Keep only last 1000 entries to prevent memory leaks
|
||||
if (_memoryLogs.length > 1000) {
|
||||
_memoryLogs.splice(0, _memoryLogs.length - 1000);
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
#### **Step 1.2: Update logger.ts**
|
||||
```typescript
|
||||
// In logger.ts - Replace memoryLogs usage:
|
||||
// Remove: import { memoryLogs } from "@/db/databaseUtil";
|
||||
|
||||
// Add self-contained implementation:
|
||||
const _memoryLogs: string[] = [];
|
||||
|
||||
export function appendToMemoryLogs(message: string): void {
|
||||
_memoryLogs.push(`${new Date().toISOString()}: ${message}`);
|
||||
if (_memoryLogs.length > 1000) {
|
||||
_memoryLogs.splice(0, _memoryLogs.length - 1000);
|
||||
}
|
||||
}
|
||||
|
||||
export function getMemoryLogs(): string[] {
|
||||
return [..._memoryLogs];
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 2: Add Missing Utility Functions (1 hour)**
|
||||
|
||||
#### **Step 2.1: Add generateInsertStatement to PlatformServiceMixin**
|
||||
```typescript
|
||||
// Add to PlatformServiceMixin methods:
|
||||
_generateInsertStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
): { sql: string; params: unknown[] } {
|
||||
const columns = Object.keys(model).filter((key) => model[key] !== undefined);
|
||||
const values = Object.values(model)
|
||||
.filter((value) => value !== undefined)
|
||||
.map((value) => {
|
||||
if (value === null || value === undefined) return null;
|
||||
if (typeof value === "object" && value !== null) {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
if (typeof value === "boolean") return value ? 1 : 0;
|
||||
return value;
|
||||
});
|
||||
const placeholders = values.map(() => "?").join(", ");
|
||||
const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`;
|
||||
|
||||
return { sql: insertSql, params: values };
|
||||
},
|
||||
```
|
||||
|
||||
#### **Step 2.2: Add generateUpdateStatement to PlatformServiceMixin**
|
||||
```typescript
|
||||
// Add to PlatformServiceMixin methods:
|
||||
_generateUpdateStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
whereClause: string,
|
||||
whereParams: unknown[] = [],
|
||||
): { sql: string; params: unknown[] } {
|
||||
const setClauses: string[] = [];
|
||||
const params: unknown[] = [];
|
||||
|
||||
Object.entries(model).forEach(([key, value]) => {
|
||||
setClauses.push(`${key} = ?`);
|
||||
let convertedValue = value ?? null;
|
||||
if (convertedValue !== null) {
|
||||
if (typeof convertedValue === "object") {
|
||||
convertedValue = JSON.stringify(convertedValue);
|
||||
} else if (typeof convertedValue === "boolean") {
|
||||
convertedValue = convertedValue ? 1 : 0;
|
||||
}
|
||||
}
|
||||
params.push(convertedValue);
|
||||
});
|
||||
|
||||
if (setClauses.length === 0) {
|
||||
throw new Error("No valid fields to update");
|
||||
}
|
||||
|
||||
const sql = `UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE ${whereClause}`;
|
||||
return { sql, params: [...params, ...whereParams] };
|
||||
},
|
||||
```
|
||||
|
||||
#### **Step 2.3: Add Public Wrapper Methods**
|
||||
```typescript
|
||||
// Add to PlatformServiceMixin methods:
|
||||
$generateInsertStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
): { sql: string; params: unknown[] } {
|
||||
return this._generateInsertStatement(model, tableName);
|
||||
},
|
||||
|
||||
$generateUpdateStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
whereClause: string,
|
||||
whereParams: unknown[] = [],
|
||||
): { sql: string; params: unknown[] } {
|
||||
return this._generateUpdateStatement(model, tableName, whereClause, whereParams);
|
||||
},
|
||||
```
|
||||
|
||||
### **Phase 3: Update Type Definitions (30 minutes)**
|
||||
|
||||
#### **Step 3.1: Update IPlatformServiceMixin Interface**
|
||||
```typescript
|
||||
// Add to IPlatformServiceMixin interface:
|
||||
$generateInsertStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
): { sql: string; params: unknown[] };
|
||||
$generateUpdateStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
whereClause: string,
|
||||
whereParams?: unknown[],
|
||||
): { sql: string; params: unknown[] };
|
||||
$appendToMemoryLogs(message: string): void;
|
||||
```
|
||||
|
||||
#### **Step 3.2: Update ComponentCustomProperties**
|
||||
```typescript
|
||||
// Add to ComponentCustomProperties interface:
|
||||
$generateInsertStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
): { sql: string; params: unknown[] };
|
||||
$generateUpdateStatement(
|
||||
model: Record<string, unknown>,
|
||||
tableName: string,
|
||||
whereClause: string,
|
||||
whereParams?: unknown[],
|
||||
): { sql: string; params: unknown[] };
|
||||
$appendToMemoryLogs(message: string): void;
|
||||
```
|
||||
|
||||
### **Phase 4: Test PlatformServiceMixin (1 hour)**
|
||||
|
||||
#### **Step 4.1: Create Test Component**
|
||||
```typescript
|
||||
// Create test file: src/test/PlatformServiceMixin.test.ts
|
||||
// Test all methods including new utility functions
|
||||
```
|
||||
|
||||
#### **Step 4.2: Run Linting and Type Checking**
|
||||
```bash
|
||||
npm run lint
|
||||
npx tsc --noEmit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **DAY 2: Migrate All 52 Files (6-8 hours)**
|
||||
|
||||
### **Migration Strategy**
|
||||
|
||||
#### **Priority Order:**
|
||||
1. **Views** (25 files) - User-facing components
|
||||
2. **Components** (15 files) - Reusable UI components
|
||||
3. **Services** (8 files) - Business logic
|
||||
4. **Utils** (4 files) - Utility functions
|
||||
|
||||
#### **Migration Pattern for Each File:**
|
||||
|
||||
**Step 1: Add PlatformServiceMixin**
|
||||
```typescript
|
||||
// Add to component imports:
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
|
||||
// Add to component definition:
|
||||
export default class ComponentName extends Vue {
|
||||
// Add mixin
|
||||
mixins = [PlatformServiceMixin];
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Replace databaseUtil Imports**
|
||||
```typescript
|
||||
// Remove:
|
||||
import {
|
||||
generateInsertStatement,
|
||||
generateUpdateStatement,
|
||||
parseJsonField,
|
||||
mapColumnsToValues,
|
||||
logToDb,
|
||||
logConsoleAndDb
|
||||
} from "@/db/databaseUtil";
|
||||
|
||||
// Replace with mixin methods:
|
||||
// generateInsertStatement → this.$generateInsertStatement
|
||||
// generateUpdateStatement → this.$generateUpdateStatement
|
||||
// parseJsonField → this._parseJsonField
|
||||
// mapColumnsToValues → this._mapColumnsToValues
|
||||
// logToDb → this.$log
|
||||
// logConsoleAndDb → this.$logAndConsole
|
||||
```
|
||||
|
||||
**Step 3: Update Method Calls**
|
||||
```typescript
|
||||
// Before:
|
||||
const { sql, params } = generateInsertStatement(contact, 'contacts');
|
||||
|
||||
// After:
|
||||
const { sql, params } = this.$generateInsertStatement(contact, 'contacts');
|
||||
```
|
||||
|
||||
### **File Migration Checklist**
|
||||
|
||||
#### **Views (25 files) - Priority 1**
|
||||
- [ ] QuickActionBvcEndView.vue
|
||||
- [ ] ProjectsView.vue
|
||||
- [ ] ClaimReportCertificateView.vue
|
||||
- [ ] NewEditAccountView.vue
|
||||
- [ ] OnboardMeetingSetupView.vue
|
||||
- [ ] SearchAreaView.vue
|
||||
- [ ] TestView.vue
|
||||
- [ ] InviteOneView.vue
|
||||
- [ ] IdentitySwitcherView.vue
|
||||
- [ ] HelpNotificationsView.vue
|
||||
- [ ] StartView.vue
|
||||
- [ ] OfferDetailsView.vue
|
||||
- [ ] ContactEditView.vue
|
||||
- [ ] SharedPhotoView.vue
|
||||
- [ ] ContactQRScanShowView.vue
|
||||
- [ ] ContactGiftingView.vue
|
||||
- [ ] DiscoverView.vue
|
||||
- [ ] ImportAccountView.vue
|
||||
- [ ] ConfirmGiftView.vue
|
||||
- [ ] SeedBackupView.vue
|
||||
- [ ] [5 more view files]
|
||||
|
||||
#### **Components (15 files) - Priority 2**
|
||||
- [ ] ActivityListItem.vue
|
||||
- [ ] AmountInput.vue
|
||||
- [ ] ChoiceButtonDialog.vue
|
||||
- [ ] ContactNameDialog.vue
|
||||
- [ ] DataExportSection.vue
|
||||
- [ ] EntityGrid.vue
|
||||
- [ ] EntityIcon.vue
|
||||
- [ ] EntitySelectionStep.vue
|
||||
- [ ] EntitySummaryButton.vue
|
||||
- [ ] FeedFilters.vue
|
||||
- [ ] GiftDetailsStep.vue
|
||||
- [ ] GiftedDialog.vue
|
||||
- [ ] GiftedPrompts.vue
|
||||
- [ ] HiddenDidDialog.vue
|
||||
- [ ] IconRenderer.vue
|
||||
|
||||
#### **Services (8 files) - Priority 3**
|
||||
- [ ] api.ts
|
||||
- [ ] endorserServer.ts
|
||||
- [ ] partnerServer.ts
|
||||
- [ ] [5 more service files]
|
||||
|
||||
#### **Utils (4 files) - Priority 4**
|
||||
- [ ] LogCollector.ts
|
||||
- [ ] [3 more util files]
|
||||
|
||||
### **Migration Tools**
|
||||
|
||||
#### **Automated Script for Common Patterns**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# migration-helper.sh
|
||||
|
||||
# Find all databaseUtil imports
|
||||
echo "Files with databaseUtil imports:"
|
||||
find src -name "*.vue" -o -name "*.ts" | xargs grep -l "import.*databaseUtil"
|
||||
|
||||
# Common replacement patterns
|
||||
echo "Common replacement patterns:"
|
||||
echo "generateInsertStatement → this.\$generateInsertStatement"
|
||||
echo "generateUpdateStatement → this.\$generateUpdateStatement"
|
||||
echo "parseJsonField → this._parseJsonField"
|
||||
echo "mapColumnsToValues → this._mapColumnsToValues"
|
||||
echo "logToDb → this.\$log"
|
||||
echo "logConsoleAndDb → this.\$logAndConsole"
|
||||
```
|
||||
|
||||
#### **Validation Script**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# validate-migration.sh
|
||||
|
||||
# Check for remaining databaseUtil imports
|
||||
echo "Checking for remaining databaseUtil imports..."
|
||||
find src -name "*.vue" -o -name "*.ts" | xargs grep -l "import.*databaseUtil"
|
||||
|
||||
# Run linting
|
||||
echo "Running linting..."
|
||||
npm run lint
|
||||
|
||||
# Run type checking
|
||||
echo "Running type checking..."
|
||||
npx tsc --noEmit
|
||||
|
||||
echo "Migration validation complete!"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **Success Criteria**
|
||||
|
||||
### **Day 1 Success Criteria:**
|
||||
- [ ] PlatformServiceMixin has no circular dependencies
|
||||
- [ ] All utility functions implemented and tested
|
||||
- [ ] Type definitions complete and accurate
|
||||
- [ ] Linting passes with no errors
|
||||
- [ ] TypeScript compilation passes
|
||||
|
||||
### **Day 2 Success Criteria:**
|
||||
- [ ] 0 files importing databaseUtil
|
||||
- [ ] All 52 files migrated to PlatformServiceMixin
|
||||
- [ ] No runtime errors in migrated components
|
||||
- [ ] All tests passing
|
||||
- [ ] Performance maintained or improved
|
||||
|
||||
### **Overall Success Criteria:**
|
||||
- [ ] Complete elimination of databaseUtil dependency
|
||||
- [ ] PlatformServiceMixin is the single source of truth for database operations
|
||||
- [ ] Migration fence is fully implemented
|
||||
- [ ] Ready for Phase 3: Cleanup and Optimization
|
||||
|
||||
---
|
||||
|
||||
## 🚀 **Post-Migration Benefits**
|
||||
|
||||
1. **80% reduction** in database boilerplate code
|
||||
2. **Centralized caching** for improved performance
|
||||
3. **Type-safe** database operations
|
||||
4. **Eliminated circular dependencies**
|
||||
5. **Simplified testing** with mockable mixin
|
||||
6. **Consistent error handling** across all components
|
||||
7. **Ready for SQLite-only mode**
|
||||
|
||||
---
|
||||
|
||||
## 📋 **Daily Progress Tracking**
|
||||
|
||||
### **Day 1 Progress:**
|
||||
- [ ] Phase 1: Circular dependency resolved
|
||||
- [ ] Phase 2: Utility functions added
|
||||
- [ ] Phase 3: Type definitions updated
|
||||
- [ ] Phase 4: Testing completed
|
||||
|
||||
### **Day 2 Progress:**
|
||||
- [ ] Views migrated (0/25)
|
||||
- [ ] Components migrated (0/15)
|
||||
- [ ] Services migrated (0/8)
|
||||
- [ ] Utils migrated (0/4)
|
||||
- [ ] Validation completed
|
||||
|
||||
---
|
||||
|
||||
## 🆘 **Contingency Plans**
|
||||
|
||||
### **If Day 1 Takes Longer:**
|
||||
- Focus on core functionality first
|
||||
- Defer advanced utility functions to Day 2
|
||||
- Prioritize circular dependency resolution
|
||||
|
||||
### **If Day 2 Takes Longer:**
|
||||
- Focus on high-impact views first
|
||||
- Batch similar components together
|
||||
- Use automated scripts for common patterns
|
||||
|
||||
### **If Issues Arise:**
|
||||
- Document specific problems
|
||||
- Create targeted fixes
|
||||
- Maintain backward compatibility during transition
|
||||
Reference in New Issue
Block a user