Files
smartserve/ts/decorators/decorators.methods.ts
2025-11-29 15:24:00 +00:00

118 lines
2.8 KiB
TypeScript

/**
* HTTP method decorators (@Get, @Post, @Put, @Delete, @Patch, @All)
*/
import type { THttpMethod, IMethodOptions } from '../core/smartserve.interfaces.js';
import { addRoute, normalizePath } from './decorators.metadata.js';
/**
* Factory for creating HTTP method decorators
*/
function createMethodDecorator(httpMethod: THttpMethod) {
return function (pathOrOptions?: string | IMethodOptions) {
return function <This, Args extends any[], Return>(
target: (this: This, ...args: Args) => Return,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
if (context.kind !== 'method') {
throw new Error(`@${httpMethod} can only decorate methods`);
}
const options: IMethodOptions = typeof pathOrOptions === 'string'
? { path: pathOrOptions }
: pathOrOptions ?? {};
// Use addInitializer to ensure we have access to the class prototype
context.addInitializer(function (this: This) {
addRoute(this, context.name, {
method: httpMethod,
path: normalizePath(options.path ?? ''),
options,
handler: target as unknown as Function,
});
});
return target;
};
};
}
/**
* @Get decorator - handles GET requests
*
* @example
* ```typescript
* @Get('/users')
* listUsers(ctx: IRequestContext) { ... }
*
* @Get('/:id')
* getUser(ctx: IRequestContext) { ... }
* ```
*/
export const Get = createMethodDecorator('GET');
/**
* @Post decorator - handles POST requests
*
* @example
* ```typescript
* @Post('/users')
* createUser(ctx: IRequestContext<ICreateUserBody>) { ... }
* ```
*/
export const Post = createMethodDecorator('POST');
/**
* @Put decorator - handles PUT requests
*
* @example
* ```typescript
* @Put('/users/:id')
* updateUser(ctx: IRequestContext<IUpdateUserBody>) { ... }
* ```
*/
export const Put = createMethodDecorator('PUT');
/**
* @Delete decorator - handles DELETE requests
*
* @example
* ```typescript
* @Delete('/users/:id')
* deleteUser(ctx: IRequestContext) { ... }
* ```
*/
export const Delete = createMethodDecorator('DELETE');
/**
* @Patch decorator - handles PATCH requests
*
* @example
* ```typescript
* @Patch('/users/:id')
* patchUser(ctx: IRequestContext<IPartialUser>) { ... }
* ```
*/
export const Patch = createMethodDecorator('PATCH');
/**
* @Head decorator - handles HEAD requests
*/
export const Head = createMethodDecorator('HEAD');
/**
* @Options decorator - handles OPTIONS requests
*/
export const Options = createMethodDecorator('OPTIONS');
/**
* @All decorator - handles all HTTP methods
*
* @example
* ```typescript
* @All('/proxy/*')
* proxyRequest(ctx: IRequestContext) { ... }
* ```
*/
export const All = createMethodDecorator('ALL');