Files
ignis/apps/ignis-server/server/plugins/headless-sync/index.js

112 lines
2.7 KiB
JavaScript
Raw Normal View History

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-30 21:05:47 +02:00
const { SyncBroadcaster } = require("./broadcaster");
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",
2026-03-30 22:23:42 +02:00
version: "0.3.0",
2026-03-29 17:53:07 +02:00
//TODO: add server plugin manifest
2026-03-28 16:22:15 +01:00
2026-05-24 02:37:44 +02:00
obsidianPlugin: path.join(__dirname, "obsidian"),
2026-03-28 16:22:15 +01:00
_ctx: null,
_obStatus: null,
2026-03-28 18:50:32 +01:00
_syncManager: null,
2026-03-30 21:05:47 +02:00
_broadcaster: 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.");
}
// Redirect ob's HOME under the plugin's data dir so its config (per-vault sync setups, etc.)
// survives container recreates. Must happen before auth.loadToken since loadToken pushes the token into ob's config location via syncToObCli.
obCli.configure({ dataDir: ctx.dataDir });
2026-03-28 16:22:15 +01:00
const token = auth.loadToken(ctx.dataDir);
if (token) {
ctx.log("Auth token loaded");
}
2026-03-30 21:05:47 +02:00
this._broadcaster = new SyncBroadcaster(ctx.wss);
this._syncManager = new SyncManager(ctx, this._broadcaster);
2026-03-28 18:50:32 +01:00
// 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
};