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"; import { timeLimit } from "./utils.js"; import becca from "../becca/becca.js"; import type { SetupStatusResponse, SetupSyncSeedResponse } from "./api-interface.js"; async function hasSyncServerSchemaAndSeed() { const response = await requestToSyncServer("GET", "/api/setup/status"); 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.` ); } return response.schemaExists; } function triggerSync() { log.info("Triggering sync."); // it's ok to not wait for it here syncService.sync().then((res) => { if (res.success) { sqlInit.setDbAsInitialized(); } }); } async function sendSeedToSyncServer() { log.info("Initiating sync to server"); await requestToSyncServer("POST", "/api/setup/sync-seed", { options: getSyncSeedOptions(), syncVersion: appInfo.syncVersion }); // this is a completely new sync, need to reset counters. If this was not a new sync, // the previous request would have failed. optionService.setOption("lastSyncedPush", 0); optionService.setOption("lastSyncedPull", 0); } async function requestToSyncServer(method: string, path: string, body?: string | {}): Promise { const timeout = syncOptions.getSyncTimeout(); return (await timeLimit( request.exec({ method, url: syncOptions.getSyncServerHost() + path, body, proxy: syncOptions.getSyncProxy(), timeout: timeout }), timeout )) as T; } async function setupSyncFromSyncServer(syncServerHost: string, syncProxy: string, password: string) { if (sqlInit.isDbInitialized()) { return { result: "failure", error: "DB is already initialized." }; } try { log.info("Getting document options FROM sync server."); // the response is expected to contain documentId and documentSecret options const resp = await request.exec({ method: "get", url: `${syncServerHost}/api/setup/sync-seed`, auth: { password }, proxy: syncProxy, timeout: 30000 // seed request should not take long }); 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 }; } await sqlInit.createDatabaseForSync(resp.options, syncServerHost, syncProxy); triggerSync(); return { result: "success" }; } catch (e: any) { log.error(`Sync failed: '${e.message}', stack: ${e.stack}`); return { result: "failure", error: e.message }; } } function getSyncSeedOptions() { return [becca.getOption("documentId"), becca.getOption("documentSecret")]; } export default { hasSyncServerSchemaAndSeed, triggerSync, sendSeedToSyncServer, setupSyncFromSyncServer, getSyncSeedOptions };