diff --git a/package.json b/package.json index 637f1761..6a713929 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "titanium", - "version": "8.1.5", + "version": "8.2.0", "author": "TiDev, Inc. ", "description": "Command line interface for building Titanium SDK apps", "type": "module", diff --git a/src/cli.js b/src/cli.js index cb793a7d..39557e33 100644 --- a/src/cli.js +++ b/src/cli.js @@ -36,7 +36,8 @@ const sdkCommands = { build: 'builds a project', clean: 'removes previous build directories', create: 'creates a new project', - project: 'get and set tiapp.xml settings' + project: 'get and set tiapp.xml settings', + serve: 'serves a project through the Titanium Vite runtime', }; /** @@ -416,12 +417,17 @@ export class CLI { const cmd = args.pop(); args.pop(); // discard argv - // remove any trailing undefined args - while (args.length && args[args.length - 1] === undefined) { - args.pop(); + // Commander keeps declared and excess positional args on the command. + const positionalArgs = Array.isArray(cmd?.args) ? cmd.args.slice() : []; + if (positionalArgs.length) { + this.argv._ = positionalArgs; + } else { + // Fallback for command handlers that pass positional args directly. + while (args.length && args[args.length - 1] === undefined) { + args.pop(); + } + this.argv._ = args; } - - this.argv._ = args; this.applyArgv(cmd); if (!this.ready) { @@ -621,20 +627,19 @@ export class CLI { } /** - * If the current command is the "build" command, this function will check - * if the "build" command has a `--platform` option (which is should), then - * prompt for the platform is not explicitly passed in. + * If the current command supports platform-specific config, this function + * checks for the `--platform` option and prompts when missing. * - * Finally, the platform specific options and flags are added to the - * Commander.js "build" command context so that the second parse will - * pick up the newly defined options/flags. + * Finally, the platform specific options and flags are added to the command + * context so that the second parse picks up the newly defined options/flags. * * @returns {Promise} * @access private */ async initBuildPlatform() { const cmdName = this.command.name(); - if (cmdName !== 'build') { + // Commands with build-style platform branches. + if (cmdName !== 'build' && cmdName !== 'serve') { return; } @@ -643,6 +648,15 @@ export class CLI { return; } + // Support shorthand positional platform syntax, e.g. `ti serve ios`. + // Commander parses this into processedArgs via the [platform] argument + // declared in loadCommand(). + const positionalPlatform = this.command.processedArgs?.[0]; + if (!this.argv.platform && positionalPlatform && platformOption.values.includes(positionalPlatform)) { + this.debugLogger.trace(`Converting positional platform argument "${positionalPlatform}" to --platform`); + this.argv.platform = positionalPlatform; + } + // when specifying `--platform ios`, the SDK's option callback converts // it to `iphone`, however the platform config uses `ios` and we must // convert it back @@ -983,6 +997,8 @@ export class CLI { this.command.createHelp = () => { return Object.assign(new TiHelp(this, conf.platforms), this.command.configureHelp()); }; + + cmd.argument('[platform]', 'target platform'); } applyCommandConfig(this, cmdName, cmd, conf); diff --git a/test/commands/ti-build.test.js b/test/commands/ti-build.test.js index f1148598..e4e67135 100644 --- a/test/commands/ti-build.test.js +++ b/test/commands/ti-build.test.js @@ -9,7 +9,7 @@ describe('ti build', () => { const output = stripColor(stdout); assert.match(output, /Titanium Command-Line Interface/); - assert.match(output, /Usage: titanium build \[options\]/); + assert.match(output, /Usage: titanium build \[options\] \[platform\]/); assert.match(output, /Builds an existing app or module project./); assert.match(output, /Build Options:/); assert.match(output, /Global Options:/);