@wix/himalaya-cli 0.1130.0 → 0.1131.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 +38 -3
- package/guides/counter.service.ts +1 -1
- package/guides/designing-himi-screens.md +5 -3
- package/guides/dynamic-list.service.ts +2 -2
- package/guides/form-submit.service.ts +2 -2
- package/guides/himi-test.md +8 -0
- package/guides/onboarding.service.ts +1 -1
- package/guides/search-list.service.ts +2 -2
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -24749,6 +24749,7 @@ function shouldRevealError(args) {
|
|
|
24749
24749
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
24750
24750
|
var init_validation = __esm({
|
|
24751
24751
|
"../../core/ts/src/validation.ts"() {
|
|
24752
|
+
"use strict";
|
|
24752
24753
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
24753
24754
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
24754
24755
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -29149,6 +29150,7 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
29149
29150
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
29150
29151
|
var init_worker_subtree = __esm({
|
|
29151
29152
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
29153
|
+
"use strict";
|
|
29152
29154
|
init_worker_subtree_safe_types_generated();
|
|
29153
29155
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
29154
29156
|
maxEncodedBytes: 65536,
|
|
@@ -43143,7 +43145,7 @@ async function crawlScreenInner(opts) {
|
|
|
43143
43145
|
severity: "error",
|
|
43144
43146
|
...source ? { source } : {},
|
|
43145
43147
|
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`
|
|
43148
|
+
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
43149
|
});
|
|
43148
43150
|
}
|
|
43149
43151
|
for (const [svc, s] of Object.entries(state)) {
|
|
@@ -43357,7 +43359,7 @@ async function crawlScreenInner(opts) {
|
|
|
43357
43359
|
try {
|
|
43358
43360
|
await handle.dispatch(parsed.action, ...workerArgs(dispatched));
|
|
43359
43361
|
} catch (e) {
|
|
43360
|
-
errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e)}`, ...e.stack ? { stack: e.stack } : {} });
|
|
43362
|
+
errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e)}`, ...e.stack ? { stack: e.stack } : {}, argless: workerArgs(dispatched).length === 0 });
|
|
43361
43363
|
}
|
|
43362
43364
|
exercised += 1;
|
|
43363
43365
|
const { state, defects } = snapshot(w);
|
|
@@ -73095,6 +73097,35 @@ Transport: same targets/tokens as himi-serve \u2014 --target <local|prod|bo>, --
|
|
|
73095
73097
|
--telemetry-url, --control-token/--telemetry-token, or HIMI_* env.
|
|
73096
73098
|
Guides: ${DEVELOPER_PORTAL_URL}`;
|
|
73097
73099
|
var ONLY_USAGE = "himi push --only <selector>[,<selector>\u2026] (--draft|--live) [--from-release <id>] [--accept-regressions] [--accept-partial]";
|
|
73100
|
+
var LOGIN_HELP = `himi login \u2014 get a scoped serve-control token and store it in
|
|
73101
|
+
~/.himalaya/serve-targets.json, so push / promote / preview need no pasted token.
|
|
73102
|
+
|
|
73103
|
+
himi login [--browser | --wix | --dpx] [--target <t>] [--no-open]
|
|
73104
|
+
|
|
73105
|
+
MODES \u2014 pick by who is at the keyboard
|
|
73106
|
+
--browser YOUR OWN Wix account, in a browser. No VPN, no BO. The DEFAULT when the target
|
|
73107
|
+
has no BO issuer, which is the \`wix\` target \u2014 and \`wix\` is the default target
|
|
73108
|
+
off-repo, so a bare \`himi login\` there is this mode. --no-open prints the URL
|
|
73109
|
+
instead of opening it (a headless shell).
|
|
73110
|
+
--wix HEADLESS. Uses the machine's EXISTING Wix CLI credential (\`wix login\`, or
|
|
73111
|
+
\`wix login --api-key\` in a pod) \u2014 the mode a CI job or an agent container can
|
|
73112
|
+
satisfy. It does not create a credential; log the Wix CLI in first.
|
|
73113
|
+
--dpx Wix EMPLOYEE. Reads the BO session at ~/.dpx/session/token (dpx 2.x:
|
|
73114
|
+
\`dpx auth login\` then \`dpx auth token > ~/.dpx/session/token\`). Internal
|
|
73115
|
+
targets only (--target bo); VPN-gated.
|
|
73116
|
+
|
|
73117
|
+
TARGET
|
|
73118
|
+
--target <t> which serve plane the token is for. Resolved like every other command:
|
|
73119
|
+
--target, then HIMI_SERVE_TARGET, then serve-targets.json \`default\`, then
|
|
73120
|
+
\`wix\` off-repo. Log in to the SAME target you push to \u2014 a token is stored
|
|
73121
|
+
per target, and a push to another one will not find it.
|
|
73122
|
+
|
|
73123
|
+
CHECK IT
|
|
73124
|
+
himi doctor which login modes would work on this machine, before you try one
|
|
73125
|
+
himi whoami what the stored token is scoped to
|
|
73126
|
+
|
|
73127
|
+
OTHER
|
|
73128
|
+
--issue-url <url>, --owner-issue-url <url> override the issuer (advanced / tests)`;
|
|
73098
73129
|
var PATCH_HELP = `himi patch \u2014 change ONE item of a published app, from a raw file, on a machine
|
|
73099
73130
|
that does not have the content package.
|
|
73100
73131
|
|
|
@@ -74985,7 +75016,7 @@ async function runCommand(argv, io, deps) {
|
|
|
74985
75016
|
io.log(flags.json ? JSON.stringify({ himi: v }, null, 2) : `himi v${v}`);
|
|
74986
75017
|
return 0;
|
|
74987
75018
|
}
|
|
74988
|
-
const VERB_HELP = /* @__PURE__ */ new Set(["patch"]);
|
|
75019
|
+
const VERB_HELP = /* @__PURE__ */ new Set(["patch", "login"]);
|
|
74989
75020
|
if (!command || command === "help" || flags.help === true && !VERB_HELP.has(command)) {
|
|
74990
75021
|
const footer = `
|
|
74991
75022
|
|
|
@@ -79681,6 +79712,10 @@ ${label2}`);
|
|
|
79681
79712
|
return allOk ? 0 : 1;
|
|
79682
79713
|
}
|
|
79683
79714
|
case "login": {
|
|
79715
|
+
if (flags.help === true) {
|
|
79716
|
+
io.log(LOGIN_HELP);
|
|
79717
|
+
return 0;
|
|
79718
|
+
}
|
|
79684
79719
|
const target = targetName();
|
|
79685
79720
|
const prevControlToken = loadTargetsFile().targets?.[target]?.controlToken;
|
|
79686
79721
|
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); `
|
|
187
|
-
|
|
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
|
|
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
|
package/guides/himi-test.md
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.1131.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": "
|
|
70
|
+
"falconPackageHash": "4920f7f92ed5d3cccc334bbc8ff870b7299ebb01377a75b9829788cd"
|
|
71
71
|
}
|