Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bin/commands/runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ module.exports = function run(args, rawArgs) {
// set the no-wrap
utils.setNoWrap(bsConfig, args);

// process auto-import dev dependencies
utils.processAutoImportDependencies(bsConfig.run_settings);

// add cypress dependency if missing
utils.setCypressNpmDependency(bsConfig);

Expand Down
2 changes: 2 additions & 0 deletions bin/helpers/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ const createBuild = (bsConfig, zip) => {
if(error.response) {
logger.error(utils.formatRequest(error.response.statusText, error.response, error.response.data));
reject(`${Constants.userMessages.BUILD_FAILED} Error: ${error.response.data.message}`);
} else {
reject(error);
}
}
}).catch(function(err){
Expand Down
8 changes: 7 additions & 1 deletion bin/helpers/capabilityHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,17 @@ const getAccessibilityPlatforms = (bsConfig) => {
const addCypressZipStartLocation = (runSettings) => {
let resolvedHomeDirectoryPath = path.resolve(runSettings.home_directory);
let resolvedCypressConfigFilePath = path.resolve(runSettings.cypressConfigFilePath);
runSettings.cypressZipStartLocation = path.dirname(resolvedCypressConfigFilePath.split(resolvedHomeDirectoryPath)[1]);

// Convert to POSIX style paths for consistent behavior
let posixHomePath = resolvedHomeDirectoryPath.split(path.sep).join(path.posix.sep);
let posixConfigPath = resolvedCypressConfigFilePath.split(path.sep).join(path.posix.sep);

runSettings.cypressZipStartLocation = path.posix.dirname(posixConfigPath.split(posixHomePath)[1]);
runSettings.cypressZipStartLocation = runSettings.cypressZipStartLocation.substring(1);
logger.debug(`Setting cypress zip start location = ${runSettings.cypressZipStartLocation}`);
}


const validate = (bsConfig, args) => {
return new Promise(function (resolve, reject) {
logger.info(Constants.userMessages.VALIDATING_CONFIG);
Expand Down
22 changes: 22 additions & 0 deletions bin/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,28 @@ const validationMessages = {
"You have specified '--record' flag but you've not provided the '--record-key' and we could not find any value in 'CYPRESS_RECORD_KEY' environment variable. Your record functionality on cypress.io dashboard might not work as it needs the key and projectId",
NODE_VERSION_PARSING_ERROR:
"We weren't able to successfully parse the specified nodeVersion. We will be using the default nodeVersion to run your tests.",
AUTO_IMPORT_CONFLICT_ERROR:
"Cannot use both 'auto_import_dev_dependencies' and manual npm dependency configuration. Please either set 'auto_import_dev_dependencies' to false or remove manual 'npm_dependencies', 'win_npm_dependencies', and 'mac_npm_dependencies' configurations.",
AUTO_IMPORT_INVALID_TYPE:
"'auto_import_dev_dependencies' must be a boolean value (true or false).",
PACKAGE_JSON_NOT_FOUND:
"package.json not found in project directory. Cannot auto-import devDependencies.",
PACKAGE_JSON_PERMISSION_DENIED:
"Cannot read package.json due to permission issues. Please check file permissions.",
PACKAGE_JSON_MALFORMED:
"package.json contains invalid JSON syntax. Please fix the JSON format.",
PACKAGE_JSON_NOT_OBJECT:
"package.json must contain a JSON object, not an array or other type.",
DEVDEPS_INVALID_FORMAT:
"devDependencies field in package.json must be an object, not an array or other type.",
EXCLUDE_DEPS_INVALID_TYPE:
"'exclude_dependencies' must be an array of strings.",
EXCLUDE_DEPS_INVALID_PATTERNS:
"'exclude_dependencies' must contain only string values representing regex patterns.",
INVALID_REGEX_PATTERN:
"Invalid regex pattern found in 'exclude_dependencies': {pattern}. Please provide valid regex patterns.",
DEPENDENCIES_PARAM_INVALID:
"Dependencies parameter must be an object.",
};

const cliMessages = {
Expand Down
5 changes: 3 additions & 2 deletions bin/helpers/packageInstaller.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ const setupPackageFolder = (runSettings, directoryPath) => {
}

// Combine win and mac specific dependencies if present
if (typeof runSettings.npm_dependencies === 'object') {
const combinedDependencies = combineMacWinNpmDependencies(runSettings);
if (combinedDependencies && Object.keys(combinedDependencies).length > 0) {
Object.assign(packageJSON, {
devDependencies: combineMacWinNpmDependencies(runSettings),
devDependencies: combinedDependencies,
});
}

Expand Down
183 changes: 172 additions & 11 deletions bin/helpers/readCypressConfigUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,159 @@ exports.detectLanguage = (cypress_config_filename) => {
return constants.CYPRESS_V10_AND_ABOVE_CONFIG_FILE_EXTENSIONS.includes(extension) ? extension : 'js'
}

function resolveTsConfigPath(bsConfig, cypress_config_filepath) {
const utils = require("./utils");
const working_dir = path.dirname(cypress_config_filepath);
const project_root = process.cwd();

// Priority order for finding tsconfig with secure path validation
const candidates = [];

// User specified path - validate it's within project bounds
if (bsConfig.run_settings && bsConfig.run_settings.ts_config_file_path) {
try {
const safePath = utils.validateSecurePath(bsConfig.run_settings.ts_config_file_path, project_root);
candidates.push(safePath);
} catch (error) {
logger.warn(`Invalid user-specified tsconfig path: ${error.message}`);
}
}

// Safe predefined paths
try {
candidates.push(utils.validateSecurePath(path.join(working_dir, 'tsconfig.json'), project_root));

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
} catch (error) {
logger.debug(`Working directory tsconfig path validation failed: ${error.message}`);
}

try {
candidates.push(utils.validateSecurePath(path.join(working_dir, '..', 'tsconfig.json'), project_root));

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
} catch (error) {
logger.debug(`Parent directory tsconfig path validation failed: ${error.message}`);
}

candidates.push(path.join(project_root, 'tsconfig.json'));

for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
logger.debug(`Found tsconfig at: ${candidate}`);
return candidate;
}
}

return null;
}

function generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath) {
const utils = require("./utils");
const working_dir = path.dirname(cypress_config_filepath);
const project_root = process.cwd();

// Sanitize and validate paths to prevent command injection
let safe_bstack_node_modules_path;
let safe_cypress_config_filepath;
let safe_working_dir;

try {
safe_bstack_node_modules_path = utils.sanitizeCommandPath(bstack_node_modules_path);
safe_cypress_config_filepath = utils.sanitizeCommandPath(cypress_config_filepath);
safe_working_dir = utils.sanitizeCommandPath(working_dir);

// Additional validation - ensure paths are within expected bounds
utils.validateSecurePath(safe_bstack_node_modules_path, project_root);
utils.validateSecurePath(safe_cypress_config_filepath, project_root);
} catch (error) {
throw new Error(`Invalid file paths detected: ${error.message}`);
}

const typescript_path = path.join(safe_bstack_node_modules_path, 'typescript', 'bin', 'tsc');

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
const tsc_alias_path = path.join(safe_bstack_node_modules_path, 'tsc-alias', 'dist', 'bin', 'index.js');

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

// Smart tsconfig detection and validation
const resolvedTsConfigPath = resolveTsConfigPath(bsConfig, safe_cypress_config_filepath);
let hasValidTsConfig = false;

if (resolvedTsConfigPath) {
try {
// Validate the tsconfig is readable and valid JSON
const tsConfigContent = fs.readFileSync(resolvedTsConfigPath, 'utf8');
JSON.parse(tsConfigContent);
hasValidTsConfig = true;
logger.info(`Using existing tsconfig: ${resolvedTsConfigPath}`);
} catch (error) {
logger.warn(`Invalid tsconfig file: ${resolvedTsConfigPath}, falling back to default configuration. Error: ${error.message}`);
hasValidTsConfig = false;
}
} else {
logger.info('No tsconfig found, using default TypeScript configuration');
}

let tempTsConfig;

if (hasValidTsConfig) {
// Scenario 1: User has valid tsconfig - use extends approach
tempTsConfig = {
extends: resolvedTsConfigPath,
compilerOptions: {
// Force override critical parameters for BrowserStack compatibility
"outDir": path.basename(complied_js_dir),
"listEmittedFiles": true,
// Ensure these are always set regardless of base tsconfig
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
include: [safe_cypress_config_filepath]
};
} else {
// Scenario 2: No tsconfig or invalid tsconfig - create standalone with all basic parameters
tempTsConfig = {
compilerOptions: {
// Preserve old command-line parameters for backwards compatibility
"outDir": path.basename(complied_js_dir),
"listEmittedFiles": true,
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"declaration": false,

// Add essential missing parameters for robust compilation
"target": "es2017",
"moduleResolution": "node",
"esModuleInterop": true,
"allowJs": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"strict": false, // Avoid breaking existing code
"noEmitOnError": false // Continue compilation even with errors
},
include: [safe_cypress_config_filepath],
exclude: ["node_modules", "dist", "build"]
};
}

// Write the temporary tsconfig
const tempTsConfigPath = path.join(safe_working_dir, 'tsconfig.singlefile.tmp.json');

Check warning

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.
fs.writeFileSync(tempTsConfigPath, JSON.stringify(tempTsConfig, null, 2));
logger.info(`Temporary tsconfig created at: ${tempTsConfigPath}`);

// Platform-specific command generation with sanitized paths
const isWindows = /^win/.test(process.platform);

if (isWindows) {
// Windows: Use && to chain commands, no space after SET
const setNodePath = `set NODE_PATH=${safe_bstack_node_modules_path}`;
const tscCommand = `${setNodePath} && node "${typescript_path}" --project "${tempTsConfigPath}" && ${setNodePath} && node "${tsc_alias_path}" --project "${tempTsConfigPath}" --verbose`;
logger.info(`TypeScript compilation command: ${tscCommand}`);
return { tscCommand, tempTsConfigPath };
} else {
// Unix/Linux/macOS: Use ; to separate commands or && to chain
const nodePathPrefix = `NODE_PATH=${safe_bstack_node_modules_path}`;
const tscCommand = `${nodePathPrefix} node "${typescript_path}" --project "${tempTsConfigPath}" && ${nodePathPrefix} node "${tsc_alias_path}" --project "${tempTsConfigPath}" --verbose`;
logger.info(`TypeScript compilation command: ${tscCommand}`);
return { tscCommand, tempTsConfigPath };
}
}

exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_modules_path) => {
const cypress_config_filename = bsConfig.run_settings.cypress_config_filename
const working_dir = path.dirname(cypress_config_filepath);
Expand All @@ -22,19 +175,12 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
}
fs.mkdirSync(complied_js_dir, { recursive: true })

const typescript_path = path.join(bstack_node_modules_path, 'typescript', 'bin', 'tsc')
const { tscCommand, tempTsConfigPath } = generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath);

let tsc_command = `NODE_PATH=${bstack_node_modules_path} node "${typescript_path}" --outDir "${complied_js_dir}" --listEmittedFiles true --allowSyntheticDefaultImports --module commonjs --declaration false "${cypress_config_filepath}"`

if (/^win/.test(process.platform)) {
tsc_command = `set NODE_PATH=${bstack_node_modules_path}&& node "${typescript_path}" --outDir "${complied_js_dir}" --listEmittedFiles true --allowSyntheticDefaultImports --module commonjs --declaration false "${cypress_config_filepath}"`
}


let tsc_output
try {
logger.debug(`Running: ${tsc_command}`)
tsc_output = cp.execSync(tsc_command, { cwd: working_dir })
logger.debug(`Running: ${tscCommand}`)
tsc_output = cp.execSync(tscCommand, { cwd: working_dir })

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.detect-child-process.detect-child-process

Detected calls to child_process from a function argument `bsConfig`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.detect-child-process.detect-child-process

Detected calls to child_process from a function argument `bstack_node_modules_path`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

Check failure

Code scanning / Semgrep OSS

Semgrep Finding: javascript.lang.security.detect-child-process.detect-child-process

Detected calls to child_process from a function argument `cypress_config_filepath`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

Check warning

Code scanning / CodeQL

Shell command built from environment values

This shell command depends on an uncontrolled [absolute path](1).

Copilot Autofix

AI about 1 year ago

To fix the problem, we should avoid constructing shell commands as strings with interpolated environment values. Instead, we should use child_process.execFileSync (or spawnSync) and pass the command and its arguments as separate parameters. This prevents the shell from interpreting special characters in the arguments, eliminating the risk of command injection. Specifically, in convertTsConfig, instead of building a string like NODE_PATH=... node ..., we should set the environment variable via the env option and pass the script and its arguments as an array. This requires refactoring both the command construction in generateTscCommandAndTempTsConfig and the execution in convertTsConfig. We need to:

  • Refactor generateTscCommandAndTempTsConfig to return the command and arguments separately for each step (setting NODE_PATH, running node, etc.).
  • In convertTsConfig, execute each step using execFileSync, passing the environment variable via the env option.
  • Ensure platform compatibility (Windows vs. Unix) by setting environment variables appropriately.
  • Remove the use of shell command chaining (&&) and instead run each command sequentially.

All changes are to be made in bin/helpers/readCypressConfigUtil.js.

Suggested changeset 1
bin/helpers/readCypressConfigUtil.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/bin/helpers/readCypressConfigUtil.js b/bin/helpers/readCypressConfigUtil.js
--- a/bin/helpers/readCypressConfigUtil.js
+++ b/bin/helpers/readCypressConfigUtil.js
@@ -150,20 +150,19 @@
   
   // Platform-specific command generation with sanitized paths
   const isWindows = /^win/.test(process.platform);
-  
-  if (isWindows) {
-    // Windows: Use && to chain commands, no space after SET
-    const setNodePath = `set NODE_PATH=${safe_bstack_node_modules_path}`;
-    const tscCommand = `${setNodePath} && node "${typescript_path}" --project "${tempTsConfigPath}" && ${setNodePath} && node "${tsc_alias_path}" --project "${tempTsConfigPath}" --verbose`;
-    logger.info(`TypeScript compilation command: ${tscCommand}`);
-    return { tscCommand, tempTsConfigPath };
-  } else {
-    // Unix/Linux/macOS: Use ; to separate commands or && to chain
-    const nodePathPrefix = `NODE_PATH=${safe_bstack_node_modules_path}`;
-    const tscCommand = `${nodePathPrefix} node "${typescript_path}" --project "${tempTsConfigPath}" && ${nodePathPrefix} node "${tsc_alias_path}" --project "${tempTsConfigPath}" --verbose`;
-    logger.info(`TypeScript compilation command: ${tscCommand}`);
-    return { tscCommand, tempTsConfigPath };
-  }
+
+  // Prepare command and arguments for execFileSync
+  const nodeEnv = Object.assign({}, process.env, { NODE_PATH: safe_bstack_node_modules_path });
+  const tscArgs = ["--project", tempTsConfigPath];
+  const tscAliasArgs = ["--project", tempTsConfigPath, "--verbose"];
+  // Return command/args/env for both steps
+  return {
+    commands: [
+      { command: "node", args: [typescript_path, ...tscArgs], env: nodeEnv },
+      { command: "node", args: [tsc_alias_path, ...tscAliasArgs], env: nodeEnv }
+    ],
+    tempTsConfigPath
+  };
 }
 
 exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_modules_path) => {
@@ -175,17 +174,26 @@
     }
     fs.mkdirSync(complied_js_dir, { recursive: true })
 
-    const { tscCommand, tempTsConfigPath } = generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath);
+    const { commands, tempTsConfigPath } = generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath);
 
-    let tsc_output
+    let tsc_output = Buffer.alloc(0);
     try {
-        logger.debug(`Running: ${tscCommand}`)
-        tsc_output = cp.execSync(tscCommand, { cwd: working_dir })
+        for (const cmdObj of commands) {
+            logger.debug(`Running: ${cmdObj.command} ${cmdObj.args.join(" ")}`);
+            // execFileSync returns Buffer, concatenate outputs
+            const output = cp.execFileSync(cmdObj.command, cmdObj.args, { cwd: working_dir, env: cmdObj.env });
+            tsc_output = Buffer.concat([tsc_output, output]);
+        }
     } catch (err) {
         // error while compiling ts files
         logger.debug(err.message);
-        logger.debug(err.output.toString());
-        tsc_output = err.output // if there is an error, tsc adds output of complilation to err.output key
+        if (err.output) {
+            logger.debug(err.output.toString());
+            tsc_output = err.output; // if there is an error, tsc adds output of complilation to err.output key
+        } else if (err.stdout) {
+            logger.debug(err.stdout.toString());
+            tsc_output = err.stdout;
+        }
     } finally {
         logger.debug(`Saved compiled js output at: ${complied_js_dir}`);
         logger.debug(`Finding compiled cypress config file in: ${complied_js_dir}`);
EOF
@@ -150,20 +150,19 @@

// Platform-specific command generation with sanitized paths
const isWindows = /^win/.test(process.platform);

if (isWindows) {
// Windows: Use && to chain commands, no space after SET
const setNodePath = `set NODE_PATH=${safe_bstack_node_modules_path}`;
const tscCommand = `${setNodePath} && node "${typescript_path}" --project "${tempTsConfigPath}" && ${setNodePath} && node "${tsc_alias_path}" --project "${tempTsConfigPath}" --verbose`;
logger.info(`TypeScript compilation command: ${tscCommand}`);
return { tscCommand, tempTsConfigPath };
} else {
// Unix/Linux/macOS: Use ; to separate commands or && to chain
const nodePathPrefix = `NODE_PATH=${safe_bstack_node_modules_path}`;
const tscCommand = `${nodePathPrefix} node "${typescript_path}" --project "${tempTsConfigPath}" && ${nodePathPrefix} node "${tsc_alias_path}" --project "${tempTsConfigPath}" --verbose`;
logger.info(`TypeScript compilation command: ${tscCommand}`);
return { tscCommand, tempTsConfigPath };
}

// Prepare command and arguments for execFileSync
const nodeEnv = Object.assign({}, process.env, { NODE_PATH: safe_bstack_node_modules_path });
const tscArgs = ["--project", tempTsConfigPath];
const tscAliasArgs = ["--project", tempTsConfigPath, "--verbose"];
// Return command/args/env for both steps
return {
commands: [
{ command: "node", args: [typescript_path, ...tscArgs], env: nodeEnv },
{ command: "node", args: [tsc_alias_path, ...tscAliasArgs], env: nodeEnv }
],
tempTsConfigPath
};
}

exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_modules_path) => {
@@ -175,17 +174,26 @@
}
fs.mkdirSync(complied_js_dir, { recursive: true })

const { tscCommand, tempTsConfigPath } = generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath);
const { commands, tempTsConfigPath } = generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath);

let tsc_output
let tsc_output = Buffer.alloc(0);
try {
logger.debug(`Running: ${tscCommand}`)
tsc_output = cp.execSync(tscCommand, { cwd: working_dir })
for (const cmdObj of commands) {
logger.debug(`Running: ${cmdObj.command} ${cmdObj.args.join(" ")}`);
// execFileSync returns Buffer, concatenate outputs
const output = cp.execFileSync(cmdObj.command, cmdObj.args, { cwd: working_dir, env: cmdObj.env });
tsc_output = Buffer.concat([tsc_output, output]);
}
} catch (err) {
// error while compiling ts files
logger.debug(err.message);
logger.debug(err.output.toString());
tsc_output = err.output // if there is an error, tsc adds output of complilation to err.output key
if (err.output) {
logger.debug(err.output.toString());
tsc_output = err.output; // if there is an error, tsc adds output of complilation to err.output key
} else if (err.stdout) {
logger.debug(err.stdout.toString());
tsc_output = err.stdout;
}
} finally {
logger.debug(`Saved compiled js output at: ${complied_js_dir}`);
logger.debug(`Finding compiled cypress config file in: ${complied_js_dir}`);
Copilot is powered by AI and may make mistakes. Always verify output.
} catch (err) {
// error while compiling ts files
logger.debug(err.message);
Expand All @@ -44,6 +190,21 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
logger.debug(`Saved compiled js output at: ${complied_js_dir}`);
logger.debug(`Finding compiled cypress config file in: ${complied_js_dir}`);

// Clean up the temporary tsconfig file
if (fs.existsSync(tempTsConfigPath)) {
fs.unlinkSync(tempTsConfigPath);
logger.debug(`Temporary tsconfig file removed: ${tempTsConfigPath}`);
}

if (tsc_output) {
logger.debug(tsc_output.toString());
}

if (!tsc_output) {
logger.error('No TypeScript compilation output available');
return null;
}

const lines = tsc_output.toString().split('\n');
let foundLine = null;
for (let i = 0; i < lines.length; i++) {
Expand All @@ -53,7 +214,7 @@ exports.convertTsConfig = (bsConfig, cypress_config_filepath, bstack_node_module
}
}
if (foundLine === null) {
logger.error(`No compiled cypress config found. There might some error running ${tsc_command} command`)
logger.error(`No compiled cypress config found. There might some error running ${tscCommand} command`)
return null
} else {
const compiled_cypress_config_filepath = foundLine.split('TSFILE: ').pop()
Expand Down
Loading