| 12345678910111213141516171819202122232425262728293031323334353637383940 |
- import { existsSync } from "node:fs";
- import { resolve, isAbsolute } from "node:path";
- // IMPORTANT: this module imports `node:fs` / `node:path` and must NEVER be
- // re-exported from the main `@pipeline/shared` barrel (which client bundles
- // import). Reach it only via the `@pipeline/shared/node` subpath.
- // Files that mark the monorepo root. Used so CLI (cwd = repo root) and the web
- // app (cwd = apps/web) — and the Docker container (cwd = /app/apps/web) — all
- // resolve the same unified output directory.
- const ROOT_MARKERS = ["pnpm-workspace.yaml", "turbo.json"];
- /**
- * Walk up from `from` (default: cwd) until a monorepo marker file is found.
- * Falls back to `from` when no marker is discovered (e.g. running outside the repo).
- */
- export function findMonorepoRoot(from: string = process.cwd()): string {
- let dir = resolve(from);
- for (let i = 0; i < 8; i++) {
- if (ROOT_MARKERS.some((m) => existsSync(resolve(dir, m)))) {
- return dir;
- }
- const parent = resolve(dir, "..");
- if (parent === dir) break;
- dir = parent;
- }
- return resolve(from);
- }
- /**
- * Resolve the unified output base directory.
- *
- * Resolution order: `OUTPUT_DIR` env var > `configured` (config/default.yaml
- * `output.dir`) > `./output`. Relative paths are resolved against the monorepo
- * root (not cwd), so CLI / HTTP / web all land in the same physical directory.
- */
- export function resolveOutputDir(configured?: string): string {
- const raw = process.env.OUTPUT_DIR || configured || "./output";
- return isAbsolute(raw) ? raw : resolve(findMonorepoRoot(), raw);
- }
|