muddle/decorators/Root.ts
2026-10-23 08:53:07 -04:00

75 lines
2.1 KiB
TypeScript

import "../core/metadata.ts";
import { defineMetadata, getMetadata } from "../core/metadata.ts";
import { callerFile } from "../core/paths.ts";
import { existsSync } from "node:fs";
import { dirname, isAbsolute, join, resolve } from "node:path";
export const ROOT_METADATA_KEY = "muddle:root";
export interface RootMetadata {
/** Absolute path of the directory. */
path: string;
}
/** Declares the static root of a controller. */
export function Root(path: string): ClassDecorator {
return (target) => {
const caller = callerFile();
const base = caller ? dirname(caller) : process.cwd();
const absolute = isAbsolute(path) ? path : resolve(base, path);
defineMetadata(
ROOT_METADATA_KEY,
{ path: absolute } satisfies RootMetadata,
target as object,
);
return target;
};
}
/** Reads the static root of a controller. */
export function getRoot(target: object): RootMetadata | undefined {
return getMetadata(ROOT_METADATA_KEY, target) as RootMetadata | undefined;
}
export const VIEW_ROOT_METADATA_KEY = "muddle:view-root";
export interface ViewRootMetadata {
/** Absolute path of the folder. */
path: string;
}
/** Declares the view folder of a controller. */
export function ViewRoot(path: string): ClassDecorator {
return (target) => {
const caller = callerFile();
const base = caller ? dirname(caller) : process.cwd();
const absolute = isAbsolute(path) ? path : resolve(base, path);
defineMetadata(
VIEW_ROOT_METADATA_KEY,
{ path: absolute } satisfies ViewRootMetadata,
target as object,
);
return target;
};
}
/** Reads the view folder of a controller. */
export function getViewRoot(target: object): ViewRootMetadata | undefined {
return getMetadata(VIEW_ROOT_METADATA_KEY, target) as
| ViewRootMetadata
| undefined;
}
/**
* Resolves the folder of the templates of a controller.
*/
export function resolveViewRoot(target: object, fallback: string): string {
const root = getViewRoot(target);
if (root) return root.path;
return fallback;
}
/** `true` when the directory exists. */
export function isDirectory(path: string): boolean {
return existsSync(path) && existsSync(join(path, "."));
}