From 2b82fa3c4b83bcd97fb1fe1f68e78880c25c006d Mon Sep 17 00:00:00 2001 From: Gianluca Zuccarelli Date: Tue, 17 Dec 2024 11:50:06 +0000 Subject: [PATCH] tsconfig: cockpit plumbing It was necessary to do a bit of plumbing to get typescript, webpack & vitest all happy. To do this we had had to create a separate tsconfig for the on-prem version and the service frontend. We override the module resolution for both config files. For on-prem we check modules in `pkg/lib` and for the service we resolve the modules to stub functions of the `cockpit` & `cockpit/fsinfo` modules. This was so typescript and webpack would not complain. For on-prem we had to intruct webpack to resolve modules from both `node_modules` and `pkg/lib`. While for the service we set the resulotion for the two modules to false, which means they won't get bundled with the service. Lastly, we needed to set some aliases in the vitest config so that vitest could resolve the `cockpit` & `cockpit/fsinfo` modules. Using the cjs `require` keyword to import cockpit would have worked to make typescript and webpack compile since these imports are not statically analysed like the `import` keyword is. However, this approach broke the tests as `require` imports are not supported in vitest. --- cockpit/tsconfig.json | 14 ++++++++++++++ cockpit/webpack.config.ts | 14 +++++++++++--- fec.config.js | 11 ++++++++++- src/store/cockpitApi.ts | 10 ++++++++++ tsconfig.json | 10 +++++++++- vitest.config.ts | 12 ++++++++++++ 6 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 cockpit/tsconfig.json diff --git a/cockpit/tsconfig.json b/cockpit/tsconfig.json new file mode 100644 index 00000000..1465e85e --- /dev/null +++ b/cockpit/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "*": [ + // this allows us to pull in the `cockpit` and + // `cockpit/fsinfo` modules from the `pkg/lib` + // directory + "../pkg/lib/*" + ] + } + } +} diff --git a/cockpit/webpack.config.ts b/cockpit/webpack.config.ts index 50ed2ed5..6f0c6189 100644 --- a/cockpit/webpack.config.ts +++ b/cockpit/webpack.config.ts @@ -27,16 +27,24 @@ module.exports = { mode, devtool, plugins, - externals: { cockpit: 'cockpit' }, resolve: { - modules: ['node_modules'], + modules: [ + 'node_modules', + // this tells webpack to check `node_modules` + // and `pkg/lib` for modules. This allows us + // to import `cockpit` and `cockpit/fsinfo` + path.resolve(__dirname, '../pkg/lib'), + ], extensions: ['.js', '.jsx', '.ts', '.tsx'], }, module: { rules: [ { test: /\.(ts|tsx)$/, - include: [path.resolve('src')], + include: [ + path.resolve(__dirname, '../src'), + path.resolve(__dirname, '../pkg/lib'), + ], use: { loader: 'babel-loader', options: { diff --git a/fec.config.js b/fec.config.js index 04a99221..86ddb935 100644 --- a/fec.config.js +++ b/fec.config.js @@ -2,7 +2,7 @@ const path = require('path'); const CopyPlugin = require('copy-webpack-plugin'); -const { sentryWebpackPlugin } = require("@sentry/webpack-plugin"); +const { sentryWebpackPlugin } = require('@sentry/webpack-plugin'); const webpack = require('webpack'); const plugins = []; @@ -105,6 +105,15 @@ module.exports = { useAgent: true, bounceProd: false, proxyVerbose: true, + resolve: { + alias: { + // we don't wan't these packages bundled with + // the service frontend, so we can set the aliases + // to false + cockpit: false, + 'cockpit/fsinfo': false, + }, + }, routes: { ...(process.env.CONFIG_PORT && { [`${process.env.BETA ? '/beta' : ''}/config`]: { diff --git a/src/store/cockpitApi.ts b/src/store/cockpitApi.ts index 40250541..cc67317f 100644 --- a/src/store/cockpitApi.ts +++ b/src/store/cockpitApi.ts @@ -1,3 +1,13 @@ +// Note: for the on-prem version of the frontend we have configured +// this so that we check `node_modules` and `pkg/lib` for packages. +// To get around this for the hosted service, we have configured +// the `tsconfig` to stubs of the `cockpit` and `cockpit/fsinfo` +// modules. These stubs are in the `src/test/mocks/cockpit` directory. +// We also needed to create an alias in vitest to make this work. +/* eslint-disable @typescript-eslint/no-unused-vars */ +import cockpit from 'cockpit'; +import { fsinfo } from 'cockpit/fsinfo'; + import { emptyCockpitApi } from './emptyCockpitApi'; import { GetArchitecturesApiResponse, diff --git a/tsconfig.json b/tsconfig.json index a6b70cdb..a285dfdf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,14 @@ ], "exactOptionalPropertyTypes": true, "strictNullChecks": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "paths": { + "*": [ + // Needed so we can resolve `cockpit` & `cockpit/fsinfo` + // types. We have stubbed those functions out for the + // as this is the tsconfig file for the service. + "./src/test/mocks/*" + ] + } } } diff --git a/vitest.config.ts b/vitest.config.ts index da35d42f..ea646e57 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,4 +1,5 @@ import react from '@vitejs/plugin-react'; +import path from 'path'; const config = { plugins: [react()], @@ -16,6 +17,7 @@ const config = { }, testTimeout: 10000, fileParallelism: false, + exclude: ['./pkg/lib/**', '**/node_modules/**', '**/dist/**'], }, reporters: ['default', 'junit'], outputFile: { @@ -23,6 +25,16 @@ const config = { }, resolve: { mainFields: ['module'], + alias: { + // we have to point vitest to the mocks for `cockpit` and `cockpit/fsinfo` + // by using aliases. This allows vitest to resolve these two packages + // and allows the tests to pass + cockpit: path.resolve(__dirname, 'src/test/mocks/cockpit'), + 'cockpit/fsinfo': path.resolve( + __dirname, + 'src/test/mocks/cockpit/fsinfo' + ), + }, }, esbuild: { loader: 'tsx',