@tantawowa/hosanna-tools 2.25.0 → 3.0.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.
- package/dist/build-info.json +3 -3
- package/dist/cli.js +300 -44
- package/dist/cli.js.map +1 -1
- package/dist/device/device-cli.js +2 -0
- package/dist/device/device-cli.js.map +1 -1
- package/dist/device/drivers/roku-driver.d.ts +2 -0
- package/dist/device/drivers/roku-driver.js +11 -0
- package/dist/device/drivers/roku-driver.js.map +1 -1
- package/dist/device/log-stream.d.ts +1 -0
- package/dist/device/log-stream.js +11 -0
- package/dist/device/log-stream.js.map +1 -1
- package/dist/device/types.d.ts +2 -0
- package/dist/index.d.ts +11 -15
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/native/app-entry-generation.d.ts +9 -0
- package/dist/native/app-entry-generation.js +100 -0
- package/dist/native/app-entry-generation.js.map +1 -0
- package/dist/native/native-project.d.ts +103 -0
- package/dist/native/native-project.js +848 -0
- package/dist/native/native-project.js.map +1 -0
- package/dist/native/templates/android/AndroidManifest.xml +20 -0
- package/dist/native/templates/android/app-build.gradle.kts +186 -0
- package/dist/native/templates/android/build.gradle.kts +4 -0
- package/dist/native/templates/android/colors.xml +3 -0
- package/dist/native/templates/android/gradle-wrapper.properties +5 -0
- package/dist/native/templates/android/gradle.properties +2 -0
- package/dist/native/templates/android/gradlew +11 -0
- package/dist/native/templates/android/gradlew.bat +12 -0
- package/dist/native/templates/android/launcher.xml +12 -0
- package/dist/native/templates/android/settings.gradle.kts +18 -0
- package/dist/native/templates/android/strings.xml +3 -0
- package/dist/native/templates/android/styles.xml +8 -0
- package/dist/native/templates/apple/AppIconContents.json +7 -0
- package/dist/native/templates/apple/Info.plist +24 -0
- package/dist/native/templates/apple/Podfile.example +7 -0
- package/dist/native/templates/apple/project.yml +95 -0
- package/dist/run/android-emulator.d.ts +8 -2
- package/dist/run/android-emulator.js +206 -39
- package/dist/run/android-emulator.js.map +1 -1
- package/dist/run/apple-tv.d.ts +5 -2
- package/dist/run/apple-tv.js +33 -32
- package/dist/run/apple-tv.js.map +1 -1
- package/dist/run/executor.d.ts +14 -0
- package/dist/run/executor.js +93 -0
- package/dist/run/executor.js.map +1 -0
- package/dist/run/ios-device.d.ts +4 -1
- package/dist/run/ios-device.js +19 -24
- package/dist/run/ios-device.js.map +1 -1
- package/dist/run/ios-simulator.d.ts +1 -1
- package/dist/run/ios-simulator.js +15 -23
- package/dist/run/ios-simulator.js.map +1 -1
- package/dist/run/native-build.d.ts +18 -0
- package/dist/run/native-build.js +154 -0
- package/dist/run/native-build.js.map +1 -0
- package/dist/run/planner.d.ts +99 -0
- package/dist/run/planner.js +872 -0
- package/dist/run/planner.js.map +1 -0
- package/dist/run/run-config.d.ts +13 -0
- package/dist/run/run-config.js +115 -32
- package/dist/run/run-config.js.map +1 -1
- package/dist/run/run-controller.d.ts +26 -1
- package/dist/run/run-controller.js +372 -32
- package/dist/run/run-controller.js.map +1 -1
- package/dist/run/targets.d.ts +4 -1
- package/dist/run/targets.js +5 -2
- package/dist/run/targets.js.map +1 -1
- package/dist/run/types.d.ts +1 -1
- package/dist/run/types.js +3 -1
- package/dist/run/types.js.map +1 -1
- package/dist/support-tools/android-dev-server.d.ts +2 -0
- package/dist/support-tools/android-dev-server.js +122 -0
- package/dist/support-tools/android-dev-server.js.map +1 -0
- package/dist/support-tools/android-metro-build.d.ts +2 -0
- package/dist/support-tools/android-metro-build.js +265 -0
- package/dist/support-tools/android-metro-build.js.map +1 -0
- package/dist/support-tools/apple-bundler.d.ts +7 -0
- package/dist/support-tools/apple-bundler.js +331 -0
- package/dist/support-tools/apple-bundler.js.map +1 -0
- package/dist/support-tools/run-roku.d.ts +2 -0
- package/dist/support-tools/run-roku.js +28 -8
- package/dist/support-tools/run-roku.js.map +1 -1
- package/dist/support-tools/tsc-filter.d.ts +2 -0
- package/dist/support-tools/tsc-filter.js +62 -0
- package/dist/support-tools/tsc-filter.js.map +1 -0
- package/dist/vite.d.ts +53 -0
- package/dist/vite.js +566 -0
- package/dist/vite.js.map +1 -0
- package/package.json +19 -8
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -60,6 +60,74 @@ const env_info_js_1 = require("./lib/env-info.js");
|
|
|
60
60
|
const hosanna_tools_utils_js_1 = require("./lib/hosanna-tools-utils.js");
|
|
61
61
|
const cli_app_config_resolve_js_1 = require("./lib/cli.app-config-resolve.js");
|
|
62
62
|
const hosanna_config_js_1 = require("./lib/hosanna-config.js");
|
|
63
|
+
function formatRunPlanText(plan, explain) {
|
|
64
|
+
const lines = [
|
|
65
|
+
`hst run plan: ${plan.resolved.platform} ${plan.resolved.env} ${plan.resolved.target}`,
|
|
66
|
+
'',
|
|
67
|
+
...plan.shellPreview.map(line => ` ${line}`),
|
|
68
|
+
];
|
|
69
|
+
if (explain) {
|
|
70
|
+
lines.push('', 'Resolution sources:');
|
|
71
|
+
for (const [key, value] of Object.entries(plan.sources)) {
|
|
72
|
+
lines.push(` ${key}: ${value}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
function rawCommandPositionals(command) {
|
|
78
|
+
const raw = (0, helpers_1.hideBin)(process.argv);
|
|
79
|
+
const index = raw.indexOf(command);
|
|
80
|
+
if (index === -1)
|
|
81
|
+
return [];
|
|
82
|
+
const result = [];
|
|
83
|
+
for (const token of raw.slice(index + 1)) {
|
|
84
|
+
if (token === '--' || token.startsWith('-'))
|
|
85
|
+
break;
|
|
86
|
+
result.push(token);
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
function rawHasFlag(name) {
|
|
91
|
+
const dashName = `--${name}`;
|
|
92
|
+
return (0, helpers_1.hideBin)(process.argv).some(token => token === dashName || token.startsWith(`${dashName}=`));
|
|
93
|
+
}
|
|
94
|
+
const NATIVE_PLATFORM_CHOICES = ['apple', 'ios', 'apple-tv', 'android', 'android-tv', 'all'];
|
|
95
|
+
function nativeInputFromArgs(args) {
|
|
96
|
+
return {
|
|
97
|
+
cwd: process.cwd(),
|
|
98
|
+
platform: nativePlatformArg(args.platform),
|
|
99
|
+
app: stringArg(args.app),
|
|
100
|
+
displayName: stringArg(args['display-name']),
|
|
101
|
+
bundleId: stringArg(args['bundle-id']),
|
|
102
|
+
iosBundleId: stringArg(args['ios-bundle-id']),
|
|
103
|
+
appleTvBundleId: stringArg(args['apple-tv-bundle-id']),
|
|
104
|
+
androidPackage: stringArg(args['android-package']),
|
|
105
|
+
androidTvPackage: stringArg(args['android-tv-package']),
|
|
106
|
+
teamId: stringArg(args['team-id']),
|
|
107
|
+
versionName: stringArg(args['version-name']),
|
|
108
|
+
versionCode: numberOrStringArg(args['version-code']),
|
|
109
|
+
referenceRoot: stringArg(args['reference-root']),
|
|
110
|
+
replace: Boolean(args.replace),
|
|
111
|
+
dryRun: Boolean(args['dry-run']),
|
|
112
|
+
nonInteractive: Boolean(args['non-interactive']),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function nativePlatformArg(value) {
|
|
116
|
+
return typeof value === 'string' && value.trim()
|
|
117
|
+
? value.trim()
|
|
118
|
+
: undefined;
|
|
119
|
+
}
|
|
120
|
+
function nativeFormatArg(args) {
|
|
121
|
+
return args.format === 'json' ? 'json' : 'text';
|
|
122
|
+
}
|
|
123
|
+
function stringArg(value) {
|
|
124
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
125
|
+
}
|
|
126
|
+
function numberOrStringArg(value) {
|
|
127
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
128
|
+
return value;
|
|
129
|
+
return stringArg(value);
|
|
130
|
+
}
|
|
63
131
|
// Read build date, version, and git hash embedded at build time
|
|
64
132
|
let buildDate = 'unknown';
|
|
65
133
|
let buildVersion = 'unknown';
|
|
@@ -86,7 +154,7 @@ catch (err) {
|
|
|
86
154
|
// Let yargs handle all commands including env
|
|
87
155
|
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
88
156
|
.version(`${buildVersion}\n git: ${buildGitHash}\n built: ${buildDate}`)
|
|
89
|
-
.usage('$0 [command] [options]', `Hosanna Tools CLI\nVersion: ${buildVersion}\nBuild Date: ${buildDate}\n\nCommand Groups:\n compiler:* Compiler lifecycle (install, status, list)\n config hosanna.json management (wizard, show, set)\n env Environment checks and repair (check, fix, prepare-gitignore)\n dev:* Local development execution\n debugger:* Command debugger control\n mcp:* Hosanna MCP server control\n run Cross-platform launch orchestration\n target:* Run target discovery and inventory\n roku:* Roku deployment & packaging (run, package, map-stack)\n device:* Device discovery and run workflows\n generate:* Code and asset generation\n sdk:* Hosanna SDK/framework installation\n build-config:* Build/runtime configuration resolution\n ci:* Continuous integration helpers\n framework:* Framework distribution helpers\n license:* Hosanna framework licensing\n secrets:* Portable .secrets files\n test:* UI testing\n rasp:* RASP cert scripts`)
|
|
157
|
+
.usage('$0 [command] [options]', `Hosanna Tools CLI\nVersion: ${buildVersion}\nBuild Date: ${buildDate}\n\nCommand Groups:\n compiler:* Compiler lifecycle (install, status, list)\n config hosanna.json management (wizard, show, set)\n env Environment checks and repair (check, fix, prepare-gitignore)\n dev:* Local development execution\n debugger:* Command debugger control\n mcp:* Hosanna MCP server control\n run Cross-platform launch orchestration\n native:* Native platform bootstrap and validation\n target:* Run target discovery and inventory\n roku:* Roku deployment & packaging (run, package, map-stack)\n device:* Device discovery and run workflows\n generate:* Code and asset generation\n sdk:* Hosanna SDK/framework installation\n build-config:* Build/runtime configuration resolution\n ci:* Continuous integration helpers\n framework:* Framework distribution helpers\n license:* Hosanna framework licensing\n secrets:* Portable .secrets files\n test:* UI testing\n rasp:* RASP cert scripts`)
|
|
90
158
|
.option('verbose', {
|
|
91
159
|
type: 'boolean',
|
|
92
160
|
default: false,
|
|
@@ -237,6 +305,112 @@ catch (err) {
|
|
|
237
305
|
console.error(`Failed to resolve app config: ${message}`);
|
|
238
306
|
process.exit(1);
|
|
239
307
|
}
|
|
308
|
+
})
|
|
309
|
+
.command('native:init [platform]', 'Initialize app-owned Hosanna native thin projects and config', yargs => yargs
|
|
310
|
+
.positional('platform', { type: 'string', choices: NATIVE_PLATFORM_CHOICES, default: 'all', describe: 'Native platform family to initialize' })
|
|
311
|
+
.option('app', { type: 'string', describe: 'App key/name used when inferring defaults' })
|
|
312
|
+
.option('display-name', { type: 'string', describe: 'Native display name' })
|
|
313
|
+
.option('bundle-id', { type: 'string', describe: 'Base bundle/package identifier' })
|
|
314
|
+
.option('ios-bundle-id', { type: 'string', describe: 'iOS bundle identifier' })
|
|
315
|
+
.option('apple-tv-bundle-id', { type: 'string', describe: 'tvOS bundle identifier' })
|
|
316
|
+
.option('android-package', { type: 'string', describe: 'Android namespace and phone package base' })
|
|
317
|
+
.option('android-tv-package', { type: 'string', describe: 'Android TV application id' })
|
|
318
|
+
.option('team-id', { type: 'string', describe: 'Apple development team id for generated xcconfig files' })
|
|
319
|
+
.option('version-name', { type: 'string', describe: 'Native marketing/versionName value' })
|
|
320
|
+
.option('version-code', { type: 'number', describe: 'Native build/versionCode value' })
|
|
321
|
+
.option('reference-root', { type: 'string', default: 'hosanna-ui', describe: 'Installed framework/runtime root inside the app repo' })
|
|
322
|
+
.option('replace', { type: 'boolean', default: false, describe: 'Replace unchanged hst-managed native template files' })
|
|
323
|
+
.option('dry-run', { type: 'boolean', default: false, describe: 'Print the native init plan without writing files' })
|
|
324
|
+
.option('format', { type: 'string', choices: ['text', 'json'], default: 'text', describe: 'Output format' })
|
|
325
|
+
.option('non-interactive', { type: 'boolean', default: false, describe: 'Fail instead of prompting when a decision is needed' })
|
|
326
|
+
.example('$0 native:init all --display-name "Hope Stream"', 'Initialize Apple and Android app-owned native projects')
|
|
327
|
+
.example('$0 native:init android-tv --dry-run --format json', 'Preview Android TV native setup as JSON'), async (args) => {
|
|
328
|
+
try {
|
|
329
|
+
const mod = await Promise.resolve().then(() => __importStar(require('./native/native-project.js')));
|
|
330
|
+
const input = nativeInputFromArgs(args);
|
|
331
|
+
const format = nativeFormatArg(args);
|
|
332
|
+
const plan = mod.createNativeInitPlan(input);
|
|
333
|
+
if (input.dryRun) {
|
|
334
|
+
console.info(format === 'json' ? JSON.stringify(plan, null, 2) : mod.formatNativeInitPlanText(plan));
|
|
335
|
+
process.exit(plan.errors.length > 0 ? 1 : 0);
|
|
336
|
+
}
|
|
337
|
+
const result = await mod.executeNativeInitPlan(plan);
|
|
338
|
+
if (format === 'json') {
|
|
339
|
+
console.info(JSON.stringify(result, null, 2));
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
console.info(`hst native:init applied for ${plan.requestedPlatforms.join(', ')}`);
|
|
343
|
+
console.info(mod.formatNativeInitPlanText(plan));
|
|
344
|
+
}
|
|
345
|
+
process.exit(0);
|
|
346
|
+
}
|
|
347
|
+
catch (err) {
|
|
348
|
+
console.error('❌ native:init failed');
|
|
349
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
})
|
|
353
|
+
.command('native:doctor [platform]', 'Validate Hosanna native platform setup and print actionable fixes', yargs => yargs
|
|
354
|
+
.positional('platform', { type: 'string', choices: NATIVE_PLATFORM_CHOICES, default: 'all', describe: 'Native platform family to validate' })
|
|
355
|
+
.option('app', { type: 'string', describe: 'App key/name used when inferring defaults' })
|
|
356
|
+
.option('display-name', { type: 'string', describe: 'Native display name' })
|
|
357
|
+
.option('bundle-id', { type: 'string', describe: 'Base bundle/package identifier' })
|
|
358
|
+
.option('ios-bundle-id', { type: 'string', describe: 'iOS bundle identifier' })
|
|
359
|
+
.option('apple-tv-bundle-id', { type: 'string', describe: 'tvOS bundle identifier' })
|
|
360
|
+
.option('android-package', { type: 'string', describe: 'Android namespace and phone package base' })
|
|
361
|
+
.option('android-tv-package', { type: 'string', describe: 'Android TV application id' })
|
|
362
|
+
.option('team-id', { type: 'string', describe: 'Apple development team id for generated xcconfig files' })
|
|
363
|
+
.option('version-name', { type: 'string', describe: 'Native marketing/versionName value' })
|
|
364
|
+
.option('version-code', { type: 'number', describe: 'Native build/versionCode value' })
|
|
365
|
+
.option('reference-root', { type: 'string', default: 'hosanna-ui', describe: 'Installed framework/runtime root inside the app repo' })
|
|
366
|
+
.option('replace', { type: 'boolean', default: false, describe: 'Plan replacement checks for unchanged hst-managed native files' })
|
|
367
|
+
.option('dry-run', { type: 'boolean', default: false, describe: 'Accepted for script parity; doctor never writes files' })
|
|
368
|
+
.option('format', { type: 'string', choices: ['text', 'json'], default: 'text', describe: 'Output format' })
|
|
369
|
+
.option('non-interactive', { type: 'boolean', default: false, describe: 'Fail instead of prompting when a decision is needed' })
|
|
370
|
+
.example('$0 native:doctor all --format json', 'Validate native setup as JSON'), async (args) => {
|
|
371
|
+
try {
|
|
372
|
+
const mod = await Promise.resolve().then(() => __importStar(require('./native/native-project.js')));
|
|
373
|
+
const report = mod.createNativeDoctorReport(nativeInputFromArgs(args));
|
|
374
|
+
const format = nativeFormatArg(args);
|
|
375
|
+
console.info(format === 'json' ? JSON.stringify(report, null, 2) : mod.formatNativeDoctorReportText(report));
|
|
376
|
+
process.exit(0);
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
console.error('❌ native:doctor failed');
|
|
380
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
381
|
+
process.exit(1);
|
|
382
|
+
}
|
|
383
|
+
})
|
|
384
|
+
.command('native:prepare [platform]', 'Run lightweight Hosanna native prebuild validation', yargs => yargs
|
|
385
|
+
.positional('platform', { type: 'string', choices: NATIVE_PLATFORM_CHOICES, default: 'all', describe: 'Native platform family to prepare' })
|
|
386
|
+
.option('app', { type: 'string', describe: 'App key/name used when inferring defaults' })
|
|
387
|
+
.option('display-name', { type: 'string', describe: 'Native display name' })
|
|
388
|
+
.option('bundle-id', { type: 'string', describe: 'Base bundle/package identifier' })
|
|
389
|
+
.option('ios-bundle-id', { type: 'string', describe: 'iOS bundle identifier' })
|
|
390
|
+
.option('apple-tv-bundle-id', { type: 'string', describe: 'tvOS bundle identifier' })
|
|
391
|
+
.option('android-package', { type: 'string', describe: 'Android namespace and phone package base' })
|
|
392
|
+
.option('android-tv-package', { type: 'string', describe: 'Android TV application id' })
|
|
393
|
+
.option('team-id', { type: 'string', describe: 'Apple development team id for generated xcconfig files' })
|
|
394
|
+
.option('version-name', { type: 'string', describe: 'Native marketing/versionName value' })
|
|
395
|
+
.option('version-code', { type: 'number', describe: 'Native build/versionCode value' })
|
|
396
|
+
.option('reference-root', { type: 'string', default: 'hosanna-ui', describe: 'Installed framework/runtime root inside the app repo' })
|
|
397
|
+
.option('replace', { type: 'boolean', default: false, describe: 'Accepted for script parity; prepare never writes files' })
|
|
398
|
+
.option('dry-run', { type: 'boolean', default: false, describe: 'Accepted for script parity; prepare never writes files' })
|
|
399
|
+
.option('format', { type: 'string', choices: ['text', 'json'], default: 'text', describe: 'Output format' })
|
|
400
|
+
.option('non-interactive', { type: 'boolean', default: false, describe: 'Fail instead of prompting when a decision is needed' })
|
|
401
|
+
.example('$0 native:prepare ios', 'Validate native iOS setup before building'), async (args) => {
|
|
402
|
+
try {
|
|
403
|
+
const mod = await Promise.resolve().then(() => __importStar(require('./native/native-project.js')));
|
|
404
|
+
const result = await mod.prepareNativeProject(nativeInputFromArgs(args));
|
|
405
|
+
const format = nativeFormatArg(args);
|
|
406
|
+
console.info(format === 'json' ? JSON.stringify(result, null, 2) : mod.formatNativeDoctorReportText(result.report));
|
|
407
|
+
process.exit(0);
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
console.error('❌ native:prepare failed');
|
|
411
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
412
|
+
process.exit(1);
|
|
413
|
+
}
|
|
240
414
|
})
|
|
241
415
|
.command('roku:package', 'Package and sign a Roku channel using roku-deploy. Flags fall back to env vars.', yargs => yargs
|
|
242
416
|
.option('ip', { type: 'string', describe: 'Roku device IP (env: ROKU_IP)' })
|
|
@@ -1148,7 +1322,12 @@ catch (err) {
|
|
|
1148
1322
|
process.exit(1);
|
|
1149
1323
|
}
|
|
1150
1324
|
})
|
|
1151
|
-
.command('target:list', 'List run targets discovered by hst, including web previews, simulators, and physical devices', yargs => yargs
|
|
1325
|
+
.command('target:list [platform]', 'List run targets discovered by hst, including web previews, simulators, and physical devices', yargs => yargs
|
|
1326
|
+
.positional('platform', {
|
|
1327
|
+
type: 'string',
|
|
1328
|
+
choices: ['web', 'roku', 'ios', 'apple-tv', 'android', 'android-tv'],
|
|
1329
|
+
describe: 'Filter by launch platform',
|
|
1330
|
+
})
|
|
1152
1331
|
.option('platform', {
|
|
1153
1332
|
type: 'string',
|
|
1154
1333
|
choices: ['web', 'roku', 'ios', 'apple-tv', 'android', 'android-tv'],
|
|
@@ -1156,7 +1335,7 @@ catch (err) {
|
|
|
1156
1335
|
})
|
|
1157
1336
|
.option('target', {
|
|
1158
1337
|
type: 'string',
|
|
1159
|
-
choices: ['web', 'device', 'simulator', 'emulator', 'simulated', 'emulated'],
|
|
1338
|
+
choices: ['browser', 'web', 'device', 'simulator', 'emulator', 'simulated', 'emulated'],
|
|
1160
1339
|
describe: 'Filter by target kind',
|
|
1161
1340
|
})
|
|
1162
1341
|
.option('form-factor', {
|
|
@@ -1168,9 +1347,15 @@ catch (err) {
|
|
|
1168
1347
|
type: 'boolean',
|
|
1169
1348
|
default: false,
|
|
1170
1349
|
describe: 'Print machine-readable JSON',
|
|
1350
|
+
})
|
|
1351
|
+
.option('format', {
|
|
1352
|
+
type: 'string',
|
|
1353
|
+
choices: ['text', 'json'],
|
|
1354
|
+
default: 'text',
|
|
1355
|
+
describe: 'Output format',
|
|
1171
1356
|
})
|
|
1172
1357
|
.example('$0 target:list --platform roku', 'List Roku web/device targets')
|
|
1173
|
-
.example('$0 target:list --platform ios --target
|
|
1358
|
+
.example('$0 target:list --platform ios --target browser --json', 'List the iOS browser target as JSON')
|
|
1174
1359
|
.example('$0 target:list --platform ios --target simulator --json', 'List iOS simulator targets as JSON')
|
|
1175
1360
|
.example('$0 target:list --platform ios --target device --json', 'List physical iOS device targets as JSON')
|
|
1176
1361
|
.example('$0 target:list --platform android --target emulator --json', 'List Android phone emulator targets as JSON')
|
|
@@ -1186,7 +1371,7 @@ catch (err) {
|
|
|
1186
1371
|
formFactor: args['form-factor'],
|
|
1187
1372
|
});
|
|
1188
1373
|
const targets = await mod.collectRunTargets(Object.assign(Object.assign({ cwd: process.cwd() }, filters), { env: process.env }));
|
|
1189
|
-
if (args.json) {
|
|
1374
|
+
if (args.json || args.format === 'json') {
|
|
1190
1375
|
console.info(JSON.stringify(mod.formatRunTargetsJson(targets), null, 2));
|
|
1191
1376
|
}
|
|
1192
1377
|
else {
|
|
@@ -1200,27 +1385,52 @@ catch (err) {
|
|
|
1200
1385
|
process.exit(1);
|
|
1201
1386
|
}
|
|
1202
1387
|
})
|
|
1203
|
-
.command('run', 'Launch a Hosanna app on a platform target (web, Roku, iOS, Apple TV, Android, and Android TV targets are supported)', yargs => yargs
|
|
1204
|
-
.parserConfiguration({ 'boolean-negation': false })
|
|
1388
|
+
.command('run [platform] [env] [target] [deviceSelector]', 'Launch a Hosanna app on a platform target (web, Roku, iOS, Apple TV, Android, and Android TV targets are supported)', yargs => yargs
|
|
1389
|
+
.parserConfiguration({ 'boolean-negation': false, 'populate--': true })
|
|
1390
|
+
.positional('platform', {
|
|
1391
|
+
type: 'string',
|
|
1392
|
+
describe: 'Launch platform. Defaults from flags, env, .hosanna-tools/run.json, then web.',
|
|
1393
|
+
})
|
|
1394
|
+
.positional('env', {
|
|
1395
|
+
type: 'string',
|
|
1396
|
+
describe: 'Build environment, e.g. dev, qa, or prod.',
|
|
1397
|
+
})
|
|
1398
|
+
.positional('target', {
|
|
1399
|
+
type: 'string',
|
|
1400
|
+
describe: 'Target kind: browser, device, simulator, or emulator.',
|
|
1401
|
+
})
|
|
1402
|
+
.positional('deviceSelector', {
|
|
1403
|
+
type: 'string',
|
|
1404
|
+
describe: 'Device IP, serial/UDID, AVD name, simulator name, or case-insensitive name substring.',
|
|
1405
|
+
})
|
|
1205
1406
|
.option('platform', {
|
|
1206
1407
|
type: 'string',
|
|
1207
1408
|
choices: ['web', 'roku', 'ios', 'apple-tv', 'android', 'android-tv'],
|
|
1208
|
-
|
|
1209
|
-
|
|
1409
|
+
describe: 'Launch platform.',
|
|
1410
|
+
})
|
|
1411
|
+
.option('env', {
|
|
1412
|
+
type: 'string',
|
|
1413
|
+
describe: 'Build environment, e.g. dev, qa, or prod.',
|
|
1210
1414
|
})
|
|
1211
1415
|
.option('target', {
|
|
1212
1416
|
type: 'string',
|
|
1213
|
-
choices: ['web', 'device', 'simulator', 'emulator', 'simulated', 'emulated'],
|
|
1214
|
-
describe: 'Target kind. Defaults
|
|
1417
|
+
choices: ['browser', 'web', 'device', 'simulator', 'emulator', 'simulated', 'emulated'],
|
|
1418
|
+
describe: 'Target kind. Defaults by platform.',
|
|
1215
1419
|
})
|
|
1216
1420
|
.option('device', {
|
|
1217
1421
|
type: 'string',
|
|
1218
|
-
describe: 'Device IP, serial/UDID, case-insensitive name substring, or web preset id for --target
|
|
1422
|
+
describe: 'Device IP, serial/UDID, case-insensitive name substring, or web preset id for --target browser',
|
|
1219
1423
|
})
|
|
1220
1424
|
.option('appName', {
|
|
1221
1425
|
type: 'string',
|
|
1222
1426
|
describe: 'App name used for debugger/session identity',
|
|
1223
1427
|
})
|
|
1428
|
+
.option('app', { type: 'string', describe: 'Run config app/flavor selector (env: HOSANNA_RUN_APP)' })
|
|
1429
|
+
.option('profile', { type: 'string', describe: 'Build config profile (env: HS_BUILD_PROFILE)' })
|
|
1430
|
+
.option('allow-profile-in-prod', { type: 'boolean', default: false, describe: 'Allow applying --profile with --env prod' })
|
|
1431
|
+
.option('app-config', { type: 'string', describe: 'Runtime app config selector passed to web/native launch inputs' })
|
|
1432
|
+
.option('hot-reload', { type: 'boolean', default: false, describe: 'Use native JS dev server where supported' })
|
|
1433
|
+
.option('bundled', { type: 'boolean', default: false, describe: 'Use bundled native JS/assets where supported' })
|
|
1224
1434
|
.option('vitePort', { type: 'number', description: 'Port for Vite dev server', default: 5173 })
|
|
1225
1435
|
.option('webAppPort', { type: 'number', description: 'Port for web app debugger client', default: 59151 })
|
|
1226
1436
|
.option('deviceAppPort', { type: 'number', description: 'Port for device app debugger client', default: 59152 })
|
|
@@ -1232,60 +1442,94 @@ catch (err) {
|
|
|
1232
1442
|
.option('no-open', { type: 'boolean', default: false, describe: 'Do not open the default browser for web runtime launches' })
|
|
1233
1443
|
.option('non-interactive', { type: 'boolean', default: false, describe: 'Fail instead of prompting when a decision is needed' })
|
|
1234
1444
|
.option('json', { type: 'boolean', default: false, describe: 'Print run result as JSON when the command returns' })
|
|
1445
|
+
.option('dry-run', { type: 'boolean', default: false, describe: 'Print the resolved RunPlan without executing it' })
|
|
1446
|
+
.option('format', { type: 'string', choices: ['text', 'json'], default: 'text', describe: 'Output format for --dry-run and run result' })
|
|
1447
|
+
.option('explain', { type: 'boolean', default: false, describe: 'Include resolution source details in text dry-run output' })
|
|
1235
1448
|
.option('no-build', { type: 'boolean', default: false, describe: 'Skip the platform build step for device runs' })
|
|
1449
|
+
.option('build-only', { type: 'boolean', default: false, describe: 'Plan or run build steps without opening browser/log streams where supported' })
|
|
1236
1450
|
.option('no-logs', { type: 'boolean', default: false, describe: 'Do not stream device logs after launch where supported' })
|
|
1237
1451
|
.option('build-cmd', { type: 'string', describe: 'Override the platform build command for device runs' })
|
|
1452
|
+
.option('hsc-project', { type: 'string', describe: 'Explicit Roku HSC project file for hst run planning' })
|
|
1453
|
+
.option('config', { type: 'string', describe: 'Alias for --hsc-project' })
|
|
1238
1454
|
.option('app-package', { type: 'string', describe: 'Roku app .zip or folder to deploy for device runs' })
|
|
1239
1455
|
.option('source-root', { type: 'string', describe: 'Roku source root to deploy for device runs' })
|
|
1240
1456
|
.option('source-map-root', { type: 'string', describe: 'Roku source map root for log resolution' })
|
|
1241
1457
|
.option('files', { type: 'array', describe: 'Roku file globs when deploying a folder' })
|
|
1458
|
+
.option('deploy-timeout-ms', { type: 'number', describe: 'Roku deploy request timeout in milliseconds' })
|
|
1242
1459
|
.option('installer-password', { type: 'string', describe: 'Roku installer password (env: ROKU_DEVPASSWORD)' })
|
|
1243
1460
|
.option('logs', { type: 'boolean', default: false, describe: 'Enable verbose deploy logging where supported' })
|
|
1244
1461
|
.option('applySourceMapToPaths', { type: 'boolean', default: true, describe: 'Resolve Roku stack trace paths with source maps during log streaming' })
|
|
1245
1462
|
.example('$0 run --platform web', 'Start/reuse web dev services for this app')
|
|
1246
|
-
.example('$0 run --platform roku --target
|
|
1247
|
-
.example('$0 run --platform ios --target
|
|
1248
|
-
.example('$0 run --platform android --target
|
|
1249
|
-
.example('$0 run --platform apple-tv --target
|
|
1250
|
-
.example('$0 run --platform android-tv --target
|
|
1463
|
+
.example('$0 run --platform roku --target browser', 'Start/reuse the Roku TV browser preview')
|
|
1464
|
+
.example('$0 run --platform ios --target browser', 'Start/reuse the iPhone-shaped browser runtime profile')
|
|
1465
|
+
.example('$0 run --platform android --target browser --device pixel-8', 'Start/reuse the Android-shaped browser runtime profile')
|
|
1466
|
+
.example('$0 run --platform apple-tv --target browser --no-open', 'Start/reuse the Apple TV browser runtime profile without opening a browser')
|
|
1467
|
+
.example('$0 run --platform android-tv --target browser', 'Start/reuse the Android TV browser runtime profile')
|
|
1251
1468
|
.example('$0 run --platform ios --target simulator --device "iPhone 17 Pro"', 'Build, install, and launch on an iOS simulator')
|
|
1252
1469
|
.example('$0 run --platform ios --target device --device "George iPhone" --no-logs', 'Build, install, and launch on a physical iPhone')
|
|
1253
1470
|
.example('$0 run --platform android --target emulator --device "Pixel_8" --no-logs', 'Build, install, and launch on an Android phone emulator')
|
|
1254
1471
|
.example('$0 run --platform android --target device --device "RF8M62694QT" --no-logs', 'Build, install, and launch on a physical Android device')
|
|
1255
1472
|
.example('$0 run --platform android-tv --target emulator --device "Television_1080p" --no-logs', 'Build, install, and launch on an Android TV emulator')
|
|
1256
1473
|
.example('$0 run --platform apple-tv --target simulator --device "Apple TV 4K"', 'Build, install, and launch on an Apple TV simulator')
|
|
1257
|
-
.example('$0 run --platform roku --target device --device "living room"', 'Build, deploy, launch, and stream logs on a Roku device')
|
|
1474
|
+
.example('$0 run --platform roku --target device --device "living room"', 'Build, deploy, launch, and stream logs on a Roku device')
|
|
1475
|
+
.example('$0 run roku dev device --app criterion', 'Run a configured monorepo app/flavor')
|
|
1476
|
+
.example('$0 run roku prod device --hsc-project platforms/hsconfig.criterion.prod.json', 'Override the Roku HSC project file'), async (args) => {
|
|
1258
1477
|
var _a, _b, _c;
|
|
1259
1478
|
try {
|
|
1260
|
-
const
|
|
1261
|
-
const
|
|
1479
|
+
const planner = await Promise.resolve().then(() => __importStar(require('./run/planner.js')));
|
|
1480
|
+
const executor = await Promise.resolve().then(() => __importStar(require('./run/executor.js')));
|
|
1481
|
+
const positionalArgv = rawCommandPositionals('run');
|
|
1482
|
+
const format = (args.json || args.format === 'json') ? 'json' : 'text';
|
|
1483
|
+
const plan = planner.createRunPlan({
|
|
1262
1484
|
cwd: process.cwd(),
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1485
|
+
argv: positionalArgv,
|
|
1486
|
+
flags: {
|
|
1487
|
+
platform: rawHasFlag('platform') ? args.platform : undefined,
|
|
1488
|
+
env: rawHasFlag('env') ? args.env : undefined,
|
|
1489
|
+
app: rawHasFlag('app') ? args.app : undefined,
|
|
1490
|
+
target: rawHasFlag('target') ? args.target : undefined,
|
|
1491
|
+
device: rawHasFlag('device') ? args.device : undefined,
|
|
1492
|
+
profile: rawHasFlag('profile') ? args.profile : undefined,
|
|
1493
|
+
appConfig: rawHasFlag('app-config') ? args['app-config'] : undefined,
|
|
1494
|
+
hotReload: rawHasFlag('hot-reload') ? Boolean(args['hot-reload']) : undefined,
|
|
1495
|
+
bundled: rawHasFlag('bundled') ? Boolean(args.bundled) : undefined,
|
|
1496
|
+
noBuild: rawHasFlag('no-build') ? Boolean(args['no-build']) : undefined,
|
|
1497
|
+
buildOnly: rawHasFlag('build-only') ? Boolean(args['build-only']) : undefined,
|
|
1498
|
+
noLogs: rawHasFlag('no-logs') ? Boolean(args['no-logs']) : undefined,
|
|
1499
|
+
logs: rawHasFlag('logs') ? Boolean(args.logs) : undefined,
|
|
1500
|
+
sourceRoot: rawHasFlag('source-root') ? args['source-root'] : undefined,
|
|
1501
|
+
appPackage: rawHasFlag('app-package') ? args['app-package'] : undefined,
|
|
1502
|
+
files: rawHasFlag('files') ? args.files : undefined,
|
|
1503
|
+
deployTimeoutMs: rawHasFlag('deploy-timeout-ms') ? args['deploy-timeout-ms'] : undefined,
|
|
1504
|
+
config: rawHasFlag('config') ? args.config : undefined,
|
|
1505
|
+
hscProject: rawHasFlag('hsc-project') ? args.hscProject : undefined,
|
|
1506
|
+
vitePort: rawHasFlag('vitePort') ? args.vitePort : undefined,
|
|
1507
|
+
webAppPort: rawHasFlag('webAppPort') ? args.webAppPort : undefined,
|
|
1508
|
+
deviceAppPort: rawHasFlag('deviceAppPort') ? args.deviceAppPort : undefined,
|
|
1509
|
+
extensionPort: rawHasFlag('extensionPort') ? args.extensionPort : undefined,
|
|
1510
|
+
managementPort: rawHasFlag('managementPort') ? args.managementPort : undefined,
|
|
1511
|
+
appName: rawHasFlag('appName') ? args.appName : undefined,
|
|
1512
|
+
replace: rawHasFlag('replace') ? Boolean(args.replace) : undefined,
|
|
1513
|
+
nonInteractive: rawHasFlag('non-interactive') ? Boolean(args['non-interactive']) : undefined,
|
|
1514
|
+
dryRun: Boolean(args['dry-run']),
|
|
1515
|
+
format,
|
|
1516
|
+
explain: rawHasFlag('explain') ? Boolean(args.explain) : undefined,
|
|
1517
|
+
allowProfileInProd: rawHasFlag('allow-profile-in-prod') ? Boolean(args['allow-profile-in-prod']) : undefined,
|
|
1518
|
+
passthroughArgs: args['--'],
|
|
1519
|
+
},
|
|
1286
1520
|
env: process.env,
|
|
1287
1521
|
});
|
|
1288
|
-
if (args
|
|
1522
|
+
if (args['dry-run']) {
|
|
1523
|
+
if (format === 'json') {
|
|
1524
|
+
console.info(JSON.stringify(plan, null, 2));
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
console.info(formatRunPlanText(plan, Boolean(args.explain)));
|
|
1528
|
+
}
|
|
1529
|
+
process.exit(0);
|
|
1530
|
+
}
|
|
1531
|
+
const result = await executor.executeRunPlan(plan);
|
|
1532
|
+
if (format === 'json') {
|
|
1289
1533
|
console.info(JSON.stringify(result, null, 2));
|
|
1290
1534
|
}
|
|
1291
1535
|
else if (result.status === 'reused') {
|
|
@@ -1409,6 +1653,16 @@ catch (err) {
|
|
|
1409
1653
|
type: 'boolean',
|
|
1410
1654
|
default: false,
|
|
1411
1655
|
describe: 'Connect to telnet and pipe Roku device log output to terminal. In log mode, press r to redeploy (use --log-output, not --log-output true)'
|
|
1656
|
+
})
|
|
1657
|
+
.option('deploy-timeout-ms', {
|
|
1658
|
+
type: 'number',
|
|
1659
|
+
default: 30000,
|
|
1660
|
+
describe: 'Roku deploy request timeout in milliseconds'
|
|
1661
|
+
})
|
|
1662
|
+
.option('log-connect-timeout-ms', {
|
|
1663
|
+
type: 'number',
|
|
1664
|
+
default: 10000,
|
|
1665
|
+
describe: 'Roku telnet log connection timeout in milliseconds'
|
|
1412
1666
|
})
|
|
1413
1667
|
.option('applySourceMapToPaths', {
|
|
1414
1668
|
type: 'boolean',
|
|
@@ -1450,6 +1704,8 @@ catch (err) {
|
|
|
1450
1704
|
logs: Boolean(args.logs),
|
|
1451
1705
|
logOutput: Boolean(args['log-output']),
|
|
1452
1706
|
applySourceMapToPaths: Boolean(args['applySourceMapToPaths']),
|
|
1707
|
+
deployTimeoutMs: args['deploy-timeout-ms'],
|
|
1708
|
+
logConnectTimeoutMs: args['log-connect-timeout-ms'],
|
|
1453
1709
|
dotenv: true,
|
|
1454
1710
|
});
|
|
1455
1711
|
process.exit(0);
|