Skip to content
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

Titanium CLI v7 Beta 1 #618

Merged
merged 117 commits into from
Jan 11, 2024
Merged

Titanium CLI v7 Beta 1 #618

merged 117 commits into from
Jan 11, 2024

Conversation

cb1kenobi
Copy link
Contributor

@cb1kenobi cb1kenobi commented Sep 11, 2023

The Titanium CLI has been long overdue for a little ❤️

Dependencies are extremely out-of-date. Some of them are deprecated, abandoned, and/or contained critical issues. Things got so bad, we disabled Dependabot. Since the Titanium CLI wasn't an ES module, we couldn't adopt newer libraries.

On top of that, the Titanium CLI is littered with a bunch of half baked ideas. It supported for localized strings, but we sadly lost all of the translated strings a long time ago. It sorta had the beginnings of shell tab completion, but I never finished it. The whole "selected SDK" concept was really bad (sorry). The list goes on and on.

After a nearly a month of late nights and weekends, I essentially rewrote the entire CLI. Let's start at the top.

1. Node.js 18 or newer is required

Node.js 16 and older are all end-of-life. We will continue to test and support any actively maintained Node.js release.

2. The Titanium CLI is now a proper ES module.

This means the CLI and SDK can use any ES module npm package!

3. Remove all Appcelerator/Axway related stuff

Removed the ti login, ti logout, and ti whoami commands. Removed telemetry. This was dead code.

4. Removed i18n logic

The CLI would detect your locale and display messages in your preferred language, however really only had strings in English. A long time ago we had Spanish, Hindi, and a good chunk of Ukrainian, but we sadly lost all of the translations. So the whole i18n stuff was pointless.

5. Removed incomplete tab completion code

Never worked. Dead code. Removed.

6. No more selected SDK

Back in the day, we were adding new iOS and Android settings to the tiapp.xml every release, so I put the tiapp.xml parser in the SDK, not the CLI. Part of the reason besides new settings being added was the logic that translated the XML into JSON was rather strict. Another part was we sorta thought we would ship the SDK way more often than the CLI. Turns out, we would ship a new CLI every release.

The CLI would have to load a Titanium SDK so that it could parse the tiapp.xml and get the project's <sdk-version>. If that version didn't match the one used to read the tiapp.xml, it would "fork" the CLI again with the correct SDK. This was slow.

Another artifact was when you did ti sdk install, we would say pass in --default to select the newly installed SDK. You would use ti sdk select to change the selected SDK.

I have finally fixed this horrible design. I have removed ti sdk select. There is no more need for the --default flag when you install an SDK. No more forking the correct SDK. The CLI now parses the tiapp.xml and selects the correct SDK based on your project or the --sdk option. When you create a new project, it will prompt you which SDK to create the project for.

image

7. --log-level is now a global option

This used to be a SDK command option, but the logger is owned by the CLI, not the SDK. It didn't make sense. The "trace" level logging will now output a some extra CLI related info, but in general you should stick with "info" or "debug".

When I started building the CLI, it wasn't clear as to how the logger was going to be used. We didn't know if we were going to write it to disk or exactly how the log levels were going to work. We chose the winston package, but I had to hack it a bit to do what I needed. Now that we're a little older and wiser, Winston is no longer needed. I ripped it out and replaced it with a lightweight logger. It doesn't have bells and whistles, but it gets the job done.

Furthermore, trace, debug, warn, and error log messages are written to stderr. info and normal console.log() output is written to stdout. Undecided if this was the best idea, so we'll see.

Lastly, if you set --log-level trace, it displays a total command run time at the end. Maybe interesting if you do a dist build or something, not so much for simulator/emulator builds as the process stays running to display app logs.

8. ti config changes

Before ti config --output json would display the config with the key being the dot notation name and ti config --output json-object would display the config as an object. This was dumb. I've replaced this with a simple ti config --json which returns the object form of the config. Simple.

9. paths.commands setting removed

This was a list of paths to search for commands to add in addition to the build-in commands and SDK commands. Since this setting was probably never used and searching/loading additional commands is slow, this setting has been removed.

10. ti info changes

Like ti config, --output json has been replaced with a simple --json.

The following information has been removed:

  • haxm (used for speeding up old arm-based Android emulators)
  • Genymotion (to be deprecated)
  • VirtualBox (used for Genymotion)
  • macOS and Xcode CLI tools (unused)
  • JDK jarsigner executable (unsued, no need now that we use Gradle)
  • nodeAppcVer in CLI/SDK info (unused)

Also removed the old "v1" Android and iOS detection code. This code path would only run if there wasn't an SDK installed. "v2" Android and iOS detection is done by the SDK. If you don't have an SDK, then there's nothing to detect.

11. ti module changes

This command displays installed modules. The JSON output contains both iphone and ios data which are exactly the same. This is an artifact of when the iPad was released and I started trying to move away from calling things iphone.

12. ti sdk changes

As listed above, ti sdk select removed and ti sdk install no longer supports --default.

ti sdk list can now be invoked by running ti sdk ls. ti sdk install has been shortened to ti sdk i and ti sdk uninstall has been shortened to ti sdk rm.

ti sdk list supports --json and no longer returns an activeSDK property.

ti sdk install now uses undici to download the SDK. It's suppose to be faster. Can you tell?

13. ti setup changes

Removed all Windows publishing info, user locale, and SDK setup. It's no longer needed.

Under the "check" screen, removed a bunch of useless info such as haxm, Xcode CLI tools, and CLI dependency info.

14. Updated dependencies

The CLI no longer relies on the outdated node-appc. This package was a collection of common code to be shared across all Appc Node.js-based projects, however Titanium packages were the ones that really used it. Since this package contains more code than the CLI needs and this package is so out-of-date, only the necessary pieces were copied and updated into the CLI code base.

Other packages where replaced with modern alternatives:

  • Replaced colors with chalk
  • Replaced fields with prompts
  • Replaced humanize with pretty-bytes
  • Replaced request with undici

15. Command Line Parsing

The Titanium CLI originally used optimist, but it wasn't long before optimist was copied directly into the Titanium CLI and heavily modified. I needed to make it parse args out-of-order, lazy load additional command contexts and options, etc. I figured it was time to modernize this and I have switched over to Commander.js.

As cool as this idea is, I sort of regret it. In short, Commander.js isn't great at loading additional options and such while parsing. I had to do a bunch of hacks using hooks and manipulating state. It works, but it's still gross. I passed the point of no return long before I realized this. I was tempted to use cli-kit, a library I wrote for the Axway CLI and Appc Daemon, but at the end of the day, the complications all stem from the platform specific code in the SDK, not the CLI. The idea now is to refactor the SDK code to use Commander.js better.

16. Prompting

As apart of this refactor, I've switched the default prompt library from fields to prompts. I wrote fields and it was pretty rad, but I didn't really take it to the next level. There wasn't time to introduce new cute prompts. I had hoped to take fields and modernize it as apart of cli-kit, but that never happened. prompts is a decent library and the default prompt library. Just note that some of the prompts are coming from the SDK and continue to use fields.

17. Switching to pnpm

For development, I've switched over to the superior pnpm package manager. Just run pnpm i to install the dependencies. There's no build command because there's no transpilation, no TypeScript, no Babel. Maybe someday...

18. Tests and Linting

All test were incredibly out-of-date. It's much easier to start over. Sit tight, they'll be back.

19. Performance Improvement?

Sadly I don't have benchmarks, but hopefully there's a noticable speed gain. Here's what changed:

  • Minify source using esbuild
  • Lazy load modules as much as possible, within reason
  • Removed tons of old dead code
  • Use smaller alternative dependencies
  • Added total run time log message when --log-level trace

Prelimiary package deltas:

Titanium CLI 6.1.2 Titanium CLI 7.0.0
# Files 39 files 35 files
Tarball Size 80 KB 37.4 KB
Extracted Size 317.9 KB 106.5 KB
Install Size on Disk w/ Deps 14.1 MB 4.23 MB
Vulnerabilities 4 moderate 0

Help Wanted

This is a monster PR that needs lots of testing. You must use Node 18 or newer. Clone and pull this PR. Run pnpm i. Link the bin/ti.js script to ti. I developed this on Windows with very limited testing on macOS. I have not tested Linux at all. I have not tested this with the VS Code or Atom plugins. I expect issues.

Here's the plan:

  • Add back the linting and some tests
  • Manually test this PR
  • Fix issues
  • Merge this PR into the 7_0_X branch
  • Publish it as a public beta and tagged next so users can then npm i -g titanium@next to test it
  • When ready, publish 7.0.0 as GA and tagged latest

Cheers!

@m1ga
Copy link
Contributor

m1ga commented Jan 8, 2024

Did a very quick test with the latest version, but only info, sdk and create.

The short-cut to create a project in one line: tidev/titanium-sdk#13641 (comment) is not working anymore. It think that's how the editors call the CLI but I'll have to double check.

Do you think the Which Titanium SDK would you like to use? is needed? I would use the latest stable. If people want to use an older (or testing) SDK they can do it in the tiapp.xml.

Think this:
Screenshot_20240108_204123
should be use arrows to select and return to submit or something like this.

@cb1kenobi
Copy link
Contributor Author

I tested ti create -t app -f -d . -n test -p all --id test -u . and it worked. I dunno what the --alloy flag does. What error did you see when creating a project?

The Which Titanium SDK would you like to use? prompt should only appear if you run ti create without any options. Yes the code path is there for any command, but I think ti create is the only one that prompts. I kinda like it, but I'm open to removing the SDK prompt and using the latest installed.

Fixed the SDK prompt hint!

@m1ga
Copy link
Contributor

m1ga commented Jan 8, 2024

Ah, I just saw it was showing the package.json error again because I'm running it in the CLI folder which has a package.json. If I run it in a normal folder it works! We had that before, didn't see the error before as it was showing the help page again.

--alloy was the shortcut to create an Alloy project right away without the need to go into the folder and calling alloy new by hand. The linked PR above has the code for it. Basically it looks for cli.argv.alloy and runs alloy new for you.

Keep the Which Titanium SDK would you like to use?. Looks nice. Most people will use the editor to create new projects anyways

@cb1kenobi
Copy link
Contributor Author

Is the package.json error a v7 thing?

Ah, I see. OK, --alloy is probably a legit bug.

@m1ga
Copy link
Contributor

m1ga commented Jan 8, 2024

If you run it in a folder with a package.json it will output

Error: Cannot find module 'package.json'
Require stack:
- /home/miga/.titanium/mobilesdk/linux/12.2.1.GA/cli/hooks/webpack.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1082:15)
    at Module._load (node:internal/modules/cjs/loader:928:27)
    at Module.require (node:internal/modules/cjs/loader:1149:19)
    at require (node:internal/modules/helpers:121:18)
    at getWebpackProjectType (/home/miga/.titanium/mobilesdk/linux/12.2.1.GA/cli/hooks/webpack.js:145:14)
    at /home/miga/.titanium/mobilesdk/linux/12.2.1.GA/cli/hooks/webpack.js:41:17
    at file:///home/miga/tools/ti-cli-v7/src/cli.js:323:19
    at async file:///home/miga/tools/ti-cli-v7/src/cli.js:307:5

@cb1kenobi
Copy link
Contributor Author

Fixed the --alloy issue.

I cannot reproduce the package.json issue. It is happening with cli.argv['project-dir'] is an empty string. I'm not sure how you got in that state. I'll keep testing.

@cb1kenobi
Copy link
Contributor Author

Fixed package.json issue.

The webpack.js hook has a bug. It processes cli.argv['project-dir'], then validates that the command is the build command, however the project-dir is a build command option, so really the code should have validated the command first, then the project-dir.

--project-dir is now a global option in v7 and thus it was defaulting it to '.' whereas it was undefined in v6 and why things worked before.

In any case, I fixed v7 to properly resolve the path making webpack.js happy, even though it's doing unnecessary work.

@cb1kenobi cb1kenobi changed the title Titanium CLI v7 ALPHA Titanium CLI v7 Beta 1 Jan 11, 2024
@cb1kenobi
Copy link
Contributor Author

@m1ga says:

SHIP IT 😄

@cb1kenobi cb1kenobi merged commit 69c126f into tidev:7_0_X Jan 11, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants