Skip to content

Feat: Enhanced TS support for browserstack-cypress-cli #982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
85 changes: 73 additions & 12 deletions bin/helpers/readCypressConfigUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,65 @@
return constants.CYPRESS_V10_AND_ABOVE_CONFIG_FILE_EXTENSIONS.includes(extension) ? extension : 'js'
}

function generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, cypress_config_filepath) {
const working_dir = path.dirname(cypress_config_filepath);
const typescript_path = path.join(bstack_node_modules_path, 'typescript', 'bin', 'tsc');
const tsc_alias_path = path.join(bstack_node_modules_path, 'tsc-alias', 'dist', 'bin', 'index.js');
const tsConfigFilePath = bsConfig.run_settings.ts_config_file_path;

// Prepare base temp tsconfig
const tempTsConfig = {
compilerOptions: {
"outDir": `${path.basename(complied_js_dir)}`, // Add ./ prefix for consistency
"listEmittedFiles": true,
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"declaration": false,
"baseUrl": ".", // Default fallback baseUrl
"skipLibCheck": true
},
include: [cypress_config_filepath]
};

// Inject paths and baseUrl from original tsconfig if available
if (tsConfigFilePath && fs.existsSync(tsConfigFilePath) && path.extname(tsConfigFilePath).toLowerCase() === '.json') {
const tsConfig = JSON.parse(fs.readFileSync(tsConfigFilePath, 'utf8'));
if (tsConfig.compilerOptions) {
if (tsConfig.compilerOptions.paths) {
tempTsConfig.compilerOptions.baseUrl = path.dirname(path.resolve(tsConfigFilePath));
tempTsConfig.compilerOptions.paths = tsConfig.compilerOptions.paths;
}
}
} else {
logger.warn(`tsconfig file not found or invalid: ${tsConfigFilePath}`);
}

// Write the temporary tsconfig
const tempTsConfigPath = path.join(working_dir, 'tsconfig.singlefile.tmp.json');
fs.writeFileSync(tempTsConfigPath, JSON.stringify(tempTsConfig, null, 2));
logger.info(`Temporary tsconfig created at: ${tempTsConfigPath}`);

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

if (isWindows) {
// Windows: Use && to chain commands, no space after SET
const setNodePath = isWindows
? `set NODE_PATH=${bstack_node_modules_path}`
: `NODE_PATH="${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=${bsConfig.run_settings.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 +81,13 @@
}
fs.mkdirSync(complied_js_dir, { recursive: true })

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

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}"`
}
const { tscCommand, tempTsConfigPath } = generateTscCommandAndTempTsConfig(bsConfig, bstack_node_modules_path, complied_js_dir, 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 })
cp.execSync(tscCommand, { cwd: working_dir })
} catch (err) {
// error while compiling ts files
logger.debug(err.message);
Expand All @@ -44,6 +97,14 @@
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.info(`Temporary tsconfig file removed: ${tempTsConfigPath}`);
}

logger.info(tsc_output.toString());

const lines = tsc_output.toString().split('\n');
let foundLine = null;
for (let i = 0; i < lines.length; i++) {
Expand All @@ -53,7 +114,7 @@
}
}
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 Expand Up @@ -113,4 +174,4 @@
fs.rmdirSync(complied_js_dir, { recursive: true })
}
}
}
}
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@
"browserstack-local": "1.5.4",
"chalk": "4.1.2",
"cli-progress": "^3.10.0",
"decompress": "4.2.1",
"form-data": "^4.0.0",
"fs-extra": "8.1.0",
"getmac": "5.20.0",
"git-last-commit": "^1.0.1",
"git-repo-info": "^2.1.1",
"gitconfiglocal": "^2.1.0",
"glob": "^7.2.0",
"mocha": "^10.2.0",
"mkdirp": "1.0.4",
"mocha": "^10.2.0",
"node-ipc": "9.1.1",
"table": "5.4.6",
"unzipper": "^0.12.3",
"update-notifier": "7.0.0",
"uuid": "8.3.2",
"windows-release": "^5.1.0",
"winston": "2.4.4",
"yargs": "14.2.3",
"decompress": "4.2.1",
"unzipper": "^0.12.3"
"yargs": "14.2.3"
},
"repository": {
"type": "git",
Expand Down
Loading