UNPKG

@equinor/fusion-framework-cli

Version:

--- title: Fusion Framework CLI ---

125 lines 5.23 kB
/** * Preserve token for executing proxy assets * * @remarks * This assumes the client will execute a api call using bearer token before * acquiring a asset. By default the Framework will execute a rest call to load * application manifest for resolving build assets to import. * * @remarks * This is a quick and dirty method to authorize requests without bearer token * like browser `import`. * The correct way would be to have a auth controller within the dev-server, * but since the token is only exposed to the plugin and the cli is a tool for local * development, this should be sufficient. */ let __APP_API_TOKEN__ = ''; /** * The `appProxyPlugin` function creates a Vite plugin that configures a proxy for API and bundle requests * to the Fusion apps backend. It also serves the app manifest, config, and local bundles if an app is provided. * * @param {AppProxyPluginOptions} options - The options for configuring the app proxy plugin. * * @returns {Plugin} - The configured Vite plugin. * * @example * ```typescript * const plugin = appProxyPlugin({ * proxy: { * path: '/app-proxy', * target: 'https://apps.ci.api.fusion-dev.net', * onProxyReq: (proxyReq, req, res) => { * proxyReq.on('response', (res) => { console.log(res.statusCode) }); * }, * }, * app: { * key: 'my-app', * version: '1.0.0', * generateConfig: async () => ({}), * generateManifest: async () => ({}), * }, * }); * * // api calls * fetch('/app-proxy/apps/my-app/builds/1.0.0/config'); // will generate app config by provided function * fetch('/app-proxy/apps/my-app/builds/0.0.9/config'); // will proxy to the target, since version does not match * fetch('/app-proxy/apps/other-app/builds/1.0.0/config'); // will proxy to the target, since app key does not match * * // asset calls * fetch('/app-proxy/bundles/my-app/builds/1.0.0/index.js'); // will generate bundle by provided function * fetch('/app-proxy/bundles/my-app/builds/0.0.9/index.js'); // will proxy to the target, since version does not match * ``` * */ export const appProxyPlugin = (options) => { const { proxy: { onProxyReq = () => void 0, path: proxyPath, target }, } = options; return { name: 'fusion:app-proxy', apply: 'serve', config(config) { config.server ??= {}; config.server.proxy ??= {}; config.server.proxy[proxyPath] = { target, changeOrigin: true, secure: false, rewrite: (path) => path.replace(proxyPath, ''), configure: (proxy) => { proxy.on('proxyReq', (proxyReq) => { const token = proxyReq.getHeader('authorization'); if (typeof token === 'string') { // preserve token for executing proxy assets __APP_API_TOKEN__ = token; } else if (__APP_API_TOKEN__) { // apply token to proxy request proxyReq.setHeader('authorization', __APP_API_TOKEN__); } }); proxy.on('proxyReq', onProxyReq); }, }; }, configureServer(server) { const { app } = options; // disable local assets if no app configuration provided if (!app) return; // serve app config if request matches the current app and version const configPath = [ proxyPath, app.configPath ?? `apps/${app.key}/builds/${app.version}/config`, ].join('/'); server.middlewares.use(configPath, async (_req, res) => { res.setHeader('content-type', 'application/json'); res.end(JSON.stringify(await app.generateConfig())); }); // serve app manifest if request matches the current app const manifestPath = [proxyPath, app.manifestPath ?? `apps/${app.key}`].join('/'); server.middlewares.use(async (req, res, next) => { // We only want to match the exact path const [requestPath] = (req.url ?? '').split('?'); if (requestPath === manifestPath) { res.setHeader('content-type', 'application/json'); res.end(JSON.stringify(await app.generateManifest())); return; } next(); }); // serve local bundles if request matches the current app and version const bundlePath = [ proxyPath, app.bundlePath ?? `bundles/apps/${app.key}/${app.version}`, ].join('/'); server.middlewares.use(async (req, _res, next) => { if (req.url?.match(bundlePath)) { // remove proxy path from url req.url = req.url.replace(bundlePath, ''); } next(); }); }, }; }; export default appProxyPlugin; //# sourceMappingURL=app-proxy-plugin.js.map