import { dirname, isAbsolute, resolve } from "node:path"; /** Root directory of the framework package. */ export const frameworkRoot = resolve(import.meta.dir, ".."); const INTERNAL_MARKERS = ["/bun:", "node:internal", "node_modules"]; export const frameworkSources = [ "adapters", "contracts", "core", "decorators", "integrations", "orm", "views", ].map((folder) => resolve(frameworkRoot, folder)); /** Extracts the file path of a stack frame. */ function frameFile(frame: string): string | undefined { let text = frame.trim(); text = text.replace(/^at\s+/, ""); const parenthesised = /\((.*)\)$/.exec(text); if (parenthesised) text = parenthesised[1] as string; text = text.replace(/:\d+(?::\d+)?$/, ""); if (text.length === 0) return undefined; if (text.startsWith("file://")) return text.slice(7); if (!text.startsWith("/")) return undefined; return text; } /** Returns the file that called the caller of this function. */ export function callerFile( skipDirs: string[] = frameworkSources, skip = 0, ): string | undefined { const stack = new Error("caller").stack; if (!stack) return undefined; const frames = stack.split("\n").slice(1); let seen = 0; for (const frame of frames) { const file = frameFile(frame); if (!file) continue; if (INTERNAL_MARKERS.some((marker) => file.startsWith(marker))) continue; if (skipDirs.some((dir) => file.startsWith(dir))) continue; if (seen < skip) { seen += 1; continue; } return file; } return undefined; } /** Directory of the file that called the caller of this function. */ export function callerDirectory( skipDirs: string[] = frameworkSources, skip = 0, ): string | undefined { const file = callerFile(skipDirs, skip + 1); return file ? dirname(file) : undefined; } /** Resolves a path relative to the project root. */ export function fromRoot(root: string, path: string): string { return isAbsolute(path) ? path : resolve(root, path); } /** Normalises a path to posix separators, relative to the project root. */ export function relativeTo(root: string, path: string): string { const resolvedRoot = resolve(root); const resolvedPath = resolve(path); if (!resolvedPath.startsWith(resolvedRoot)) return resolvedPath; return resolvedPath.slice(resolvedRoot.length + 1).replace(/\\/g, "/"); } /** Removes the extension of a path. */ export function stripExtension(path: string): string { return path.replace(/\.[^./]+$/, ""); }