@rancher/shell 3.0.0-rc.1 → 3.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/styles/base/_variables.scss +1 -0
- package/assets/styles/global/_layout.scss +3 -3
- package/assets/styles/global/_select.scss +1 -1
- package/assets/styles/global/_tooltip.scss +37 -71
- package/components/ActionDropdown.vue +9 -13
- package/components/ActionMenu.vue +1 -1
- package/components/ButtonDropdown.vue +9 -8
- package/components/CruResource.vue +4 -2
- package/components/InputOrDisplay.vue +21 -33
- package/components/LocaleSelector.vue +1 -1
- package/components/Questions/__tests__/Boolean.test.ts +1 -2
- package/components/Questions/__tests__/Float.test.ts +1 -2
- package/components/Questions/__tests__/Int.test.ts +1 -2
- package/components/Questions/__tests__/String.test.ts +1 -2
- package/components/Questions/__tests__/Yaml.test.ts +1 -1
- package/components/Questions/__tests__/utils/questions-defaults.ts +2 -2
- package/components/SideNav.vue +3 -3
- package/components/__tests__/CodeMirror.test.ts +91 -94
- package/components/__tests__/ConsumptionGauge.test.ts +2 -2
- package/components/__tests__/NamespaceFilter.test.ts +10 -7
- package/components/auth/AllowedPrincipals.vue +2 -2
- package/components/auth/RoleDetailEdit.vue +13 -17
- package/components/auth/SelectPrincipal.vue +1 -1
- package/components/fleet/FleetStatus.vue +13 -14
- package/components/form/ArrayList.vue +1 -1
- package/components/form/ArrayListGrouped.vue +18 -5
- package/components/form/LabeledSelect.vue +16 -11
- package/components/form/Select.vue +17 -1
- package/components/form/__tests__/Command.test.ts +6 -5
- package/components/form/__tests__/Taints.test.ts +9 -9
- package/components/formatter/AppSummaryGraph.vue +1 -1
- package/components/formatter/FleetSummaryGraph.vue +1 -1
- package/components/formatter/MachineSummaryGraph.vue +1 -1
- package/components/formatter/Scale.vue +1 -1
- package/components/formatter/Weight.vue +1 -1
- package/components/nav/Header.vue +31 -14
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/TopLevelMenu.vue +7 -6
- package/components/nav/WindowManager/ContainerLogs.vue +1 -1
- package/components/nav/WindowManager/ContainerShell.vue +7 -2
- package/components/nav/WindowManager/__tests__/ContainerLogs.test.ts +195 -192
- package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +23 -19
- package/core/plugin-routes.ts +42 -29
- package/core/plugins-loader.js +2 -0
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +16 -8
- package/detail/helm.cattle.io.projecthelmchart.vue +26 -27
- package/edit/__tests__/namespace.test.ts +7 -9
- package/edit/__tests__/service.test.ts +14 -2
- package/edit/auth/__tests__/azuread.test.ts +10 -11
- package/edit/auth/azuread.vue +1 -1
- package/edit/fleet.cattle.io.clustergroup.vue +3 -3
- package/edit/management.cattle.io.fleetworkspace.vue +3 -3
- package/edit/management.cattle.io.node.vue +3 -2
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +3 -2
- package/edit/namespace.vue +3 -1
- package/edit/networking.k8s.io.ingress/index.vue +3 -2
- package/edit/networking.k8s.io.networkpolicy/index.vue +2 -2
- package/edit/node.vue +3 -3
- package/edit/persistentvolume/__tests__/persistentvolume.test.ts +9 -4
- package/edit/persistentvolume/index.vue +3 -3
- package/edit/persistentvolumeclaim.vue +3 -3
- package/edit/policy.poddisruptionbudget.vue +3 -3
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +5 -6
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +13 -6
- package/edit/provisioning.cattle.io.cluster/rke2.vue +7 -1
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +6 -7
- package/edit/service.vue +2 -2
- package/edit/serviceaccount.vue +3 -3
- package/edit/storage.k8s.io.storageclass/index.vue +3 -3
- package/edit/workload/Job.vue +2 -2
- package/edit/workload/__tests__/Job.test.ts +5 -5
- package/edit/workload/index.vue +2 -2
- package/edit/workload/storage/Mount.vue +7 -4
- package/edit/workload/storage/__tests__/Mount.test.ts +6 -2
- package/edit/workload/storage/index.vue +10 -23
- package/initialize/entry-helpers.js +0 -5
- package/mixins/page-actions.js +1 -1
- package/package.json +1 -1
- package/pages/c/_cluster/istio/index.vue +2 -2
- package/pages/c/_cluster/longhorn/__tests__/longhorn.index.test.ts +3 -2
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +7 -29
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
- package/vue.config.js +409 -391
- package/plugins/clean-html-directive.js +0 -10
- package/plugins/clean-tooltip-directive.js +0 -9
- package/plugins/int-number.js +0 -9
- package/plugins/positive-int-number.js +0 -9
- package/plugins/trim-whitespace.js +0 -10
package/vue.config.js
CHANGED
|
@@ -4,9 +4,12 @@ const webpack = require('webpack');
|
|
|
4
4
|
const { generateDynamicTypeImport } = require('./pkg/auto-import');
|
|
5
5
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
|
6
6
|
const serverMiddlewares = require('./server/server-middleware.js');
|
|
7
|
-
const
|
|
7
|
+
const {
|
|
8
|
+
dev, devPorts, api, proxyWsOpts, proxyOpts, proxyMetaOpts, proxyPrimeOpts
|
|
9
|
+
} = require('./vue-config-helper.js');
|
|
8
10
|
const har = require('./server/har-file');
|
|
9
11
|
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
|
|
12
|
+
const VirtualModulesPlugin = require('webpack-virtual-modules');
|
|
10
13
|
|
|
11
14
|
// Suppress info level logging messages from http-proxy-middleware
|
|
12
15
|
// This hides all of the "[HPM Proxy created] ..." messages
|
|
@@ -16,33 +19,24 @@ console.info = () => {}; // eslint-disable-line no-console
|
|
|
16
19
|
|
|
17
20
|
const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
18
21
|
|
|
22
|
+
// TODO: Add explanation of this logic
|
|
19
23
|
console.info = oldInfoLogger; // eslint-disable-line no-console
|
|
20
24
|
|
|
21
25
|
// This is currently hardcoded to avoid importing the TS
|
|
22
26
|
// const { STANDARD } = require('./config/private-label');
|
|
23
27
|
const STANDARD = 1;
|
|
24
28
|
|
|
25
|
-
const dev = configHelper.dev;
|
|
26
|
-
const devPorts = configHelper.devPorts;
|
|
27
|
-
|
|
28
29
|
// human readable version used on rancher dashboard about page
|
|
29
30
|
const dashboardVersion = process.env.DASHBOARD_VERSION;
|
|
30
31
|
|
|
31
32
|
const pl = process.env.PL || STANDARD;
|
|
32
33
|
const commit = process.env.COMMIT || 'head';
|
|
33
34
|
const perfTest = (process.env.PERF_TEST === 'true'); // Enable performance testing when in dev
|
|
34
|
-
const instrumentCode = (process.env.TEST_INSTRUMENT === 'true'); // Instrument code for code coverage in e2e tests
|
|
35
|
-
|
|
36
|
-
const api = configHelper.api;
|
|
37
|
-
// ===============================================================================================
|
|
38
|
-
// Nuxt configuration
|
|
39
|
-
// ===============================================================================================
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Paths to the shell folder when it is included as a node dependency
|
|
36
|
+
/**
|
|
37
|
+
* Paths to the shell folder when it is included as a node dependency
|
|
38
|
+
*/
|
|
39
|
+
const getShellPaths = (dir) => {
|
|
46
40
|
let SHELL_ABS = path.join(dir, 'node_modules/@rancher/shell');
|
|
47
41
|
let COMPONENTS_DIR = path.join(SHELL_ABS, 'rancher-components');
|
|
48
42
|
|
|
@@ -59,274 +53,455 @@ module.exports = function(dir, _appConfig) {
|
|
|
59
53
|
|
|
60
54
|
// If we have a local folder named 'shell' then use that rather than the one in node_modules
|
|
61
55
|
// This will be the case in the main dashboard repository.
|
|
62
|
-
if (fs.existsSync(path.
|
|
63
|
-
SHELL_ABS = path.
|
|
56
|
+
if (fs.existsSync(path.join(dir, 'shell'))) {
|
|
57
|
+
SHELL_ABS = path.join(dir, 'shell');
|
|
64
58
|
COMPONENTS_DIR = path.join(dir, 'pkg', 'rancher-components', 'src', 'components');
|
|
65
59
|
}
|
|
66
60
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// ===============================================================================================
|
|
61
|
+
return { SHELL_ABS, COMPONENTS_DIR };
|
|
62
|
+
};
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
const getProxyConfig = (proxyConfig) => ({
|
|
65
|
+
...proxyConfig,
|
|
66
|
+
'/k8s': proxyWsOpts(api), // Straight to a remote cluster (/k8s/clusters/<id>/)
|
|
67
|
+
'/pp': proxyWsOpts(api), // For (epinio) standalone API
|
|
68
|
+
'/api': proxyWsOpts(api), // Management k8s API
|
|
69
|
+
'/apis': proxyWsOpts(api), // Management k8s API
|
|
70
|
+
'/v1': proxyWsOpts(api), // Management Steve API
|
|
71
|
+
'/v3': proxyWsOpts(api), // Rancher API
|
|
72
|
+
'/v3-public': proxyOpts(api), // Rancher Unauthed API
|
|
73
|
+
'/api-ui': proxyOpts(api), // Browser API UI
|
|
74
|
+
'/meta': proxyMetaOpts(api), // Browser API UI
|
|
75
|
+
'/v1-*': proxyOpts(api), // SAML, KDM, etc
|
|
76
|
+
'/rancherversion': proxyPrimeOpts(api), // Rancher version endpoint
|
|
77
|
+
// These are for Ember embedding
|
|
78
|
+
'/c/*/edit': proxyOpts('https://127.0.0.1:8000'), // Can't proxy all of /c because that's used by Vue too
|
|
79
|
+
'/k/': proxyOpts('https://127.0.0.1:8000'),
|
|
80
|
+
'/g/': proxyOpts('https://127.0.0.1:8000'),
|
|
81
|
+
'/n/': proxyOpts('https://127.0.0.1:8000'),
|
|
82
|
+
'/p/': proxyOpts('https://127.0.0.1:8000'),
|
|
83
|
+
'/assets': proxyOpts('https://127.0.0.1:8000'),
|
|
84
|
+
'/translations': proxyOpts('https://127.0.0.1:8000'),
|
|
85
|
+
'/engines-dist': proxyOpts('https://127.0.0.1:8000'),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @pkg imports must be resolved to the package that it importing them - this allows a package to use @pkg as an alias
|
|
90
|
+
* to the root of that particular package
|
|
91
|
+
*/
|
|
92
|
+
const getPackageImport = (dir) => new webpack.NormalModuleReplacementPlugin(/^@pkg/, (resource) => {
|
|
93
|
+
const ctx = resource.context.split('/');
|
|
94
|
+
// Find 'pkg' folder in the context
|
|
95
|
+
const index = ctx.findIndex((s) => s === 'pkg');
|
|
96
|
+
|
|
97
|
+
if (index !== -1 && (index + 1) < ctx.length) {
|
|
98
|
+
const pkg = ctx[index + 1];
|
|
99
|
+
let p = path.resolve(dir, 'pkg', pkg, resource.request.substr(5));
|
|
100
|
+
|
|
101
|
+
if (resource.request.startsWith(`@pkg/${ pkg }`)) {
|
|
102
|
+
p = path.resolve(dir, 'pkg', resource.request.substr(5));
|
|
103
|
+
}
|
|
73
104
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
105
|
+
resource.request = p;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Instrument code for code coverage in e2e tests
|
|
111
|
+
*/
|
|
112
|
+
const instrumentCode = () => {
|
|
113
|
+
const instrumentedCode = (process.env.TEST_INSTRUMENT === 'true');
|
|
114
|
+
|
|
115
|
+
// Instrument code for tests
|
|
116
|
+
const babelPlugins = [
|
|
117
|
+
// TODO: Browser support; also add explanation to this TODO
|
|
118
|
+
// ['@babel/plugin-transform-modules-commonjs'],
|
|
119
|
+
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
|
120
|
+
['@babel/plugin-proposal-class-properties', { loose: true }]
|
|
78
121
|
];
|
|
79
122
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
123
|
+
if (instrumentedCode) {
|
|
124
|
+
babelPlugins.push([
|
|
125
|
+
'babel-plugin-istanbul', { extension: ['.js', '.vue'] }, 'add-vue'
|
|
126
|
+
]);
|
|
84
127
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
128
|
+
console.warn('Instrumenting code for coverage'); // eslint-disable-line no-console
|
|
129
|
+
}
|
|
130
|
+
};
|
|
88
131
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
132
|
+
const getLoaders = (SHELL_ABS) => [
|
|
133
|
+
// Ensure there is a fallback for browsers that don't support web workers
|
|
134
|
+
{
|
|
135
|
+
test: /web-worker.[a-z-]+.js/i,
|
|
136
|
+
loader: 'worker-loader',
|
|
137
|
+
options: { inline: 'fallback' },
|
|
138
|
+
},
|
|
139
|
+
// Handler for csv files (e.g. ec2 instance data)
|
|
140
|
+
{
|
|
141
|
+
test: /\.csv$/i,
|
|
142
|
+
loader: 'csv-loader',
|
|
143
|
+
options: {
|
|
144
|
+
dynamicTyping: true,
|
|
145
|
+
header: true,
|
|
146
|
+
skipEmptyLines: true
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
// Handler for yaml files (used for i18n files, for example)
|
|
150
|
+
{
|
|
151
|
+
test: /\.ya?ml$/i,
|
|
152
|
+
loader: 'js-yaml-loader',
|
|
153
|
+
options: { name: '[path][name].[ext]' },
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
test: /\.m?[tj]sx?$/,
|
|
157
|
+
// This excludes no modules except for node_modules/@rancher/... so that plugins can properly compile
|
|
158
|
+
// when referencing @rancher/shell
|
|
159
|
+
exclude: /node_modules\/(?!(@rancher)\/).*/,
|
|
160
|
+
use: [
|
|
161
|
+
{
|
|
162
|
+
loader: 'cache-loader',
|
|
163
|
+
options: {
|
|
164
|
+
cacheDirectory: 'node_modules/.cache/babel-loader',
|
|
165
|
+
cacheIdentifier: 'e93f32da'
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
test: /\.tsx?$/,
|
|
172
|
+
use: [
|
|
173
|
+
{
|
|
174
|
+
loader: 'cache-loader',
|
|
175
|
+
options: {
|
|
176
|
+
cacheDirectory: 'node_modules/.cache/ts-loader',
|
|
177
|
+
cacheIdentifier: '3596741e'
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
loader: 'ts-loader',
|
|
182
|
+
options: {
|
|
183
|
+
transpileOnly: true,
|
|
184
|
+
happyPackMode: false,
|
|
185
|
+
appendTsxSuffixTo: [
|
|
186
|
+
'\\.vue$'
|
|
187
|
+
],
|
|
188
|
+
configFile: path.join(SHELL_ABS, 'tsconfig.json')
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
// Prevent warning in log with the md files in the content folder
|
|
194
|
+
{
|
|
195
|
+
test: /\.md$/,
|
|
196
|
+
use: [
|
|
197
|
+
{
|
|
198
|
+
loader: 'frontmatter-markdown-loader',
|
|
199
|
+
options: { mode: ['body'] }
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
];
|
|
92
204
|
|
|
93
|
-
|
|
205
|
+
const getDevServerConfig = (proxy) => {
|
|
206
|
+
const harFile = process.env.HAR_FILE;
|
|
207
|
+
// HAR File support - load network responses from the specified .har file and use those rather than communicating to the Rancher server
|
|
208
|
+
const harData = harFile ? har.loadFile(harFile, devPorts ? 8005 : 80, '') : undefined;
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
client: { webSocketURL: { hostname: '0.0.0.0', port: devPorts ? 8005 : 80 } },
|
|
212
|
+
server: {
|
|
213
|
+
type: 'https',
|
|
214
|
+
options: {
|
|
215
|
+
key: fs.readFileSync(path.resolve(__dirname, 'server/server.key')),
|
|
216
|
+
cert: fs.readFileSync(path.resolve(__dirname, 'server/server.crt'))
|
|
94
217
|
}
|
|
95
|
-
}
|
|
96
|
-
|
|
218
|
+
},
|
|
219
|
+
port: (devPorts ? 8005 : 80),
|
|
220
|
+
host: '0.0.0.0',
|
|
221
|
+
setupMiddlewares(middlewares, devServer) {
|
|
222
|
+
const socketProxies = {};
|
|
97
223
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
224
|
+
if (!devServer) {
|
|
225
|
+
// eslint-disable-next-line no-console
|
|
226
|
+
console.error('webpack-dev-server is not defined');
|
|
102
227
|
|
|
103
|
-
|
|
104
|
-
|
|
228
|
+
return middlewares;
|
|
229
|
+
}
|
|
105
230
|
|
|
106
|
-
|
|
107
|
-
// Add in the code to automatically import the types from that package
|
|
108
|
-
// This imports models, edit, detail, list etc
|
|
109
|
-
// When built as a UI package, shell/pkg/vue.config.js does the same thing
|
|
110
|
-
const autoImportTypes = {};
|
|
111
|
-
const VirtualModulesPlugin = require('webpack-virtual-modules');
|
|
112
|
-
let reqs = '';
|
|
113
|
-
const pkgFolder = path.relative(dir, './pkg');
|
|
231
|
+
const app = devServer.app;
|
|
114
232
|
|
|
115
|
-
|
|
116
|
-
|
|
233
|
+
// Close down quickly in response to CTRL + C
|
|
234
|
+
process.once('SIGINT', () => {
|
|
235
|
+
devServer.close();
|
|
236
|
+
console.log('\n'); // eslint-disable-line no-console
|
|
237
|
+
process.exit(1);
|
|
238
|
+
});
|
|
117
239
|
|
|
118
|
-
|
|
119
|
-
items.filter((name) => !name.startsWith('.')).forEach((name) => {
|
|
120
|
-
const f = require(path.join(dir, 'pkg', name, 'package.json'));
|
|
240
|
+
app.use(serverMiddlewares);
|
|
121
241
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
242
|
+
if (harData) {
|
|
243
|
+
console.log('Installing HAR file middleware'); // eslint-disable-line no-console
|
|
244
|
+
app.use(har.harProxy(harData, process.env.HAR_DIR));
|
|
126
245
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
246
|
+
devServer.webSocketProxies.push({
|
|
247
|
+
upgrade(req, socket, head) {
|
|
248
|
+
const responseHeaders = ['HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade'];
|
|
130
249
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
250
|
+
socket.write(`${ responseHeaders.join('\r\n') }\r\n\r\n`);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
134
254
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const pkg = ctx[ctx.length - 1];
|
|
255
|
+
Object.keys(proxy).forEach((p) => {
|
|
256
|
+
const px = createProxyMiddleware({
|
|
257
|
+
...proxy[p],
|
|
258
|
+
ws: false // We will handle the web socket upgrade
|
|
259
|
+
});
|
|
141
260
|
|
|
142
|
-
|
|
143
|
-
|
|
261
|
+
if (proxy[p].ws) {
|
|
262
|
+
socketProxies[p] = px;
|
|
263
|
+
}
|
|
264
|
+
app.use(p, px);
|
|
265
|
+
});
|
|
144
266
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// Find 'pkg' folder in the contxt
|
|
150
|
-
const index = ctx.findIndex((s) => s === 'pkg');
|
|
267
|
+
// TODO: Verify after migration completed
|
|
268
|
+
devServer.webSocketProxies.push({
|
|
269
|
+
upgrade(req, socket, head) {
|
|
270
|
+
const path = Object.keys(socketProxies).find((path) => req.url.startsWith(path));
|
|
151
271
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let p = path.resolve(dir, 'pkg', pkg, resource.request.substr(5));
|
|
272
|
+
if (path) {
|
|
273
|
+
const proxy = socketProxies[path];
|
|
155
274
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
275
|
+
if (proxy.upgrade) {
|
|
276
|
+
proxy.upgrade(req, socket, head);
|
|
277
|
+
} else {
|
|
278
|
+
console.log(`Upgrade for Proxy is not defined. Cannot upgrade Web socket for ${ req.url }`); // eslint-disable-line no-console
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
console.log(`Unknown Web socket upgrade request for ${ req.url }`); // eslint-disable-line no-console
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
});
|
|
159
285
|
|
|
160
|
-
|
|
286
|
+
return middlewares;
|
|
161
287
|
}
|
|
162
|
-
}
|
|
288
|
+
};
|
|
289
|
+
};
|
|
163
290
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
291
|
+
/**
|
|
292
|
+
* Generate a virtual module '@rancher/dynamic.js` which imports all of the packages that should be built into the application
|
|
293
|
+
* This is imported in 'shell/extensions/extension-loader.js` which ensures the all code for plugins to be included is imported in the application
|
|
294
|
+
*/
|
|
295
|
+
const getVirtualModules = (dir, includePkg) => {
|
|
296
|
+
// Find any UI packages in node_modules
|
|
297
|
+
const modulePaths = path.join(dir, 'node_modules');
|
|
298
|
+
const requiredPackages = require(path.join(dir, 'package.json'));
|
|
299
|
+
const librariesIndex = {};
|
|
167
300
|
|
|
168
|
-
|
|
169
|
-
|
|
301
|
+
if (requiredPackages && requiredPackages.dependencies) {
|
|
302
|
+
Object.keys(requiredPackages.dependencies).forEach((requiredPackage) => {
|
|
303
|
+
const library = require(path.join(modulePaths, requiredPackage, 'package.json'));
|
|
170
304
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
305
|
+
// The package.json must have the 'rancher' property to mark it as a UI package
|
|
306
|
+
if (library.rancher) {
|
|
307
|
+
const id = `${ library.name }-${ library.version }`;
|
|
174
308
|
|
|
175
|
-
|
|
176
|
-
|
|
309
|
+
librariesIndex[id] = library.main;
|
|
310
|
+
}
|
|
311
|
+
});
|
|
177
312
|
}
|
|
178
313
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
314
|
+
let reqs = '';
|
|
315
|
+
const pkgFolder = path.relative(dir, './pkg');
|
|
182
316
|
|
|
183
|
-
if (
|
|
184
|
-
|
|
317
|
+
if (fs.existsSync(pkgFolder)) {
|
|
318
|
+
fs.readdirSync(pkgFolder)
|
|
319
|
+
.filter((name) => !name.startsWith('.')) // Ignore hidden folders
|
|
320
|
+
.forEach((name) => {
|
|
321
|
+
const library = require(path.join(dir, 'pkg', name, 'package.json'));
|
|
322
|
+
|
|
323
|
+
// Package file must have rancher field to be a plugin
|
|
324
|
+
if (includePkg(name) && library.rancher) {
|
|
325
|
+
reqs += `$plugin.initPlugin('${ name }', require(\'~/pkg/${ name }\')); `;
|
|
326
|
+
}
|
|
327
|
+
});
|
|
185
328
|
}
|
|
186
329
|
|
|
187
|
-
|
|
188
|
-
|
|
330
|
+
Object.keys(librariesIndex).forEach((i) => {
|
|
331
|
+
reqs += `$plugin.loadAsync('${ i }', '/pkg/${ i }/${ librariesIndex[i] }');`;
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
return new VirtualModulesPlugin({ 'node_modules/@rancher/dynamic.js': `export default function ($plugin) { ${ reqs } };` });
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const getAutoImport = () => new webpack.NormalModuleReplacementPlugin(/^@rancher\/auto-import$/, (resource) => {
|
|
338
|
+
const ctx = resource.context.split('/');
|
|
339
|
+
const pkg = ctx[ctx.length - 1];
|
|
340
|
+
|
|
341
|
+
resource.request = `@rancher/auto-import/${ pkg }`;
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* For each package in the pkg folder that is being compiled into the application,
|
|
346
|
+
* Add in the code to automatically import the types from that package
|
|
347
|
+
* This imports models, edit, detail, list etc
|
|
348
|
+
* When built as a UI package, shell/pkg/vue.config.js does the same thing
|
|
349
|
+
*/
|
|
350
|
+
const getVirtualModulesAutoImport = (dir) => {
|
|
351
|
+
const autoImportTypes = {};
|
|
352
|
+
const pkgFolder = path.relative(dir, './pkg');
|
|
353
|
+
|
|
354
|
+
if (fs.existsSync(pkgFolder)) {
|
|
355
|
+
fs.readdirSync(pkgFolder)
|
|
356
|
+
.filter((name) => !name.startsWith('.')) // Ignore hidden folders
|
|
357
|
+
.forEach((name) => {
|
|
358
|
+
autoImportTypes[`node_modules/@rancher/auto-import/${ name }`] = generateDynamicTypeImport(`@pkg/${ name }`, path.join(dir, `pkg/${ name }`));
|
|
359
|
+
});
|
|
189
360
|
}
|
|
190
361
|
|
|
362
|
+
return new VirtualModulesPlugin(autoImportTypes);
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* DefinePlugin does string replacement within our code. We may want to consider replacing it with something else. In code we'll see something like
|
|
367
|
+
* process.env.commit even though process and env aren't even defined objects. This could cause people to be mislead.
|
|
368
|
+
*/
|
|
369
|
+
const createEnvVariablesPlugin = (routerBasePath, rancherEnv) => new webpack.DefinePlugin({
|
|
370
|
+
'process.env.commit': JSON.stringify(commit),
|
|
371
|
+
'process.env.version': JSON.stringify(dashboardVersion),
|
|
372
|
+
'process.env.dev': JSON.stringify(dev),
|
|
373
|
+
'process.env.pl': JSON.stringify(pl),
|
|
374
|
+
'process.env.perfTest': JSON.stringify(perfTest),
|
|
375
|
+
'process.env.loginLocaleSelector': JSON.stringify(process.env.LOGIN_LOCALE_SELECTOR || 'true'),
|
|
376
|
+
'process.env.excludeOperatorPkg': JSON.stringify(process.env.EXCLUDE_OPERATOR_PKG || 'false'),
|
|
377
|
+
'process.env.rancherEnv': JSON.stringify(rancherEnv),
|
|
378
|
+
'process.env.harvesterPkgUrl': JSON.stringify(process.env.HARVESTER_PKG_URL),
|
|
379
|
+
'process.env.api': JSON.stringify(api),
|
|
380
|
+
// Store the Router Base as env variable that we can use in `shell/config/router.js`
|
|
381
|
+
'process.env.routerBase': JSON.stringify(routerBasePath),
|
|
382
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Ensure we process files in the @rancher/shell folder
|
|
387
|
+
*/
|
|
388
|
+
const processShellFiles = (config, SHELL_ABS) => {
|
|
389
|
+
config.module.rules.forEach((rule) => {
|
|
390
|
+
if ('test.js'.match(rule.test)) {
|
|
391
|
+
if (rule.exclude) {
|
|
392
|
+
const orig = rule.exclude;
|
|
393
|
+
|
|
394
|
+
rule.exclude = function(modulePath) {
|
|
395
|
+
if (modulePath.indexOf(SHELL_ABS) === 0 || typeof orig !== 'function') {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return orig(modulePath);
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Update vue-loader to set whitespace to 'preserve'
|
|
408
|
+
* This was the setting with nuxt, but is not the default with vue cli
|
|
409
|
+
* Need to find the vue loader in the webpack config and update the setting
|
|
410
|
+
*/
|
|
411
|
+
const preserveWhitespace = (config) => {
|
|
412
|
+
config.module.rules.forEach((loader) => {
|
|
413
|
+
if (loader.use) {
|
|
414
|
+
loader.use.forEach((use) => {
|
|
415
|
+
if (use.loader.includes('vue-loader')) {
|
|
416
|
+
use.options.compilerOptions = { ...use.options.compilerOptions, whitespace: 'preserve' };
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const printLogs = (dev, dashboardVersion, resourceBase, routerBasePath, pl, rancherEnv) => {
|
|
191
424
|
console.log(`Build: ${ dev ? 'Development' : 'Production' }`); // eslint-disable-line no-console
|
|
192
425
|
|
|
193
|
-
if (
|
|
426
|
+
if (!dev) {
|
|
194
427
|
console.log(`Version: ${ dashboardVersion }`); // eslint-disable-line no-console
|
|
195
428
|
}
|
|
196
429
|
|
|
197
|
-
if (
|
|
430
|
+
if (resourceBase) {
|
|
198
431
|
console.log(`Resource Base URL: ${ resourceBase }`); // eslint-disable-line no-console
|
|
199
432
|
}
|
|
200
433
|
|
|
201
|
-
if (
|
|
434
|
+
if (routerBasePath !== '/') {
|
|
202
435
|
console.log(`Router Base Path: ${ routerBasePath }`); // eslint-disable-line no-console
|
|
203
436
|
}
|
|
204
437
|
|
|
205
|
-
if (
|
|
438
|
+
if (pl !== STANDARD) {
|
|
206
439
|
console.log(`PL: ${ pl }`); // eslint-disable-line no-console
|
|
207
440
|
}
|
|
208
|
-
const rancherEnv = process.env.RANCHER_ENV || 'web';
|
|
209
|
-
|
|
210
|
-
const loginLocaleSelector = process.env.LOGIN_LOCALE_SELECTOR || 'true';
|
|
211
|
-
const excludeOperatorPkg = process.env.EXCLUDE_OPERATOR_PKG || 'false';
|
|
212
441
|
|
|
213
442
|
console.log(`API: '${ api }'. Env: '${ rancherEnv }'`); // eslint-disable-line no-console
|
|
214
|
-
|
|
215
|
-
...appConfig.proxies,
|
|
216
|
-
'/k8s': configHelper.proxyWsOpts(api), // Straight to a remote cluster (/k8s/clusters/<id>/)
|
|
217
|
-
'/pp': configHelper.proxyWsOpts(api), // For (epinio) standalone API
|
|
218
|
-
'/api': configHelper.proxyWsOpts(api), // Management k8s API
|
|
219
|
-
'/apis': configHelper.proxyWsOpts(api), // Management k8s API
|
|
220
|
-
'/v1': configHelper.proxyWsOpts(api), // Management Steve API
|
|
221
|
-
'/v3': configHelper.proxyWsOpts(api), // Rancher API
|
|
222
|
-
'/v3-public': configHelper.proxyOpts(api), // Rancher Unauthed API
|
|
223
|
-
'/api-ui': configHelper.proxyOpts(api), // Browser API UI
|
|
224
|
-
'/meta': configHelper.proxyMetaOpts(api), // Browser API UI
|
|
225
|
-
'/v1-*': configHelper.proxyOpts(api), // SAML, KDM, etc
|
|
226
|
-
'/rancherversion': configHelper.proxyPrimeOpts(api), // Rancher version endpoint
|
|
227
|
-
// These are for Ember embedding
|
|
228
|
-
'/c/*/edit': configHelper.proxyOpts('https://127.0.0.1:8000'), // Can't proxy all of /c because that's used by Vue too
|
|
229
|
-
'/k/': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
230
|
-
'/g/': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
231
|
-
'/n/': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
232
|
-
'/p/': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
233
|
-
'/assets': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
234
|
-
'/translations': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
235
|
-
'/engines-dist': configHelper.proxyOpts('https://127.0.0.1:8000'),
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
// HAR File support - load network responses from the specified .har file and use those rather than communicating to the Rancher server
|
|
239
|
-
const harFile = process.env.HAR_FILE;
|
|
240
|
-
let harData;
|
|
241
|
-
|
|
242
|
-
if (harFile) {
|
|
243
|
-
harData = har.loadFile(harFile, devPorts ? 8005 : 80, ''); // eslint-disable-line no-console
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const config = {
|
|
247
|
-
// Vue server
|
|
248
|
-
devServer: {
|
|
249
|
-
client: { webSocketURL: { hostname: '0.0.0.0', port: devPorts ? 8005 : 80 } },
|
|
250
|
-
server: {
|
|
251
|
-
type: 'https',
|
|
252
|
-
options: {
|
|
253
|
-
key: fs.readFileSync(path.resolve(__dirname, 'server/server.key')),
|
|
254
|
-
cert: fs.readFileSync(path.resolve(__dirname, 'server/server.crt'))
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
port: (devPorts ? 8005 : 80),
|
|
258
|
-
host: '0.0.0.0',
|
|
259
|
-
setupMiddlewares(middlewares, devServer) {
|
|
260
|
-
const socketProxies = {};
|
|
261
|
-
|
|
262
|
-
if (!devServer) {
|
|
263
|
-
// eslint-disable-next-line no-console
|
|
264
|
-
console.error('webpack-dev-server is not defined');
|
|
265
|
-
|
|
266
|
-
return middlewares;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const app = devServer.app;
|
|
270
|
-
|
|
271
|
-
// Close down quickly in response to CTRL + C
|
|
272
|
-
process.once('SIGINT', () => {
|
|
273
|
-
devServer.close();
|
|
274
|
-
console.log('\n'); // eslint-disable-line no-console
|
|
275
|
-
process.exit(1);
|
|
276
|
-
});
|
|
443
|
+
};
|
|
277
444
|
|
|
278
|
-
|
|
445
|
+
/**
|
|
446
|
+
* Add ignored paths based on env var configuration and known cases
|
|
447
|
+
* TODO: Verify after migration completed
|
|
448
|
+
* In Webpack5 only RegExp, string and [string] types are accepted
|
|
449
|
+
* https://webpack.js.org/configuration/watch/#watchoptionsignored
|
|
450
|
+
* Example conversion:
|
|
451
|
+
* - as list: [/.shell/, /dist-pkg/, /scripts\/standalone/, /\/pkg.test-pkg/, /\/pkg.harvester/]
|
|
452
|
+
* - as chained regex rule: /.shell|dist-pkg|scripts\/standalone|\/pkg.test-pkg|\/pkg.harvester/
|
|
453
|
+
*/
|
|
454
|
+
const getWatcherIgnored = (excludes) => {
|
|
455
|
+
const paths = [
|
|
456
|
+
/node_modules/,
|
|
457
|
+
/dist-pkg/,
|
|
458
|
+
/scripts\/standalone/,
|
|
459
|
+
];
|
|
460
|
+
const pathExcludedPkg = excludes.map((excluded) => new RegExp(`/pkg.${ excluded }`));
|
|
461
|
+
const pathsCombined = [...paths, ...pathExcludedPkg];
|
|
462
|
+
const regexCombined = new RegExp(pathsCombined.map(({ source }) => source).join('|'));
|
|
279
463
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
app.use(har.harProxy(harData, process.env.HAR_DIR));
|
|
464
|
+
return regexCombined;
|
|
465
|
+
};
|
|
283
466
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
467
|
+
/**
|
|
468
|
+
* Expose a function that can be used by an app to provide a nuxt configuration for building an application
|
|
469
|
+
* This takes the directory of the application as the first argument so that we can derive folder locations
|
|
470
|
+
* from it, rather than from the location of this file
|
|
471
|
+
*/
|
|
472
|
+
module.exports = function(dir, _appConfig) {
|
|
473
|
+
require('events').EventEmitter.defaultMaxListeners = 20;
|
|
474
|
+
require('dotenv').config();
|
|
287
475
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
476
|
+
const { SHELL_ABS, COMPONENTS_DIR } = getShellPaths(dir);
|
|
477
|
+
const appConfig = _appConfig || {};
|
|
478
|
+
const excludes = appConfig.excludes || [];
|
|
292
479
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
});
|
|
480
|
+
const includePkg = (name) => {
|
|
481
|
+
if (name.startsWith('.') || name === 'node_modules') {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
298
484
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
app.use(p, px);
|
|
303
|
-
});
|
|
485
|
+
return !excludes || (excludes && !excludes.includes(name));
|
|
486
|
+
};
|
|
304
487
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
488
|
+
const routerBasePath = process.env.ROUTER_BASE ?? '/';
|
|
489
|
+
let resourceBase = process.env.RESOURCE_BASE ?? '';
|
|
490
|
+
const outputDir = process.env.OUTPUT_DIR ?? 'dist';
|
|
491
|
+
const rancherEnv = process.env.RANCHER_ENV || 'web';
|
|
309
492
|
|
|
310
|
-
|
|
311
|
-
|
|
493
|
+
if ( resourceBase && !resourceBase.endsWith('/') ) {
|
|
494
|
+
resourceBase += '/';
|
|
495
|
+
}
|
|
312
496
|
|
|
313
|
-
|
|
314
|
-
proxy.upgrade(req, socket, head);
|
|
315
|
-
} else {
|
|
316
|
-
console.log(`Upgrade for Proxy is not defined. Cannot upgrade Web socket for ${ req.url }`); // eslint-disable-line no-console
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
console.log(`Unknown Web socket upgrade request for ${ req.url }`); // eslint-disable-line no-console
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
});
|
|
497
|
+
printLogs(dev, dashboardVersion, resourceBase, routerBasePath, pl, rancherEnv);
|
|
323
498
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
publicPath:
|
|
329
|
-
css:
|
|
499
|
+
const proxy = getProxyConfig(appConfig.proxy);
|
|
500
|
+
const config = {
|
|
501
|
+
// Vue server
|
|
502
|
+
devServer: getDevServerConfig(proxy),
|
|
503
|
+
publicPath: resourceBase || undefined,
|
|
504
|
+
css: {
|
|
330
505
|
extract: false, // inline css styles instead of including with `<links`
|
|
331
506
|
loaderOptions: {
|
|
332
507
|
sass: {
|
|
@@ -340,16 +515,13 @@ module.exports = function(dir, _appConfig) {
|
|
|
340
515
|
}
|
|
341
516
|
}
|
|
342
517
|
},
|
|
343
|
-
|
|
344
518
|
outputDir,
|
|
345
|
-
|
|
346
519
|
pages: {
|
|
347
520
|
index: {
|
|
348
521
|
entry: path.join(SHELL_ABS, '/initialize/entry.js'),
|
|
349
522
|
template: path.join(SHELL_ABS, '/public/index.html')
|
|
350
523
|
}
|
|
351
524
|
},
|
|
352
|
-
|
|
353
525
|
configureWebpack(config) {
|
|
354
526
|
// TODO VUE3: We may want to look into what we want the value to actually be. For the time being this was causing a warning in our CLI because it would set process.env.NODE_ENV to 'development' even thought it was
|
|
355
527
|
// already set to 'dev' and we're using 'dev' in other locations so I don't think we want to do that. Config details found here: https://webpack.js.org/configuration/optimization/#optimizationnodeenv.
|
|
@@ -364,57 +536,21 @@ module.exports = function(dir, _appConfig) {
|
|
|
364
536
|
config.resolve.alias['@components'] = COMPONENTS_DIR;
|
|
365
537
|
config.resolve.alias['vue$'] = dev ? path.resolve(process.cwd(), 'node_modules', 'vue') : 'vue';
|
|
366
538
|
config.resolve.modules.push(__dirname);
|
|
367
|
-
config.plugins.push(
|
|
368
|
-
config.plugins.push(
|
|
369
|
-
config.plugins.push(
|
|
370
|
-
config.plugins.push(
|
|
539
|
+
config.plugins.push(getVirtualModules(dir, includePkg));
|
|
540
|
+
config.plugins.push(getAutoImport());
|
|
541
|
+
config.plugins.push(getVirtualModulesAutoImport(dir));
|
|
542
|
+
config.plugins.push(getPackageImport(dir));
|
|
543
|
+
config.plugins.push(createEnvVariablesPlugin(routerBasePath, rancherEnv));
|
|
371
544
|
config.plugins.push(new NodePolyfillPlugin()); // required from Webpack 5 to polyfill node modules
|
|
372
|
-
// DefinePlugin does string replacement within our code. We may want to consider replacing it with something else. In code we'll see something like
|
|
373
|
-
// process.env.commit even though process and env aren't even defined objects. This could cause people to be mislead.
|
|
374
|
-
config.plugins.push(new webpack.DefinePlugin({
|
|
375
|
-
'process.env.commit': JSON.stringify(commit),
|
|
376
|
-
'process.env.version': JSON.stringify(dashboardVersion),
|
|
377
|
-
'process.env.dev': JSON.stringify(dev),
|
|
378
|
-
'process.env.pl': JSON.stringify(pl),
|
|
379
|
-
'process.env.perfTest': JSON.stringify(perfTest),
|
|
380
|
-
'process.env.loginLocaleSelector': JSON.stringify(loginLocaleSelector),
|
|
381
|
-
'process.env.excludeOperatorPkg': JSON.stringify(excludeOperatorPkg),
|
|
382
|
-
'process.env.rancherEnv': JSON.stringify(rancherEnv),
|
|
383
|
-
'process.env.harvesterPkgUrl': JSON.stringify(process.env.HARVESTER_PKG_URL),
|
|
384
|
-
'process.env.api': JSON.stringify(api),
|
|
385
|
-
// Store the Router Base as env variable that we can use in `shell/config/router.js`
|
|
386
|
-
'process.env.routerBase': JSON.stringify(routerBasePath),
|
|
387
|
-
|
|
388
|
-
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
|
|
389
|
-
|
|
390
|
-
// This is a replacement of the nuxt publicRuntimeConfig
|
|
391
|
-
'nuxt.publicRuntimeConfig': JSON.stringify({
|
|
392
|
-
rancherEnv,
|
|
393
|
-
dashboardVersion
|
|
394
|
-
}),
|
|
395
|
-
|
|
396
|
-
}));
|
|
397
545
|
|
|
398
546
|
// The static assets need to be in the built assets directory in order to get served (primarily the favicon)
|
|
399
547
|
config.plugins.push(new CopyWebpackPlugin({ patterns: [{ from: path.join(SHELL_ABS, 'static'), to: '.' }] }));
|
|
400
548
|
|
|
401
549
|
config.resolve.extensions.push(...['.tsx', '.ts', '.js', '.vue', '.scss']);
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
* In Webpack5 only RegExp, string and [string] types are accepted
|
|
407
|
-
* https://webpack.js.org/configuration/watch/#watchoptionsignored
|
|
408
|
-
* Example conversion:
|
|
409
|
-
* - as list: [/.shell/, /dist-pkg/, /scripts\/standalone/, /\/pkg.test-pkg/, /\/pkg.harvester/]
|
|
410
|
-
* - as chained regex rule: /.shell|dist-pkg|scripts\/standalone|\/pkg.test-pkg|\/pkg.harvester/
|
|
411
|
-
*/
|
|
412
|
-
config.watchOptions = config.watchOptions || {};
|
|
413
|
-
const ignoredPkgs = excludes.map((excluded) => new RegExp(`/pkg.${ excluded }`));
|
|
414
|
-
const watcherIgnoresPaths = [...watcherIgnores, ...ignoredPkgs];
|
|
415
|
-
const combinedRegex = new RegExp(watcherIgnoresPaths.map(({ source }) => source).join('|'));
|
|
416
|
-
|
|
417
|
-
config.watchOptions.ignored = combinedRegex;
|
|
550
|
+
config.watchOptions = {
|
|
551
|
+
...(config.watchOptions || {}),
|
|
552
|
+
ignored: getWatcherIgnored(excludes)
|
|
553
|
+
};
|
|
418
554
|
|
|
419
555
|
if (dev) {
|
|
420
556
|
config.devtool = 'cheap-module-source-map';
|
|
@@ -423,128 +559,10 @@ module.exports = function(dir, _appConfig) {
|
|
|
423
559
|
}
|
|
424
560
|
|
|
425
561
|
config.resolve.symlinks = false;
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
config.module.rules.
|
|
429
|
-
|
|
430
|
-
if (r.exclude) {
|
|
431
|
-
const orig = r.exclude;
|
|
432
|
-
|
|
433
|
-
r.exclude = function(modulePath) {
|
|
434
|
-
if (modulePath.indexOf(SHELL_ABS) === 0 || typeof orig !== 'function') {
|
|
435
|
-
return false;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
return orig(modulePath);
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
// Instrument code for tests
|
|
445
|
-
const babelPlugins = [
|
|
446
|
-
// TODO: Browser support
|
|
447
|
-
// ['@babel/plugin-transform-modules-commonjs'],
|
|
448
|
-
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
|
449
|
-
['@babel/plugin-proposal-class-properties', { loose: true }]
|
|
450
|
-
];
|
|
451
|
-
|
|
452
|
-
if (instrumentCode) {
|
|
453
|
-
babelPlugins.push([
|
|
454
|
-
'babel-plugin-istanbul', { extension: ['.js', '.vue'] }, 'add-vue'
|
|
455
|
-
]);
|
|
456
|
-
|
|
457
|
-
console.warn('Instrumenting code for coverage'); // eslint-disable-line no-console
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
const loaders = [
|
|
461
|
-
// Ensure there is a fallback for browsers that don't support web workers
|
|
462
|
-
{
|
|
463
|
-
test: /web-worker.[a-z-]+.js/i,
|
|
464
|
-
loader: 'worker-loader',
|
|
465
|
-
options: { inline: 'fallback' },
|
|
466
|
-
},
|
|
467
|
-
// Handler for csv files (e.g. ec2 instance data)
|
|
468
|
-
{
|
|
469
|
-
test: /\.csv$/i,
|
|
470
|
-
loader: 'csv-loader',
|
|
471
|
-
options: {
|
|
472
|
-
dynamicTyping: true,
|
|
473
|
-
header: true,
|
|
474
|
-
skipEmptyLines: true
|
|
475
|
-
},
|
|
476
|
-
},
|
|
477
|
-
// Handler for yaml files (used for i18n files, for example)
|
|
478
|
-
{
|
|
479
|
-
test: /\.ya?ml$/i,
|
|
480
|
-
loader: 'js-yaml-loader',
|
|
481
|
-
options: { name: '[path][name].[ext]' },
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
test: /\.m?[tj]sx?$/,
|
|
485
|
-
// This excludes no modules except for node_modules/@rancher/... so that plugins can properly compile
|
|
486
|
-
// when referencing @rancher/shell
|
|
487
|
-
exclude: /node_modules\/(?!(@rancher)\/).*/,
|
|
488
|
-
use: [
|
|
489
|
-
{
|
|
490
|
-
loader: 'cache-loader',
|
|
491
|
-
options: {
|
|
492
|
-
cacheDirectory: 'node_modules/.cache/babel-loader',
|
|
493
|
-
cacheIdentifier: 'e93f32da'
|
|
494
|
-
}
|
|
495
|
-
},
|
|
496
|
-
]
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
test: /\.tsx?$/,
|
|
500
|
-
use: [
|
|
501
|
-
{
|
|
502
|
-
loader: 'cache-loader',
|
|
503
|
-
options: {
|
|
504
|
-
cacheDirectory: 'node_modules/.cache/ts-loader',
|
|
505
|
-
cacheIdentifier: '3596741e'
|
|
506
|
-
}
|
|
507
|
-
},
|
|
508
|
-
{
|
|
509
|
-
loader: 'ts-loader',
|
|
510
|
-
options: {
|
|
511
|
-
transpileOnly: true,
|
|
512
|
-
happyPackMode: false,
|
|
513
|
-
appendTsxSuffixTo: [
|
|
514
|
-
'\\.vue$'
|
|
515
|
-
],
|
|
516
|
-
configFile: path.join(SHELL_ABS, 'tsconfig.json')
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
]
|
|
520
|
-
},
|
|
521
|
-
// Prevent warning in log with the md files in the content folder
|
|
522
|
-
{
|
|
523
|
-
test: /\.md$/,
|
|
524
|
-
use: [
|
|
525
|
-
{
|
|
526
|
-
loader: 'frontmatter-markdown-loader',
|
|
527
|
-
options: { mode: ['body'] }
|
|
528
|
-
}
|
|
529
|
-
]
|
|
530
|
-
},
|
|
531
|
-
];
|
|
532
|
-
|
|
533
|
-
config.module.rules.push(...loaders);
|
|
534
|
-
|
|
535
|
-
// TODO: Verify after migration completed
|
|
536
|
-
// Update vue-loader to set whitespace to 'preserve'
|
|
537
|
-
// This was the setting with nuxt, but is not the default with vue cli
|
|
538
|
-
// Need to find the vue loader in the webpack config and update the setting
|
|
539
|
-
config.module.rules.forEach((loader) => {
|
|
540
|
-
if (loader.use) {
|
|
541
|
-
loader.use.forEach((use) => {
|
|
542
|
-
if (use.loader.includes('vue-loader')) {
|
|
543
|
-
use.options.compilerOptions = { ...use.options.compilerOptions, whitespace: 'preserve' };
|
|
544
|
-
}
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
});
|
|
562
|
+
processShellFiles(config, SHELL_ABS);
|
|
563
|
+
instrumentCode();
|
|
564
|
+
config.module.rules.push(...getLoaders(SHELL_ABS));
|
|
565
|
+
preserveWhitespace(config);
|
|
548
566
|
},
|
|
549
567
|
};
|
|
550
568
|
|