@ -64,6 +64,27 @@
Compare Databases
Compare Databases
< / button >
< / button >
< button
: disabled = "isLoading || !isDexieEnabled || !comparison"
class = "inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed"
@ click = "migrateAll"
>
< IconRenderer
v - if = "isLoading"
icon - name = "spinner"
svg - class = "animate-spin -ml-1 mr-3 h-5 w-5 text-white"
fill = "currentColor"
/ >
< IconRenderer
v - else
icon - name = "check"
svg - class = "-ml-1 mr-3 h-5 w-5"
/ >
Migrate All ( Recommended )
< / button >
< div class = "w-full border-t border-gray-200 my-4" > < / div >
< button
< button
: disabled = "isLoading || !isDexieEnabled || !comparison"
: disabled = "isLoading || !isDexieEnabled || !comparison"
class = "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed"
class = "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed"
@ -110,6 +131,49 @@
< / button >
< / button >
< / div >
< / div >
<!-- Migration Information -- >
< div
v - if = "comparison"
class = "mb-6 bg-blue-50 border border-blue-200 rounded-lg p-4"
>
< div class = "flex" >
< div class = "flex-shrink-0" >
< IconRenderer
icon - name = "info"
svg - class = "h-5 w-5 text-blue-400"
fill = "currentColor"
/ >
< / div >
< div class = "ml-3" >
< h3 class = "text-sm font-medium text-blue-800" >
Migration Order & Recommendations
< / h3 >
< div class = "mt-2 text-sm text-blue-700" >
< p class = "mb-2" >
< strong > Recommended : < / strong > Use "Migrate All" to ensure proper
data integrity and avoid foreign key issues .
< / p >
< p class = "mb-2" >
< strong > Migration Order : < / strong > Accounts → Settings → Contacts
< / p >
< ul class = "list-disc list-inside space-y-1" >
< li >
< strong > Accounts : < / strong > Foundation data containing DIDs
< / li >
< li >
< strong > Settings : < / strong > References accountDid and activeDid
from accounts
< / li >
< li >
< strong > Contacts : < / strong > Independent data , migrated last for
consistency
< / li >
< / ul >
< / div >
< / div >
< / div >
< / div >
<!-- Loading State -- >
<!-- Loading State -- >
< div v-if ="isLoading" class="text-center py-12" >
< div v-if ="isLoading" class="text-center py-12" >
< div
< div
@ -596,6 +660,7 @@ import {
migrateContacts ,
migrateContacts ,
migrateSettings ,
migrateSettings ,
migrateAccounts ,
migrateAccounts ,
migrateAll ,
generateComparisonYaml ,
generateComparisonYaml ,
type DataComparison ,
type DataComparison ,
type MigrationResult ,
type MigrationResult ,
@ -646,6 +711,56 @@ export default class DatabaseMigration extends Vue {
return USE_DEXIE_DB ;
return USE_DEXIE_DB ;
}
}
/ * *
* Migrates all data from Dexie to SQLite in the proper order
*
* This method performs a complete migration of all data from Dexie to SQLite
* in the correct order to avoid foreign key constraint issues :
* 1. Accounts ( foundational - contains DIDs )
* 2. Settings ( references accountDid , activeDid )
* 3. Contacts ( independent , but migrated after accounts for consistency )
*
* This is the recommended approach as it ensures data integrity and
* handles all foreign key relationships automatically .
*
* @ async
* @ returns { Promise < void > }
* /
async migrateAll ( ) : Promise < void > {
this . setLoading ( "Migrating all data (Accounts → Settings → Contacts)..." ) ;
this . clearMessages ( ) ;
try {
const result : MigrationResult = await migrateAll ( this . overwriteExisting ) ;
if ( result . success ) {
const totalMigrated =
result . accountsMigrated +
result . settingsMigrated +
result . contactsMigrated ;
this . successMessage = ` Successfully migrated ${ totalMigrated } total records: ${ result . accountsMigrated } accounts, ${ result . settingsMigrated } settings, ${ result . contactsMigrated } contacts. ` ;
if ( result . warnings . length > 0 ) {
this . successMessage += ` ${ result . warnings . length } warnings. ` ;
}
logger . info (
"[DatabaseMigration] Complete migration successful" ,
result ,
) ;
} else {
this . error = ` Migration failed: ${ result . errors . join ( ", " ) } ` ;
logger . error (
"[DatabaseMigration] Complete migration failed:" ,
result . errors ,
) ;
}
} catch ( error ) {
this . error = ` Failed to migrate all data: ${ error } ` ;
logger . error ( "[DatabaseMigration] Complete migration failed:" , error ) ;
} finally {
this . setLoading ( "" ) ;
}
}
/ * *
/ * *
* Compares data between Dexie and SQLite databases
* Compares data between Dexie and SQLite databases
*
*