import { FlinkApp, FlinkPlugin, FlinkRequest } from "@flink-app/flink"; import log from "node-color-log"; export enum HttpMethod { get = "get", post = "post", put = "put", delete = "delete", patch = "patch", } export type GenericRequestOptions = { /** * Path for request */ path: string; /** * Function to handle the request */ handler: any; /** * Http method for this request */ method: HttpMethod; /** * Optional permission(s) required to access this route. * If set, the auth plugin will validate the request before calling the handler. * Requires an auth plugin (e.g., jwt-auth-plugin) to be configured in FlinkApp. */ permissions?: string | string[]; }; export const genericRequestPlugin = (options: GenericRequestOptions): FlinkPlugin => { return { id: "genericRequestPlugin", init: (app) => init(app, options), }; }; function init(app: FlinkApp, options: GenericRequestOptions) { const { expressApp } = app; if (!expressApp) { throw new Error("Express app not initialized"); } expressApp[options.method](options.path, async (req, res) => { // Validate permissions if set if (options.permissions) { if (!app.auth) { throw new Error(`Route ${options.method.toUpperCase()} ${options.path} requires permissions but no auth plugin is configured`); } // Express Request is structurally compatible with FlinkRequest for auth purposes // (both have headers and user properties). This follows the same pattern as FlinkApp.ts:826 const authenticated = await app.auth.authenticateRequest(req as FlinkRequest, options.permissions); if (!authenticated) { return res.status(401).json({ status: 401, error: { title: "Unauthorized", detail: "Authentication required or insufficient permissions", }, }); } } // Call the handler options.handler(req, res, app); }); log.info(`Registered genericRequest route ${options.method} ${options.path}`); }