@tantawowa/hosanna-tools 3.6.1 → 3.7.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/README.md +36 -9
- package/dist/build-info.json +3 -3
- package/dist/cli.js +44 -4
- package/dist/cli.js.map +1 -1
- package/dist/lib/hosanna-config.d.ts +3 -2
- package/dist/lib/hosanna-config.js +102 -34
- package/dist/lib/hosanna-config.js.map +1 -1
- package/dist/support-tools/framework-sync.js +2 -0
- package/dist/support-tools/framework-sync.js.map +1 -1
- package/dist/support-tools/roku-command.d.ts +37 -0
- package/dist/support-tools/roku-command.js +136 -0
- package/dist/support-tools/roku-command.js.map +1 -0
- package/dist/updater/framework-installer.d.ts +1 -0
- package/dist/updater/framework-installer.js +20 -4
- package/dist/updater/framework-installer.js.map +1 -1
- package/dist/updater/license-manager.d.ts +24 -0
- package/dist/updater/license-manager.js +87 -7
- package/dist/updater/license-manager.js.map +1 -1
- package/dist/updater/local-sdk-manager.d.ts +8 -0
- package/dist/updater/local-sdk-manager.js +198 -0
- package/dist/updater/local-sdk-manager.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,19 +20,32 @@ npm install . -g # path to the hosanna-tools directory
|
|
|
20
20
|
|
|
21
21
|
## Hosanna source install modes
|
|
22
22
|
|
|
23
|
-
Client projects can switch between Keygen source tarballs,
|
|
24
|
-
local
|
|
23
|
+
Client projects can switch between private Keygen source tarballs, an embedded
|
|
24
|
+
copy, a shared local checkout, and the legacy git/local modes:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
hst config source
|
|
28
|
-
hst config source keygen --
|
|
29
|
-
hst config source
|
|
30
|
-
hst config source
|
|
27
|
+
hst config source # show current mode and immutable install identity
|
|
28
|
+
hst config source keygen --sdk-version latest --install # newest valid private publication across all lanes
|
|
29
|
+
hst config source keygen --sdk-version v1.29.1 --install # pin an exact immutable production release
|
|
30
|
+
hst config source embedded --source-path ../hosanna-ui --install # filtered, reproducible copy
|
|
31
|
+
hst config source shared --source-path ../hosanna-ui --install # portable relative link for local development
|
|
32
|
+
hst config source git --install # legacy git checkout
|
|
33
|
+
hst config source local # caller-provided LOCAL_SDK checkout
|
|
31
34
|
```
|
|
32
35
|
|
|
33
|
-
Keygen mode writes `distribution: "keygen"`
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
Keygen mode writes `distribution: "keygen"`, `flavour: "fullSource"`, and no
|
|
37
|
+
platform list to `hosanna.json`. Bare `latest` means the newest valid published
|
|
38
|
+
full-source release by Keygen publication time, whether it came from a nightly,
|
|
39
|
+
manual, or tag run. `@latest` remains the stable-lane alias and `@nightly`
|
|
40
|
+
remains the development-lane alias. Exact versions are immutable pins.
|
|
41
|
+
|
|
42
|
+
Use `--replace-existing` with `--install` when switching an existing project
|
|
43
|
+
between modes. Replacement is refused for an unrecognized or modified source
|
|
44
|
+
root; `--force` is required for a dirty git checkout. Embedded installs exclude
|
|
45
|
+
repository/build/secret state, write a content-hash manifest, and never modify
|
|
46
|
+
the source checkout. Shared installs validate the source and create a relative
|
|
47
|
+
symlink. Granular flavours and platform subsets are deliberately rejected with
|
|
48
|
+
`NOT SUPPORTED YET — use flavour "fullSource"`.
|
|
36
49
|
|
|
37
50
|
## Embedding as a library
|
|
38
51
|
|
|
@@ -197,9 +210,23 @@ hst target:list --form-factor tv --json
|
|
|
197
210
|
|
|
198
211
|
### Roku Commands (`roku:*`) - Roku Deployment & Packaging
|
|
199
212
|
- `roku:run` - Deploy a Roku app to a device (supports .zip file or folder)
|
|
213
|
+
- `roku:command` - Send a Hosanna command to an installed channel through Roku ECP
|
|
200
214
|
- `roku:package` - Package and sign a Roku channel using roku-deploy
|
|
201
215
|
- `roku:map-stack` - Resolve Roku `.brs` stack traces, compile errors, and crash snippets to original TypeScript locations using `.brs.map` files
|
|
202
216
|
|
|
217
|
+
Send a command to the sideloaded `dev` channel (the default app ID):
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
hst roku:command clearRegistry --device 192.168.1.50
|
|
221
|
+
hst roku:command clearRegistry --device "Living Room" --yes
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The device can also come from `ROKU_IP` or the preferred/default Roku in `.hosanna-tools/devices.json`. Destructive commands such as `clearRegistry` prompt for confirmation unless `--yes` is passed. Use `--app-id` for another installed channel and `--dry-run` to print the encoded ECP request without sending it:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
hst roku:command clearRegistry --app-id 8518 --dry-run
|
|
228
|
+
```
|
|
229
|
+
|
|
203
230
|
Resolve pasted Roku output:
|
|
204
231
|
|
|
205
232
|
```bash
|
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -250,7 +250,7 @@ catch (err) {
|
|
|
250
250
|
// Let yargs handle all commands including env
|
|
251
251
|
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
252
252
|
.version(`${buildVersion}\n git: ${buildGitHash}\n built: ${buildDate}`)
|
|
253
|
-
.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 build Cross-platform build orchestration\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`)
|
|
253
|
+
.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 build Cross-platform build orchestration\n run Cross-platform launch orchestration\n native:* Native platform bootstrap and validation\n target:* Run target discovery and inventory\n roku:* Roku deployment, commands & packaging (run, command, 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`)
|
|
254
254
|
.option('verbose', {
|
|
255
255
|
type: 'boolean',
|
|
256
256
|
default: false,
|
|
@@ -551,6 +551,44 @@ catch (err) {
|
|
|
551
551
|
console.error('❌ Failed to publish Roku package:', err);
|
|
552
552
|
process.exit(1);
|
|
553
553
|
}
|
|
554
|
+
})
|
|
555
|
+
.command('roku:command <command>', 'Send a Hosanna command to an installed Roku channel through ECP', yargs => yargs
|
|
556
|
+
.positional('command', { type: 'string', demandOption: true, describe: 'Hosanna command name, e.g. clearRegistry' })
|
|
557
|
+
.option('device', { alias: 'ip', type: 'string', describe: 'Roku IP or configured device name (env: ROKU_IP)' })
|
|
558
|
+
.option('app-id', { type: 'string', default: 'dev', describe: 'Installed Roku channel ID (default: dev)' })
|
|
559
|
+
.option('timeout-ms', { type: 'number', default: 10000, describe: 'ECP request timeout in milliseconds' })
|
|
560
|
+
.option('yes', { alias: 'y', type: 'boolean', default: false, describe: 'Confirm destructive commands without prompting' })
|
|
561
|
+
.option('dry-run', { type: 'boolean', default: false, describe: 'Resolve the device and print the ECP request without sending it' })
|
|
562
|
+
.option('non-interactive', { type: 'boolean', default: false, describe: 'Fail instead of prompting for destructive command confirmation' })
|
|
563
|
+
.example('$0 roku:command clearRegistry --device 192.168.1.50', 'Clear the sideloaded dev channel registry after confirmation')
|
|
564
|
+
.example('$0 roku:command clearRegistry --device "living room" --yes', 'Clear the configured Roku registry non-interactively')
|
|
565
|
+
.example('$0 roku:command clearRegistry --app-id 8518 --dry-run', 'Preview a command for an installed production channel'), async (args) => {
|
|
566
|
+
try {
|
|
567
|
+
const mod = await Promise.resolve().then(() => __importStar(require('./support-tools/roku-command.js')));
|
|
568
|
+
const result = await mod.runRokuCommand({
|
|
569
|
+
command: args.command,
|
|
570
|
+
cwd: process.cwd(),
|
|
571
|
+
device: args.device,
|
|
572
|
+
appId: args['app-id'],
|
|
573
|
+
timeoutMs: args['timeout-ms'],
|
|
574
|
+
yes: Boolean(args.yes),
|
|
575
|
+
dryRun: Boolean(args['dry-run']),
|
|
576
|
+
nonInteractive: Boolean(args['non-interactive']),
|
|
577
|
+
env: process.env,
|
|
578
|
+
});
|
|
579
|
+
if (result.dryRun) {
|
|
580
|
+
console.info(`Dry run: POST ${result.url}`);
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
console.info(`✅ Sent Hosanna command "${result.command}" to Roku ${result.deviceIp} (app ${result.appId}).`);
|
|
584
|
+
}
|
|
585
|
+
process.exit(0);
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
588
|
+
console.error('❌ roku:command failed');
|
|
589
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
590
|
+
process.exit(1);
|
|
591
|
+
}
|
|
554
592
|
})
|
|
555
593
|
.command('roku:map-stack', 'Resolve Roku BrightScript stack traces or compile errors to original TypeScript locations using .brs.map files', yargs => yargs
|
|
556
594
|
.option('source-map-root', {
|
|
@@ -747,7 +785,7 @@ catch (err) {
|
|
|
747
785
|
})
|
|
748
786
|
.positional('mode', {
|
|
749
787
|
type: 'string',
|
|
750
|
-
choices: ['show', 'keygen', 'git', 'local'],
|
|
788
|
+
choices: ['show', 'keygen', 'git', 'local', 'embedded', 'shared'],
|
|
751
789
|
describe: 'Source install mode when action is source',
|
|
752
790
|
})
|
|
753
791
|
.option('git-url', { type: 'string', describe: 'Set hosanna.json git-url' })
|
|
@@ -756,8 +794,9 @@ catch (err) {
|
|
|
756
794
|
.option('transpiler-version', { type: 'string', describe: 'Set hosanna.json transpiler-version' })
|
|
757
795
|
.option('config-catalog-url', { type: 'string', describe: 'Persist a remote catalog URL into hosanna.json' })
|
|
758
796
|
.option('catalog-url', { type: 'string', describe: 'Use a remote catalog URL for this run without writing it' })
|
|
759
|
-
.option('flavour', { type: 'string', choices: ['core', 'game', 'full'], describe: 'Keygen source flavour when action is source (
|
|
760
|
-
.option('platforms', { type: 'string', array: true, describe: '
|
|
797
|
+
.option('flavour', { type: 'string', choices: ['fullSource', 'core', 'game', 'full'], describe: 'Keygen source flavour when action is source (supported: fullSource)' })
|
|
798
|
+
.option('platforms', { type: 'string', array: true, describe: 'Future split-platform selection; omit for fullSource' })
|
|
799
|
+
.option('source-path', { type: 'string', describe: 'Hosanna UI checkout to copy for embedded mode or link for shared mode' })
|
|
761
800
|
.option('install', { type: 'boolean', default: false, describe: 'Install the selected source mode atomically after updating config' })
|
|
762
801
|
.option('replace-existing', { type: 'boolean', default: false, describe: 'Allow --install to replace an existing hosanna-ui source root when switching modes' })
|
|
763
802
|
.option('force', { type: 'boolean', default: false, describe: 'Allow --install to replace a dirty git checkout when used with --replace-existing' })
|
|
@@ -774,6 +813,7 @@ catch (err) {
|
|
|
774
813
|
mode: (typeof args.mode === 'string' ? args.mode : 'show'),
|
|
775
814
|
flavour: args.flavour,
|
|
776
815
|
platforms: (0, hosanna_config_js_1.parsePlatformList)(stringArrayArg(args.platforms)),
|
|
816
|
+
sourcePath: typeof args.sourcePath === 'string' ? args.sourcePath : undefined,
|
|
777
817
|
sdkVersion: typeof args.sdkVersion === 'string' ? args.sdkVersion : undefined,
|
|
778
818
|
gitUrl: typeof args.gitUrl === 'string' ? args.gitUrl : undefined,
|
|
779
819
|
branch: typeof args.branch === 'string' ? args.branch : undefined,
|