45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
|
|
/**
|
||
|
|
* Resolve the repo root for the markdown exporter when called from tRPC
|
||
|
|
* mutations. Sibling of `apps/mcp-server/src/lib/repo-root.ts`; same
|
||
|
|
* contract (env var > pnpm-workspace.yaml walk > cwd), but lives here
|
||
|
|
* because the web app's tsconfig and bundle layout differ enough from
|
||
|
|
* the MCP server's that a single shared helper would need its own
|
||
|
|
* package. Duplication is cheap; the function is twenty lines.
|
||
|
|
*
|
||
|
|
* In production (Coolify) there is no `plans/` directory and no
|
||
|
|
* `pnpm-workspace.yaml` in the bundled image, so the walk returns null
|
||
|
|
* and the exporter is skipped cleanly.
|
||
|
|
*/
|
||
|
|
import { existsSync } from "node:fs";
|
||
|
|
import { dirname, join } from "node:path";
|
||
|
|
import { fileURLToPath } from "node:url";
|
||
|
|
|
||
|
|
const WORKSPACE_MARKER = "pnpm-workspace.yaml";
|
||
|
|
const MAX_WALK = 10;
|
||
|
|
|
||
|
|
function findByMarker(start: string): string | null {
|
||
|
|
let dir = start;
|
||
|
|
for (let i = 0; i < MAX_WALK; i++) {
|
||
|
|
if (existsSync(join(dir, WORKSPACE_MARKER))) return dir;
|
||
|
|
const parent = dirname(dir);
|
||
|
|
if (parent === dir) return null;
|
||
|
|
dir = parent;
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function resolveRepoRoot(): string | null {
|
||
|
|
const env = process.env.MARKDOWN_BACKLOG_REPO_ROOT?.trim();
|
||
|
|
if (env === "" || env === "0" || env?.toLowerCase() === "off") return null;
|
||
|
|
if (env && env.length > 0) return env;
|
||
|
|
|
||
|
|
const fileDir = dirname(fileURLToPath(import.meta.url));
|
||
|
|
const fromFile = findByMarker(fileDir);
|
||
|
|
if (fromFile) return fromFile;
|
||
|
|
|
||
|
|
const fromCwd = findByMarker(process.cwd());
|
||
|
|
if (fromCwd) return fromCwd;
|
||
|
|
|
||
|
|
return null;
|
||
|
|
}
|