@wix/himalaya-cli 0.1130.0 → 0.1132.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/cli.mjs CHANGED
@@ -43143,7 +43143,7 @@ async function crawlScreenInner(opts) {
43143
43143
  severity: "error",
43144
43144
  ...source ? { source } : {},
43145
43145
  message: `${e.service}: ${e.message}`,
43146
- hint: isTransportReject(e.message) ? `the worker let the transport rejection escape instead of handling it \u2014 catch it and set an error state, or crawl with a net fixture (--net)` : /Cannot read properties of|is not a function|undefined is not/.test(e.message) ? `a TypeError on a property read is usually a WRONG REFERENCE, not a failed fetch \u2014 check the receiver first (classic: \`svc.actions.<x>(\u2026)\` \u2014 actions are DIRECT methods on the handle, \`.actions\` is undefined on device; or indexing into a possibly-empty list). Wrapping a wrong reference in try/catch silences the crash but leaves the control dead.` : `an uncaught throw here leaves the screen on whatever state it had \u2014 wrap the failing call and set an error state`
43146
+ hint: isTransportReject(e.message) ? `the worker let the transport rejection escape instead of handling it \u2014 catch it and set an error state, or crawl with a net fixture (--net)` : e.argless && /Cannot destructure/.test(e.message) ? `the crawl dispatched this action with NO payload \u2014 it only types a value it can read off the app (docs/himi-test.md \u2192 Typed form journeys), so a field hook it cannot aim arrives with no argument. A device always sends the control's payload key, but a reducer should still tolerate a bare call: default the payload parameter (\`(s, { value } = {}) => \u2026\`), or add a himi-test.json journey that types a real value.` : /Cannot read properties of|is not a function|undefined is not/.test(e.message) ? `a TypeError on a property read is usually a WRONG REFERENCE, not a failed fetch \u2014 check the receiver first (classic: \`svc.actions.<x>(\u2026)\` \u2014 actions are DIRECT methods on the handle, \`.actions\` is undefined on device; or indexing into a possibly-empty list). Wrapping a wrong reference in try/catch silences the crash but leaves the control dead.` : `an uncaught throw here leaves the screen on whatever state it had \u2014 wrap the failing call and set an error state`
43147
43147
  });
43148
43148
  }
43149
43149
  for (const [svc, s] of Object.entries(state)) {
@@ -43357,7 +43357,7 @@ async function crawlScreenInner(opts) {
43357
43357
  try {
43358
43358
  await handle.dispatch(parsed.action, ...workerArgs(dispatched));
43359
43359
  } catch (e) {
43360
- errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e)}`, ...e.stack ? { stack: e.stack } : {} });
43360
+ errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e)}`, ...e.stack ? { stack: e.stack } : {}, argless: workerArgs(dispatched).length === 0 });
43361
43361
  }
43362
43362
  exercised += 1;
43363
43363
  const { state, defects } = snapshot(w);
@@ -73095,6 +73095,35 @@ Transport: same targets/tokens as himi-serve \u2014 --target <local|prod|bo>, --
73095
73095
  --telemetry-url, --control-token/--telemetry-token, or HIMI_* env.
73096
73096
  Guides: ${DEVELOPER_PORTAL_URL}`;
73097
73097
  var ONLY_USAGE = "himi push --only <selector>[,<selector>\u2026] (--draft|--live) [--from-release <id>] [--accept-regressions] [--accept-partial]";
73098
+ var LOGIN_HELP = `himi login \u2014 get a scoped serve-control token and store it in
73099
+ ~/.himalaya/serve-targets.json, so push / promote / preview need no pasted token.
73100
+
73101
+ himi login [--browser | --wix | --dpx] [--target <t>] [--no-open]
73102
+
73103
+ MODES \u2014 pick by who is at the keyboard
73104
+ --browser YOUR OWN Wix account, in a browser. No VPN, no BO. The DEFAULT when the target
73105
+ has no BO issuer, which is the \`wix\` target \u2014 and \`wix\` is the default target
73106
+ off-repo, so a bare \`himi login\` there is this mode. --no-open prints the URL
73107
+ instead of opening it (a headless shell).
73108
+ --wix HEADLESS. Uses the machine's EXISTING Wix CLI credential (\`wix login\`, or
73109
+ \`wix login --api-key\` in a pod) \u2014 the mode a CI job or an agent container can
73110
+ satisfy. It does not create a credential; log the Wix CLI in first.
73111
+ --dpx Wix EMPLOYEE. Reads the BO session at ~/.dpx/session/token (dpx 2.x:
73112
+ \`dpx auth login\` then \`dpx auth token > ~/.dpx/session/token\`). Internal
73113
+ targets only (--target bo); VPN-gated.
73114
+
73115
+ TARGET
73116
+ --target <t> which serve plane the token is for. Resolved like every other command:
73117
+ --target, then HIMI_SERVE_TARGET, then serve-targets.json \`default\`, then
73118
+ \`wix\` off-repo. Log in to the SAME target you push to \u2014 a token is stored
73119
+ per target, and a push to another one will not find it.
73120
+
73121
+ CHECK IT
73122
+ himi doctor which login modes would work on this machine, before you try one
73123
+ himi whoami what the stored token is scoped to
73124
+
73125
+ OTHER
73126
+ --issue-url <url>, --owner-issue-url <url> override the issuer (advanced / tests)`;
73098
73127
  var PATCH_HELP = `himi patch \u2014 change ONE item of a published app, from a raw file, on a machine
73099
73128
  that does not have the content package.
73100
73129
 
@@ -74985,7 +75014,7 @@ async function runCommand(argv, io, deps) {
74985
75014
  io.log(flags.json ? JSON.stringify({ himi: v }, null, 2) : `himi v${v}`);
74986
75015
  return 0;
74987
75016
  }
74988
- const VERB_HELP = /* @__PURE__ */ new Set(["patch"]);
75017
+ const VERB_HELP = /* @__PURE__ */ new Set(["patch", "login"]);
74989
75018
  if (!command || command === "help" || flags.help === true && !VERB_HELP.has(command)) {
74990
75019
  const footer = `
74991
75020
 
@@ -79681,6 +79710,10 @@ ${label2}`);
79681
79710
  return allOk ? 0 : 1;
79682
79711
  }
79683
79712
  case "login": {
79713
+ if (flags.help === true) {
79714
+ io.log(LOGIN_HELP);
79715
+ return 0;
79716
+ }
79684
79717
  const target = targetName();
79685
79718
  const prevControlToken = loadTargetsFile().targets?.[target]?.controlToken;
79686
79719
  let issue2;
@@ -10,7 +10,7 @@
10
10
  // examples/counter-t5.descriptor.json (its logicBundle.integrity is the SRI of the
11
11
  // built bundle). Authoritative bundle-authoring doc: docs/tier-5-add-a-screen.md.
12
12
 
13
- import { defineService } from "@himalaya/state";
13
+ import { defineService } from "@wix/himalaya/state";
14
14
 
15
15
  interface CounterState {
16
16
  value: number;
@@ -183,8 +183,10 @@ cells inside a `Card([VStack(spacing: 0)])`.
183
183
  > horizontal rail) where its own virtualized scroll is what you want.
184
184
 
185
185
  **Text** — `Text` for a single styled string (`maxLines` to truncate); `RichText` for inline mixed
186
- marks (bold/italic/link within one paragraph); `Label` for an icon+text pair; `Marquee` only for
187
- genuinely scrolling text. *Reach for `RichText`, not concatenated `Text`, when marks vary mid-line.*
186
+ marks (bold/italic/link within one paragraph); `RichContent` for a Wix Ricos document with blocks,
187
+ media, lists, or tables; `Label` for an icon+text pair; `Marquee` only for genuinely scrolling text.
188
+ *Reach for `RichText`, not concatenated `Text`, when marks vary mid-line; use `RichContent` for
189
+ long-form Ricos content rather than flattening it into text rows.*
188
190
 
189
191
  **Inputs & forms** — field controls: `TextField` (with `keyboard`/`autoCapitalization`/`secure`),
190
192
  `SearchField`, `Toggle`, `Stepper`, `Slider`, `SelectionControl` (checkbox/radio),
@@ -279,7 +281,7 @@ Concrete patterns lifted from real usage:
279
281
  - **Cell list** — `card([ vstack({ spacing: 0, alignment: "leading", children: [ …ListItem cells… ] }) ])`. `spacing: 0` because the cells own their own dividers/padding.
280
282
  - **Overlay** — `zstack({ alignment: "center", children: [ backdropImage(cornerRadius 12), withModifiers(label, { padding, background: { token: "accentPrimary" }, cornerRadius: 10 }) ] })`.
281
283
  - **Responsive** — `grid({ columns: 1, columnsMedium: 2, spacing: 12 })` for 1-up on phone / 2-up on tablet; `splitView({ primary, detail, primaryMaxWidth: 280 })` for master/detail that stacks on a phone; set `contentMaxWidth` in tokens so wide surfaces keep a readable column instead of running edge-to-edge.
282
- - **Centered separator, not a flanked divider** — the classic "—— or ——" needs each `divider()` to take equal remaining width, and the HStack row-share only kicks in for controls with an intrinsic fill (a bare `divider()` inside an HStack collapses to a tick). Use a **centered caption** instead: `hstack({ children: [spacer(), text("or continue with", "caption", { color: "textSecondary" }), spacer()] })`, optionally over a single full-width `divider()`.
284
+ - **Centered separator, not a flanked divider** — the classic "—— or ——" needs each `divider()` to take equal remaining width, and the HStack row-share only kicks in for controls with an intrinsic fill. **Never put a bare `divider()` inside an HStack**: it is a horizontal rule on every surface, and on web and Android it claims the row's full width and squeezes its siblings (a stat row's `12` wraps to `1`/`2`); only iOS draws a thin vertical line. For a stats row, separate the columns with `spacer()`s or spacing instead. Use a **centered caption** instead: `hstack({ children: [spacer(), text("or continue with", "caption", { color: "textSecondary" }), spacer()] })`, optionally over a single full-width `divider()`.
283
285
 
284
286
  > **Intrinsic-fill controls grab the row.** `Button` and `TextField` have an intrinsic FILL, so the next four idioms are about NOT letting that surprise you (they were the papercuts every off-repo app hit):
285
287
 
@@ -10,8 +10,8 @@
10
10
  // Because this worker rides the Wix transport (globalThis.himalaya.wixApi), the
11
11
  // descriptor's logicBundle.declaredCapabilities MUST include "wix_api" (RFC 0043 D4).
12
12
 
13
- import { defineService } from "@himalaya/state";
14
- import { productPrice, queryStoreProducts, type StoreProduct } from "@himalaya/wix-stores";
13
+ import { defineService } from "@wix/himalaya/state";
14
+ import { productPrice, queryStoreProducts, type StoreProduct } from "@wix/himalaya/wix-stores";
15
15
 
16
16
  // FLAT strings only — the row template binds `$item.name`, never `$item.priceData.…`.
17
17
  // All shaping happens here in normalize(), not at the binding site.
@@ -11,8 +11,8 @@
11
11
  // The write rides the Wix transport → the descriptor's logicBundle MUST declare
12
12
  // "wix_api" (RFC 0043 D4).
13
13
 
14
- import { defineService } from "@himalaya/state";
15
- import { createDraftPost, type WixDraftPostWrite, type WixRichContent } from "@himalaya/wix-blog";
14
+ import { defineService } from "@wix/himalaya/state";
15
+ import { createDraftPost, type WixDraftPostWrite, type WixRichContent } from "@wix/himalaya/wix-blog";
16
16
 
17
17
  interface PostFormState {
18
18
  // Prefill values — what the fields SHOW (edit mode / echo after save). The
@@ -73,6 +73,14 @@ the payload contract names. A `Slider`, `Stepper`, `Toggle` or `DatePicker` has
73
73
  those still dispatch with the descriptor's default (often empty) value, and the gap ledger says so
74
74
  per screen.
75
75
 
76
+ **An argless dispatch carries no payload at all.** When the descriptor's own `params`/`args` are
77
+ empty and the crawl has nothing to type, it calls the reducer with **no argument** — the same
78
+ calling convention the host uses for an empty payload. A device always sends the control's payload
79
+ key (`value` for a field's `onChange`), but a reducer written `(s, { value }) => …` throws
80
+ `Cannot destructure property 'value' of 'undefined'` under the crawl. That `worker-threw` is a real
81
+ catch, not a crawl bug, and its hint says so: default the parameter (`(s, { value } = {}) => …`,
82
+ or read `p?.value`), or add a journey below that types a real value.
83
+
76
84
  For a flow where the real proof is **typed value → submit → visible completion** — several fields,
77
85
  in order, ending in a rendered result — add a short screen-local journey to `himi-test.json`:
78
86
 
@@ -9,7 +9,7 @@
9
9
  // hosts expose globalThis.himalaya.storage, web falls back to localStorage,
10
10
  // and a missing/failing store just means the card shows again next launch.
11
11
 
12
- import { defineService } from "@himalaya/state";
12
+ import { defineService } from "@wix/himalaya/state";
13
13
 
14
14
  const ONBOARDING_KEY = "myapp.onboarded";
15
15
 
@@ -9,8 +9,8 @@
9
9
  // Builds on the dynamic-list recipe (worker owns the array, four-state display
10
10
  // strings) — see examples/dynamic-list.* for that base. Declares "wix_api".
11
11
 
12
- import { defineService } from "@himalaya/state";
13
- import { queryPosts, type WixPost } from "@himalaya/wix-blog";
12
+ import { defineService } from "@wix/himalaya/state";
13
+ import { queryPosts, type WixPost } from "@wix/himalaya/wix-blog";
14
14
 
15
15
  interface PostRow {
16
16
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1130.0",
3
+ "version": "0.1132.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": [
@@ -67,5 +67,5 @@
67
67
  "artifactId": "himalaya-cli"
68
68
  }
69
69
  },
70
- "falconPackageHash": "8340fceb4deeef12cc58c6969904b2b33ae4c90a5923c20cef72d267"
70
+ "falconPackageHash": "a856f2af4efab6699ad258e66da48dd5fb9d589f371ed97cc6bed181"
71
71
  }