All files / src session-token.ts

100% Statements 40/40
100% Branches 30/30
100% Functions 4/4
100% Lines 32/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71                                      9x     828x 828x   826x 3x   823x 2x 2x   821x 821x       347x 347x 692x 692x 689x 689x 345x   344x       347x 347x 346x 345x 345x   344x       428x 426x 426x 426x 50x 50x 50x   3x      
/**
 * Auto-discovery of the lilbee session token.
 *
 * The lilbee server writes a freshly-generated bearer token to
 * `${data_root}/data/server.json` on every start. Rather than asking the user
 * to paste this token, the plugin locates the server's data root using the
 * same resolution order the server itself uses and reads the token directly.
 *
 * Resolution order (matches `_resolve_data_root` in `lilbee/config.py`):
 *   1. `LILBEE_DATA` environment variable
 *   2. walk up from the vault path looking for a `.lilbee/` directory
 *   3. platform-default directory
 *      - macOS:   ~/Library/Application Support/lilbee
 *      - Windows: %LOCALAPPDATA%/lilbee
 *      - Linux:   $XDG_DATA_HOME/lilbee (or ~/.local/share/lilbee)
 */
import { node } from "./binary-manager";
import { PLATFORM } from "./types";
 
const MAX_WALK_UP_DEPTH = 32;
 
export function getDefaultLilbeeDataRoot(): string | null {
    const home = process.env.HOME ?? process.env.USERPROFILE;
    if (!home) return null;
 
    if (process.platform === PLATFORM.DARWIN) {
        return `${home}/Library/Application Support/lilbee`;
    }
    if (process.platform === PLATFORM.WIN32) {
        const local = process.env.LOCALAPPDATA;
        return local ? `${local}/lilbee` : `${home}/AppData/Local/lilbee`;
    }
    const xdg = process.env.XDG_DATA_HOME;
    return xdg ? `${xdg}/lilbee` : `${home}/.local/share/lilbee`;
}
 
export function findLocalLilbeeRoot(startDir: string): string | null {
    let current = startDir;
    for (let i = 0; i < MAX_WALK_UP_DEPTH; i++) {
        const candidate = `${current}/.lilbee`;
        if (node.existsSync(candidate)) return candidate;
        const parent = current.replace(/[/\\][^/\\]+$/, "");
        if (!parent || parent === current) break;
        current = parent;
    }
    return null;
}
 
export function resolveExternalDataRoot(vaultPath: string | null): string | null {
    const envOverride = process.env.LILBEE_DATA;
    if (envOverride) return envOverride;
    if (vaultPath) {
        const local = findLocalLilbeeRoot(vaultPath);
        if (local) return local;
    }
    return getDefaultLilbeeDataRoot();
}
 
export function readSessionToken(dataRoot: string | null): string | null {
    if (!dataRoot) return null;
    const tokenPath = `${dataRoot}/data/server.json`;
    try {
        if (!node.existsSync(tokenPath)) return null;
        const content = node.readFileSync(tokenPath, "utf-8");
        const parsed = JSON.parse(content) as { token?: unknown };
        return typeof parsed.token === "string" ? parsed.token : null;
    } catch {
        return null;
    }
}