@equinor/fusion-framework-vite-plugin-api-service
Version:
Vite plugin for proxying service discovery and mocking
104 lines (90 loc) • 3.46 kB
text/typescript
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;