@@ -13,21 +13,93 @@ exports.detectLanguage = (cypress_config_filename) => {
13
13
return constants . CYPRESS_V10_AND_ABOVE_CONFIG_FILE_EXTENSIONS . includes ( extension ) ? extension : 'js'
14
14
}
15
15
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
+
16
37
function generateTscCommandAndTempTsConfig ( bsConfig , bstack_node_modules_path , complied_js_dir , cypress_config_filepath ) {
17
38
const working_dir = path . dirname ( cypress_config_filepath ) ;
18
39
const typescript_path = path . join ( bstack_node_modules_path , 'typescript' , 'bin' , 'tsc' ) ;
19
40
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 ) ;
21
41
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
+ }
31
103
32
104
// Write the temporary tsconfig
33
105
const tempTsConfigPath = path . join ( working_dir , 'tsconfig.singlefile.tmp.json' ) ;
@@ -48,7 +120,7 @@ function generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, c
48
120
return { tscCommand, tempTsConfigPath } ;
49
121
} else {
50
122
// 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 } ` ;
52
124
const tscCommand = `${ nodePathPrefix } node "${ typescript_path } " --project "${ tempTsConfigPath } " && ${ nodePathPrefix } node "${ tsc_alias_path } " --project "${ tempTsConfigPath } " --verbose` ;
53
125
logger . info ( `TypeScript compilation command: ${ tscCommand } ` ) ;
54
126
return { tscCommand, tempTsConfigPath } ;
@@ -70,7 +142,6 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
70
142
try {
71
143
logger . debug ( `Running: ${ tscCommand } ` )
72
144
tsc_output = cp . execSync ( tscCommand , { cwd : working_dir } )
73
- cp . execSync ( tscCommand , { cwd : working_dir } )
74
145
} catch ( err ) {
75
146
// error while compiling ts files
76
147
logger . debug ( err . message ) ;
@@ -83,10 +154,17 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
83
154
// Clean up the temporary tsconfig file
84
155
if ( fs . existsSync ( tempTsConfigPath ) ) {
85
156
fs . unlinkSync ( tempTsConfigPath ) ;
86
- logger . info ( `Temporary tsconfig file removed: ${ tempTsConfigPath } ` ) ;
157
+ logger . debug ( `Temporary tsconfig file removed: ${ tempTsConfigPath } ` ) ;
87
158
}
88
159
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
+ }
90
168
91
169
const lines = tsc_output . toString ( ) . split ( '\n' ) ;
92
170
let foundLine = null ;
@@ -157,4 +235,4 @@ exports.readCypressConfigFile = (bsConfig) => {
157
235
fs . rmdirSync ( complied_js_dir , { recursive : true } )
158
236
}
159
237
}
160
- }
238
+ }
0 commit comments