import * as plugins from './plugins.js'; import * as paths from './paths.js'; import * as tsbuild from './tsbuild.exports.js'; export const runCli = async () => { const tsbuildCli = new plugins.smartcli.Smartcli(); /** * the standard task compiles anything in ts/ directory to dist directory */ tsbuildCli.standardCommand().subscribe(async (argvArg) => { tsbuild.compileGlobStringObject( { './ts/**/*.ts': './dist_ts', }, {}, process.cwd(), argvArg ); }); /** * the custom command compiles any customDir to dist_customDir */ tsbuildCli.addCommand('custom').subscribe(async (argvArg) => { const listedDirectories = argvArg._; listedDirectories.shift(); // removes the first element that is "custom" const compilationCommandObject: { [key: string]: string } = {}; for (const directory of listedDirectories) { compilationCommandObject[`./${directory}/**/*.ts`] = `./dist_${directory}`; } await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg); }); /** * the emitcheck command checks if a TypeScript file can be emitted without actually emitting it */ tsbuildCli.addCommand('emitcheck').subscribe(async (argvArg) => { const patterns = argvArg._.slice(1); // Remove the first element which is 'emitcheck' if (patterns.length === 0) { console.error('Error: Please provide at least one TypeScript file path or glob pattern'); process.exit(1); } const cwd = process.cwd(); let allFiles: string[] = []; // Process each pattern - could be a direct file path or a glob pattern for (const pattern of patterns) { // Check if the pattern looks like a glob pattern if (pattern.includes('*') || pattern.includes('{') || pattern.includes('?')) { // Handle as glob pattern console.log(`Processing glob pattern: ${pattern}`); try { const matchedFiles = await plugins.smartfile.fs.listFileTree(cwd, pattern); // Ensure matchedFiles contains only strings const stringMatchedFiles = Array.isArray(matchedFiles) ? matchedFiles.filter((item): item is string => typeof item === 'string') : []; if (stringMatchedFiles.length === 0) { console.warn(`Warning: No files matched the pattern '${pattern}'`); } else { console.log(`Found ${stringMatchedFiles.length} files matching pattern '${pattern}'`); // Transform to absolute paths const absoluteMatchedFiles = plugins.smartpath.transform.toAbsolute( stringMatchedFiles, cwd ) as string[]; // Add to the list of all files to check allFiles = allFiles.concat(absoluteMatchedFiles); } } catch (err) { console.error(`Error processing glob pattern '${pattern}': ${err}`); } } else { // Handle as direct file path const filePath = plugins.path.isAbsolute(pattern) ? pattern : plugins.path.join(cwd, pattern); try { await plugins.smartfile.fs.fileExists(filePath); allFiles.push(filePath); } catch (err) { console.error(`Error: File not found: ${filePath}`); process.exit(1); } } } // Filter to only TypeScript files allFiles = allFiles.filter(file => file.endsWith('.ts') || file.endsWith('.tsx')); if (allFiles.length === 0) { console.error('Error: No TypeScript files found to check'); process.exit(1); } console.log(`Found ${allFiles.length} TypeScript files to check`); // Process compiler options const compilerOptions = tsbuild.mergeCompilerOptions({}, argvArg); // Run emit check const success = await tsbuild.emitCheck(allFiles, compilerOptions, argvArg); // Exit with appropriate code process.exit(success ? 0 : 1); }); /** * the custom command compiles any customDir to dist_customDir */ tsbuildCli.addCommand('tsfolders').subscribe(async (argvArg) => { const tsFolders = await plugins.smartfile.fs.listFolders(paths.cwd, /^ts/); // Now tsFolders contains all other folders except 'ts_shared' and 'ts_interfaces' // We've established a base order. Now let's look at tspublish.json based ranking. const tsPublishInstance = new plugins.tspublish.TsPublish(); const tsPublishModules = await tsPublishInstance.getModuleSubDirs(paths.cwd); // tsPublishModules is an object: { [folderName]: tspublishJsonData } // Create an array with folder names and their ranks const foldersWithOrder = []; for (const folder of tsFolders) { let rank = Infinity; // Default rank if not specified if (tsPublishModules[folder] && tsPublishModules[folder].order !== undefined) { rank = tsPublishModules[folder].order; } foldersWithOrder.push({ folder, rank }); } // Sort the folders based on rank foldersWithOrder.sort((a, b) => a.rank - b.rank); // Construct the sorted list of folders const sortedTsFolders = []; // Add the rest of the folders in sorted order for (const item of foldersWithOrder) { sortedTsFolders.push(item.folder); } // Let's make sure 'ts_shared' is always transpiled first const ensurePosition = (folderNameArg: string, ensuredPosition: number) => { if (tsFolders.indexOf(folderNameArg) > -1 && Object.keys(tsPublishModules).indexOf(folderNameArg) === -1) { sortedTsFolders.splice(tsFolders.indexOf(folderNameArg), 1); sortedTsFolders.splice(ensuredPosition, 0, folderNameArg); } } ensurePosition('ts_interfaces', 0); ensurePosition('ts_shared', 1); const compilationCommandObject: { [key: string]: string } = {}; console.log(`compiling in this order:`); console.log(sortedTsFolders); for (const tsFolder of sortedTsFolders) { compilationCommandObject[`./${tsFolder}/**/*.ts`] = `./dist_${tsFolder}`; } await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg); }); tsbuildCli.startParse(); };