11import { exists } from "jsr:@std/fs@^1" ;
2- import { dirname , esbuild , parseJsonc } from "./deps.ts" ;
2+ import { dirname , esbuild , isAbsolute , parseJsonc } from "./deps.ts" ;
33
44import {
55 denoPlugin ,
@@ -10,7 +10,14 @@ import {
1010 resolve ,
1111} from "./deps.ts" ;
1212import { serve , setServeDir } from "./serve.ts" ;
13- import { DEFAULT_SERVE_DIR , IS_DEV , omitKeys } from "./stuff.ts" ;
13+ import {
14+ DEFAULT_SERVE_DIR ,
15+ DenoTempFile ,
16+ IS_DEV ,
17+ omitKeys ,
18+ REACT_STATIC_TS_CONFIG ,
19+ REACT_STATIC_TS_CONFIG_DEV ,
20+ } from "./stuff.ts" ;
1421
1522/**
1623 * Options for configuring the build process
@@ -79,6 +86,71 @@ export type BuildOptions = {
7986
8087let isFirstBuild = true ;
8188
89+ /**
90+ * Configuration resource for managing TypeScript/JSX config conformance
91+ */
92+ type ConformedConfig = {
93+ readonly path : string | undefined ;
94+ [ Symbol . dispose ] ( ) : void ;
95+ } ;
96+
97+ /**
98+ * Creates a conformed config with automatic resource cleanup
99+ * @param options - Config options
100+ * @returns Resource-managed config object
101+ */
102+ async function withConformedConfig ( {
103+ configPath,
104+ inFiles,
105+ isDev
106+ } : {
107+ configPath ?: string ;
108+ inFiles ?: string [ ] ;
109+ isDev : boolean ;
110+ } ) : Promise < ConformedConfig > {
111+ // Check if input files contain JSX/TSX
112+ const isJsx = inFiles ?. find ( ( file ) =>
113+ file . endsWith ( ".jsx" ) || file . endsWith ( ".tsx" )
114+ ) ;
115+
116+ const finalConfig = configPath
117+ ? parseJsonc ( await Deno . readTextFile ( configPath ) ) as Record < string , any >
118+ : isJsx
119+ ? isDev ? REACT_STATIC_TS_CONFIG_DEV : REACT_STATIC_TS_CONFIG
120+ : undefined ;
121+
122+ // Adjust JSX compiler options based on dev mode
123+ if ( finalConfig && "compilerOptions" in finalConfig ) {
124+ if ( ! isDev && finalConfig [ "compilerOptions" ] ?. [ "jsx" ] === "react-jsxdev" ) {
125+ finalConfig [ "compilerOptions" ] [ "jsx" ] = "react-jsx" ;
126+ }
127+ if ( isDev && finalConfig [ "compilerOptions" ] ?. [ "jsx" ] === "react-jsx" ) {
128+ finalConfig [ "compilerOptions" ] [ "jsx" ] = "react-jsxdev" ;
129+ }
130+ }
131+
132+ if ( finalConfig && configPath && "importMap" in finalConfig ) {
133+ // Convert to absolute path if not already
134+ if ( finalConfig [ "importMap" ] && ! isAbsolute ( finalConfig [ "importMap" ] ) ) {
135+ finalConfig [ "importMap" ] = resolve ( dirname ( configPath ) , finalConfig [ "importMap" ] as string ) ;
136+ }
137+ }
138+
139+
140+ const tmpFile = finalConfig
141+ ? new DenoTempFile ( JSON . stringify ( finalConfig ) )
142+ : undefined ;
143+
144+ const finalConfigPath = tmpFile ? tmpFile . getPath ( ) : configPath ;
145+
146+ return {
147+ path : finalConfigPath ,
148+ [ Symbol . dispose ] ( ) {
149+ tmpFile ?. [ Symbol . dispose ] ( ) ;
150+ }
151+ } ;
152+ }
153+
82154/**
83155 * Builds a project using esbuild
84156 * @param options - Build options
@@ -136,6 +208,15 @@ export const build = async (options: BuildOptions): Promise<void> => {
136208 }
137209 }
138210
211+ // Conform config json to match needed JSX config
212+ using config = await withConformedConfig ( {
213+ configPath : finalConfigPath ,
214+ inFiles : inFiles ,
215+ isDev : IS_DEV
216+ } ) ;
217+
218+ finalConfigPath = config . path ;
219+
139220 const opts : esbuild . BuildOptions = {
140221 plugins : [
141222 denoPlugin ( {
0 commit comments