27 lines
1.1 KiB
TypeScript
27 lines
1.1 KiB
TypeScript
import path from "node:path";
|
|
import { HttpError } from "./errors";
|
|
|
|
/** The portfolio checkout. In Docker it is bind-mounted at /repo; for local
|
|
* `npm run dev` it defaults to the sibling ../portfolio folder. */
|
|
export const REPO_DIR = path.resolve(/*turbopackIgnore: true*/
|
|
process.env.REPO_DIR ?? path.join(/*turbopackIgnore: true*/ process.cwd(), "..", "portfolio")
|
|
);
|
|
|
|
/** Repo-relative paths the manager owns. Publishing commits only these. */
|
|
export const POSTS_REL = "data/blog-posts.json";
|
|
export const IMG_REL = "public/img/blog";
|
|
|
|
export const POSTS_FILE = path.join(REPO_DIR, POSTS_REL);
|
|
export const PUBLIC_DIR = path.join(REPO_DIR, "public");
|
|
export const IMG_ROOT = path.join(REPO_DIR, IMG_REL);
|
|
|
|
/** path.resolve(root, ...segments), refusing anything that escapes root. */
|
|
export function safeJoin(root: string, ...segments: string[]): string {
|
|
const resolved = path.resolve(/*turbopackIgnore: true*/ root, ...segments);
|
|
const rel = path.relative(root, resolved);
|
|
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
throw new HttpError(400, "path escapes its root");
|
|
}
|
|
return resolved;
|
|
}
|