@wix/himalaya-cli 0.891.0 → 0.893.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 +110 -18
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -5241,7 +5241,6 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
5241
5241
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
5242
5242
|
var init_bindings = __esm({
|
|
5243
5243
|
"../../core/ts/src/bindings.ts"() {
|
|
5244
|
-
"use strict";
|
|
5245
5244
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
5246
5245
|
BINDING_SIGIL_RE = new RegExp(
|
|
5247
5246
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -28784,6 +28783,7 @@ __export(widgets_exports, {
|
|
|
28784
28783
|
MAX_PRODUCE_CACHE_ENTRIES: () => MAX_PRODUCE_CACHE_ENTRIES,
|
|
28785
28784
|
PRODUCE_CACHE_TTL_MS: () => PRODUCE_CACHE_TTL_MS,
|
|
28786
28785
|
WIDGET_BUDGET_MS: () => WIDGET_BUDGET_MS,
|
|
28786
|
+
WidgetRealmUnavailableError: () => WidgetRealmUnavailableError,
|
|
28787
28787
|
buildViewSnapshot: () => buildViewSnapshot,
|
|
28788
28788
|
buildWidgetSnapshot: () => buildWidgetSnapshot,
|
|
28789
28789
|
describeThrown: () => describeThrown,
|
|
@@ -28811,9 +28811,7 @@ async function widgetRealm() {
|
|
|
28811
28811
|
try {
|
|
28812
28812
|
return await realmPromise;
|
|
28813
28813
|
} catch (err) {
|
|
28814
|
-
throw new
|
|
28815
|
-
"the widget producer's isolated realm (QuickJS-in-WASM) could not be loaded, so widget bundles would have been evaluated in node:vm (which is not a security boundary): " + (err instanceof Error ? err.message : String(err))
|
|
28816
|
-
);
|
|
28814
|
+
throw new WidgetRealmUnavailableError(err);
|
|
28817
28815
|
}
|
|
28818
28816
|
}
|
|
28819
28817
|
function resetWidgetRealm() {
|
|
@@ -29433,7 +29431,7 @@ function freezeOverrideSnapshot(input, opts = {}) {
|
|
|
29433
29431
|
}
|
|
29434
29432
|
return snapshot2;
|
|
29435
29433
|
}
|
|
29436
|
-
var MAX_TIMELINE_FRAMES, WIDGET_BUDGET_MS, realmPromise, PRODUCE_CACHE_TTL_MS, MAX_PRODUCE_CACHE_ENTRIES, MAX_PRODUCE_ENTRY_BYTES, MAX_PRODUCE_CACHE_BYTES, produceCache, produceCacheGeneration, CAPTURE_SLOT, READBACK_SERVICE;
|
|
29434
|
+
var MAX_TIMELINE_FRAMES, WIDGET_BUDGET_MS, realmPromise, WidgetRealmUnavailableError, PRODUCE_CACHE_TTL_MS, MAX_PRODUCE_CACHE_ENTRIES, MAX_PRODUCE_ENTRY_BYTES, MAX_PRODUCE_CACHE_BYTES, produceCache, produceCacheGeneration, CAPTURE_SLOT, READBACK_SERVICE;
|
|
29437
29435
|
var init_widgets = __esm({
|
|
29438
29436
|
"../../core/dev-server/src/widgets.ts"() {
|
|
29439
29437
|
init_validator();
|
|
@@ -29441,6 +29439,15 @@ var init_widgets = __esm({
|
|
|
29441
29439
|
MAX_TIMELINE_FRAMES = 48;
|
|
29442
29440
|
WIDGET_BUDGET_MS = 5e3;
|
|
29443
29441
|
realmPromise = null;
|
|
29442
|
+
WidgetRealmUnavailableError = class extends Error {
|
|
29443
|
+
constructor(cause) {
|
|
29444
|
+
super(
|
|
29445
|
+
"the widget producer's isolated realm (QuickJS-in-WASM) could not be loaded, so widget bundles would have been evaluated in node:vm (which is not a security boundary): " + describeThrown(cause)
|
|
29446
|
+
);
|
|
29447
|
+
this.cause = cause;
|
|
29448
|
+
this.name = "WidgetRealmUnavailableError";
|
|
29449
|
+
}
|
|
29450
|
+
};
|
|
29444
29451
|
PRODUCE_CACHE_TTL_MS = 6e4;
|
|
29445
29452
|
MAX_PRODUCE_CACHE_ENTRIES = 2048;
|
|
29446
29453
|
MAX_PRODUCE_ENTRY_BYTES = 4 * 1024 * 1024;
|
|
@@ -31871,18 +31878,32 @@ async function scanWidgets(dir) {
|
|
|
31871
31878
|
out.push({ ...e, bundle: name });
|
|
31872
31879
|
}
|
|
31873
31880
|
} catch (err) {
|
|
31881
|
+
if (err instanceof WidgetRealmUnavailableError) throw err;
|
|
31874
31882
|
console.warn(`[widgets] skipped bundle "${name}": ${describeThrown(err)}`);
|
|
31875
31883
|
}
|
|
31876
31884
|
}
|
|
31877
31885
|
return out;
|
|
31878
31886
|
}
|
|
31879
31887
|
async function handleWidgetList(res, dir) {
|
|
31880
|
-
|
|
31888
|
+
try {
|
|
31889
|
+
sendJson(res, 200, { widgets: await scanWidgets(dir) });
|
|
31890
|
+
} catch (err) {
|
|
31891
|
+
if (!(err instanceof WidgetRealmUnavailableError)) throw err;
|
|
31892
|
+
console.error(`[widgets] ${err.message}`);
|
|
31893
|
+
sendJson(res, 503, { error: "widget_realm_unavailable", message: err.message });
|
|
31894
|
+
}
|
|
31881
31895
|
}
|
|
31882
31896
|
async function buildSnapshotForId(widgetId, dir) {
|
|
31883
31897
|
const override = widgetOverrides.get(widgetId);
|
|
31884
31898
|
if (override) return { ok: true, snapshot: override };
|
|
31885
|
-
|
|
31899
|
+
let entry;
|
|
31900
|
+
try {
|
|
31901
|
+
entry = (await scanWidgets(dir)).find((w) => w.widgetId === widgetId);
|
|
31902
|
+
} catch (err) {
|
|
31903
|
+
if (!(err instanceof WidgetRealmUnavailableError)) throw err;
|
|
31904
|
+
console.error(`[widgets] ${err.message}`);
|
|
31905
|
+
return { ok: false, status: 503, error: "widget_realm_unavailable", message: err.message };
|
|
31906
|
+
}
|
|
31886
31907
|
if (!entry) return { ok: false, status: 404, error: "widget_not_found" };
|
|
31887
31908
|
const loaded = await readBundleFile(entry.bundle, dir);
|
|
31888
31909
|
if (!loaded) return { ok: false, status: 404, error: "widget_not_found" };
|
|
@@ -54301,7 +54322,7 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
54301
54322
|
himi deeplinks --app <app> --release <id>
|
|
54302
54323
|
nav map + web/player deeplinks for a release
|
|
54303
54324
|
himi logs --app <app> [--release <id>] [--screen <id>] [--level <l>] [--follow] worker console read-back
|
|
54304
|
-
himi promote --app <app> --release <id> [--force] flip a draft LIVE
|
|
54325
|
+
himi promote --app <app> --release <id> [--ring <r>] [--percent 0-100] [--force] flip a draft LIVE; --ring also points a rollout ring at it
|
|
54305
54326
|
himi patch screen <id> --app <a> --file <descriptor.json> [--bundle <sha256|none>]
|
|
54306
54327
|
himi patch bundle --app <a> --file <bundle.js> (--for-screen <id>[,<id>] | --no-rebind)
|
|
54307
54328
|
himi patch tokens --app <a> --file <tokens.json>
|
|
@@ -54601,7 +54622,7 @@ var COMMANDS = [
|
|
|
54601
54622
|
{ name: "diagnose", summary: "remote screen triage against a pushed release (GET /v1/preview/\u2026/diagnose) \u2014 bindings/schema/boot; exit 1 if ok:false", required: "<screenId> --app --release" },
|
|
54602
54623
|
{ name: "deeplinks", summary: "nav map + web/player deeplinks for a release (GET /v1/preview/\u2026/deeplinks)", required: "--app --release" },
|
|
54603
54624
|
{ name: "logs", summary: "worker console read-back (GET /v1/telemetry/logs); --follow tails via the seq cursor", required: "--app [--release] [--screen] [--level] [--follow]" },
|
|
54604
|
-
{ name: "promote", summary: "flip a stored draft LIVE (POST /v1/admin/release/activate); a release pushed past errors needs an explicit --force override", required: "--app --release [--force] (--control-token)" },
|
|
54625
|
+
{ name: "promote", summary: "flip a stored draft LIVE (POST /v1/admin/release/activate); --ring also points a rollout ring at it in the same command (POST /v1/admin/promote), which ring-based clients need in order to resolve at all \u2014 without it they stay unresolved and the warning goes to stderr; --percent sets that ring's rollout share; a release pushed past errors needs an explicit --force override", required: "--app --release [--ring <ring>] [--percent 0-100] [--force] (--control-token)" },
|
|
54605
54626
|
{ name: "patch", summary: 'change ONE item of a published app \u2014 a screen descriptor, a Tier-5 bundle, tokens, or the app-config baseline \u2014 from a RAW FILE, with no content package and no build. The low-level door: it does not lint your package, because there is no package here; `himi push --only <selector>` is the same edit with the full build + lint gate and is what to reach for when the package is in hand. Derives a new release from the app\'s current LIVE release, or from `--from-release <id>`. An explicit `--draft` or `--live` is REQUIRED \u2014 a patch has no default blast radius \u2014 and `--notes` is required with `--live` on a screen or app-config patch, because off-repo `gitSha` is "dev" and the ledger notes are then the only durable record of bytes that correspond to no commit. A branch does not merge: activating one derived from an older release reverts every item the patch does not move, so that case is refused until `--accept-regressions`. A bundle patch must repoint a screen (`--for-screen`) or the bytes land under a manifest key nothing reads. It cannot ADD a screen (screens are git-only, RFC 0012), never claims a slug \u2014 the app must already be published \u2014 and carries no attestation, source archive, assets, icon or minBinaryVersion, each named in the output.', required: "screen <id> --file <descriptor.json> [--bundle <sha256|none>] | bundle --file <bundle.js> (--for-screen <id>[,<id>] | --no-rebind) | tokens --file <tokens.json> | app-config --file <app-config.json> ; (--draft|--live) --app <a> [--from-release <id>] [--accept-regressions] [--label <n>] [--notes <t>] [--force] [--target <t>] (--control-token)" },
|
|
54606
54627
|
{ name: "visibility", summary: "read (no value) or set whether the public registry (/v1/apps + the Himi Player picker) LISTS the app. `public` lists it for everyone; `unlisted` hides it from listings while direct reads by app id \u2014 deep links, previews \u2014 keep working. App from --app or the content dir. Setting it needs no republish.", required: "[public|unlisted] [--app <a>] [--content <dir>] (--control-token)" },
|
|
54607
54628
|
{ name: "dist", summary: "build an INSTALLABLE QA binary (signed IPA / APK) on the Wix Job Service Mac pool and return an install link \u2014 the serve plane brokers the job, the pool builds it. WAITS for the build by default (~4 min) and prints the install link; `--no-wait` returns a jobId immediately instead. Omitting `--release` builds whatever is LIVE for the app. A named draft is refused unless `--allow-draft` makes that exceptional build explicit. `status <jobId>` / `watch <jobId>` / `list --app <a>` / `cancel <jobId>` inspect and stop builds (`watch` reports up front whether the job mints its own signing identity or borrows one, so a doomed iOS build is cancellable in seconds rather than after the archive). Off-repo, name a target \u2014 `--target wix` for a self-serve Wix login or `--target bo` for the internal employee path (the in-repo default is a local dev plane that isn't reachable off-repo); self-serve callers may build their OWN apps under a tighter budget (2 in flight / 5 per 24h), while a manage-only owner-role credential is refused. `--shell` picks the native host to sign into (branded-lite | owner-lite | player | demo-app). `--signing` defaults to `wix-managed` \u2014 the Wix Apple account mints a per-app signing identity for the build, so the caller provisions no Apple credentials of their own; `--signing byo` (sign with your own Apple account) is reserved and 501s. `--android-signing` is the Android counterpart and a SEPARATE axis (a keystore, not an Apple account): `qa-keystore` (default \u2014 the repo's committed QA key, identical on every pool machine, so a build installs over the previous one), `wix-keystore` (the Wix key the pool machine carries; the build FAILS naming the paths searched if it carries none, rather than quietly signing with something else), or `debug` (the old per-machine key \u2014 QA must uninstall any previous build first). NOT the normal way to ship: screens, Tier-5 bundles, tokens and app-config all go over the air with `himi push` in seconds \u2014 a binary trip is only needed for a NATIVE delta (a new SDUI component, a new declared capability/entitlement, a new bundle id, or a minBinaryVersion floor bump). Refuses to build an app whose launcher icon is missing, a placeholder, or one a store would reject \u2014 the one thing a binary carries that no later OTA push can fix; `--force` builds anyway", required: "[--app <a>] [--platform ios,android] [--release <id>] [--allow-draft] [--target <t>] [--shell branded-lite|owner-lite|player|demo-app] [--signing wix-managed|byo] [--android-signing qa-keystore|wix-keystore|debug] [--borrow-ios-id <bundleId>] [--no-wait] [--force] | status <jobId> [--target <t>] | watch <jobId> [--target <t>] [--interval <ms>] | list --app <a> [--target <t>] | cancel <jobId> [--target <t>]" },
|
|
@@ -55581,7 +55602,10 @@ async function producedWidgetFamilies(dir) {
|
|
|
55581
55602
|
let extracted;
|
|
55582
55603
|
try {
|
|
55583
55604
|
extracted = await widgetsModule.extractWidgets(js);
|
|
55584
|
-
} catch {
|
|
55605
|
+
} catch (err) {
|
|
55606
|
+
if (err instanceof widgetsModule.WidgetRealmUnavailableError) {
|
|
55607
|
+
return { families: void 0, source: "producer-unavailable" };
|
|
55608
|
+
}
|
|
55585
55609
|
continue;
|
|
55586
55610
|
}
|
|
55587
55611
|
for (const [widgetId, def] of Object.entries(extracted.widgets)) {
|
|
@@ -58539,18 +58563,86 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
58539
58563
|
return 2;
|
|
58540
58564
|
}
|
|
58541
58565
|
const target = targetName();
|
|
58542
|
-
const
|
|
58566
|
+
const force = flags.force === true;
|
|
58567
|
+
const ringGiven = flags.ring !== void 0;
|
|
58568
|
+
const ring = str5(flags.ring);
|
|
58569
|
+
if (ringGiven && !ring) {
|
|
58570
|
+
io.error(JSON.stringify({ error: "--ring needs a ring name, e.g. --ring ga" }));
|
|
58571
|
+
return 2;
|
|
58572
|
+
}
|
|
58573
|
+
const percentGiven = flags.percent !== void 0;
|
|
58574
|
+
const percent = num(flags.percent);
|
|
58575
|
+
if (percentGiven && (percent === void 0 || percent < 0 || percent > 100)) {
|
|
58576
|
+
io.error(JSON.stringify({ error: `--percent must be 0..100, got ${String(flags.percent)}` }));
|
|
58577
|
+
return 2;
|
|
58578
|
+
}
|
|
58579
|
+
if (percentGiven && !ring) {
|
|
58580
|
+
io.error(JSON.stringify({ error: "--percent sets a ring's rollout share, so it needs --ring" }));
|
|
58581
|
+
return 2;
|
|
58582
|
+
}
|
|
58583
|
+
const r = await client2().activateRelease(app, release, force);
|
|
58584
|
+
if (!r.ok || !ring) {
|
|
58585
|
+
if (r.ok) {
|
|
58586
|
+
io.error(JSON.stringify({
|
|
58587
|
+
warning: "no rollout ring was promoted \u2014 ring-based clients stay unresolved",
|
|
58588
|
+
next: `himi promote --app ${app} --release ${release} --ring <ring>${force ? " --force" : ""} --target ${target}`
|
|
58589
|
+
}));
|
|
58590
|
+
}
|
|
58591
|
+
print({
|
|
58592
|
+
status: r.status,
|
|
58593
|
+
...r.json ?? {},
|
|
58594
|
+
...r.ok ? {
|
|
58595
|
+
ringPromoted: false,
|
|
58596
|
+
note: "activation updates the live release but does not select a rollout ring; ring-based clients remain unresolved until a ring is promoted",
|
|
58597
|
+
// No `nextAuth` here: this `next` is a plain `himi promote`, which resolves its own
|
|
58598
|
+
// credential. It used to name `$TOK` because the hint was a `himi-serve` command.
|
|
58599
|
+
next: `himi promote --app ${app} --release ${release} --ring <ring>${force ? " --force" : ""} --target ${target}`
|
|
58600
|
+
} : {}
|
|
58601
|
+
});
|
|
58602
|
+
return r.ok ? 0 : 1;
|
|
58603
|
+
}
|
|
58604
|
+
const flagsFor = (o = {}) => `${o.percent !== void 0 ? ` --percent ${o.percent}` : ""}${force ? " --force" : ""} --target ${target}`;
|
|
58605
|
+
if (!percentGiven) {
|
|
58606
|
+
io.error(JSON.stringify({
|
|
58607
|
+
warning: `no --percent given: an existing ring "${ring}" keeps its current share, and a NEW one is created at the plane's default (100% on the hosted plane)`,
|
|
58608
|
+
next: `himi promote --app ${app} --release ${release} --ring ${ring}${flagsFor({ percent: "<0-100>" })}`
|
|
58609
|
+
}));
|
|
58610
|
+
}
|
|
58611
|
+
let p;
|
|
58612
|
+
const ringOnlyRetry = `himi-serve release promote --app ${app} --ring ${ring} --release ${release}${percent !== void 0 ? ` --percent ${percent}` : ""}${force ? " --force" : ""} --target ${target} --control-token "$TOK"`;
|
|
58613
|
+
try {
|
|
58614
|
+
p = await client2().promote(app, ring, release, percent, force);
|
|
58615
|
+
} catch (e) {
|
|
58616
|
+
io.error(JSON.stringify({
|
|
58617
|
+
error: `the release was ACTIVATED, but the ring request did not complete: ${e.message}`,
|
|
58618
|
+
activated: true,
|
|
58619
|
+
ringPromoted: false,
|
|
58620
|
+
ring,
|
|
58621
|
+
next: ringOnlyRetry,
|
|
58622
|
+
nextAuth: `set TOK to a serve-control token for target ${target}`
|
|
58623
|
+
}));
|
|
58624
|
+
return 1;
|
|
58625
|
+
}
|
|
58543
58626
|
print({
|
|
58544
|
-
status:
|
|
58627
|
+
status: p.status,
|
|
58628
|
+
// BOTH responses: the activation's own fields (`visibility`, any warning it carries)
|
|
58629
|
+
// are part of what happened and were being dropped on this path.
|
|
58545
58630
|
...r.json ?? {},
|
|
58546
|
-
...
|
|
58547
|
-
|
|
58548
|
-
|
|
58549
|
-
|
|
58631
|
+
...p.json ?? {},
|
|
58632
|
+
activated: true,
|
|
58633
|
+
ringPromoted: p.ok,
|
|
58634
|
+
ring,
|
|
58635
|
+
// REQUESTED, not applied. The git-backed `applyPromote` takes no percent at all
|
|
58636
|
+
// (promote.ts), so echoing `percent` as fact would report a share that plane never
|
|
58637
|
+
// set. Only the hosted CloudStore path honours it.
|
|
58638
|
+
...percent !== void 0 ? { percentRequested: percent } : {},
|
|
58639
|
+
...p.ok ? {} : {
|
|
58640
|
+
note: `the release was ACTIVATED, but promoting ring "${ring}" failed \u2014 retry the RING half alone with \`himi-serve release promote\`, which does not re-activate`,
|
|
58641
|
+
next: ringOnlyRetry,
|
|
58550
58642
|
nextAuth: `set TOK to a serve-control token for target ${target}`
|
|
58551
|
-
}
|
|
58643
|
+
}
|
|
58552
58644
|
});
|
|
58553
|
-
return
|
|
58645
|
+
return p.ok ? 0 : 1;
|
|
58554
58646
|
}
|
|
58555
58647
|
// The RAW-FILE patch door. No content package, no build, no package lint — that is the whole
|
|
58556
58648
|
// reason it exists, and the reason `himi push --only` is the one to reach for when a package
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.893.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": [
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"artifactId": "himalaya-cli"
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
|
-
"falconPackageHash": "
|
|
67
|
+
"falconPackageHash": "f38e92c2fdf1c758a5d00cb4fa45c3ff0f9945647a1ef9932642c7f0"
|
|
68
68
|
}
|