Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | 24x 24x 1x 1x 23x 1x 1x 22x 1x 21x 24x 24x 24x 2x 2x 19x 1x 1x 1x 18x 1x 1x 1x 17x 17x 1x 1x 16x 1x 1x 1x 15x 1x 1x 14x 21x 21x | /**
* Cli
* Main CLI orchestrator that handles argument parsing, config loading,
* and dispatching to appropriate commands
*/
import { dirname, resolve } from "node:path";
import { existsSync, statSync } from "node:fs";
import ArgParser from "./ArgParser";
import ConfigLoader from "./ConfigLoader";
import ConfigPrinter from "./ConfigPrinter";
import PlatformIOCommand from "./PlatformIOCommand";
import CleanCommand from "./CleanCommand";
import PathNormalizer from "./PathNormalizer";
import ICliResult from "./types/ICliResult";
import ICliConfig from "./types/ICliConfig";
import IParsedArgs from "./types/IParsedArgs";
import IFileConfig from "./types/IFileConfig";
/**
* Main CLI orchestrator
*/
class Cli {
/**
* Run the CLI
* @returns CLI result with configuration for Runner if transpilation should run
*/
static run(): ICliResult {
// Parse arguments (yargs handles --help and --version automatically)
const args = ArgParser.parse(process.argv);
// Early exits for PlatformIO commands
if (args.pioInstall) {
PlatformIOCommand.install();
return { shouldRun: false, exitCode: 0 };
}
if (args.pioUninstall) {
PlatformIOCommand.uninstall();
return { shouldRun: false, exitCode: 0 };
}
// Early exit for serve mode (JSON-RPC server)
if (args.serveMode) {
return {
shouldRun: false,
exitCode: 0,
serveMode: true,
serveDebug: args.verbose,
};
}
// Load config file (searches up from input file directory)
const configDir =
args.inputFiles.length > 0
? dirname(resolve(args.inputFiles[0]))
: process.cwd();
const fileConfig = ConfigLoader.load(configDir);
// Merge CLI args with file config
const config = this.mergeConfig(args, fileConfig);
// Handle --config: show effective configuration
if (args.showConfig) {
ConfigPrinter.showConfig(config, fileConfig);
return { shouldRun: false, exitCode: 0 };
}
// Validate single entry point
if (args.inputFiles.length > 1) {
console.error("Error: Only one entry point file is supported");
console.error(
"Other files are discovered automatically via #include directives",
);
return { shouldRun: false, exitCode: 1 };
}
if (!config.input) {
console.error("Error: No input file specified");
console.error("Usage: cnext <file.cnx>");
return { shouldRun: false, exitCode: 1 };
}
const resolvedInput = resolve(config.input);
if (!existsSync(resolvedInput)) {
console.error(`Error: Input not found: ${config.input}`);
return { shouldRun: false, exitCode: 1 };
}
if (statSync(resolvedInput).isDirectory()) {
console.error(
"Error: Directory input not supported. Specify an entry point file.",
);
console.error(`Example: cnext ${config.input}/main.cnx`);
return { shouldRun: false, exitCode: 1 };
}
// Handle --clean: delete generated files
if (args.cleanMode) {
CleanCommand.execute(
config.input,
config.outputPath,
config.headerOutDir,
);
return { shouldRun: false, exitCode: 0 };
}
return { shouldRun: true, exitCode: 0, config };
}
/**
* Merge CLI arguments with file configuration
* CLI flags take precedence over config file values
*/
private static mergeConfig(
args: IParsedArgs,
fileConfig: IFileConfig,
): ICliConfig {
const rawConfig: ICliConfig = {
input: args.inputFiles[0] ?? "",
outputPath: args.outputPath || fileConfig.output || "",
// Merge include dirs: config includes come first, CLI includes override/append
includeDirs: [...(fileConfig.include ?? []), ...args.includeDirs],
defines: args.defines,
preprocess: args.preprocess,
verbose: args.verbose,
cppRequired: args.cppRequired || fileConfig.cppRequired || false,
noCache: args.noCache || fileConfig.noCache === true,
parseOnly: args.parseOnly,
headerOutDir: args.headerOutDir ?? fileConfig.headerOut,
basePath: args.basePath ?? fileConfig.basePath,
target: args.target ?? fileConfig.target,
debugMode: args.debugMode || fileConfig.debugMode,
};
return PathNormalizer.normalizeConfig(rawConfig);
}
}
export default Cli;
|