2026-03-28 16:22:15 +01:00
|
|
|
const path = require("path");
|
|
|
|
|
const obCli = require("./ob-cli");
|
|
|
|
|
const auth = require("./auth");
|
2026-03-28 18:50:32 +01:00
|
|
|
const { SyncManager } = require("./sync-manager");
|
2026-03-28 16:22:15 +01:00
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
id: "headless-sync",
|
|
|
|
|
name: "Headless Sync",
|
|
|
|
|
description: "Server-side vault sync via obsidian-headless CLI",
|
|
|
|
|
|
|
|
|
|
obsidianPlugin: path.join(__dirname, "plugin"),
|
|
|
|
|
|
|
|
|
|
_ctx: null,
|
|
|
|
|
_obStatus: null,
|
2026-03-28 18:50:32 +01:00
|
|
|
_syncManager: null,
|
2026-03-28 16:22:15 +01:00
|
|
|
|
|
|
|
|
async register(ctx) {
|
|
|
|
|
this._ctx = ctx;
|
|
|
|
|
|
|
|
|
|
this._obStatus = obCli.checkInstalled();
|
|
|
|
|
|
|
|
|
|
if (this._obStatus.installed) {
|
|
|
|
|
ctx.log(`ob CLI available (${this._obStatus.version})`);
|
|
|
|
|
} else {
|
|
|
|
|
ctx.log("ob CLI not found. Install obsidian-headless to enable sync.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const token = auth.loadToken(ctx.dataDir);
|
|
|
|
|
|
|
|
|
|
if (token) {
|
|
|
|
|
ctx.log("Auth token loaded");
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 18:50:32 +01:00
|
|
|
this._syncManager = new SyncManager(ctx);
|
|
|
|
|
|
|
|
|
|
// Load saved sync states for enabled vaults
|
|
|
|
|
const enabledVaults = ctx.getEnabledVaults();
|
|
|
|
|
const vaultMap = {};
|
|
|
|
|
|
|
|
|
|
for (const vaultId of enabledVaults) {
|
|
|
|
|
const vaultPath = ctx.config.getVaultPath(vaultId);
|
|
|
|
|
|
|
|
|
|
if (vaultPath) {
|
|
|
|
|
vaultMap[vaultId] = vaultPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._syncManager.loadStates(vaultMap);
|
|
|
|
|
|
|
|
|
|
// Auto-start syncs that were running before shutdown
|
|
|
|
|
if (this._obStatus.installed && auth.isAuthenticated(ctx.dataDir)) {
|
|
|
|
|
this._syncManager.autoStartAll();
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 16:22:15 +01:00
|
|
|
const { mountRoutes } = require("./routes");
|
|
|
|
|
mountRoutes(ctx.router, this);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async shutdown() {
|
2026-03-28 18:50:32 +01:00
|
|
|
if (this._syncManager) {
|
|
|
|
|
await this._syncManager.shutdown();
|
|
|
|
|
this._syncManager = null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 16:22:15 +01:00
|
|
|
this._ctx = null;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async onVaultEnabled(vaultId, vaultPath) {
|
|
|
|
|
if (this._ctx) {
|
|
|
|
|
this._ctx.log(`Vault enabled: ${vaultId}`);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async onVaultDisabled(vaultId, vaultPath) {
|
2026-03-28 18:50:32 +01:00
|
|
|
if (!this._ctx) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._ctx.log(`Vault disabled: ${vaultId}`);
|
|
|
|
|
|
|
|
|
|
// Stop sync if running, but keep the config
|
|
|
|
|
if (this._syncManager) {
|
|
|
|
|
const state = this._syncManager.getState(vaultId);
|
|
|
|
|
|
|
|
|
|
if (state && state.status === "running") {
|
|
|
|
|
this._syncManager.stopSync(vaultId);
|
|
|
|
|
}
|
2026-03-28 16:22:15 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getObStatus() {
|
|
|
|
|
return this._obStatus;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getCtx() {
|
|
|
|
|
return this._ctx;
|
|
|
|
|
},
|
2026-03-28 18:50:32 +01:00
|
|
|
|
|
|
|
|
getSyncManager() {
|
|
|
|
|
return this._syncManager;
|
|
|
|
|
},
|
2026-03-28 16:22:15 +01:00
|
|
|
};
|