ApiRouteDefinition
interfaz
Contrato de un endpoint de server/api/<ruta>.<método>.ts: schemas de entrada y respuesta,
autenticación, autorización y handler. Se declara con defineApiRoute.
import type { ApiRouteDefinition } from "@meekojs/meeko/server";Código fuente src/server/api/contracts.ts:96
Declaración #
interface ApiRouteDefinition<P extends Schema | undefined, Q extends Schema | undefined, B extends Schema | undefined, R extends Schema | undefined, S = unknown, L = undefined, T extends ApiSuccessStatus = ApiSuccessStatus> {
params?: P
query?: Q
body?: B
response?: R
status?: T
auth?: 'required' | 'optional'
origin?: 'required' | 'none'
rateLimit?: RateLimitOptions<S>
contentType?: 'json' | 'response'
form?: true | ApiFormOptions<ApiFormResult<R, T>, S>
authorize?: (context: RequestContext<S>) => boolean | Promise<boolean>
locals?: (context: RequestContext<S>) => L | Promise<L>
handler: (args: { params: OptionalOutput<P>; query: OptionalOutput<Q>; body: OptionalOutput<B>; context: RequestContext<S>; locals: L }) => Promise<ApiHandlerResult<R, T>> | ApiHandlerResult<R, T>
}Parámetros de tipo #
-
Pextends Schema | undefined Schema de
params.-
Qextends Schema | undefined Schema de
query.-
Bextends Schema | undefined Schema de
body.-
Rextends Schema | undefined Schema de la respuesta.
-
S= unknown Tipo de los servicios.
-
L= undefined Valor de
localsque recibe el handler;undefinedsinlocals.-
Textends ApiSuccessStatus = ApiSuccessStatus Estado de éxito declarado con
status(desde1.2).
Ejemplo #
import type { ApiRouteDefinition, Schema } from "@meekojs/meeko/server";
type Health = ApiRouteDefinition<undefined, undefined, undefined, Schema<{ ok: boolean }>>;Propiedades #
body
#
body?: BCuerpo JSON (application/json, hasta 1 MiB) y, con form (desde 1.7), el de un formulario nativo.
response
#
response?: RSchema de la respuesta; obligatorio salvo con contentType: "response" o status: 204.
status
#
status?: TEstado HTTP de la respuesta correcta (desde 1.2): 200 por defecto, 201 al crear, 202
al aceptar trabajo diferido o 204 sin cuerpo. Con 200, 201 y 202 la respuesta sigue
siendo JSON validado con response; con 204 el handler no devuelve nada y no se declara
response. No se combina con contentType: "response". Debe ser un literal para que el
generador lo lea.
origin
#
origin?: 'required' | 'none'Comprobación de Origin en las peticiones POST, PUT, PATCH y DELETE. Desde 1.8, por
defecto (sin origin) responden 403 INVALID_ORIGIN si su Origin falta, es null o no es
el de la aplicación ni uno de SessionManager.allowedOrigins, haya o no sesión. "required"
(desde 1.2) equivale al valor por defecto y lo deja explícito.
"none" (desde 1.2, inseguro) desactiva la comprobación en las peticiones sin sesión,
también en un formulario nativo (form), para webhooks (incluidos los que envían
application/x-www-form-urlencoded), APIs públicas y clientes que no envían Origin, y
permite que session.create() cree una sesión sin un Origin permitido. Expone la ruta al
CSRF y al login CSRF: úsela sólo con otra prueba de que la petición no viene de otra web,
como una firma o un token. Una petición con sesión sigue exigiendo Origin y el token CSRF.
rateLimit
#
rateLimit?: RateLimitOptions<S>Límite de peticiones (desde 1.2), como { limit: 5, window: "5m" }: por encima responde
429 RATE_LIMITED con Retry-After, tras Origin y CSRF y antes de auth, authorize, la
entrada y el handler. Cuenta en el store de sesiones (Redis entre instancias) y, si el store
falla, la petición se rechaza.
contentType
#
contentType?: 'json' | 'response'"response" deja que el handler devuelva su propio Response.
form
#
form?: true | ApiFormOptions<ApiFormResult<R, T>, S>Acepta también formularios HTML nativos (desde 1.7): application/x-www-form-urlencoded y
multipart/form-data, validados con el mismo schema de body. Un envío correcto responde
303 See Other a redirect, al campo return o a la página de Referer; un error vuelve a
esa página con 303 y su estado, que useForm({ action }) pinta en el SSR. Exige siempre un
Origin permitido. Sin form, esos tipos responden 415 UNSUPPORTED_MEDIA_TYPE.
authorize
#
authorize?: (context: RequestContext<S>) => boolean | Promise<boolean>Devolver false responde 403 FORBIDDEN.
locals
#
locals?: (context: RequestContext<S>) => L | Promise<L>Calcula un valor por petición que el handler recibe como locals (desde 1.2), como el
usuario actual. Se ejecuta tras Origin, CSRF, auth, authorize y la validación de la
entrada, y justo antes del handler; un ApiError que lance (por ejemplo 401 o 403) es la
respuesta. Declárelo antes de handler para que TypeScript infiera su tipo.
handler
#
handler: (args: { params: OptionalOutput<P>; query: OptionalOutput<Q>; body: OptionalOutput<B>; context: RequestContext<S>; locals: L }) => Promise<ApiHandlerResult<R, T>> | ApiHandlerResult<R, T>Recibe la entrada validada, el contexto y locals; su resultado se valida con response. Con
status: 204 no devuelve nada.