@wix/himalaya-cli 0.1622.0 → 0.1624.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.
Binary file
@@ -581,7 +581,7 @@
581
581
  "category": "Feedback",
582
582
  "propsType": "AlertDialogProps",
583
583
  "bindings": [],
584
- "propsSource": "export interface AlertDialogProps {\n title: string;\n message?: string;\n confirmAction: Action;\n cancelAction?: Action;\n destructive?: boolean;\n /** #1059 — confirm button label; overridable (mirrors NavigationActionRouter's\n * `confirmLabel`). Default \"Confirm\", or \"Delete\" when `destructive`. */\n confirmLabel?: string;\n /** #1059 — cancel button label; overridable. Default \"Cancel\". */\n cancelLabel?: string;\n /** The overlay traps focus and hides the rest of the tree from AT while\n * presented (iOS `accessibilityViewIsModal`, Android `isTraversalGroup`, ARIA\n * `aria-modal`). TRI-STATE: absent takes this component's default (**true**), an\n * explicit `false` opts it out. */\n modal?: boolean;\n}"
584
+ "propsSource": "export interface AlertDialogProps {\n title: string;\n message?: string;\n /** Required unless `buttons` is set. */\n confirmAction?: Action;\n cancelAction?: Action;\n destructive?: boolean;\n /** #1059 — confirm button label; overridable (mirrors NavigationActionRouter's\n * `confirmLabel`). Default \"Confirm\", or \"Delete\" when `destructive`. */\n confirmLabel?: string;\n /** #1059 — cancel button label; overridable. Default \"Cancel\". */\n cancelLabel?: string;\n /** The overlay traps focus and hides the rest of the tree from AT while\n * presented (iOS `accessibilityViewIsModal`, Android `isTraversalGroup`, ARIA\n * `aria-modal`). TRI-STATE: absent takes this component's default (**true**), an\n * explicit `false` opts it out. */\n modal?: boolean;\n /** Up to three buttons, drawn in platform order (iOS/macOS: the cancel button in the\n * cancel position, two side by side, three stacked; Android/web: Material order). They replace\n * `confirmAction`/`cancelAction`; setting both is a validator warning, and the buttons win. */\n buttons?: AlertButton[];\n}"
585
585
  },
586
586
  {
587
587
  "name": "RichText",
@@ -1288,6 +1288,8 @@
1288
1288
  "TabItem": "export interface TabItem {\n id: string;\n label: string;\n badge?: string;\n}",
1289
1289
  "PickerOption": "export interface PickerOption {\n id: string;\n label: string;\n /** #3801 — a colour chip before the label: a colour token name or \"#RRGGBB\". Drawn first. */\n swatch?: string;\n /** #3801 — a small remote thumbnail before the label (drawn when there is no swatch). */\n imageUrl?: string;\n /** #3801 — a leading icon name (drawn when there is no swatch or image). */\n icon?: IconRef;\n /** #3801 — shown but not choosable; never dispatched through `onChange`. */\n disabled?: boolean;\n}",
1290
1290
  "PickerFieldStyle": "export interface PickerFieldStyle {\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n minHeight?: number;\n padding?: number;\n chevronIcon?: string;\n placeholderColor?: string;\n}",
1291
+ "AlertButtonRole": "export type AlertButtonRole = \"default\" | \"cancel\" | \"destructive\";",
1292
+ "AlertButton": "export interface AlertButton {\n id: string;\n label: string;\n /** `\"cancel\"` (at most one) takes the cancel position and is what scrim/back/Esc dismissal\n * resolves as; `\"destructive\"` draws with the `danger` token. Default `\"default\"`. */\n role?: AlertButtonRole;\n /** Runs on press. */\n action?: Action;\n}",
1291
1293
  "GaugeRing": "export interface GaugeRing {\n /** Fraction 0..1 for this ring. */\n value?: number;\n /** `$service:`/`$item.` binding → a live number (overrides `value`). */\n valuePath?: string;\n tint?: TokenName;\n}",
1292
1294
  "WidgetTimeRef": "export interface WidgetTimeRef {\n /** Epoch seconds the style counts from/to. */\n at: number;\n /** SwiftUI `Text.DateStyle` / Android time style (default \"timer\"). */\n style?: \"timer\" | \"relative\" | \"date\" | \"time\" | \"offset\";\n}",
1293
1295
  "CornerRadii": "export interface CornerRadii {\n topLeading?: number;\n topTrailing?: number;\n bottomLeading?: number;\n bottomTrailing?: number;\n}",
@@ -1235,7 +1235,8 @@ export interface SnackbarProps {
1235
1235
  export interface AlertDialogProps {
1236
1236
  title: string;
1237
1237
  message?: string;
1238
- confirmAction: Action;
1238
+ /** Required unless `buttons` is set. */
1239
+ confirmAction?: Action;
1239
1240
  cancelAction?: Action;
1240
1241
  destructive?: boolean;
1241
1242
  /** #1059 — confirm button label; overridable (mirrors NavigationActionRouter's
@@ -1248,6 +1249,10 @@ export interface AlertDialogProps {
1248
1249
  * `aria-modal`). TRI-STATE: absent takes this component's default (**true**), an
1249
1250
  * explicit `false` opts it out. */
1250
1251
  modal?: boolean;
1252
+ /** Up to three buttons, drawn in platform order (iOS/macOS: the cancel button in the
1253
+ * cancel position, two side by side, three stacked; Android/web: Material order). They replace
1254
+ * `confirmAction`/`cancelAction`; setting both is a validator warning, and the buttons win. */
1255
+ buttons?: AlertButton[];
1251
1256
  }
1252
1257
  ```
1253
1258
 
@@ -2508,7 +2513,9 @@ A few props take a typed **object** rather than nested components. Some are arra
2508
2513
  `TabItem[]`, `Picker.options` / `WheelPicker.options` are a `PickerOption[]` (and
2509
2514
  `Picker.field` is a single `PickerFieldStyle`, the drawn field's look), and
2510
2515
  `Gauge.rings` is a `GaugeRing[]` (concentric rings, drawn outer→inner), and
2511
- `RichContentEditor.tools` is a `RichContentEditorTool[]` (a fixed list of toolbar buttons).
2516
+ `RichContentEditor.tools` is a `RichContentEditorTool[]` (a fixed list of toolbar buttons), and
2517
+ `AlertDialog.buttons` is an `AlertButton[]` (1–3 buttons, at most one `cancel`; it replaces
2518
+ `confirmAction`/`cancelAction`).
2512
2519
  `Shape` takes three objects: `cornerRadii` is a `CornerRadii` (layout-direction corners,
2513
2520
  also `modifiers.clipCornerRadii`), `fillGradient` is a `Gradient` and `stroke` is a
2514
2521
  `ShapeStroke` (its `dash` is on/off lengths; empty is solid).
@@ -2592,6 +2599,18 @@ export interface ShapeStroke {
2592
2599
  /** on/off dash lengths in pt/dp; empty ⇒ solid. RN draws any dash as its fixed `dashed` style. */
2593
2600
  dash?: number[];
2594
2601
  }
2602
+
2603
+ export type AlertButtonRole = "default" | "cancel" | "destructive";
2604
+
2605
+ export interface AlertButton {
2606
+ id: string;
2607
+ label: string;
2608
+ /** `"cancel"` (at most one) takes the cancel position and is what scrim/back/Esc dismissal
2609
+ * resolves as; `"destructive"` draws with the `danger` token. Default `"default"`. */
2610
+ role?: AlertButtonRole;
2611
+ /** Runs on press. */
2612
+ action?: Action;
2613
+ }
2595
2614
  ```
2596
2615
 
2597
2616
  ## Modifiers
@@ -332,7 +332,9 @@ scroll. *Reach for `SegmentedControl` for 2–4 in-content modes; `Tabs`/tab-bar
332
332
  > explicit `PageControl` if the dots need to read.
333
333
 
334
334
  **Feedback & overlays** — `Banner` for a persistent inline message (with a retry action when a refresh fails over content you kept; a screen with nothing to show uses an `ErrorState`, see §5);
335
- `Snackbar` for a transient confirmation; `AlertDialog` for a blocking decision; `BottomSheet` for
335
+ `Snackbar` for a transient confirmation; `AlertDialog` for a blocking decision (up to three `buttons`
336
+ — "Save / Discard / Cancel" — with roles `default` / `cancel` / `destructive`; a worker's
337
+ `ui.alert({ buttons })` resolves `{ buttonId }`); `BottomSheet` for
336
338
  contextual actions/detail; `Tooltip`/`Popover` for a small anchored hint. *Reach for `Snackbar`, not
337
339
  `AlertDialog`, to confirm a completed action — don't block on success.* The `Snackbar` COMPONENT draws
338
340
  inline where you place it; for a transient toast that floats at the bottom of the screen — an app
@@ -464,6 +464,40 @@ top-level `code` on stderr.
464
464
  `navLogicBundle` that differs, or its `navigation` cannot be edited safely; the
465
465
  literal to merge is returned in `snippet` and nothing is written (exit 1).
466
466
 
467
+ ## `himi one-app access` codes
468
+
469
+ Carries the source's locked pages (members only, a badge, a paid plan) and its app-wide login requirement into a
470
+ migrated app. Success prints `ok: true` and a `status`: `written`, `unchanged`, `would_write` (`--dry-run`), `in_sync`
471
+ (`--check`) or `no_gates`; `unmapped` lists locked pages with no Himi screen, which are never guessed, and `loginWall`
472
+ says `required`, `not_required` or `unknown` with its `basis` (`evidence`, `flag` or `none`); when it is `required` it also
473
+ lists `enforcedOn` (`ios`, `android`) and `notEnforcedOn` (`web`: the web host enforces a wall only for its own account
474
+ mode). `loginWall.kept` is true when the source does not require login but the app already has a wall (for example one chosen with `--login-wall required`): it stays, and only an explicit `--login-wall none` is refused. `homeEntries` lists the locked pages whose entry is the app's home destination: it stays on the bar behind its lock screen and is never hidden. `himi one-app migrate` adds
475
+ the warning `access_policy_unavailable` to the manifest when the source did not report the login setting. Failures print `ok: false` and a top-level `code`
476
+ on stderr.
477
+
478
+ - `invalid_usage`: required options are missing, duplicated or unknown, `--screen` is not `<layoutItemId>=<screenId>`,
479
+ `--login-wall` is not `required` or `none`, or `--dry-run` and `--check` are both given (exit 2).
480
+ - `evidence_invalid`: the evidence manifest or `raw-structure.json` is missing, invalid or fails its recorded hash,
481
+ `access-policy.json` does not match the hash in the manifest, or the coverage ledger cannot be read or has rows whose
482
+ source changed (exit 1).
483
+ - `app_uninspectable`: `config.ts` or `dev/index.ts` cannot be read or parsed, `dev/index.ts` has no literal `SCREENS`,
484
+ or a file cannot be written; in that case every file written so far is put back as it was (exit 1).
485
+ - `access_engine_missing`: the app lacks `tier5-src/_shared/access-gates.ts` or
486
+ `tier5-src/himi-branded-lite-access-nav`, so a table naming gates would lock nothing; re-scaffold from the current
487
+ template (exit 1).
488
+ - `gate_screen_missing`: a `--screen` names a screen `dev/index.ts` does not declare (exit 1).
489
+ - `app_services_unavailable`: page locks read app-level state through app services, which only an app that has never
490
+ shipped an older binary may use, and the app neither declares `app: { newApp: true }` nor was given `--new-app`; nothing
491
+ is written (exit 1). `--new-app` is the author's statement that the app is new.
492
+ - `needs_manual_merge`: a locked page is mapped to another screen than the app carries (`moved` lists `layoutItemId`, `from`, `to`: the old screen is still wrapped in its lock), a screen payload holds more than `id`, `body` and `modifiers` (or is not a literal object), an entry or row already has a
493
+ different `hiddenPath`, `navigation.navLogicBundle` is a worker that does not answer the gates, `config.ts` has no
494
+ literal `auth`, or the app requires login (`requireLogin`) while the source no longer does; nothing is written (exit 1).
495
+ - `gates_removed`: the app carries gates that this run would not carry: the source has none, or fewer `--screen`
496
+ mappings were given than the app already has gates; `dropped` names the gate keys. Taking a lock out is not
497
+ automatic (exit 1).
498
+ - `access_out_of_sync` (`--check`): the app does not carry the source's rules as they are now; `outOfSync` names the
499
+ files, and a locked page with no `--screen` yet counts too, so a script that gates on the exit code never passes while a locked page is open (exit 1).
500
+
467
501
  ## `himi one-app validate-design` codes
468
502
 
469
503
  - `invalid_usage`: required options are missing or incompatible (exit 2).
@@ -388,6 +388,8 @@ Apply these interpretation rules:
388
388
  - Keep navigation visibility, reachability and data access separate. Reevaluate
389
389
  membership/plan/badge gates at runtime; an operator's successful read is not an
390
390
  end-user access policy. Never expose protected content beneath a visual gate.
391
+ Carry a locked page's rule with `himi one-app access` (see "Locked pages" below):
392
+ it is a presentation rule, and the data stays protected by its own Wix API.
391
393
  - Exclude `ntt.*` definitions and placements from coverage. Preserve configured
392
394
  header/top-bar intent; do not add unconfigured drawer or header surfaces.
393
395
  - Before publishing, run the migration-only top-bar coverage check:
@@ -1306,6 +1308,108 @@ then compare those four source journeys in the real host. Keep their missing
1306
1308
  behavior explicit in coverage and the report. A stock template screenshot or a
1307
1309
  passing identity check cannot substitute for the fresh reconstruction/device pass.
1308
1310
 
1311
+ ### Locked pages: members only, a badge, a paid plan
1312
+
1313
+ A One App owner can lock a page (a layout item) for members only, for holders of a badge or for holders of a paid
1314
+ plan, and choose whether a viewer who may not enter sees a lock screen with the owner's message and button, or no
1315
+ tab at all. Those rules are in the AUTHORED structure (`raw-structure.json`, `layoutItems[].permissions`). The
1316
+ structure a Visitor reads is already evaluated for that Visitor: every rule becomes "members only" and the badge and
1317
+ plan ids are gone, so never read the rules from an enriched view. `himi one-app coverage` lists each rule as an
1318
+ `access` row; the rows stay `unresolved` until you carry the rule:
1319
+
1320
+ ```bash
1321
+ himi one-app access --evidence-dir .himi/one-app --content . --new-app \
1322
+ --screen <layoutItemId>=<himiScreenId> --screen <layoutItemId>=<himiScreenId>
1323
+ ```
1324
+
1325
+ Pass every `--screen` of the app each time: a run that names fewer screens than the gates already in the app would
1326
+ drop a lock, and is refused (`gates_removed`, which lists what it would drop).
1327
+
1328
+ The route decision (which Himi screen a locked page became) is yours; no file records it, so pass it with `--screen`
1329
+ (or `--screens-file`). A locked page with no screen is listed under `unmapped`, never guessed. The command:
1330
+
1331
+ - writes `tier5-src/_shared/access-gates-table.ts`, the gate table the nav worker reads;
1332
+ - puts each gated screen behind a lock screen: the screen's `payload` becomes a `FragmentSlot` whose `open` case is
1333
+ the original screen, moved as it was, and whose default case is the lock, so the page body is not mounted until the
1334
+ viewer is shown to be allowed (a cold start, an unresolved value and an unknown value all render the lock);
1335
+ - binds the tab-bar and drawer entries, and the rows that open the screen, of every gate that may hide (hidden mode,
1336
+ or a lock only members see) to the gate's flag in the app-level nav worker: `$service:brandedLiteNav.accessHidden.<key>`
1337
+ on a tab or drawer entry, `$app:brandedLiteNav.accessHidden.<key>` on a row inside a screen. Tab and drawer
1338
+ entries also get `hiddenUntilResolved`, so they stay off the bar until the worker answers;
1339
+ The home destination (the first tab, the first rail item, or the first drawer row of an app with neither) is the one
1340
+ entry that is never hidden: the boot route, deep links and push taps root on it, and the nav check rejects
1341
+ `hiddenUntilResolved` there. A lock on the home page stays on the bar and shows its lock screen instead; the output
1342
+ lists it as `homeEntries`;
1343
+ - reads the gate's answer inside each lock screen from the same worker, through `$app:brandedLiteNav.accessState.<key>`.
1344
+ A screen has its own worker, so a `$service:` binding there would read that worker and never see the answer;
1345
+ `$app:` reads the app-level one. App services are a feature of apps that have never shipped an older binary, so the
1346
+ command needs your word that this app is new: `--new-app` writes `app: { newApp: true }` into `config.ts`. Without it
1347
+ (and without that declaration already in the file) the command stops with `app_services_unavailable` and writes
1348
+ nothing. An app that has already shipped gets page locks only after its native floor supports app services (1.9.0 or later):
1349
+ until then the command refuses it, and that is by design;
1350
+ - points the app-level bundle (`navigation.navLogicBundle`, or `app.logicBundle` when the app already uses that
1351
+ spelling; declaring both is refused) at `himi-branded-lite-access-nav`, the badges worker that also answers the
1352
+ gates. Ids that normalize to one gate key (`page-a`, `page_a`) get a short hash suffix, so no two pages share a decision; a key an earlier run wrote stays with its page, so a later run never renames it. Mapping a locked page to a different screen than before is refused (`needs_manual_merge`, `moved`): the old screen is still wrapped in its lock. An app whose source locks no page keeps the badges-only worker, byte for byte, and pays nothing;
1353
+ - ties each `access` row of the coverage ledger to the screen and gate (`target`), and never overwrites a target you
1354
+ set. The status stays `unresolved`: it moves only on recorded `access-state` evidence from a device.
1355
+
1356
+ It is idempotent. `--dry-run` writes nothing; `--check` fails with `access_out_of_sync` and names the files that no
1357
+ longer carry the source's rules, so run it after any change to the source or the screens. It refuses to edit what it
1358
+ cannot edit safely (`needs_manual_merge`) and removes nothing it wrote earlier (`gates_removed`).
1359
+
1360
+ **What the lock is.** It is PRESENTATION ONLY, as it is in the One App. The data behind a page stays protected by its
1361
+ own Wix API: a Visitor's call still gets a 401, 403 or 428, and a screen shows its sign-in state. The descriptor is
1362
+ served to every device, and the One App itself sends a locked page's structure to the viewer it denies, so static
1363
+ content in a locked screen is not a secret. What the lock keeps is the owner's rule on the tab, for public data too.
1364
+
1365
+ **Who sees what** (decided by the worker in `tier5-src/_shared/access-gates.ts`):
1366
+
1367
+ - No rule: open. Rules by precedence: badges, then paid plans, then members only.
1368
+ - A Visitor is blocked by every rule and always gets the sign-in lock, with the owner's message and button when the
1369
+ owner set them, else the stock copy. When only members may see the lock, the tab is hidden for a Visitor and the
1370
+ stock copy applies.
1371
+ - A member opens a badge gate with one of its badge ids (`POST /badges/v4/assignments/query`, filtered to the member)
1372
+ and a plan gate with an active plan order of one of its plan ids (`@himalaya/checkout` `activePlanIds`). A blocked
1373
+ member sees the lock for the rule's own kind: a badge asks to contact the business, a plan offers the plans, or asks to
1374
+ contact the business when none of its plans is on offer any more.
1375
+ - Hidden mode removes the tab for anyone blocked. There is NO owner or admin bypass: an owner uses the owner app.
1376
+ - Every gate starts locked and opens only on proof. A read that fails leaves the member locked with that rule's button,
1377
+ except that a gate already open stays open through a failed re-read (a blip while offline). Nothing is persisted or
1378
+ restored: a snapshot can never open a tab. A new identity closes every gate before the next answer is read.
1379
+
1380
+ **One cost of locking a list.** A screen whose body is a paged list now has that list inside the lock's `FragmentSlot`.
1381
+ The descriptor check reports it as the warning `paged_list_not_at_scroll_root`: Android recycles rows only for a list
1382
+ that sits directly in the root column, so a long locked list is drawn without recycling. Renderers accept it and the
1383
+ lock works; keep a locked list short, or lock a screen that holds the list in a detail page.
1384
+
1385
+ **Differences from the One App to report.** The plans lock does not name the plans (the One App does); the badge button
1386
+ opens the business chat without the prefilled request message; two stock lines (`plansDescription`, `contact*`) are this
1387
+ repository's own, because the One App's zero-plans strings are not in any source read. Translate the stock copy through
1388
+ the app's catalog like any other string. A gated screen's own worker still loads while locked (the lock is a
1389
+ presentation rule), and an entry that is not a tab, drawer entry or a row that opens the screen directly (a button, a
1390
+ link, a card) is not hidden: it opens the lock. A row bound inside a screen is hidden only once the app worker has answered: a
1391
+ node-level `hiddenPath` has no fail-closed mode (only tab, drawer and rail entries have `hiddenUntilResolved`), so until the worker
1392
+ answers, or for good when it never loads, a Visitor sees that row. Opening it shows the lock, never the page.
1393
+
1394
+ **The app-wide login requirement.** The dashboard's Sign up & login switch decides whether the source app asks for a
1395
+ sign-in before showing anything (`visitorModeEnabled` false) or lets people browse first. `himi one-app migrate` reads it
1396
+ as the site's Visitor (no owner login) and saves it as `access-policy.json`, bound to the manifest hash. It is
1397
+ supporting context: when the source does not report it, the value is `null` and the manifest warns
1398
+ (`access_policy_unavailable`); unknown is never read as either answer. `himi one-app access` then turns the app's own
1399
+ login wall on when the source requires login: `auth` in `config.ts` becomes `requireLogin(...)`, a one-line helper
1400
+ written beside the imports that sets `required: true` on the provider block. With the wall on, the app shows the sign-in
1401
+ (the stock one, or your own gate screen) before any content, and a Visitor session does not pass it. The command never
1402
+ takes a wall out (`needs_manual_merge`): dropping a login requirement is yours to decide. For evidence collected before
1403
+ the setting was recorded, or when the owner tells you, decide it explicitly with `--login-wall required|none`; the
1404
+ explicit choice wins over the evidence. The wall works with or without locked pages.
1405
+ The wall is enforced on iOS and Android. The web host enforces a wall only for its own account mode, so a
1406
+ migrated app opened in the web host still shows its content to a Visitor: the command's output says so
1407
+ (`loginWall.notEnforcedOn`), and a web release must not rely on it. Enforcing the wall on web is a separate follow-up, not part of this command.
1408
+
1409
+ **Check on a device**, as a Visitor, as a signed-in member who has neither the badge nor the plan, and as one who has
1410
+ it, and record the result as the rows' `access-state` evidence. The member probe of the badge read is the one thing no
1411
+ source read can prove: `queryBadgeAssignments` is declared for the app identity, so confirm it answers a member session.
1412
+
1309
1413
  ### Screen-content contract
1310
1414
 
1311
1415
  Use the current [screen design guide](https://apps.wix.com/_api/himi-serve/docs/designing-himi-screens.md) and the app's
@@ -5302,7 +5302,19 @@
5302
5302
  "name": "AlertOptions",
5303
5303
  "kind": "interface",
5304
5304
  "jsdoc": "",
5305
- "decl": "export interface AlertOptions {\n /** Required — the native presenters drop alerts with an empty title. */\n title: string;\n message?: string;\n /** Confirm button label. Default \"Confirm\". */\n confirmLabel?: string;\n /** Cancel button label. OMIT for a single-button alert (no cancel button). */\n cancelLabel?: string;\n /** Style the confirm button with the `danger` token. A destructive confirm is not the\n * affirmative button: its `confirm.actionId` still runs, but without gesture credit. */\n destructive?: boolean;\n /** The affirmative button's ACTION. Pressing it runs `actionId` as a NEW invocation\n * with user-gesture origin (so an app service's `app.<svc>.<action>` may return `_nav` and\n * navigate — the \"Ready — View\" alert). `label` replaces `confirmLabel`. The id is checked when\n * you set it, against this worker: a `capability.<id>.*` needs `<id>` allowed, an `app.*` from a\n * screen worker needs `app_services` and an exported action, a `tier5.*` must be this worker's\n * own; anything else rejects (`action_not_allowed`). Cancel and dismissal run nothing. */\n confirm?: AlertConfirm;\n}"
5305
+ "decl": "export interface AlertOptions {\n /** Required — the native presenters drop alerts with an empty title. */\n title: string;\n message?: string;\n /** Confirm button label. Default \"Confirm\". */\n confirmLabel?: string;\n /** Cancel button label. OMIT for a single-button alert (no cancel button). */\n cancelLabel?: string;\n /** Style the confirm button with the `danger` token. A destructive confirm is not the\n * affirmative button: its `confirm.actionId` still runs, but without gesture credit. */\n destructive?: boolean;\n /** The affirmative button's ACTION. Pressing it runs `actionId` as a NEW invocation\n * with user-gesture origin (so an app service's `app.<svc>.<action>` may return `_nav` and\n * navigate — the \"Ready — View\" alert). `label` replaces `confirmLabel`. The id is checked when\n * you set it, against this worker: a `capability.<id>.*` needs `<id>` allowed, an `app.*` from a\n * screen worker needs `app_services` and an exported action, a `tier5.*` must be this worker's\n * own; anything else rejects (`action_not_allowed`). Cancel and dismissal run nothing. */\n confirm?: AlertConfirm;\n /** Up to three buttons, replacing the four options above; see `AlertButtonOptions`. */\n buttons?: AlertButtonOptions[];\n}"
5306
+ },
5307
+ {
5308
+ "name": "AlertButtonRole",
5309
+ "kind": "type",
5310
+ "jsdoc": "/** #4659 — `\"cancel\"` (at most one) sits in the cancel position and is what dismissal by scrim, back\n * or Esc resolves as; `\"destructive\"` draws with the `danger` token. Default `\"default\"`. */",
5311
+ "decl": "export type AlertButtonRole = \"default\" | \"cancel\" | \"destructive\";"
5312
+ },
5313
+ {
5314
+ "name": "AlertButtonOptions",
5315
+ "kind": "interface",
5316
+ "jsdoc": "/** #4659 — one button of an `alert({ buttons })`. Test id `alert.<id>`; its label is the accessible\n * name. Buttons draw in platform order and the result names the one pressed (`buttonId`). With\n * `buttons`, `confirmLabel` / `cancelLabel` / `destructive` / `confirm` are not sent; `confirm` is\n * shorthand for one `role: \"default\"` button. Each `actionId` is checked when you set it exactly as\n * `confirm.actionId` is (reject, show nothing); from an app service only a `default`-role press\n * carries gesture credit. More than three buttons, more than one `cancel`, or an empty / repeated\n * `id` or empty `label` rejects `invalid_buttons`. */",
5317
+ "decl": "export interface AlertButtonOptions {\n id: string;\n label: string;\n role?: AlertButtonRole;\n /** Run on press, as a new invocation (see `AlertOptions.confirm`). Omit to just await the press. */\n actionId?: string;\n /** Passed to the action (JSON types kept). */\n args?: Record<string, unknown>;\n}"
5306
5318
  },
5307
5319
  {
5308
5320
  "name": "AlertConfirm",
@@ -5314,7 +5326,7 @@
5314
5326
  "name": "AlertResult",
5315
5327
  "kind": "interface",
5316
5328
  "jsdoc": "",
5317
- "decl": "export interface AlertResult {\n /** true ⇒ the user tapped confirm; false ⇒ cancel or the alert was dismissed\n * externally (e.g. a deep-link reset cleared all presented overlays). */\n confirmed: boolean;\n}"
5329
+ "decl": "export interface AlertResult {\n /** true ⇒ the user tapped confirm (with `buttons`: a `default`-role button); false ⇒ cancel,\n * another button, or the alert was dismissed externally (e.g. a deep-link reset cleared all\n * presented overlays). */\n confirmed: boolean;\n /** #4659 — the id of the button pressed: one of `buttons`, or `\"confirm\"` / `\"cancel\"` for the\n * legacy options. Dismissal by scrim/back/Esc resolves as the `cancel` button; with none, or when\n * the host clears the alert, it is `null`. */\n buttonId: string | null;\n}"
5318
5330
  },
5319
5331
  {
5320
5332
  "name": "alert",
@@ -8722,6 +8734,44 @@
8722
8734
  "jsdoc": "",
8723
8735
  "decl": "export function updateBadgesOrder(\n req: WixUpdateBadgesOrderRequest = {} as WixUpdateBadgesOrderRequest,\n opts?: WixCallOptions,\n): Promise<WixUpdateBadgesOrderResponse>;",
8724
8736
  "http": "PATCH /badges/v4/badges/order"
8737
+ },
8738
+ {
8739
+ "name": "WixBadgeAssignment",
8740
+ "kind": "interface",
8741
+ "jsdoc": "/** One badge given to one member. */",
8742
+ "decl": "export interface WixBadgeAssignment {\n id?: string;\n badgeId?: string;\n memberId?: string;\n createdDate?: string;\n updatedDate?: string;\n}"
8743
+ },
8744
+ {
8745
+ "name": "WixQueryBadgeAssignmentsRequest",
8746
+ "kind": "interface",
8747
+ "jsdoc": "",
8748
+ "decl": "export interface WixQueryBadgeAssignmentsRequest {\n query?: { filter?: Record<string, unknown>; cursorPaging?: WixCursorPaging };\n}"
8749
+ },
8750
+ {
8751
+ "name": "WixQueryBadgeAssignmentsResponse",
8752
+ "kind": "interface",
8753
+ "jsdoc": "",
8754
+ "decl": "export interface WixQueryBadgeAssignmentsResponse {\n badgeAssignments?: WixBadgeAssignment[];\n pagingMetadata?: WixCursorPagingMetadata;\n}"
8755
+ },
8756
+ {
8757
+ "name": "WixBadgeIcon",
8758
+ "kind": "interface",
8759
+ "jsdoc": "/** The badge icon exactly as the live API sends it. The generated `WixBadge.icon` is typed `string`\n * from the upstream package, but the service returns this image object. */",
8760
+ "decl": "export interface WixBadgeIcon {\n id?: string;\n url?: string;\n height?: number;\n width?: number;\n}"
8761
+ },
8762
+ {
8763
+ "name": "queryBadgeAssignments",
8764
+ "kind": "function",
8765
+ "jsdoc": "/** Which badges members hold — POST /badges/v4/assignments/query. A Visitor can read it\n * (`BADGES.BADGE_READ_MEMBERS`), so a members list can show badges without a sign-in.\n * Filter by `memberId: { $in: [...] }` and page with `cursorPaging`: a member can hold dozens of\n * badges, so one page of many members can need several calls.\n *\n * Prefer this over the generated `listMembersBadgeIds`, whose route\n * (`POST /badges/v4/badges/members`) answers 404 on the live service.\n *\n * @scope visitor — an anonymous Visitor reads it (200, observed live). The generated spec declares the app\n * identity only, so a signed-in member's read is not yet observed: an empty or refused answer means \"no badge\n * known\", never \"no badge held\". */",
8766
+ "decl": "export function queryBadgeAssignments(\n req: WixQueryBadgeAssignmentsRequest = {},\n opts?: WixCallOptions,\n): Promise<WixQueryBadgeAssignmentsResponse>;",
8767
+ "http": "POST /badges/v4/assignments/query",
8768
+ "scope": "visitor"
8769
+ },
8770
+ {
8771
+ "name": "badgeIconUrl",
8772
+ "kind": "function",
8773
+ "jsdoc": "/** The icon image URL of a badge, or \"\" when it has none. Reads the live `{ url }` object and also the\n * plain string the generated type promises, so a caller needs no cast. */",
8774
+ "decl": "export function badgeIconUrl(badge: Pick<WixBadge, \"icon\">): string;"
8725
8775
  }
8726
8776
  ]
8727
8777
  },
@@ -18893,13 +18943,13 @@
18893
18943
  "name": "WixEventLocation",
18894
18944
  "kind": "interface",
18895
18945
  "jsdoc": "",
18896
- "decl": "export interface WixEventLocation {\n /** VENUE | ONLINE | TBD */\n type?: string;\n name?: string;\n address?: string;\n}"
18946
+ "decl": "export interface WixEventLocation {\n /** VENUE | ONLINE (Events v3 `Location.LocationType`; `TBD` is not a type). */\n type?: string;\n name?: string;\n address?: string;\n}"
18897
18947
  },
18898
18948
  {
18899
18949
  "name": "WixEvent",
18900
18950
  "kind": "interface",
18901
18951
  "jsdoc": "",
18902
- "decl": "export interface WixEvent {\n id: string;\n title?: string;\n /** Normally one of `WixEventStatus` — `UPCOMING` (published and scheduled to start),\n * `STARTED`, `ENDED`, `CANCELED`, `DRAFT`. Events v1 called the first of those `SCHEDULED`,\n * and this SDK reads v3, so a row here never carries `SCHEDULED`.\n *\n * Deliberately NOT narrowed to that union: `decodeEvent` fills this from the server's\n * `status` and passes a value it does not recognise straight through, because dropping or\n * rewriting one would lose a real event. A union here would be a claim this SDK cannot\n * enforce. Compare against `WixEventStatus` when you need the set it knows. */\n eventStatus?: string;\n /** EventType: RSVP | TICKETS | EXTERNAL | NO_REGISTRATION */\n eventType?: string;\n scheduling?: WixEventScheduling;\n location?: WixEventLocation;\n mainImage?: WixEventImage;\n slug?: string;\n about?: string;\n /** Events v3: a Ricos document ({@link WixEventRichContent}), returned only when the `TEXTS`\n * fieldset is requested (`getEvent(id, { fields: [\"TEXTS\"] })`). Older payloads sent a string. */\n description?: string | WixEventRichContent;\n}"
18952
+ "decl": "export interface WixEvent {\n id: string;\n title?: string;\n /** Normally one of `WixEventStatus` — `UPCOMING` (published and scheduled to start),\n * `STARTED`, `ENDED`, `CANCELED`, `DRAFT`. Events v1 called the first of those `SCHEDULED`,\n * and this SDK reads v3, so a row here never carries `SCHEDULED`.\n *\n * Deliberately NOT narrowed to that union: `decodeEvent` fills this from the server's\n * `status` and passes a value it does not recognise straight through, because dropping or\n * rewriting one would lose a real event. A union here would be a claim this SDK cannot\n * enforce. Compare against `WixEventStatus` when you need the set it knows. */\n eventStatus?: string;\n /** EventType: RSVP | TICKETING | EXTERNAL | NONE — the GA values of the v3\n * `RegistrationType.Type` enum that `decodeEvent` reads from `registration.type`.\n * (v1 spelled `TICKETING` / `NONE` as `TICKETS` / `NO_REGISTRATION`; v3 does not.) Not narrowed\n * to a union for the same reason as `eventStatus`: `decodeEvent` passes an unrecognised\n * value straight through rather than drop it. */\n eventType?: string;\n scheduling?: WixEventScheduling;\n location?: WixEventLocation;\n mainImage?: WixEventImage;\n slug?: string;\n about?: string;\n /** Events v3: a Ricos document ({@link WixEventRichContent}), returned only when the `TEXTS`\n * fieldset is requested (`getEvent(id, { fields: [\"TEXTS\"] })`). Older payloads sent a string. */\n description?: string | WixEventRichContent;\n}"
18903
18953
  },
18904
18954
  {
18905
18955
  "name": "WixGetEventListResponse",
@@ -18979,7 +19029,7 @@
18979
19029
  {
18980
19030
  "name": "WixEventWrite",
18981
19031
  "kind": "interface",
18982
- "jsdoc": "/** Write shape for create/update (Events v3). Verified-minimal: a create needs\n * BOTH `name` and `title`, a `dateAndTimeSettings` window, a `location`, and a\n * `registration.initialType` (RSVP | TICKETS | RSVP_AND_TICKETS). */",
19032
+ "jsdoc": "/** Write shape for create/update (Events v3). Verified-minimal: a create needs\n * BOTH `name` and `title`, a `dateAndTimeSettings` window, a `location`, and a\n * `registration.initialType` (RSVP | TICKETING in Events v3\n * `InitialRegistrationType.Type`). */",
18983
19033
  "decl": "export interface WixEventWrite {\n name?: string;\n title?: string;\n dateAndTimeSettings?: { startDate?: string; endDate?: string; timeZoneId?: string };\n location?: { type?: string; name?: string };\n registration?: { initialType?: string };\n mainImage?: WixEventImage;\n about?: string;\n /** Ricos document; replaces the whole description. */\n description?: WixEventRichContent;\n}"
18984
19034
  },
18985
19035
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1622.0",
3
+ "version": "0.1624.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": [
@@ -72,5 +72,5 @@
72
72
  "artifactId": "himalaya-cli"
73
73
  }
74
74
  },
75
- "falconPackageHash": "8493c132a80fa7832da317fe9ee68a3a247dd79165b74cbcc352855c"
75
+ "falconPackageHash": "8b49e7e93dbedda48e52f25013bfc1733182135023026eb82f93a5be"
76
76
  }
@@ -0,0 +1,8 @@
1
+ // This app's access gates: the One App page rules (members only, badge, paid plan) the app keeps.
2
+ //
3
+ // EMPTY in a scaffold, and then nothing in `access-gates.ts` reads or publishes anything. `himi one-app access`
4
+ // replaces this file for a migrated One App whose source locks a page; do not edit it by hand, re-run the command
5
+ // (it is idempotent).
6
+ import type { AccessGate } from "./access-gates.js";
7
+
8
+ export const ACCESS_GATES: readonly AccessGate[] = [];