This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

stigmergic / container / sync.ts
4.5 kB 124 lines
1// ─── Sync: pull vault + carry into container ────────────────────── 2// 3// vault: ob sync (Obsidian CLI) — needs auth token + vault config 4// carry: git pull from GitHub private repo (auth via CARRY_GITHUB_TOKEN) 5 6import { execSync } from "child_process"; 7import { existsSync, writeFileSync, mkdirSync } from "fs"; 8import { join } from "path"; 9 10const VAULT_PATH = process.env.VAULT_PATH || "/data/vault"; 11const CARRY_PATH = process.env.CARRY_PATH || "/data/carry"; 12const CARRY_GITHUB_TOKEN = process.env.CARRY_GITHUB_TOKEN || ""; 13const CARRY_BRANCH = process.env.CARRY_BRANCH || "main"; 14const CARRY_REPO = "codegod100/carry-vault.git"; 15const OBSIDIAN_AUTH_TOKEN = process.env.OBSIDIAN_AUTH_TOKEN || ""; 16const OBSIDIAN_VAULT_ID = process.env.OBSIDIAN_VAULT_ID || "6472c50492efb918c2878e61048218f2"; 17const OBSIDIAN_VAULT_NAME = process.env.OBSIDIAN_VAULT_NAME || "notes"; 18const OBSIDIAN_SYNC_HOST = process.env.OBSIDIAN_SYNC_HOST || "sync-53.obsidian.md"; 19const OBSIDIAN_ENCRYPTION_KEY = process.env.OBSIDIAN_ENCRYPTION_KEY || ""; 20const OBSIDIAN_ENCRYPTION_SALT = process.env.OBSIDIAN_ENCRYPTION_SALT || ""; 21 22function getCarryRemote(): string { 23 if (CARRY_GITHUB_TOKEN) { 24 return `https://${CARRY_GITHUB_TOKEN}@github.com/${CARRY_REPO}`; 25 } 26 return ""; 27} 28 29function setupObsidianAuth(): boolean { 30 if (!OBSIDIAN_AUTH_TOKEN) { 31 console.error("[sync] OBSIDIAN_AUTH_TOKEN not set, skipping vault sync"); 32 return false; 33 } 34 35 try { 36 // Write auth token 37 const configDir = "/root/.config/obsidian-headless"; 38 mkdirSync(configDir, { recursive: true }); 39 writeFileSync(join(configDir, "auth_token"), OBSIDIAN_AUTH_TOKEN, { mode: 0o600 }); 40 41 // Write vault sync config 42 if (OBSIDIAN_ENCRYPTION_KEY && OBSIDIAN_ENCRYPTION_SALT) { 43 const syncDir = join(configDir, "sync", OBSIDIAN_VAULT_ID); 44 mkdirSync(syncDir, { recursive: true }); 45 const vaultConfig = { 46 vaultId: OBSIDIAN_VAULT_ID, 47 vaultName: OBSIDIAN_VAULT_NAME, 48 vaultPath: VAULT_PATH, 49 host: OBSIDIAN_SYNC_HOST, 50 encryptionVersion: 3, 51 encryptionKey: OBSIDIAN_ENCRYPTION_KEY, 52 encryptionSalt: OBSIDIAN_ENCRYPTION_SALT, 53 conflictStrategy: "merge", 54 deviceName: "strata-container", 55 }; 56 writeFileSync(join(syncDir, "config.json"), JSON.stringify(vaultConfig, null, 2), { mode: 0o600 }); 57 } 58 59 console.log("[sync] obsidian auth configured"); 60 return true; 61 } catch (e: any) { 62 console.error("[sync] obsidian auth setup failed:", e.message); 63 return false; 64 } 65} 66 67export async function syncVault(): Promise<void> { 68 if (!setupObsidianAuth()) return; 69 70 try { 71 // First time: setup sync link 72 if (!existsSync(join(VAULT_PATH, ".obsidian"))) { 73 try { 74 execSync(`ob sync-setup --vault ${OBSIDIAN_VAULT_ID} --path ${VAULT_PATH}`, { 75 stdio: "pipe", 76 timeout: 30000, 77 }); 78 } catch (e: any) { 79 // sync-setup may fail if already linked; try sync directly 80 console.error("[sync] sync-setup failed (may already be linked):", e.message?.slice(0, 100)); 81 } 82 } 83 84 execSync(`ob sync --path ${VAULT_PATH}`, { stdio: "pipe", timeout: 120000 }); 85 console.log("[sync] vault synced via ob"); 86 } catch (e: any) { 87 console.error("[sync] vault sync failed:", e.message?.slice(0, 200)); 88 } 89} 90 91export async function syncCarry(): Promise<void> { 92 const remote = getCarryRemote(); 93 if (!remote) { 94 console.error("[sync] CARRY_GITHUB_TOKEN not set, skipping carry sync"); 95 return; 96 } 97 98 try { 99 // If not cloned yet, clone; otherwise pull 100 try { 101 execSync(`git -C ${CARRY_PATH} rev-parse --git-dir`, { stdio: "pipe" }); 102 execSync(`git -C ${CARRY_PATH} pull origin ${CARRY_BRANCH}`, { 103 stdio: "pipe", 104 timeout: 30000, 105 env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, 106 }); 107 console.log("[sync] carry pulled via git"); 108 } catch { 109 // Not a git repo — clone 110 execSync(`git clone --branch ${CARRY_BRANCH} --single-branch ${remote} ${CARRY_PATH}`, { 111 stdio: "pipe", 112 timeout: 60000, 113 env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, 114 }); 115 console.log("[sync] carry cloned via git"); 116 } 117 } catch (e: any) { 118 console.error("[sync] carry sync failed:", e.message?.slice(0, 200)); 119 } 120} 121 122export async function syncAll(): Promise<void> { 123 await Promise.all([syncVault(), syncCarry()]); 124}