Skip to content

refactor: move the remaining command wiring into per-feature factories - #45

Merged
beeman merged 1 commit into
mainfrom
beeman/move-remaining-command-wiring-to-features
Sep 4, 2026
Merged

refactor: move the remaining command wiring into per-feature factories#45
beeman merged 1 commit into
mainfrom
beeman/move-remaining-command-wiring-to-features

Conversation

@beeman

@beeman beeman commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #41, which moved localnet's wiring into a feature-owned factory. This does the same for the other six commands, leaving create for a third PR.

src/app.ts drops from 504 lines to 167 and now names two dependencies instead of twenty-four.

What changed

Each of device, doctor, emulator, playground, templates and webshell exports create<Name>Command(deps): Command from <name>-feature.ts, which replaces its <name>-feature-index.ts barrel. createApp registers them with addCommand in alphabetical order and forwards the whole options object; each factory picks its own keys and applies its own defaults.

AppOptions is now an intersection of the seven per-feature <Name>CommandDeps types plus checkForNewerVersion and runCreate. The keys stay flat, so every existing createApp({ runEmulatorList: … }) call site is untouched.

The feature files are wiring only, so the three barrels that held implementation split rather than move:

was now
playground-feature-index.ts (runPlayground) playground-feature-serve.ts
doctor-feature-index.ts (orchestration) doctor-feature-check.ts
doctor-feature-index.ts (pure report functions) data-access/doctor-report.ts

Doctor's split follows what its test file was already saying: test/doctor.test.ts imported everything from data-access/* except buildDoctorReport, deriveCapabilities and getDoctorExitCode, which it reached into the barrel for. Those are pure functions over check results, so they belong in data-access and that file's imports are now single-layer.

src/templates.ts — the published ./templates subpath export — keeps a byte-identical surface, now sourced directly from data-access/* and the three templates-feature-*.ts files. Verified by diffing its exported identifiers against main.

Tests

26 wiring tests move out of test/core.test.ts (1446 → 965 lines) into the feature suites that own them — 3 to device, 18 to emulator, 4 to templates, plus the device tune output-silencing helper. core.test.ts keeps only genuinely app-level tests.

It also gains one. The addCommand settings-copy from #41 is now asserted across all seven feature commands at once instead of localnet alone, so the localnet-specific guard is removed as duplicated — with seven commands on that path (eight after PR 3), a single-feature guard was the wrong shape. Verified by deleting the copy line in createApp: the new test fails and the suite goes to 1 fail.

Verification

bun run ci — build, lint, tsc -b --noEmit, 486 pass / 0 fail, the same count as before the move. Also 486/0 under a pseudo-TTY.

Behaviour is unchanged, smoke-tested on the things addCommand could plausibly have broken:

  • top-level command order and help output, identical
  • the emu alias
  • the nested emulator images install level
  • --skip-version-check accepted on a deep subcommand
  • usage-after-error on all seven commands and on the nested images level

No changeset: the solana-mobile bin and the ./templates export are unchanged.

Follow-up

PR 3: create — its 384-line barrel mixes template resolution, prompts and create-solana-dapp orchestration, which is a judgement-heavy split unrelated to commander and deserves its own review.

Summary by CodeRabbit

  • New Features

    • Added structured CLI commands for devices, doctors, emulators, playgrounds, templates, and webshell tasks.
    • Added subcommands, aliases, options, validation, help output, and consistent option handling across features.
    • Added doctor reports with capability summaries, deduplicated recommendations, and meaningful exit codes.
  • Bug Fixes

    • Improved invalid option handling and command-specific usage messages.
    • Prevented conflicting device options from being used together.
  • Tests

    • Expanded coverage for command registration, routing, validation, and option forwarding.

Every command except `create` now owns its own commander wiring. `device`, `doctor`, `emulator`, `playground`, `templates` and `webshell` each export `create<Name>Command(deps): Command` from `<name>-feature.ts`, which replaces the `<name>-feature-index.ts` barrel, and `createApp` registers them with `addCommand` in alphabetical order. `AppOptions` is now an intersection of the seven per-feature `<Name>CommandDeps` types plus `checkForNewerVersion` and `runCreate`, so `app.ts` names two dependencies instead of twenty-four and drops from 504 lines to 167.

The feature files are wiring only, so the three barrels that held implementation split rather than move: `runPlayground` to `playground-feature-serve.ts`, doctor's orchestration to `doctor-feature-check.ts`, and doctor's pure functions over check results (`buildDoctorReport`, `deriveCapabilities`, `getDoctorExitCode`) to `data-access/doctor-report.ts` — which is where `test/doctor.test.ts` already imported everything else from. `src/templates.ts` keeps a byte-identical export surface, now sourced directly from `data-access/*` and the three `templates-feature-*.ts` files instead of through a barrel.

26 wiring tests move out of `test/core.test.ts` (1446 lines to 965) into the feature suites that own them, along with the `device tune` output-silencing helper. `core.test.ts` keeps only genuinely app-level tests, and gains one: the `addCommand` settings copy is now asserted across all seven feature commands at once rather than for localnet alone, so the localnet-specific guard added with the pilot is removed as duplicated. Verified by deleting the copy line — the new test fails, the suite goes to 1 fail.

Behaviour is unchanged: 486 tests pass with and without a TTY, help output and command order are identical, the `emu` alias and the nested `emulator images` level still work, and every feature command still prints usage after an unknown-option error.
@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 0f9bffc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

bun add https://pkg.pr.new/solana-mobile/solana-mobile-cli/solana-mobile@45

commit: 0f9bffc

@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: e00f6a5a-d5e6-40e9-bdf0-83e038afc717

📥 Commits

Reviewing files that changed from the base of the PR and between 2fc829d and 0f9bffc.

📒 Files selected for processing (22)
  • src/app.ts
  • src/device/device-feature-index.ts
  • src/device/device-feature.ts
  • src/doctor/data-access/doctor-report.ts
  • src/doctor/doctor-feature-check.ts
  • src/doctor/doctor-feature.ts
  • src/emulator/emulator-feature-index.ts
  • src/emulator/emulator-feature.ts
  • src/playground/playground-feature-serve.ts
  • src/playground/playground-feature.ts
  • src/templates.ts
  • src/templates/templates-feature-index.ts
  • src/templates/templates-feature.ts
  • src/webshell/webshell-feature-index.ts
  • src/webshell/webshell-feature.ts
  • test/core.test.ts
  • test/device.test.ts
  • test/doctor.test.ts
  • test/emulator.test.ts
  • test/localnet.test.ts
  • test/playground.test.ts
  • test/templates.test.ts
💤 Files with no reviewable changes (6)
  • src/webshell/webshell-feature-index.ts
  • src/emulator/emulator-feature-index.ts
  • src/playground/playground-feature-serve.ts
  • test/localnet.test.ts
  • src/device/device-feature-index.ts
  • src/templates/templates-feature-index.ts

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.


📝 Walkthrough

Walkthrough

The CLI now delegates command construction to feature-owned Commander factories. Each factory supports injectable runners, parses feature options, and handles local validation. The application root aggregates feature dependencies and registers the factories. Tests cover command registration, delegation, validation, and root settings.

Changes

CLI command factories

Layer / File(s) Summary
Device command factory
src/device/device-feature.ts, test/device.test.ts
Added device install, list, open, and tune commands with injectable runners, option forwarding, and --all/--device validation.
Emulator command factory
src/emulator/emulator-feature.ts, test/emulator.test.ts
Added the emulator/emu command and its emulator and image subcommands with normalized arguments, numeric parsing, and delegation tests.
Supporting command factories
src/doctor/..., src/playground/..., src/templates/templates-feature.ts, src/webshell/webshell-feature.ts, test/doctor.test.ts, test/playground.test.ts, test/templates.test.ts
Added factories for doctor, playground, templates, and webshell commands. Moved doctor report utilities into doctor-report.ts.
Application command registration
src/app.ts, test/core.test.ts, test/localnet.test.ts
Replaced inline command wiring with feature factories. AppOptions now aggregates feature dependency types. Tests verify root setting propagation.
Public export cleanup
src/templates.ts, src/templates/templates-feature-index.ts, src/device/device-feature-index.ts, src/emulator/emulator-feature-index.ts, src/webshell/webshell-feature-index.ts, src/playground/playground-feature-serve.ts
Removed consolidated feature barrel exports and updated direct imports and exports.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 0f9bf

The command-factory refactor preserves the reviewed CLI behavior and has no identified merge-blocking risk.

Sequence Diagram(s)

sequenceDiagram
  participant createApp
  participant FeatureCommandFactory
  participant FeatureRunner
  createApp->>FeatureCommandFactory: create feature command with dependencies
  createApp->>FeatureCommandFactory: register command
  FeatureCommandFactory->>FeatureRunner: parse and forward command options
  FeatureRunner-->>FeatureCommandFactory: return command result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.56% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 16 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: moving command wiring into per-feature command factories.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch beeman/move-remaining-command-wiring-to-features

Comment @coderabbitai help to get the list of available commands.

@beeman
beeman added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit b1d52aa Sep 4, 2026
7 checks passed
@beeman
beeman deleted the beeman/move-remaining-command-wiring-to-features branch September 4, 2026 00:04
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.

1 participant