@wix/himalaya-cli 0.1359.0 → 0.1360.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.
@@ -1955,6 +1955,12 @@ export interface PdfViewProps {
1955
1955
  zoomable?: boolean;
1956
1956
  allowShare?: boolean;
1957
1957
  }
1958
+ /**
1959
+ * Inline video player. Needs the `media_playback` capability: the player lives in the native
1960
+ * media module, which a binary links only when the app declares `media_playback` (in
1961
+ * `capabilities` or `capabilityEnvelope`). Without it the component draws a sized placeholder,
1962
+ * and `himi validate` rejects a screen that uses it.
1963
+ */
1958
1964
  export interface VideoProps {
1959
1965
  url?: string;
1960
1966
  poster?: string;
@@ -2023,7 +2029,12 @@ export interface MediaPlayerAppearance {
2023
2029
  controlSize?: "compact" | "regular" | "large";
2024
2030
  cornerStyle?: "none" | "small" | "medium" | "large" | "pill";
2025
2031
  }
2026
- /** RFC 0044 — the server-driven audio/video/podcast/provider player. */
2032
+ /**
2033
+ * RFC 0044 — the server-driven audio/video/podcast/provider player. Needs the `media_playback`
2034
+ * capability: the player lives in the native media module, which a binary links only when the
2035
+ * app declares `media_playback` (in `capabilities` or `capabilityEnvelope`). Without it the
2036
+ * component draws a sized placeholder, and `himi validate` rejects a screen that uses it.
2037
+ */
2027
2038
  export interface MediaPlayerProps {
2028
2039
  sessionId?: string;
2029
2040
  items?: MediaItem[];
@@ -2075,7 +2086,10 @@ export interface MediaPlayerProps {
2075
2086
  * Lottie/Rive vector animation (motion grammar Batch 4). `source` is an https
2076
2087
  * URL to the animation JSON or the inline JSON string; it ships OTA. Native:
2077
2088
  * lottie-ios / lottie-compose; web: lottie-web. Reduced motion → static last
2078
- * frame. Needs an explicit `height` to compose in scroll containers.
2089
+ * frame. Needs an explicit `height` to compose in scroll containers. Needs the `animation`
2090
+ * capability: Lottie lives in the native animation module, which a binary links only when the
2091
+ * app declares `animation` (in `capabilities` or `capabilityEnvelope`). Without it the component
2092
+ * draws a sized placeholder, and `himi validate` rejects a screen that uses it.
2079
2093
  */
2080
2094
  export interface LottieProps {
2081
2095
  source?: string;
@@ -2086,7 +2100,10 @@ export interface LottieProps {
2086
2100
  }
2087
2101
  /** A Rive animation (motion grammar, Phase-2). `source` = https .riv URL shipped OTA;
2088
2102
  * `artboard`/`stateMachine` select within it. Native: rive-ios/rive-android; web:
2089
- * @rive-app/canvas (dynamic import). Reduced motion → static first frame. */
2103
+ * @rive-app/canvas (dynamic import). Reduced motion → static first frame. Needs the `animation`
2104
+ * capability: Rive lives in the native animation module, which a binary links only when the app
2105
+ * declares `animation` (in `capabilities` or `capabilityEnvelope`). Without it the component
2106
+ * draws a sized placeholder, and `himi validate` rejects a screen that uses it. */
2090
2107
  export interface RiveProps {
2091
2108
  source?: string;
2092
2109
  artboard?: string;
package/dist/cli.mjs CHANGED
@@ -7650,7 +7650,6 @@ function buttonVariant(style) {
7650
7650
  var SYSTEM_FONT_FAMILY, TONAL_ELEVATION_ALPHA, BUTTON_MIN_HIT_TARGET, nonNegative, nonEmpty, own, COLOR_TOKEN_PROPS, TYPOGRAPHY_TOKEN_PROPS, BUTTON_VARIANTS;
7651
7651
  var init_tokens = __esm({
7652
7652
  "../../core/ts/src/tokens.ts"() {
7653
- "use strict";
7654
7653
  SYSTEM_FONT_FAMILY = "$system";
7655
7654
  TONAL_ELEVATION_ALPHA = [0, 0.05, 0.08, 0.11, 0.12, 0.14];
7656
7655
  BUTTON_MIN_HIT_TARGET = 44;
@@ -7706,7 +7705,6 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
7706
7705
  var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
7707
7706
  var init_bindings = __esm({
7708
7707
  "../../core/ts/src/bindings.ts"() {
7709
- "use strict";
7710
7708
  BINDING_SIGILS = ["service", "flag", "item", "t"];
7711
7709
  BINDING_SIGIL_RE = new RegExp(
7712
7710
  `^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
@@ -17,6 +17,12 @@ A content package configures itself in three layers:
17
17
  prefix of `id`), `ports: { devServer, web }`, `schemaPackageRange: { min, max }`.
18
18
  - **Theming:** `designTokensPath` → tokens.json (the kit is chosen *inside* tokens.json's `kit` block).
19
19
  - `capabilities: Capability[]` — the app's declared native capabilities.
20
+ - `capabilityEnvelope?: Capability[]` — the native BUILD envelope, a superset of `capabilities`. The
21
+ binary is built for `capabilities ∪ capabilityEnvelope` (usage strings, entitlements, permissions and
22
+ the native modules those capabilities link), so a later release can turn an envelope capability on
23
+ over the air by widening `capabilities` — within the envelope only; beyond it needs a new binary.
24
+ `capabilities ⊆ capabilityEnvelope` is enforced (`himi validate` and `defineApp` error on an id
25
+ outside it). Omitted ⇒ defaults to `capabilities`. `himi docs capabilities` has the details.
20
26
  - `navigation: NavigationConfig`.
21
27
  - `entities: Record<string, EntityConfig>` — **required**, and `entities: {}` is the normal value.
22
28
  Each entry is a build-time DOMAIN entity and its cache materialization shape (`{ file }` or
@@ -115,6 +121,12 @@ with a native footprint only arrives with a new binary. `himi docs capabilities`
115
121
  loop — discover, declare, validate, ship — and `himi capabilities <id>` shows the import and which
116
122
  shells' binaries serve it.
117
123
 
124
+ Declared capabilities also decide which native modules link into the binary: a capability the build
125
+ does not include answers `module_not_linked` on device. Some components need one — `Video`,
126
+ `MediaPlayer` and `CarBrowse` need `media_playback`, `Lottie` and `Rive` need `animation` —
127
+ and `himi validate` errors on a screen that uses one the app does not declare.
128
+ `presigned_upload.putFile` also requires `files` on the calling screen.
129
+
118
130
  App-level capability vocabulary: `camera`, `barcode_scanner`, `biometrics`, `secure_storage`, `share`, `push`, `file_picker`, `files`, `open_url`, `pdf`, `clipboard`, `theme`, `photos`, `presigned_upload`, `ui`, `calendar`, `contacts`, `tasks`, `audio_record`, `audio_record_background`, `calls`, `location`, `location_background`, `motion`, `health`, `media_playback`, `webview`, `browser_auth`, `haptic`, `himi_apps`, `iap`, `keyboard`, `wix_cashier`, `live_activity`, `local_database`, `speech`, `speaker_diarization`, `system_intents`, `on_device_ai`, `app_info`, `release_control`, `godot`, `base44`, `animation`.
119
131
 
120
132
  ## What `himi validate` checks (7 passes)
@@ -59,6 +59,40 @@ The screen list is enforced at runtime: a call the screen did not declare is **d
59
59
  so it must name every capability the app uses. A background variant (`location_background`,
60
60
  `audio_record_background`) is declared instead of — and grants — its foreground capability.
61
61
 
62
+ ### Headroom for later: `capabilityEnvelope`
63
+
64
+ `capabilities` is what the app serves today, and by default it is also what the binary is built
65
+ for. To be able to turn a capability on later **without a new binary**, list it in
66
+ `capabilityEnvelope` as well — the native build envelope, a superset of `capabilities`:
67
+
68
+ ```ts
69
+ // config.ts — the binary carries camera's usage string and permission; the app serves only push today
70
+ capabilities: ["push"],
71
+ capabilityEnvelope: ["push", "camera"],
72
+ ```
73
+
74
+ - The binary is built for `capabilities ∪ capabilityEnvelope`: every id in the envelope gets its
75
+ usage strings, entitlements, permissions and native module, **where applicable** (ids such as
76
+ `secure_storage` or `share` add none of these), even before `capabilities` lists it.
77
+ - `capabilities ⊆ capabilityEnvelope` is enforced when `capabilityEnvelope` is **present**:
78
+ `himi validate` (and `defineApp`) reports an error for an id in `capabilities` that the envelope
79
+ lacks, because no install would carry its
80
+ native config. A background variant in the envelope covers its foreground capability.
81
+ - Turning a capability on over the air means widening `capabilities` **within** the envelope and
82
+ pushing. Going beyond the envelope still needs a new binary and a store resubmission.
83
+ - Omit `capabilityEnvelope` and it defaults to `capabilities` — the smallest binary.
84
+
85
+ ### Capabilities that need another capability
86
+
87
+ - **`presigned_upload.putFile` requires `files`.** `putFile` uploads a file from the app's document
88
+ store, so the screen that calls it must declare `files` too (and so must `config.ts`). Without
89
+ it the worker gate refuses `capability.presigned_upload.putFile` on iOS, macOS, Android and the
90
+ web. Declaring `presigned_upload` grants none of the files surface, and `put` (bytes the worker
91
+ already holds) needs only `presigned_upload`.
92
+ - **Some components need a capability** — `Video`, `MediaPlayer`, `CarBrowse`, `Lottie` and
93
+ `Rive` render through a native module, so the app must declare the capability that links
94
+ it. See [Components that need a capability](#components-that-need-a-capability).
95
+
62
96
  ### Local database and tenant switches
63
97
 
64
98
  On native hosts `local_database` is also scoped by the host's active tenant. On a multi-tenant host such as Himi Player, a worker is stamped with the tenant that was active when its boot started. The
@@ -87,10 +121,14 @@ The `capabilities` pass reports:
87
121
  - an **unknown id** (a typo such as `camara`) — an error, with a suggestion;
88
122
  - a bundle that **calls a capability its screen does not declare**;
89
123
  - a capability a screen declares that **`config.ts` `capabilities` is missing**;
90
- - when the app names its shell, a capability **that shell's binary does not serve**.
91
-
92
- An undeclared call is a warning, and an error under `--strict`. The last two describe the binary
93
- rather than your content, so they stay warnings — except a mismatch with the shared Himi Player
124
+ - when the app names its shell, a capability **that shell's binary does not serve**;
125
+ - an id in `capabilities` that a **present** `capabilityEnvelope` is missing — an error (omitting
126
+ the field defaults it to `capabilities`, so it can never trip);
127
+ - a screen using a **component whose native module the app does not link** (`Video` without
128
+ `media_playback`, `Lottie` without `animation`, …) — an error.
129
+
130
+ An undeclared call is a warning, and an error under `--strict`. The missing app-level id and the
131
+ shell mismatch describe the binary rather than your content, so they stay warnings — except a mismatch with the shared Himi Player
94
132
  binary, which is always an error: one binary hosts every app, and no content change can add to it.
95
133
 
96
134
  Name the shell your app ships in once, in `himalaya.content.json`, and both `himi validate` and
@@ -137,9 +175,18 @@ prompt.
137
175
  it "needs a new `himi dist`" — the installed binary cannot call it until you rebuild.
138
176
  - **"needs a new binary".** A successful `himi dist` remembers what its binary was built with —
139
177
  on the job (`buildCapabilities`) and in your package (`.himi/last-dist.json`). From then on
140
- `himi push` prints `needs a new binary: <ids> — run himi dist` when the release declares an id
141
- that build lacks, a following device's draft offer says the same, and `himi validate` compares
142
- against that build rather than the committed shell.
178
+ `himi validate` compares against that build rather than the committed shell, and `himi push`
179
+ checks every release against it:
180
+ - a release that declares a **permission-bearing** capability (an iOS usage string or
181
+ entitlement, an Android permission — camera, location, push, …) the last dist lacks is
182
+ **refused**: the push fails with 409 `binary_capability_gap`, naming the missing ids and each
183
+ platform's last dist that lacks them. An over-the-air push cannot add an OS permission, and on
184
+ iOS asking for one whose purpose string is missing kills the app. Run `himi dist` first, or
185
+ pass `--allow-binary-gap` when every installed binary already carries it (the release records
186
+ `allowedBinaryGap`). `himi push --only` and `himi patch` refuse the same way;
187
+ - a gap in a **permission-free** capability (share, clipboard, …) does not block: the push
188
+ prints `needs a new binary: <ids> — run himi dist`, and a following device's draft offer says
189
+ the same.
143
190
  - **Never a silent strip.** On iOS, a capability whose entitlement the signing profile cannot grant
144
191
  fails the dist job, naming the capability — the binary would otherwise build green and fail on
145
192
  the first call. The minted profile's Apple capabilities are derived from the build's own set.
@@ -150,11 +197,88 @@ prompt.
150
197
  attach it to an expense." }` — or the build uses a generic one, which App Review often rejects.
151
198
  - **What a build cannot add.** `player` (Himi Player — one binary for every app) and `demo-app` are
152
199
  fixed: a release declaring an id they do not serve is refused with `shell_capability_mismatch`,
153
- naming shells that can carry it. On an extensible shell, an id with no core handler, or one that
154
- needs wiring a build cannot do (`local_database` needs the app's data schema installed first,
155
- `live_activity` a widget extension target, `base44` / `godot` an opt-in SDK, `wix_platform` boot
156
- configuration), is refused with `unsupported_capability` and the reason. `health` is addable:
157
- the build links HealthKit and Health Connect, and `permissionCopy.health` is the iOS purpose
158
- string and the Health Connect rationale. A shell that does not carry a capability's usage
159
- string can crash the app at the permission prompt, which is why both the build and
160
- `himi validate` check before you ship.
200
+ naming shells that can carry it. On an extensible shell, a build links any capability whose
201
+ native module the platform ships (see [Native modules](#6-native-modules-what-a-capability-links))
202
+ and installs its handlers at boot. What it cannot do is the per-app **boot wiring** a few
203
+ capabilities need beyond that registration, so these are refused with `unsupported_capability`
204
+ and the reason:
205
+
206
+ | Id | Why a build cannot add it |
207
+ |---|---|
208
+ | `local_database` | the shell has to install the app's data schema first — registering it without one would store declared-encrypted entities in plaintext |
209
+ | `live_activity` | needs a WidgetKit extension target in the shell's project |
210
+ | `wix_platform` | the shell's boot has to configure it with a Wix API client and launch services |
211
+ | `himi_apps` | a multi-app host surface (Himi Player), not something one app's binary serves |
212
+ | `app_info` | the shell's boot has to configure it with the app id it reports |
213
+ | `system_intents` | the shell has to wire the system-intents host (app identity, deep-link routing, refresh) |
214
+ | `release_control` | the shell's boot has to configure it with the app id whose releases it switches |
215
+ | `base44` | the shell's boot has to bind the Base44 app it talks to; the module links, the binding is the shell's |
216
+ | `godot` | needs the shell's game surface view and, on Android, the shell's pick of the engine's C++ runtime |
217
+
218
+ An id with no handler on both iOS and Android is refused the same way. Everything else with a
219
+ native module is addable — `health` (the build links HealthKit and Health Connect, and
220
+ `permissionCopy.health` is the iOS purpose string and the Health Connect rationale), `iap`,
221
+ `calls` (the WebRTC engine), `animation`, `media_playback` and the rest. A shell that does not
222
+ carry a capability's usage string can crash the app at the permission prompt, which is why both
223
+ the build and `himi validate` check before you ship.
224
+
225
+ ## 6. Native modules: what a capability links
226
+
227
+ A capability whose native code pulls in a permission-gated OS framework or a third-party library
228
+ (HealthKit, StoreKit, WebRTC, Lottie and Rive, the media player, …) lives in its own native module.
229
+ **The capabilities your app declares decide which native code is linked into its binary**: a
230
+ build links a module only when its build set — `capabilities ∪ capabilityEnvelope`, plus what
231
+ `himi dist` bakes in — contains a capability the module serves. Everything else stays out, so the
232
+ binary carries neither the code nor the store-review footprint of a framework it does not use.
233
+
234
+ | Module | Linked by |
235
+ |---|---|
236
+ | animation | `animation` |
237
+ | audio (iOS) | `audio_record`, `audio_record_background` |
238
+ | base44 | `base44` |
239
+ | biometrics | `biometrics` |
240
+ | calendar | `calendar` |
241
+ | calls | `calls` |
242
+ | contacts | `contacts` |
243
+ | godot | `godot` |
244
+ | health | `health` |
245
+ | iap | `iap` (and `wix_cashier` on iOS) |
246
+ | live_activity | `live_activity` |
247
+ | location | `location`, `location_background` |
248
+ | location_background (iOS) | `location_background` |
249
+ | media | `media_playback` |
250
+ | motion | `motion` |
251
+ | on_device_ai (iOS) | `on_device_ai` |
252
+ | push | `push` |
253
+ | speech (iOS) | `speech` |
254
+ | tasks (iOS) | `tasks` |
255
+
256
+ What that means for a worker:
257
+
258
+ - **Undeclared means not linked.** The `capability.<id>.*` verbs always exist in the core, so the
259
+ declaration gate and the call shape are the same in every binary. In a binary that does not link
260
+ the module, the verbs answer `module_not_linked`: a permission check reports `denied` with
261
+ `reason: "module_not_linked"`, and other verbs reject with `unavailable: module_not_linked`.
262
+ The fix is to declare the capability and ship a new binary — not to retry.
263
+ - **Treat it like any other declined capability.** `himi test` already exercises the
264
+ unavailable path; a worker that handles a denied camera handles an unlinked module too.
265
+
266
+ ### Components that need a capability
267
+
268
+ A few components draw through a native module. A screen that uses one in an app whose build set
269
+ does not link that module would render a component whose library is not in the binary, so
270
+ `himi validate` reports an **error** naming the component and the capabilities that would link it.
271
+
272
+ | Component | Needs | Without it |
273
+ |---|---|---|
274
+ | `Video` | `media_playback` | sized placeholder |
275
+ | `MediaPlayer` | `media_playback` | sized placeholder |
276
+ | `CarBrowse` — the Android Auto media browse tree | `media_playback` | no car media surface |
277
+ | `Lottie` | `animation` | sized placeholder |
278
+ | `Rive` | `animation` | sized placeholder |
279
+
280
+ `animation` has no verbs and no permission: it exists only so the build links Lottie and Rive.
281
+ Add it to `capabilityEnvelope` instead of `capabilities` if a later release may start using
282
+ those components. A release whose screens use one of these components also requires the
283
+ capability from its host, so a Player binary that does not link the module refuses the release
284
+ instead of drawing placeholders.
@@ -1212,6 +1212,7 @@
1212
1212
  "name": "Video",
1213
1213
  "category": "Cross-cutting & media",
1214
1214
  "propsType": "VideoProps",
1215
+ "requiresCapability": "media_playback",
1215
1216
  "bindings": [],
1216
1217
  "notImplemented": {
1217
1218
  "props": [
@@ -1261,6 +1262,7 @@
1261
1262
  "name": "MediaPlayer",
1262
1263
  "category": "Cross-cutting & media",
1263
1264
  "propsType": "MediaPlayerProps",
1265
+ "requiresCapability": "media_playback",
1264
1266
  "bindings": [
1265
1267
  "itemsPath"
1266
1268
  ],
@@ -1320,6 +1322,7 @@
1320
1322
  "name": "Lottie",
1321
1323
  "category": "Rich vector & celebration (motion grammar Batch 4)",
1322
1324
  "propsType": "LottieProps",
1325
+ "requiresCapability": "animation",
1323
1326
  "bindings": [],
1324
1327
  "propsSource": "export interface LottieProps {\n source?: string;\n loop?: boolean;\n autoplay?: boolean;\n speed?: number;\n height?: number;\n}"
1325
1328
  },
@@ -1327,6 +1330,7 @@
1327
1330
  "name": "Rive",
1328
1331
  "category": "Rich vector & celebration (motion grammar Batch 4)",
1329
1332
  "propsType": "RiveProps",
1333
+ "requiresCapability": "animation",
1330
1334
  "bindings": [],
1331
1335
  "propsSource": "export interface RiveProps {\n source?: string;\n artboard?: string;\n stateMachine?: string;\n autoplay?: boolean;\n height?: number;\n}"
1332
1336
  },
@@ -2012,6 +2012,8 @@ export interface VideoProps {
2012
2012
  }
2013
2013
  ```
2014
2014
 
2015
+ > **Needs the `media_playback` capability.** It renders through a native module the binary links only when `config.ts` declares `media_playback` (in `capabilities` or `capabilityEnvelope`). Without it the component draws a sized placeholder, and `himi validate` rejects a screen that uses it.
2016
+
2015
2017
  > ⚠️ **Implemented, but these props are inert on ios:** `poster` — `poster` is not shown.
2016
2018
 
2017
2019
  #### PdfView
@@ -2084,6 +2086,8 @@ export interface MediaPlayerProps {
2084
2086
  }
2085
2087
  ```
2086
2088
 
2089
+ > **Needs the `media_playback` capability.** It renders through a native module the binary links only when `config.ts` declares `media_playback` (in `capabilities` or `capabilityEnvelope`). Without it the component draws a sized placeholder, and `himi validate` rejects a screen that uses it.
2090
+
2087
2091
  > ⚠️ **Not implemented on ios:** `autoplayVisibilityThreshold`, `preload`, `playbackRates`, `showQueue`, `showChapters`, `showTranscript` — `autoplayVisibilityThreshold` is ignored (whenVisible = once on appear). `preload` is ignored. `playbackRates` is ignored, and the queue/chapters/transcript panels never render.
2088
2092
 
2089
2093
  > ⚠️ **Not implemented on android:** `externalPlayback`, `appearance`, `allowCellular`, `preload`, `playbackRates`, `showQueue`, `showChapters`, `showTranscript` — `externalPlayback` is forced off. `appearance` is ignored. `allowCellular` is ignored. `preload` is ignored. `playbackRates` is ignored, and the queue/chapters/transcript panels never render.
@@ -2104,6 +2108,8 @@ export interface LottieProps {
2104
2108
  }
2105
2109
  ```
2106
2110
 
2111
+ > **Needs the `animation` capability.** It renders through a native module the binary links only when `config.ts` declares `animation` (in `capabilities` or `capabilityEnvelope`). Without it the component draws a sized placeholder, and `himi validate` rejects a screen that uses it.
2112
+
2107
2113
  #### Rive
2108
2114
 
2109
2115
  ```ts
@@ -2116,6 +2122,8 @@ export interface RiveProps {
2116
2122
  }
2117
2123
  ```
2118
2124
 
2125
+ > **Needs the `animation` capability.** It renders through a native module the binary links only when `config.ts` declares `animation` (in `capabilities` or `capabilityEnvelope`). Without it the component draws a sized placeholder, and `himi validate` rejects a screen that uses it.
2126
+
2119
2127
  #### MonthCalendar
2120
2128
 
2121
2129
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1359.0",
3
+ "version": "0.1360.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -71,5 +71,5 @@
71
71
  "artifactId": "himalaya-cli"
72
72
  }
73
73
  },
74
- "falconPackageHash": "8b9cac99029b9f7bced8bd984c585ef4ce4cd8b5fe5290a8bfb7a34d"
74
+ "falconPackageHash": "0a238e262e21ac93a2e8120f032811ae402c599e5b3e208cd0def547"
75
75
  }