2024-07-18 21:35:17 +03:00
import syncService from "./sync.js" ;
import log from "./log.js" ;
import sqlInit from "./sql_init.js" ;
import optionService from "./options.js" ;
import syncOptions from "./sync_options.js" ;
import request from "./request.js" ;
import appInfo from "./app_info.js" ;
2025-01-02 13:47:44 +01:00
import { timeLimit } from "./utils.js" ;
2024-07-18 21:35:17 +03:00
import becca from "../becca/becca.js" ;
2024-07-24 20:33:35 +03:00
import { SetupStatusResponse , SetupSyncSeedResponse } from './api-interface.js' ;
2018-09-10 20:05:10 +02:00
2018-09-11 10:01:40 +02:00
async function hasSyncServerSchemaAndSeed() {
2024-04-03 23:18:39 +03:00
const response = await requestToSyncServer < SetupStatusResponse > ( 'GET' , '/api/setup/status' ) ;
2018-09-10 20:05:10 +02:00
2019-06-11 20:42:06 +02:00
if ( response . syncVersion !== appInfo . syncVersion ) {
throw new Error ( ` Could not setup sync since local sync protocol version is ${ appInfo . syncVersion } while remote is ${ response . syncVersion } . To fix this issue, use same Trilium version on all instances. ` ) ;
}
2018-09-11 10:01:40 +02:00
return response . schemaExists ;
2018-09-10 20:05:10 +02:00
}
2018-07-24 08:12:36 +02:00
function triggerSync() {
2018-07-24 20:35:03 +02:00
log . info ( "Triggering sync." ) ;
// it's ok to not wait for it here
2020-06-20 12:31:38 +02:00
syncService . sync ( ) . then ( res = > {
2018-07-24 20:35:03 +02:00
if ( res . success ) {
2020-06-20 21:42:41 +02:00
sqlInit . setDbAsInitialized ( ) ;
2018-07-24 20:35:03 +02:00
}
2018-07-24 08:12:36 +02:00
} ) ;
}
2018-09-11 10:01:40 +02:00
async function sendSeedToSyncServer() {
2018-09-10 20:05:10 +02:00
log . info ( "Initiating sync to server" ) ;
2024-04-03 23:18:39 +03:00
await requestToSyncServer < void > ( 'POST' , '/api/setup/sync-seed' , {
2020-06-20 12:31:38 +02:00
options : getSyncSeedOptions ( ) ,
2019-06-05 22:50:03 +02:00
syncVersion : appInfo.syncVersion
2018-09-10 20:05:10 +02:00
} ) ;
2023-06-30 11:18:34 +02:00
// this is a completely new sync, need to reset counters. If this was not a new sync,
2018-09-10 20:05:10 +02:00
// the previous request would have failed.
2020-06-20 12:31:38 +02:00
optionService . setOption ( 'lastSyncedPush' , 0 ) ;
optionService . setOption ( 'lastSyncedPull' , 0 ) ;
2018-09-10 20:05:10 +02:00
}
2024-04-03 23:18:39 +03:00
async function requestToSyncServer < T > ( method : string , path : string , body? : string | { } ) : Promise < T > {
2020-06-20 12:31:38 +02:00
const timeout = syncOptions . getSyncTimeout ( ) ;
2020-06-13 10:23:36 +02:00
2025-01-02 13:47:44 +01:00
return await timeLimit ( request . exec ( {
2018-12-17 22:12:26 +01:00
method ,
2020-06-20 12:31:38 +02:00
url : syncOptions.getSyncServerHost ( ) + path ,
2018-12-17 22:12:26 +01:00
body ,
2020-06-20 12:31:38 +02:00
proxy : syncOptions.getSyncProxy ( ) ,
2020-06-13 10:23:36 +02:00
timeout : timeout
2024-04-03 23:18:39 +03:00
} ) , timeout ) as T ;
2018-09-10 20:05:10 +02:00
}
2024-04-03 23:18:39 +03:00
async function setupSyncFromSyncServer ( syncServerHost : string , syncProxy : string , password : string ) {
2020-06-20 12:31:38 +02:00
if ( sqlInit . isDbInitialized ( ) ) {
2018-07-24 08:12:36 +02:00
return {
result : 'failure' ,
error : 'DB is already initialized.'
} ;
}
try {
2020-08-06 00:06:42 +02:00
log . info ( "Getting document options FROM sync server." ) ;
2018-07-24 08:12:36 +02:00
2023-06-30 11:18:34 +02:00
// the response is expected to contain documentId and documentSecret options
2024-04-03 23:18:39 +03:00
const resp = await request . exec < SetupSyncSeedResponse > ( {
2018-12-17 22:12:26 +01:00
method : 'get' ,
2022-12-21 15:19:05 +01:00
url : ` ${ syncServerHost } /api/setup/sync-seed ` ,
2021-12-29 23:37:12 +01:00
auth : { password } ,
2019-12-29 10:19:00 +01:00
proxy : syncProxy ,
timeout : 30000 // seed request should not take long
2018-07-24 08:12:36 +02:00
} ) ;
2019-06-11 20:42:06 +02:00
if ( resp . syncVersion !== appInfo . syncVersion ) {
const message = ` Could not setup sync since local sync protocol version is ${ appInfo . syncVersion } while remote is ${ resp . syncVersion } . To fix this issue, use same Trilium version on all instances. ` ;
log . error ( message ) ;
return {
result : 'failure' ,
error : message
}
}
2024-07-29 20:41:28 +03:00
await sqlInit . createDatabaseForSync ( resp . options , syncServerHost , syncProxy ) ;
2024-12-22 15:42:15 +02:00
2018-07-24 08:12:36 +02:00
triggerSync ( ) ;
return { result : 'success' } ;
}
2024-04-03 23:18:39 +03:00
catch ( e : any ) {
2023-09-21 11:16:03 +02:00
log . error ( ` Sync failed: ' ${ e . message } ', stack: ${ e . stack } ` ) ;
2018-07-24 08:12:36 +02:00
return {
result : 'failure' ,
error : e.message
} ;
}
}
2020-06-20 12:31:38 +02:00
function getSyncSeedOptions() {
2018-07-25 09:46:57 +02:00
return [
2021-05-02 11:23:58 +02:00
becca . getOption ( 'documentId' ) ,
becca . getOption ( 'documentSecret' )
2018-07-25 09:46:57 +02:00
] ;
}
2024-07-18 21:47:30 +03:00
export default {
2018-09-11 10:01:40 +02:00
hasSyncServerSchemaAndSeed ,
2018-09-10 20:05:10 +02:00
triggerSync ,
2018-09-11 10:01:40 +02:00
sendSeedToSyncServer ,
2018-07-24 08:12:36 +02:00
setupSyncFromSyncServer ,
2018-09-10 20:05:10 +02:00
getSyncSeedOptions
2020-06-13 10:23:36 +02:00
} ;