83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
import "../core/metadata.ts";
|
|
import { defineMemberMetadata, getAllMemberMetadata } from "../core/metadata.ts";
|
|
import { callerFile } from "../core/paths.ts";
|
|
import { dirname } from "node:path";
|
|
import type { HttpMethod } from "../contracts/typegen/http/method.ts";
|
|
import { normalizeMethod } from "../contracts/typegen/http/method.ts";
|
|
import type { StatusCode } from "../contracts/typegen/http/respcode.ts";
|
|
|
|
export const VIEW_METADATA_KEY = "muddle:view";
|
|
|
|
export interface ViewOptions {
|
|
/** HTTP method of the route, defaults to `GET`. */
|
|
method?: HttpMethod | HttpMethod[];
|
|
/** Route path, derived from the template when omitted. */
|
|
path?: string;
|
|
/** Status code of the response. */
|
|
status?: StatusCode;
|
|
name?: string;
|
|
description?: string;
|
|
params?: Record<string, string>;
|
|
}
|
|
|
|
export interface ViewMetadata {
|
|
/** Name of the method the view belongs to. */
|
|
propertyKey: string;
|
|
/** Path of the template, relative to the view folder. */
|
|
path: string;
|
|
/** Directory of the file that declared the view. */
|
|
dir: string;
|
|
method: HttpMethod;
|
|
status?: StatusCode;
|
|
name?: string;
|
|
description?: string;
|
|
params?: Record<string, string>;
|
|
}
|
|
|
|
/** Declares the template rendered by a controller method. */
|
|
export function View(path?: string, options: ViewOptions = {}): MethodDecorator {
|
|
return (target, propertyKey, descriptor) => {
|
|
const caller = callerFile();
|
|
const method = String(propertyKey);
|
|
const methods = options.method
|
|
? Array.isArray(options.method)
|
|
? options.method
|
|
: [options.method]
|
|
: ["GET" as HttpMethod];
|
|
|
|
for (const httpMethod of methods) {
|
|
defineMemberMetadata(
|
|
VIEW_METADATA_KEY,
|
|
{
|
|
propertyKey: method,
|
|
path: path ?? `./${method}.spug`,
|
|
dir: caller ? dirname(caller) : process.cwd(),
|
|
method: normalizeMethod(httpMethod),
|
|
status: options.status,
|
|
name: options.name,
|
|
description: options.description,
|
|
params: options.params,
|
|
} satisfies ViewMetadata,
|
|
target as object,
|
|
propertyKey as string,
|
|
);
|
|
}
|
|
return descriptor;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Reads the view metadata of a controller class.
|
|
*
|
|
* When a property key is given, only the views of that method are returned.
|
|
*/
|
|
export function getViews(
|
|
target: object,
|
|
propertyKey?: string,
|
|
): ViewMetadata[] {
|
|
return getAllMemberMetadata(VIEW_METADATA_KEY, target)
|
|
.filter(
|
|
(entry) => propertyKey === undefined || entry.propertyKey === propertyKey,
|
|
)
|
|
.map((entry) => entry.value as ViewMetadata);
|
|
}
|