From 23306ff68e9d6d8ff5eca42b6c926ecbb978d0bd Mon Sep 17 00:00:00 2001 From: Nystik <236107-Nystik@users.noreply.gitlab.com> Date: Sun, 17 May 2026 22:11:17 +0200 Subject: [PATCH] improve token management for headless sync cli --- server/plugins/headless-sync/auth.js | 26 ++++++++++++-------- server/plugins/headless-sync/index.js | 4 +++ server/plugins/headless-sync/ob-cli.js | 34 ++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/server/plugins/headless-sync/auth.js b/server/plugins/headless-sync/auth.js index 4f56c3e..88e66cc 100644 --- a/server/plugins/headless-sync/auth.js +++ b/server/plugins/headless-sync/auth.js @@ -1,10 +1,10 @@ const fs = require("fs"); const path = require("path"); -const os = require("os"); +const { getObHome } = require("./ob-cli"); -function getObAuthFile() { +function getObAuthFile(dataDir) { return path.join( - os.homedir(), + getObHome(dataDir), ".config", "obsidian-headless", "auth_token", @@ -23,14 +23,14 @@ function loadToken(dataDir) { const data = JSON.parse(fs.readFileSync(internalFile, "utf-8")); if (data && data.token) { - syncToObCli(data.token); + syncToObCli(dataDir, data.token); return data; } } } catch {} // Fall back to ob CLI's own auth file - const obAuthFile = getObAuthFile(); + const obAuthFile = getObAuthFile(dataDir); try { if (fs.existsSync(obAuthFile)) { @@ -49,7 +49,7 @@ function loadToken(dataDir) { function saveToken(dataDir, tokenData) { saveInternal(dataDir, tokenData); - syncToObCli(tokenData.token); + syncToObCli(dataDir, tokenData.token); } function clearToken(dataDir) { @@ -61,7 +61,7 @@ function clearToken(dataDir) { } } catch {} - const obAuthFile = getObAuthFile(); + const obAuthFile = getObAuthFile(dataDir); try { if (fs.existsSync(obAuthFile)) { @@ -94,8 +94,8 @@ function saveInternal(dataDir, tokenData) { fs.writeFileSync(internalFile, JSON.stringify(tokenData, null, 2), "utf-8"); } -function syncToObCli(token) { - const obAuthFile = getObAuthFile(); +function syncToObCli(dataDir, token) { + const obAuthFile = getObAuthFile(dataDir); try { const dir = path.dirname(obAuthFile); @@ -124,4 +124,10 @@ function getTokenInfo(dataDir) { return null; } -module.exports = { loadToken, saveToken, clearToken, isAuthenticated, getTokenInfo }; +module.exports = { + loadToken, + saveToken, + clearToken, + isAuthenticated, + getTokenInfo, +}; diff --git a/server/plugins/headless-sync/index.js b/server/plugins/headless-sync/index.js index 55b45a0..4a4e679 100644 --- a/server/plugins/headless-sync/index.js +++ b/server/plugins/headless-sync/index.js @@ -29,6 +29,10 @@ module.exports = { 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 }); + const token = auth.loadToken(ctx.dataDir); if (token) { diff --git a/server/plugins/headless-sync/ob-cli.js b/server/plugins/headless-sync/ob-cli.js index 5bcd51f..5001905 100644 --- a/server/plugins/headless-sync/ob-cli.js +++ b/server/plugins/headless-sync/ob-cli.js @@ -1,8 +1,28 @@ const { spawn, execSync } = require("child_process"); +const fs = require("fs"); const os = require("os"); +const path = require("path"); const isWindows = process.platform === "win32"; +// When set via configure(), HOME for the spawned ob points under the plugin's data dir so +// ob's config dir (~/.config/obsidian-headless/) survives container recreates. +let configuredDataDir = null; + +function getObHome(dataDir) { + return path.join(dataDir, "ob-home"); +} + +function configure(opts) { + configuredDataDir = opts && opts.dataDir ? opts.dataDir : null; + + if (configuredDataDir) { + try { + fs.mkdirSync(getObHome(configuredDataDir), { recursive: true }); + } catch {} + } +} + function checkInstalled() { try { const output = execSync("ob --version", { @@ -19,8 +39,12 @@ function checkInstalled() { } function spawnOb(args, opts = {}) { + const home = configuredDataDir + ? getObHome(configuredDataDir) + : os.homedir(); + return spawn("ob", args, { - env: { ...process.env, HOME: os.homedir() }, + env: { ...process.env, HOME: home }, shell: isWindows, windowsHide: true, ...opts, @@ -58,4 +82,10 @@ function runCommand(args, opts = {}) { }); } -module.exports = { checkInstalled, spawnOb, runCommand }; +module.exports = { + checkInstalled, + spawnOb, + runCommand, + configure, + getObHome, +};