@tantawowa/hosanna-tools 3.7.8 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +8 -2
  2. package/dist/build-info.json +3 -3
  3. package/dist/cli.js +55 -2
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +2 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/native/templates/android/app-build.gradle.kts +25 -2
  9. package/dist/run/android-emulator.d.ts +1 -0
  10. package/dist/run/android-emulator.js +7 -2
  11. package/dist/run/android-emulator.js.map +1 -1
  12. package/dist/run/apple-tv.js +14 -12
  13. package/dist/run/apple-tv.js.map +1 -1
  14. package/dist/run/destination-picker.d.ts +24 -0
  15. package/dist/run/destination-picker.js +180 -0
  16. package/dist/run/destination-picker.js.map +1 -0
  17. package/dist/run/ios-device.js +7 -6
  18. package/dist/run/ios-device.js.map +1 -1
  19. package/dist/run/ios-simulator.js +7 -6
  20. package/dist/run/ios-simulator.js.map +1 -1
  21. package/dist/run/native-build.d.ts +3 -0
  22. package/dist/run/native-build.js +8 -0
  23. package/dist/run/native-build.js.map +1 -1
  24. package/dist/run/planner.js +10 -8
  25. package/dist/run/planner.js.map +1 -1
  26. package/dist/run/run-config.d.ts +9 -0
  27. package/dist/run/run-config.js +43 -3
  28. package/dist/run/run-config.js.map +1 -1
  29. package/dist/support-tools/android-metro-build.d.ts +3 -0
  30. package/dist/support-tools/android-metro-build.js +57 -2
  31. package/dist/support-tools/android-metro-build.js.map +1 -1
  32. package/dist/support-tools/apple-bundler.js +20 -8
  33. package/dist/support-tools/apple-bundler.js.map +1 -1
  34. package/dist/support-tools/build-config-resolver.js +8 -4
  35. package/dist/support-tools/build-config-resolver.js.map +1 -1
  36. package/dist/vite.d.ts +12 -0
  37. package/dist/vite.js +40 -5
  38. package/dist/vite.js.map +1 -1
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -189,7 +189,7 @@ Hosanna Tools is a comprehensive CLI toolset for the Hosanna framework that prov
189
189
  The CLI commands are organized into logical groups using colon-separated namespacing:
190
190
 
191
191
  ### Development Commands
192
- - `run` - Canonical cross-platform app launcher. Requires `--platform` and supports web, Roku, iOS, Apple TV, Android, and Android TV launch targets.
192
+ - `run` - Canonical cross-platform app launcher. Bare interactive runs show one destination picker; explicit platform options support web, Roku, iOS, Apple TV, Android, and Android TV launch targets.
193
193
  - `target:list` - List launch targets for humans or agents, including web emulators, sims, and physical devices.
194
194
  - `dev:start` - Run dev processes: vite, generator watch, and optional debugger
195
195
  - `debugger:start` - Start the command debugger WebSocket proxy (only one debugger is needed for multiple apps; if the port is already in use, a friendly message is shown instead of crashing)
@@ -197,6 +197,8 @@ The CLI commands are organized into logical groups using colon-separated namespa
197
197
  Examples:
198
198
 
199
199
  ```bash
200
+ hst run
201
+ hst run --last
200
202
  hst run --platform web
201
203
  hst run --platform roku --target emulator
202
204
  hst run --platform ios --target emulator
@@ -218,7 +220,9 @@ hst target:list --platform apple-tv --target sim --json
218
220
  hst target:list --form-factor tv --json
219
221
  ```
220
222
 
221
- `hst run` is platform-explicit by design, so non-interactive agents do not guess between iOS, Apple TV, Android, Android TV, Roku, or web. `--target emulator` starts or reuses the shared Vite/debugger dev services for any platform and opens a profiled DOM runtime URL for interactive runs; use `--device <preset-id>` to override defaults such as `iphone-15`, `pixel-8`, `apple-tv-4k`, `android-tv-1080p`, or `rokufhd`, and use `--no-open` for server-only launches. `--target sim` launches the vendor virtual device for platforms that have one: Apple Simulator for iOS and Apple TV, Android Emulator for Android and Android TV. `--target device` launches or deploys to physical local hardware. `web` and `browser` remain accepted aliases for the web emulator; `simulator` and `simulated` remain accepted aliases for `sim`; `emulated` remains an accepted alias for the web emulator. Device/sim runs record the target and refuse to overwrite a recorded session or safe-to-kill occupied resource in non-interactive mode unless `--replace` is passed. Preferred run defaults live in `.hosanna-tools/run.json`, and preferred devices live in `.hosanna-tools/devices.json` or `~/.hosanna-tools/devices.json`. Legacy `.hs-devices.json` files are still read for compatibility.
223
+ Bare `hst run` in an interactive terminal discovers runnable web previews, vendor simulators, and online physical devices, then presents one flat destination picker. The last selection is placed first, so pressing Enter repeats it; `hst run --last` skips discovery and immediately uses that remembered destination. The selection is stored in the user-level `~/.hosanna-tools/run.json`, preserving existing defaults. Explicit commands remain deterministic, and non-interactive runs never open the picker.
224
+
225
+ `--target emulator` starts or reuses the shared Vite/debugger dev services for any platform and opens a profiled DOM runtime URL for interactive runs; use `--device <preset-id>` to override defaults such as `iphone-15`, `pixel-8`, `apple-tv-4k`, `android-tv-1080p`, or `rokufhd`, and use `--no-open` for server-only launches. `--target sim` launches the vendor virtual device for platforms that have one: Apple Simulator for iOS and Apple TV, Android Emulator for Android and Android TV. `--target device` launches or deploys to physical local hardware. `web` and `browser` remain accepted aliases for the web emulator; `simulator` and `simulated` remain accepted aliases for `sim`; `emulated` remains an accepted alias for the web emulator. Device/sim runs record the target and refuse to overwrite a recorded session or safe-to-kill occupied resource in non-interactive mode unless `--replace` is passed. Preferred run defaults live in `.hosanna-tools/run.json`, and preferred devices live in `.hosanna-tools/devices.json` or `~/.hosanna-tools/devices.json`. Legacy `.hs-devices.json` files are still read for compatibility.
222
226
 
223
227
  ### Roku Commands (`roku:*`) - Roku Deployment & Packaging
224
228
  - `roku:run` - Deploy a Roku app to a device (supports .zip file or folder)
@@ -269,6 +273,8 @@ Supported inputs include `file/line: pkg:/components/source_0.brs(7475)`, `at ..
269
273
  ### Build Config Commands (`build-config`) - Runtime Configuration
270
274
  - `build-config:resolve` - Resolve `build-config/base.json`, env/platform overlays, secrets, and optional developer profiles into the canonical runtime `build-config.json`
271
275
 
276
+ Production JavaScript bundles strip `console.*` calls by default. Configure this through the normal overlay chain with `build.stripLogs`: set it to `false` in `build-config/prod.json` to retain production logs, or in `build-config/prod.apple.json` / `build-config/prod.web.json` for a platform-only exception. Non-production environments keep logs unless their overlay explicitly enables stripping. Apple `prod` builds use Xcode `Release`; other environments continue to use `Debug`.
277
+
272
278
  Native builds can resolve config immediately before the platform build:
273
279
 
274
280
  ```bash
@@ -1,6 +1,6 @@
1
1
  {
2
- "buildDate": "2026-07-14T21:40:41+00:00",
3
- "buildDateISO": "2026-07-14T21:40:41.116Z",
2
+ "buildDate": "2026-07-15T18:20:21+00:00",
3
+ "buildDateISO": "2026-07-15T18:20:21.607Z",
4
4
  "timeZone": "UTC",
5
- "gitHash": "540c18c"
5
+ "gitHash": "0a46a09"
6
6
  }
package/dist/cli.js CHANGED
@@ -144,10 +144,33 @@ async function runRunPlanCommand(command, args) {
144
144
  const executor = await Promise.resolve().then(() => __importStar(require('./run/executor.js')));
145
145
  const positionalArgv = rawCommandPositionals(command);
146
146
  const format = (args.json || args.format === 'json') ? 'json' : 'text';
147
+ let flags = runPlanFlagsFromCliArgs(args, format);
148
+ let chosenDestination;
149
+ const hasExplicitDestination = positionalArgv.length > 0 ||
150
+ rawHasFlag('platform') || rawHasFlag('target') || rawHasFlag('device');
151
+ if (command === 'run' && args.last) {
152
+ if (hasExplicitDestination) {
153
+ throw new Error('--last cannot be combined with an explicit platform, target, or device.');
154
+ }
155
+ const picker = await Promise.resolve().then(() => __importStar(require('./run/destination-picker.js')));
156
+ chosenDestination = picker.requireLastRunDestination(process.cwd());
157
+ flags = Object.assign(Object.assign({}, flags), runDestinationFlags(chosenDestination));
158
+ }
159
+ else if (command === 'run' &&
160
+ !hasExplicitDestination &&
161
+ !flags.nonInteractive &&
162
+ !args['dry-run'] &&
163
+ format === 'text' &&
164
+ process.stdin.isTTY &&
165
+ process.stdout.isTTY) {
166
+ const picker = await Promise.resolve().then(() => __importStar(require('./run/destination-picker.js')));
167
+ chosenDestination = await picker.chooseRunDestination({ cwd: process.cwd(), env: process.env });
168
+ flags = Object.assign(Object.assign({}, flags), runDestinationFlags(chosenDestination));
169
+ }
147
170
  const planInput = {
148
171
  cwd: process.cwd(),
149
172
  argv: positionalArgv,
150
- flags: runPlanFlagsFromCliArgs(args, format),
173
+ flags,
151
174
  env: process.env,
152
175
  };
153
176
  const plan = command === 'build'
@@ -162,6 +185,18 @@ async function runRunPlanCommand(command, args) {
162
185
  }
163
186
  process.exit(0);
164
187
  }
188
+ if (command === 'run' && !flags.nonInteractive && process.stdin.isTTY) {
189
+ const destination = chosenDestination !== null && chosenDestination !== void 0 ? chosenDestination : rememberedExplicitDestination(plan, hasExplicitDestination);
190
+ if (destination) {
191
+ try {
192
+ const config = await Promise.resolve().then(() => __importStar(require('./run/run-config.js')));
193
+ config.saveLastRunDestination({ cwd: process.cwd(), destination });
194
+ }
195
+ catch (err) {
196
+ console.warn(`Unable to remember the run destination: ${err instanceof Error ? err.message : String(err)}`);
197
+ }
198
+ }
199
+ }
165
200
  const result = await executor.executeRunPlan(plan);
166
201
  if (format === 'json') {
167
202
  console.info(JSON.stringify(result, null, 2));
@@ -179,6 +214,21 @@ async function runRunPlanCommand(command, args) {
179
214
  process.exit(1);
180
215
  }
181
216
  }
217
+ function runDestinationFlags(destination) {
218
+ return {
219
+ platform: destination.platform,
220
+ target: destination.target,
221
+ device: destination.device,
222
+ };
223
+ }
224
+ function rememberedExplicitDestination(plan, hasExplicitDestination) {
225
+ if (!hasExplicitDestination)
226
+ return undefined;
227
+ const target = plan.resolved.target === 'emulator' ? 'web' : plan.resolved.target;
228
+ if (target !== 'web' && !plan.resolved.deviceSelector)
229
+ return undefined;
230
+ return Object.assign({ platform: plan.resolved.platform, target }, (plan.resolved.deviceSelector ? { device: plan.resolved.deviceSelector } : {}));
231
+ }
182
232
  const NATIVE_PLATFORM_CHOICES = ['apple', 'ios', 'apple-tv', 'android', 'android-tv', 'all'];
183
233
  function nativeInputFromArgs(args) {
184
234
  return {
@@ -1662,7 +1712,7 @@ catch (err) {
1662
1712
  .parserConfiguration({ 'boolean-negation': false, 'populate--': true })
1663
1713
  .positional('platform', {
1664
1714
  type: 'string',
1665
- describe: 'Launch platform. Defaults from flags, env, .hosanna-tools/run.json, then web.',
1715
+ describe: 'Launch platform. Bare interactive runs show a destination picker; non-interactive runs default to web.',
1666
1716
  })
1667
1717
  .positional('env', {
1668
1718
  type: 'string',
@@ -1714,6 +1764,7 @@ catch (err) {
1714
1764
  .option('open', { type: 'boolean', describe: 'Open the web runtime URL in the default browser; defaults to interactive runs only' })
1715
1765
  .option('no-open', { type: 'boolean', default: false, describe: 'Do not open the default browser for web runtime launches' })
1716
1766
  .option('non-interactive', { type: 'boolean', default: false, describe: 'Fail instead of prompting when a decision is needed' })
1767
+ .option('last', { type: 'boolean', default: false, describe: 'Immediately reuse the last destination selected by an interactive run' })
1717
1768
  .option('json', { type: 'boolean', default: false, describe: 'Print run result as JSON when the command returns' })
1718
1769
  .option('dry-run', { type: 'boolean', default: false, describe: 'Print the resolved RunPlan without executing it' })
1719
1770
  .option('format', { type: 'string', choices: ['text', 'json'], default: 'text', describe: 'Output format for --dry-run and run result' })
@@ -1734,6 +1785,8 @@ catch (err) {
1734
1785
  .option('logs', { type: 'boolean', default: false, describe: 'Enable verbose deploy logging where supported' })
1735
1786
  .option('applySourceMapToPaths', { type: 'boolean', default: true, describe: 'Resolve Roku stack trace paths with source maps during log streaming' })
1736
1787
  .example('$0 run --platform web', 'Start/reuse web dev services for this app')
1788
+ .example('$0 run', 'Choose once from all available web, simulator, and physical-device destinations')
1789
+ .example('$0 run --last', 'Immediately run on the last selected destination')
1737
1790
  .example('$0 run --platform roku --target emulator', 'Start/reuse the Roku TV web emulator')
1738
1791
  .example('$0 run --platform ios --target emulator', 'Start/reuse the iPhone-shaped web emulator profile')
1739
1792
  .example('$0 run --platform android --target emulator --device pixel-8', 'Start/reuse the Android-shaped web emulator profile')