Skip to content
Merged
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
36 changes: 27 additions & 9 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
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',
};

/**
Expand Down Expand Up @@ -389,7 +390,7 @@
.reduce((promise, name) => promise.then(() => new Promise((resolve, reject) => {
const hook = this.createHook(name, data);
hook((err, result) => {
err ? reject(err) : resolve(result);

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 22 and macos-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 24 and ubuntu-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 22 and ubuntu-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 26 and ubuntu-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 26 and macos-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 24 and macos-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 22 and windows-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 26 and windows-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 393 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 24 and windows-latest

eslint(no-unused-expressions)

Expected expression to be used
});
})), Promise.resolve(this));

Expand All @@ -416,7 +417,13 @@
const cmd = args.pop();
args.pop(); // discard argv

// remove any trailing undefined args
// `args` are Commander's action-handler arguments, one entry per declared
// positional in order. Variadic positionals (e.g. `sdk uninstall
// [versions...]`) arrive as a nested array, which consumers like
// `sdk.js` rely on (`cli.argv._[0]` is the versions array). Flattening to
// `cmd.args` here would collapse that array into a string and break them.
// The `serve`/`build` positional platform is handled separately in
// `initBuildPlatform()` via `command.processedArgs`, not `argv._`.
while (args.length && args[args.length - 1] === undefined) {
args.pop();
}
Expand Down Expand Up @@ -621,20 +628,19 @@
}

/**
* 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;
}

Expand All @@ -643,6 +649,15 @@
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
Expand Down Expand Up @@ -983,6 +998,9 @@
this.command.createHelp = () => {
return Object.assign(new TiHelp(this, conf.platforms), this.command.configureHelp());
};

cmd.argument('[platform]', 'target platform');
cmd.usage('[platform] [options]');
}

applyCommandConfig(this, cmdName, cmd, conf);
Expand Down Expand Up @@ -1446,7 +1464,7 @@
opt.validated = true;
if (opt.callback) {
var val = opt.callback(this.argv[name] || '');
val !== undefined && (this.argv[name] = val);

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 22 and macos-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 24 and ubuntu-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 22 and ubuntu-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 26 and ubuntu-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 26 and macos-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 24 and macos-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 22 and windows-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 26 and windows-latest

eslint(no-unused-expressions)

Expected expression to be used

Check warning on line 1467 in src/cli.js

View workflow job for this annotation

GitHub Actions / Test on Node.js 24 and windows-latest

eslint(no-unused-expressions)

Expected expression to be used
delete opt.callback;
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/commands/ti-build.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('ti build', () => {

const output = stripColor(stdout);
expect(output).toMatch(/Titanium Command-Line Interface/);
expect(output).toMatch(/Usage: titanium build \[options\]/);
expect(output).toMatch(/Usage: titanium build \[platform\] \[options\]/);
expect(output).toMatch(/Builds an existing app or module project./);
expect(output).toMatch(/Build Options:/);
expect(output).toMatch(/Global Options:/);
Expand Down
25 changes: 25 additions & 0 deletions test/commands/ti-sdk.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,29 @@ describe('ti sdk', () => {
expect(exitCode).toBe(0);
}));
});

// Regression guard: `sdk uninstall` takes a variadic `[versions...]`
// positional, which `sdk.js` reads as the array `cli.argv._[0]`. A parsing
// change once flattened variadic positionals into individual strings, so
// `versions.filter()` threw and the command printed usage instead of running.
// These cases reproduce that without network by uninstalling versions that
// are not installed, exercising single and multi-version parsing.
describe('uninstall', () => {
it('should parse a single version positional and report not found', initSDKHome(async ({ run }) => {
const { exitCode, stdout } = await run(['sdk', 'uninstall', '99.99.99.GA', '--force']);

const output = stripColor(stdout);
expect(output).toMatch(/99\.99\.99\.GA\s+not found/);
expect(exitCode).toBe(0);
}));

it('should parse multiple version positionals and report each not found', initSDKHome(async ({ run }) => {
const { exitCode, stdout } = await run(['sdk', 'uninstall', '98.0.0.GA', '99.0.0.GA', '--force']);

const output = stripColor(stdout);
expect(output).toMatch(/98\.0\.0\.GA\s+not found/);
expect(output).toMatch(/99\.0\.0\.GA\s+not found/);
expect(exitCode).toBe(0);
}));
});
});
Loading