Skip to content

Commit f6c796d

Browse files
committed
[Draft] Enable using the ESM dependencies where possible
Issue: #5086 Signed-off-by: Victor Rubezhny <[email protected]>
1 parent 58c5771 commit f6c796d

File tree

50 files changed

+1507
-1389
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1507
-1389
lines changed

.github/workflows/continuous-integration-workflow.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ jobs:
2121
# The type of runner that the job will run on
2222
runs-on: ${{ matrix.os }}
2323
strategy:
24+
fail-fast: false
2425
matrix:
2526
os: [macos-latest, windows-latest, ubuntu-latest]
2627
node: [ 20 ]
28+
env:
29+
VERBOSE: true
2730

2831
# Steps represent a sequence of tasks that will be executed as part of the job
2932
steps:

.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ out/build**
1818
out/build/**
1919
out/coverage/**
2020
out/**/*.map
21+
out/shared/**
2122
out/src-orig/**
2223
out/test/**
2324
out/test-resources/**

build/bundle-tools.cjs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
/* eslint-disable guard-for-in */
6+
/* eslint-disable no-console */
7+
8+
const fs = require('fs');
9+
const path = require('path');
10+
const { exit } = require('process');
11+
const { esmAliasPlugin } = require('./esbuild.plugins.cjs');
12+
13+
require('esbuild').build({
14+
entryPoints: [path.resolve(__dirname, '..', 'src/downloadUtil/downloadBinaries.ts')],
15+
platform: 'node',
16+
target: 'node18',
17+
format: 'cjs',
18+
outfile: path.resolve(__dirname, '..', 'out/shared/downloadUtil.js'),
19+
bundle: true,
20+
plugins: [ esmAliasPlugin() ]
21+
}).then(() => {
22+
const { downloadFileAndCreateSha256 } = require(path.resolve(__dirname, '..', 'out/shared/downloadUtil.js'));
23+
const configData = require('../src/tools.json');
24+
25+
async function bundleTools() {
26+
if (process.env.REMOTE_CONTAINERS === 'true') {
27+
return;
28+
}
29+
const outFolder = path.resolve('.', 'out');
30+
const toolsCacheFolder = path.join(outFolder, 'tools-cache');
31+
let currentPlatform = process.env.TARGET;
32+
if (!currentPlatform) {
33+
currentPlatform = process.argv.find((arg) => arg === '--platform')
34+
? process.platform
35+
: 'all';
36+
}
37+
console.log(currentPlatform);
38+
console.info(`Download tools to '${toolsCacheFolder}'`);
39+
for (const key in configData) {
40+
const tool = configData[key];
41+
for (const OS in tool.platform) {
42+
if (currentPlatform === 'all' || OS === currentPlatform) {
43+
console.log(`Bundle '${tool.description}' for ${OS}`);
44+
const osSpecificLocation = path.join(outFolder, 'tools', OS);
45+
// eslint-disable-next-line no-await-in-loop
46+
await downloadFileAndCreateSha256(toolsCacheFolder, osSpecificLocation, tool.platform[OS]);
47+
fs.chmodSync(path.join(osSpecificLocation, tool.platform[OS].cmdFileName), 0o765);
48+
}
49+
}
50+
}
51+
}
52+
53+
bundleTools().catch((error) => {
54+
console.log(error);
55+
exit(1);
56+
});
57+
58+
}).catch(err => {
59+
console.error(err);
60+
exit(1);
61+
});

build/bundle-tools.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.

build/esbuild.build.cjs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
const { execSync } = require('child_process');
2+
const esbuild = require('esbuild');
3+
const { esmAliasPlugin, esbuildProblemMatcherPlugin, nativeNodeModulesPlugin, svgrPlugin } = require('./esbuild.plugins.cjs');
4+
const { webviews, srcDir, outDir } = require('./esbuild.settings.cjs');
5+
const { sassPlugin } = require('esbuild-sass-plugin');
6+
const { cp, mkdir, readFile, stat } = require('node:fs/promises');
7+
const path = require('path');
8+
const { sync } = require('fast-glob');
9+
10+
11+
const production = process.argv.includes('--production');
12+
13+
// eslint-disable no-console
14+
15+
// Run type-checking
16+
17+
/// Verify the extension
18+
try {
19+
// execSync('tsc --noEmit', { stdio: 'inherit' });
20+
execSync('tsc --noEmit -p tsconfig.json', { stdio: 'inherit' });
21+
} catch (err) {
22+
console.error('❌ TypeScript type-checking failed.');
23+
process.exit(1);
24+
}
25+
26+
// Verify the WebViews
27+
try {
28+
execSync('tsc --noEmit -p ./src/webview/tsconfig.json', { stdio: 'inherit' });
29+
} catch (err) {
30+
console.error('❌ TypeScript type-checking failed.');
31+
process.exit(1);
32+
}
33+
34+
35+
console.log(`esbuild: building for production: ${production ? 'Yes' : 'No'}`);
36+
37+
const baseConfig = {
38+
bundle: production,
39+
target: 'chrome108',
40+
minify: production,
41+
sourcemap: !production,
42+
logLevel: 'warning',
43+
};
44+
45+
async function build() {
46+
if (production) {
47+
// Build the extension.js
48+
const extConfig = {
49+
...baseConfig,
50+
platform: 'node',
51+
format: 'cjs',
52+
entryPoints: [`./${srcDir}/extension.ts`],
53+
outfile: `${outDir}/${srcDir}/extension.js`,
54+
external: [ 'vscode', 'shelljs', 'jsonc-parser' ],
55+
plugins: [
56+
nativeNodeModulesPlugin(),
57+
esbuildProblemMatcherPlugin(production) // this one is to be added to the end of plugins array
58+
]
59+
};
60+
await esbuild.build(extConfig);
61+
console.log('✅ Extension build completed');
62+
63+
// Build the Webviews
64+
const webviewsConfig = {
65+
...baseConfig,
66+
platform: 'browser',
67+
format: 'esm',
68+
entryPoints: [...webviews.map(webview => `./${srcDir}/webview/${webview}/app/index.tsx`)],
69+
outdir: `${outDir}`,
70+
loader: {
71+
'.png': 'file',
72+
},
73+
plugins: [
74+
sassPlugin(),
75+
svgrPlugin({ plugins: ['@svgr/plugin-jsx'] }),
76+
esbuildProblemMatcherPlugin(production) // this one is to be added to the end of plugins array
77+
]
78+
};
79+
await esbuild.build(webviewsConfig);
80+
console.log('✅ Webview build completed');
81+
} else {
82+
// Build the Extension for development
83+
const srcFiles = sync(`${srcDir}/**/*.{js,ts,tsx}`, { absolute: false });
84+
const devExtConfig = {
85+
...baseConfig,
86+
platform: 'node',
87+
format: 'cjs',
88+
entryPoints: srcFiles.map(f => `./${f}`),
89+
outbase: srcDir,
90+
outdir: `${outDir}/${srcDir}`,
91+
// external: [ 'vscode', 'shelljs', 'jsonc-parser' ],
92+
plugins: [
93+
esmAliasPlugin(),
94+
nativeNodeModulesPlugin(),
95+
esbuildProblemMatcherPlugin(production) // this one is to be added to the end of plugins array
96+
]
97+
};
98+
99+
await esbuild.build(devExtConfig);
100+
console.log('✅ Extension build completed');
101+
102+
const jsonFiles = sync('src/**/*.json', { absolute: false });
103+
for (const file of jsonFiles) {
104+
const dest = path.join('out', file);
105+
await cp(file, dest, { recursive: false, force: true });
106+
}
107+
await cp('package.json', 'out/package.json');
108+
109+
const devWebViewConfig = {
110+
...baseConfig,
111+
platform: 'browser',
112+
format: 'esm',
113+
entryPoints: [...webviews.map(webview => `./${srcDir}/webview/${webview}/app/index.tsx`)],
114+
outdir: `${outDir}`,
115+
loader: {
116+
'.png': 'file',
117+
},
118+
plugins: [
119+
sassPlugin(),
120+
svgrPlugin({ plugins: ['@svgr/plugin-jsx'] }),
121+
esbuildProblemMatcherPlugin(production) // this one is to be added to the end of plugins array
122+
]
123+
};
124+
await esbuild.build(devWebViewConfig);
125+
console.log('✅ Webview build completed');
126+
127+
// Match everything under test/, not just *.test.ts
128+
const testFiles = sync('test/**/*.{ts,tsx}', { absolute: true });
129+
const testConfig = {
130+
...baseConfig,
131+
entryPoints: testFiles,
132+
outdir: `${outDir}/test`,
133+
outbase: 'test', // preserves folder structure
134+
platform: 'node',
135+
format: 'cjs', // CommonJS for Node
136+
sourcemap: true,
137+
// target: 'es2022',
138+
plugins: [
139+
esmAliasPlugin()
140+
]
141+
}
142+
await esbuild.build(testConfig);
143+
console.log('✅ Tests build completed');
144+
}
145+
146+
async function dirExists(path) {
147+
try {
148+
if ((await stat(path)).isDirectory()) return true;
149+
} catch { /* Ignore */ }
150+
return false;
151+
}
152+
153+
// Copy webview's 'index.html's to the output webview dirs
154+
await Promise.all([
155+
...webviews.map(async webview => {
156+
const targetDir = path.join(__dirname, '..', `${outDir}/${webview}/app`);
157+
if (!dirExists(targetDir)) {
158+
await mkdir(targetDir, { recursive: true, mode: 0o750} );
159+
}
160+
sync(path.resolve(__dirname, '..', `${srcDir}/webview/${webview}/app/index.html`)).map(async srcFile => {
161+
await cp(srcFile, path.join(targetDir, `${path.basename(srcFile)}`));
162+
});
163+
})
164+
]);
165+
}
166+
167+
build().catch(err => {
168+
console.error('❌ Build failed:', err);
169+
process.exit(1);
170+
});

0 commit comments

Comments
 (0)