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

125 lines
2.9 KiB
TypeScript

import "../core/metadata.ts";
import { defineMemberMetadata, getMemberMetadata } from "../core/metadata.ts";
export const PARAM_METADATA_KEY = "muddle:params";
export type ParamKind =
| "param"
| "body"
| "query"
| "request"
| "response"
| "locals"
| "form";
export interface ParamMetadata {
index: number;
kind: ParamKind;
/** Name of the route parameter or query key. */
name?: string;
}
/** `@Param('id')`, a route parameter. */
export function Param(name?: string): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "param", name } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/** `@Body()`, the parsed request body. */
export function Body(): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "body" } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/** `@Form()`, the submitted form fields. */
export function Form(): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "form" } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/** `@Query('page')`, a query string entry. */
export function Query(name?: string): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "query", name } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/** `@Req()`, the full request context. */
export function Req(): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "request" } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/** `@Res()`, the response builder. */
export function Res(): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "response" } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/** `@Locals()`, the mutable per request scratch space. */
export function Locals(): ParameterDecorator {
return (target, _propertyKey, index) => {
defineMemberMetadata(
PARAM_METADATA_KEY,
{ index, kind: "locals" } satisfies ParamMetadata,
target as object,
_propertyKey as string,
);
};
}
/**
* Reads the parameter descriptors of a controller method.
*/
export function getParamMetadata(
target: object,
propertyKey?: string,
): Map<number, ParamMetadata> {
const entries = propertyKey
? (getMemberMetadata(
PARAM_METADATA_KEY,
target,
propertyKey,
) as ParamMetadata[])
: [];
const map = new Map<number, ParamMetadata>();
for (const entry of entries) {
map.set(entry.index, entry);
}
return map;
}