AdditionalRequest
export type AdditionalRequest = Pick<FastifyRequest, 'cookies'> & {
setCookie: (...args: Parameters<FastifyReply['setCookie']>) => void;
token: string;
};
Using AdditionalRequest
, you can extend the FastifyRequest
or Request
types.
This allows you to keep information between multiple Hooks and from Hooks to the Handler.
Frourio automatically extend the arguments of the Handler and Hooks with AdditionalRequest
defined in controller.ts
or hooks.ts
.
- Controller-level: Affects only the current endpoint. Defined in
controller.ts
. - Directory-level: Affects the current endpoint and the endpoints under it. Defined in
hooks.ts
.
The examples on this page are written with Fastify, but the same features are valid with Express.
Pull requests to add examples with Express are welcome!
Bridging Hooks and the Handler
To share values between hooks and controllers, extend and set them with AdditinalRequest
.
Example
import { defineController, defineHooks } from './$relay';
export type AdditionalRequest = {
foo: string;
};
export const hooks = defineHooks(() => ({
preHandler: (req, reply, done) => {
req.foo = 'Stored in hooks!';
done();
},
}));
export default defineController(() => ({
get: (req) => {
return { status: 200, body: req.foo };
},
}));
Relaying type extended by plugins
The first argument of the Handler method does not reflect extensions by plugins such as @fastify/cookie
because it is not a FastifyRequest
but created by Frourio.
If you want to access extended content, you must extend it with AdditinalRequest
and set the value with Hooks.
Example
import { defineController, defineHooks } from './$relay';
import { FastifyReply, FastifyRequest } from 'fastify';
export type AdditionalRequest = Pick<FastifyRequest, 'cookies'> & {
setCookie: (...args: Parameters<FastifyReply['setCookie']>) => void;
};
export const hooks = defineHooks(() => ({
preHandler: (req, reply, done) => {
Object.assign(req, {
setCookie: (...args: Parameters<FastifyReply['setCookie']>) => void reply.setCookie(...args),
});
done();
},
}));
export default defineController(() => ({
post: async ({ body: { token }, setCookie }) => {
const expiresIn = 60 * 60 * 24 * 5 * 1000;
const cookie = await getCookie(token, { expiresIn }); // some function that returns a cookie
setCookie('session', cookie, {
maxAge: expiresIn,
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
path: '/',
});
return { status: 200 };
},
delete: async ({ setCookie, cookies }) => {
const sessionId = cookies.session ?? '';
if (sessionId) await revokeSession(sessionId); // some function that revokes a session
setCookie('session', '', { maxAge: 0, path: '/' });
return { status: 200 };
},
}));