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