@@ -13,21 +13,93 @@ exports.detectLanguage = (cypress_config_filename) => {
1313 return constants . CYPRESS_V10_AND_ABOVE_CONFIG_FILE_EXTENSIONS . includes ( extension ) ? extension : 'js'
1414}
1515
16+ function resolveTsConfigPath ( bsConfig , cypress_config_filepath ) {
17+ const working_dir = path . dirname ( cypress_config_filepath ) ;
18+
19+ // Priority order for finding tsconfig
20+ const candidates = [
21+ bsConfig . run_settings && bsConfig . run_settings . ts_config_file_path , // User specified
22+ path . join ( working_dir , 'tsconfig.json' ) , // Same directory as cypress config
23+ path . join ( working_dir , '..' , 'tsconfig.json' ) , // Parent directory
24+ path . join ( process . cwd ( ) , 'tsconfig.json' ) // Project root
25+ ] . filter ( Boolean ) . map ( p => path . resolve ( p ) ) ;
26+
27+ for ( const candidate of candidates ) {
28+ if ( fs . existsSync ( candidate ) ) {
29+ logger . debug ( `Found tsconfig at: ${ candidate } ` ) ;
30+ return candidate ;
31+ }
32+ }
33+
34+ return null ;
35+ }
36+
1637function generateTscCommandAndTempTsConfig ( bsConfig , bstack_node_modules_path , complied_js_dir , cypress_config_filepath ) {
1738 const working_dir = path . dirname ( cypress_config_filepath ) ;
1839 const typescript_path = path . join ( bstack_node_modules_path , 'typescript' , 'bin' , 'tsc' ) ;
1940 const tsc_alias_path = path . join ( bstack_node_modules_path , 'tsc-alias' , 'dist' , 'bin' , 'index.js' ) ;
20- const tsConfigFilePath = path . resolve ( bsConfig . run_settings . ts_config_file_path ) ;
2141
22- // Prepare base temp tsconfig
23- const tempTsConfig = {
24- extends : tsConfigFilePath , // Use a base tsconfig if available
25- compilerOptions : {
26- "outDir" : `${ path . basename ( complied_js_dir ) } ` , // Add ./ prefix for consistency
27- "listEmittedFiles" : true ,
28- } ,
29- include : [ cypress_config_filepath ]
30- } ;
42+ // Smart tsconfig detection and validation
43+ const resolvedTsConfigPath = resolveTsConfigPath ( bsConfig , cypress_config_filepath ) ;
44+ let hasValidTsConfig = false ;
45+
46+ if ( resolvedTsConfigPath ) {
47+ try {
48+ // Validate the tsconfig is readable and valid JSON
49+ const tsConfigContent = fs . readFileSync ( resolvedTsConfigPath , 'utf8' ) ;
50+ JSON . parse ( tsConfigContent ) ;
51+ hasValidTsConfig = true ;
52+ logger . info ( `Using existing tsconfig: ${ resolvedTsConfigPath } ` ) ;
53+ } catch ( error ) {
54+ logger . warn ( `Invalid tsconfig file: ${ resolvedTsConfigPath } , falling back to default configuration. Error: ${ error . message } ` ) ;
55+ hasValidTsConfig = false ;
56+ }
57+ } else {
58+ logger . info ( 'No tsconfig found, using default TypeScript configuration' ) ;
59+ }
60+
61+ let tempTsConfig ;
62+
63+ if ( hasValidTsConfig ) {
64+ // Scenario 1: User has valid tsconfig - use extends approach
65+ tempTsConfig = {
66+ extends : resolvedTsConfigPath ,
67+ compilerOptions : {
68+ // Force override critical parameters for BrowserStack compatibility
69+ "outDir" : path . basename ( complied_js_dir ) ,
70+ "listEmittedFiles" : true ,
71+ // Ensure these are always set regardless of base tsconfig
72+ "allowSyntheticDefaultImports" : true ,
73+ "esModuleInterop" : true
74+ } ,
75+ include : [ cypress_config_filepath ]
76+ } ;
77+ } else {
78+ // Scenario 2: No tsconfig or invalid tsconfig - create standalone with all basic parameters
79+ tempTsConfig = {
80+ compilerOptions : {
81+ // Preserve old command-line parameters for backwards compatibility
82+ "outDir" : path . basename ( complied_js_dir ) ,
83+ "listEmittedFiles" : true ,
84+ "allowSyntheticDefaultImports" : true ,
85+ "module" : "commonjs" ,
86+ "declaration" : false ,
87+
88+ // Add essential missing parameters for robust compilation
89+ "target" : "es2017" ,
90+ "moduleResolution" : "node" ,
91+ "esModuleInterop" : true ,
92+ "allowJs" : true ,
93+ "skipLibCheck" : true ,
94+ "forceConsistentCasingInFileNames" : true ,
95+ "resolveJsonModule" : true ,
96+ "strict" : false , // Avoid breaking existing code
97+ "noEmitOnError" : false // Continue compilation even with errors
98+ } ,
99+ include : [ cypress_config_filepath ] ,
100+ exclude : [ "node_modules" , "dist" , "build" ]
101+ } ;
102+ }
31103
32104 // Write the temporary tsconfig
33105 const tempTsConfigPath = path . join ( working_dir , 'tsconfig.singlefile.tmp.json' ) ;
@@ -48,7 +120,7 @@ function generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, c
48120 return { tscCommand, tempTsConfigPath } ;
49121 } else {
50122 // Unix/Linux/macOS: Use ; to separate commands or && to chain
51- const nodePathPrefix = `NODE_PATH=${ bsConfig . run_settings . bstack_node_modules_path } ` ;
123+ const nodePathPrefix = `NODE_PATH=${ bstack_node_modules_path } ` ;
52124 const tscCommand = `${ nodePathPrefix } node "${ typescript_path } " --project "${ tempTsConfigPath } " && ${ nodePathPrefix } node "${ tsc_alias_path } " --project "${ tempTsConfigPath } " --verbose` ;
53125 logger . info ( `TypeScript compilation command: ${ tscCommand } ` ) ;
54126 return { tscCommand, tempTsConfigPath } ;
@@ -70,7 +142,6 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
70142 try {
71143 logger . debug ( `Running: ${ tscCommand } ` )
72144 tsc_output = cp . execSync ( tscCommand , { cwd : working_dir } )
73- cp . execSync ( tscCommand , { cwd : working_dir } )
74145 } catch ( err ) {
75146 // error while compiling ts files
76147 logger . debug ( err . message ) ;
@@ -83,10 +154,17 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
83154 // Clean up the temporary tsconfig file
84155 if ( fs . existsSync ( tempTsConfigPath ) ) {
85156 fs . unlinkSync ( tempTsConfigPath ) ;
86- logger . info ( `Temporary tsconfig file removed: ${ tempTsConfigPath } ` ) ;
157+ logger . debug ( `Temporary tsconfig file removed: ${ tempTsConfigPath } ` ) ;
87158 }
88159
89- logger . info ( tsc_output . toString ( ) ) ;
160+ if ( tsc_output ) {
161+ logger . debug ( tsc_output . toString ( ) ) ;
162+ }
163+
164+ if ( ! tsc_output ) {
165+ logger . error ( 'No TypeScript compilation output available' ) ;
166+ return null ;
167+ }
90168
91169 const lines = tsc_output . toString ( ) . split ( '\n' ) ;
92170 let foundLine = null ;
@@ -157,4 +235,4 @@ exports.readCypressConfigFile = (bsConfig) => {
157235 fs . rmdirSync ( complied_js_dir , { recursive : true } )
158236 }
159237 }
160- }
238+ }
0 commit comments