UNPKG

@equinor/fusion-framework-vite-plugin-api-service

Version:

Vite plugin for proxying service discovery and mocking

104 lines (90 loc) 3.46 kB
import type { Plugin } from 'vite'; import { type ProcessRouteOptions, processRoutes } from './process-route.js'; import type { ApiProxyHandler, ApiRoute, PluginLogger } from './types.js'; import { DEFAULT_VALUES } from './constants.js'; const pluginName = 'fusion:dev_server::api-proxy'; // Define PluginArguments with stricter type checking export type PluginArguments = { proxyHandler?: ApiProxyHandler; routes?: ApiRoute[]; } & ( | { proxyHandler: ApiProxyHandler; routes?: ApiRoute[] } | { routes: ApiRoute[]; proxyHandler?: ApiProxyHandler } ); /** * Configuration options for the API service plugin. */ export type PluginOptions = { /** * base router path for the plugin middleware * @default '/@api-proxy' */ route?: string; /** * options for processing the routes */ process?: Omit<ProcessRouteOptions, 'logger'>; /** * logger for the plugin */ logger?: PluginLogger; }; /** * Creates a Vite plugin for handling API proxying and custom routes. * * This plugin allows you to define custom API routes or proxy handlers that * can be used during development. It integrates with Vite's server configuration * to set up middleware for handling API requests. * * @param args - The arguments for the plugin. * @param args.routes - An optional array of route definitions to handle API requests. * @param args.proxyHandler - An optional proxy handler for forwarding API requests. * * @param options - The options for the plugin. * @param options.route - The base route for the API proxy. Defaults to `'/@api'`. * @param options.process - An optional function to process requests and responses. * * @returns A Vite plugin object that satisfies the `Plugin` interface. * * @throws {Error} If neither `routes` nor `proxyHandler` is provided in `args`. */ export function plugin(args: PluginArguments, options?: PluginOptions): Plugin { const { routes, proxyHandler } = args; const { logger } = options ?? {}; // Plugin requires either routes or/and proxyHandler if (!args.routes && !args.proxyHandler) { throw new Error('No routes or proxy handler provided'); } const proxyBase = options?.route ?? DEFAULT_VALUES.API_PATH; logger?.debug(`Setting up API proxy at ${proxyBase}`); return { name: 'fusion:api-proxy', config(config, env) { if (proxyHandler) { config.server ??= {}; const proxyOptions = proxyHandler.createProxyOptions(config, env); config.server.proxy = Object.assign({}, config.server.proxy, { [proxyHandler.route]: proxyOptions, }); logger?.debug(`Proxying API requests for ${proxyHandler.route} to ${proxyOptions.target}`); } }, configureServer(server) { // first handle provided routes if (routes) { server.middlewares.use(proxyBase, async (req, res, next) => { processRoutes(routes, [req, res, next], { ...options?.process, logger }); }); logger?.debug(`Added custom routes [${routes.length}] at ${proxyBase}`); } // then handle proxy handler routes if (proxyHandler) { server.middlewares.use(proxyBase, async (req, res, next) => { logger?.debug(`Processing proxy routes [${proxyHandler.routes.length}] at ${proxyBase}`); processRoutes(proxyHandler.routes, [req, res, next], { ...options?.process, logger }); }); } }, } satisfies Plugin; } export default plugin;