@tantawowa/hosanna-tools 3.13.0 → 3.14.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 CHANGED
@@ -102,6 +102,75 @@ Common build-script replacements:
102
102
 
103
103
  Long-running APIs such as `dev.run`, `debugger.start`, `mcp.start`, and RASP-owned certification capture workflows keep the same operational behavior as the corresponding CLI commands: they start services, attach to debuggers, or wait for user/session activity. `mcp.start` and `dev.run` are wired for programmatic no-exit behavior through the top-level API.
104
104
 
105
+ ## Precompiled AppConfig and static asset bundles
106
+
107
+ Projects enable the compiler in `.hosanna-tools/run.json`. Normal `hst run` and
108
+ `hst build` plans then compile before starting or packaging the target:
109
+
110
+ ```json
111
+ {
112
+ "defaults": {
113
+ "appConfigCompiler": {
114
+ "enabled": true,
115
+ "shapeDelivery": "bundled",
116
+ "fontDelivery": "bundled",
117
+ "bundleOutputDir": "public/asset-bundles",
118
+ "assetUrlRoot": "/asset-bundles",
119
+ "staticBundleManifest": "asset-bundles/static-bundles.json"
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ `staticBundleManifest` is optional. It adds scoped image, mask, JSON, media, or
126
+ other project-owned assets to the same precompile step:
127
+
128
+ ```json
129
+ {
130
+ "schemaVersion": 1,
131
+ "bundles": [
132
+ {
133
+ "bundleId": "sample-home",
134
+ "cacheBundleId": "sample-shared",
135
+ "sourceDir": "sample-assets",
136
+ "assets": [
137
+ "content/home.json",
138
+ "images/hero.jpg",
139
+ {
140
+ "source": "images/mask.png",
141
+ "fileName": "masks/home.png",
142
+ "required": true
143
+ }
144
+ ]
145
+ }
146
+ ]
147
+ }
148
+ ```
149
+
150
+ Paths are relative to the manifest. `assetsFile` may replace or supplement the
151
+ inline `assets` array; it accepts either an array or an object containing an
152
+ `assets` array. Existing descriptor-shaped source lists are accepted by using
153
+ each entry's `fileName` as its source.
154
+
155
+ Generated descriptors use `sha256:<digest>` versions derived from asset
156
+ contents, keys, required flags, bundle/cache ids, and optional revisions.
157
+ Descriptors that share a `cacheBundleId` also share one aggregate version, so
158
+ loading a second scoped descriptor cannot invalidate assets retained by the
159
+ first.
160
+ Compiler ledgers remove stale owned files. Missing required sources fail before
161
+ the application starts; optional missing sources are omitted. Re-running the
162
+ command preserves byte-identical output and does not rewrite unchanged files.
163
+
164
+ Useful commands:
165
+
166
+ ```bash
167
+ npx hst app-config:compile --expression tv --platform web \
168
+ --static-bundle-manifest asset-bundles/static-bundles.json
169
+ npx hst run web dev browser --rebuild-app-config
170
+ npx hst app-config:clean --expression tv --platform web \
171
+ --static-bundle-manifest asset-bundles/static-bundles.json
172
+ ```
173
+
105
174
  # Getting started
106
175
 
107
176
  Ensure you have Node.js 24.17.0.
@@ -1,6 +1,6 @@
1
1
  {
2
- "buildDate": "2026-07-31T15:02:33+00:00",
3
- "buildDateISO": "2026-07-31T15:02:33.275Z",
2
+ "buildDate": "2026-08-05T08:18:35+00:00",
3
+ "buildDateISO": "2026-08-05T08:18:35.471Z",
4
4
  "timeZone": "UTC",
5
- "gitHash": "64c10e3"
5
+ "gitHash": "63ba7f3"
6
6
  }
package/dist/cli.js CHANGED
@@ -574,7 +574,7 @@ catch (err) {
574
574
  process.exit(1);
575
575
  }
576
576
  })
577
- .command('app-config:compile', 'Resolve AppConfig and materialize precompiled theme shapes, bundled fonts, and an asset-bundle manifest', yargs => yargs
577
+ .command('app-config:compile', 'Resolve AppConfig and materialize precompiled theme shapes, bundled fonts, and static asset bundles', yargs => yargs
578
578
  .option('input', { type: 'string', describe: 'Input path, app.config.<name>.json filename, or short selector' })
579
579
  .option('cwd', { type: 'string', describe: 'Project root (default: current working directory)' })
580
580
  .option('expression', { type: 'string', describe: 'Expression selector such as tv, phone, or tablet' })
@@ -588,6 +588,7 @@ catch (err) {
588
588
  .option('bundle-config-key', { type: 'string', default: 'compiledTheme', describe: 'Key written beneath AppConfig assetBundles' })
589
589
  .option('bundle-output-dir', { type: 'string', default: 'public/asset-bundles', describe: 'Publishable asset-bundle output root' })
590
590
  .option('asset-url-root', { type: 'string', default: '/asset-bundles', describe: 'HTTP URL root written into bundle asset descriptors' })
591
+ .option('static-bundle-manifest', { type: 'string', describe: 'Static asset-bundle input manifest compiled alongside AppConfig assets' })
591
592
  .option('watch', { type: 'boolean', default: false, describe: 'Watch AppConfig inheritance and local bundled files' })
592
593
  .option('rebuild', { type: 'boolean', default: false, describe: 'Re-render compiler assets instead of reusing the incremental cache' })
593
594
  .option('force', { type: 'boolean', default: false, describe: 'Rewrite unchanged compiler-owned files' }), async (args) => {
@@ -606,6 +607,7 @@ catch (err) {
606
607
  bundleConfigKey: args.bundleConfigKey,
607
608
  bundleOutputDir: args.bundleOutputDir,
608
609
  assetUrlRoot: args.assetUrlRoot,
610
+ staticBundleManifest: args.staticBundleManifest,
609
611
  watch: Boolean(args.watch),
610
612
  rebuild: Boolean(args.rebuild),
611
613
  force: Boolean(args.force),
@@ -626,7 +628,8 @@ catch (err) {
626
628
  .option('platform', { type: 'string', default: 'roku', describe: 'Compilation platform' })
627
629
  .option('generated-dir', { type: 'string', describe: 'Generated target root (contains package/)' })
628
630
  .option('bundle-id', { type: 'string', describe: 'Asset bundle id to remove' })
629
- .option('bundle-output-dir', { type: 'string', default: 'public/asset-bundles', describe: 'Asset-bundle output root' }), args => {
631
+ .option('bundle-output-dir', { type: 'string', default: 'public/asset-bundles', describe: 'Asset-bundle output root' })
632
+ .option('static-bundle-manifest', { type: 'string', describe: 'Static asset-bundle input manifest whose compiler-owned outputs should be removed' }), args => {
630
633
  try {
631
634
  (0, cli_app_config_compile_js_1.runAppConfigCleanCommand)({
632
635
  cwd: args.cwd,
@@ -636,6 +639,7 @@ catch (err) {
636
639
  generatedDir: args.generatedDir,
637
640
  bundleId: args.bundleId,
638
641
  bundleOutputDir: args.bundleOutputDir,
642
+ staticBundleManifest: args.staticBundleManifest,
639
643
  });
640
644
  process.exit(0);
641
645
  }
@@ -758,14 +762,14 @@ catch (err) {
758
762
  .option('signing-password', { type: 'string', describe: 'Signing password (env: ROKU_DEV_PASSWORD)' })
759
763
  .option('key-pkg', { type: 'string', describe: 'Path or filename of the signed key package (.pkg) (env: ROKU_PKG_NAME)' })
760
764
  .option('key-pkg-base64', { type: 'string', describe: 'Base64-encoded signed key package (.pkg) (env: ROKU_PKG_KEY_BASE64)' })
761
- .option('env', { type: 'string', choices: ['prod', 'dev'], default: 'prod', describe: 'Used in output naming; does not modify project config' })
765
+ .option('env', { type: 'string', default: 'prod', describe: 'Safe environment name used only in output naming; does not modify project config' })
762
766
  .option('rootDir', { type: 'string', describe: 'Roku project root (default: ./platforms/roku/src)' })
763
767
  .option('outDir', { type: 'string', describe: 'Output directory (default: ./build)' })
764
768
  .option('prebuild', { type: 'string', describe: 'Shell command to run before packaging (e.g. "npm run transpile:prod")' })
765
769
  .option('quiet', { type: 'boolean', default: false, describe: 'Reduce output; print only errors and success' })
766
770
  .example('$0 roku:package --ip 192.168.1.10 --installer-password secret --dev-id ABC --signing-password sss --key-pkg mykey.pkg', 'Package and sign with explicit args')
767
771
  .example('$0 roku:package --key-pkg-base64 <base64-string>', 'Package using base64-encoded key package')
768
- .example('$0 roku:package --env prod', 'Use env vars including ROKU_PKG_KEY_BASE64'), async (args) => {
772
+ .example('$0 roku:package --env staging', 'Use a custom environment name with env vars including ROKU_PKG_KEY_BASE64'), async (args) => {
769
773
  if (args.verbose) {
770
774
  process.env.HOSANNA_VERBOSE = '1';
771
775
  process.env.HOSANNA_UPDATER_VERBOSE = '1';