@equinor/fusion-framework-cli
Version:
--- title: Fusion Framework CLI ---
139 lines • 6.46 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* 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) {
var _a, _b;
var _c;
(_a = config.server) !== null && _a !== void 0 ? _a : (config.server = {});
(_b = (_c = config.server).proxy) !== null && _b !== void 0 ? _b : (_c.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) {
var _a, _b, _c;
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,
(_a = app.configPath) !== null && _a !== void 0 ? _a : `apps/${app.key}/builds/${app.version}/config`,
].join('/');
server.middlewares.use(configPath, (_req, res) => __awaiter(this, void 0, void 0, function* () {
res.setHeader('content-type', 'application/json');
res.end(JSON.stringify(yield app.generateConfig()));
}));
// serve app manifest if request matches the current app
const manifestPath = [proxyPath, (_b = app.manifestPath) !== null && _b !== void 0 ? _b : `apps/${app.key}`].join('/');
server.middlewares.use((req, res, next) => __awaiter(this, void 0, void 0, function* () {
var _a;
// We only want to match the exact path
const [requestPath] = ((_a = req.url) !== null && _a !== void 0 ? _a : '').split('?');
if (requestPath === manifestPath) {
res.setHeader('content-type', 'application/json');
res.end(JSON.stringify(yield app.generateManifest()));
return;
}
next();
}));
// serve local bundles if request matches the current app and version
const bundlePath = [
proxyPath,
(_c = app.bundlePath) !== null && _c !== void 0 ? _c : `bundles/apps/${app.key}/${app.version}`,
].join('/');
server.middlewares.use((req, _res, next) => __awaiter(this, void 0, void 0, function* () {
var _a;
if ((_a = req.url) === null || _a === void 0 ? void 0 : _a.match(bundlePath)) {
// remove proxy path from url
req.url = req.url.replace(bundlePath, '');
}
next();
}));
},
};
};
export default appProxyPlugin;
//# sourceMappingURL=app-proxy-plugin.js.map