@wix/himalaya-cli 0.1366.0 → 0.1368.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
@@ -7706,6 +7706,7 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
7706
7706
  var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
7707
7707
  var init_bindings = __esm({
7708
7708
  "../../core/ts/src/bindings.ts"() {
7709
+ "use strict";
7709
7710
  BINDING_SIGILS = ["service", "flag", "item", "t"];
7710
7711
  BINDING_SIGIL_RE = new RegExp(
7711
7712
  `^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
@@ -35370,6 +35371,16 @@ function loadSupervisorRegistry() {
35370
35371
  function isPlayerHost(appName2) {
35371
35372
  return appName2 === PLAYER_APP_ID || process.env.HIMALAYA_DEV_MULTI_APP === "1";
35372
35373
  }
35374
+ function tenantsOf(hostApp) {
35375
+ if (!Object.prototype.hasOwnProperty.call(HOSTED_TENANTS, hostApp)) return [];
35376
+ const fixed = HOSTED_TENANTS[hostApp];
35377
+ const extra = (process.env.HIMALAYA_DEV_HOSTED_TENANTS ?? "").split(",").map((a2) => a2.trim()).filter((a2) => /^[a-z0-9][a-z0-9._-]{0,127}$/i.test(a2) && a2 !== hostApp && a2 !== PLAYER_APP_ID);
35378
+ return extra.length ? [...fixed, ...extra.filter((a2) => !fixed.includes(a2))] : fixed;
35379
+ }
35380
+ function optedInTenant(tenant) {
35381
+ if (Object.values(HOSTED_TENANTS).some((t2) => t2.includes(tenant))) return false;
35382
+ return (process.env.HIMALAYA_DEV_HOSTED_TENANTS ?? "").split(",").some((a2) => a2.trim() === tenant);
35383
+ }
35373
35384
  function isTenantHost(appName2) {
35374
35385
  return !!appName2 && Object.prototype.hasOwnProperty.call(HOSTED_TENANTS, appName2);
35375
35386
  }
@@ -35385,7 +35396,7 @@ function resolveTenantBase(tenant, registry2 = loadSupervisorRegistry) {
35385
35396
  if (running?.status === "running" && running.port) port = running.port;
35386
35397
  } catch {
35387
35398
  }
35388
- port ??= ledgerDevServerPort(tenant);
35399
+ if (!optedInTenant(tenant)) port ??= ledgerDevServerPort(tenant);
35389
35400
  if (port) return `http://127.0.0.1:${port}`;
35390
35401
  }
35391
35402
  return resolveServeBase();
@@ -35410,7 +35421,7 @@ function tenantPrefixed(url, hostApp, method = "GET") {
35410
35421
  return null;
35411
35422
  }
35412
35423
  if (!normalized.startsWith("/v1/") || normalized !== path2 || isTenantAdminPath(normalized)) return null;
35413
- return HOSTED_TENANTS[hostApp].includes(tenant) ? { tenant, url: tenantUrl } : null;
35424
+ return tenantsOf(hostApp).includes(tenant) ? { tenant, url: tenantUrl } : null;
35414
35425
  }
35415
35426
  function forwardedBaseUrl(req) {
35416
35427
  if (!LOOPBACK_PEERS.has(req.socket?.remoteAddress ?? "")) return null;
@@ -35492,7 +35503,9 @@ function tenantHostPlaneRead(url, headers2, hostApp, method = "GET") {
35492
35503
  if (path2 === "/v1/release/current") {
35493
35504
  const app = new URLSearchParams(query).get("app")?.trim();
35494
35505
  if (!app || app === hostApp || HOSTED_TENANTS[hostApp].includes(app)) return null;
35495
- if (targetTenant(url, headers2, hostApp) !== null) return null;
35506
+ const hdr = headers2["x-himalaya-app"];
35507
+ const headerApp = (Array.isArray(hdr) ? hdr[0] : hdr)?.trim();
35508
+ if (headerApp && tenantsOf(hostApp).includes(headerApp)) return null;
35496
35509
  return resolveServeBase() || null;
35497
35510
  }
35498
35511
  return null;
@@ -35512,7 +35525,7 @@ function targetTenant(url, headers2, hostApp) {
35512
35525
  }
35513
35526
  if (!app) return null;
35514
35527
  if (app === hostApp || app === PLAYER_APP_ID) return null;
35515
- if (hostApp && isTenantHost(hostApp) && !HOSTED_TENANTS[hostApp].includes(app)) return null;
35528
+ if (hostApp && isTenantHost(hostApp) && !tenantsOf(hostApp).includes(app)) return null;
35516
35529
  return app;
35517
35530
  }
35518
35531
  function shouldServeFromPlane(url, headers2, hostApp) {
@@ -132562,6 +132575,8 @@ function createDevServer(opts = {}) {
132562
132575
  await maybeReseedNetMocks(state);
132563
132576
  if (url.startsWith("/__dev/")) return await handleDev(req, res, state);
132564
132577
  if (isTenantHost(state.appName)) {
132578
+ const planeRead = tenantHostPlaneRead(url, req.headers, state.appName, req.method);
132579
+ if (planeRead) return await proxyToServe(planeRead, req, res);
132565
132580
  const prefixed = tenantPrefixed(url, state.appName, req.method);
132566
132581
  const tenant = prefixed?.tenant ?? (shouldServeFromPlane(url, req.headers, state.appName) && !isTenantAdminPath(url) ? targetTenant(url, req.headers, state.appName) : null);
132567
132582
  if (tenant) {
@@ -132579,8 +132594,6 @@ function createDevServer(opts = {}) {
132579
132594
  forwardAs: clientHost ? { host: clientHost, prefix: `${TENANT_PREFIX}${encodeURIComponent(tenant)}` } : void 0
132580
132595
  });
132581
132596
  }
132582
- const planeRead = tenantHostPlaneRead(url, req.headers, state.appName, req.method);
132583
- if (planeRead) return await proxyToServe(planeRead, req, res);
132584
132597
  }
132585
132598
  if (url.split("?")[0] === "/v1/app-icon" && req.method === "GET") {
132586
132599
  const iconApp = new URLSearchParams(url.split("?")[1] ?? "").get("app") ?? "";
@@ -170121,19 +170134,42 @@ function decideSiteApp(input) {
170121
170134
  ...input.installedVersion ? { installedVersion: input.installedVersion } : {}
170122
170135
  });
170123
170136
  if (!verdict.ok) return fallback(picked, verdict.reason);
170124
- if (!(input.hostable ?? NATIVELY_HOSTABLE_APPS).includes(picked)) {
170137
+ const ungranted = req.requirements.capabilities.filter((c2) => !HOSTED_APP_CAPABILITIES.includes(c2));
170138
+ if ((input.hostable ?? NATIVELY_HOSTABLE_APPS) === "any" && ungranted.length) {
170139
+ return fallback(picked, `This Spaces build does not grant a member app ${ungranted.join(", ")} yet (${picked} declares it)`);
170140
+ }
170141
+ const hostable = input.hostable ?? NATIVELY_HOSTABLE_APPS;
170142
+ if (hostable !== "any" && !hostable.includes(picked)) {
170125
170143
  return fallback(picked, `This Spaces build cannot host a custom member app yet (${picked} is compatible)`);
170126
170144
  }
170127
170145
  return { appId: picked, source: "picked" };
170128
170146
  }
170129
- var DEFAULT_SITE_APP, NATIVELY_HOSTABLE_APPS, APP_ID3;
170147
+ var DEFAULT_SITE_APP, NATIVELY_HOSTABLE_APPS, HOSTED_APP_CAPABILITIES, APP_ID3;
170130
170148
  var init_site_app = __esm({
170131
170149
  "../../apps/himi-spaces-lite/site-app.ts"() {
170132
170150
  init_host_compatibility();
170133
170151
  init_registry_app_normalize();
170134
170152
  init_site_open();
170135
170153
  DEFAULT_SITE_APP = HOSTED_MEMBER_APP;
170136
- NATIVELY_HOSTABLE_APPS = [DEFAULT_SITE_APP];
170154
+ NATIVELY_HOSTABLE_APPS = "any";
170155
+ HOSTED_APP_CAPABILITIES = [
170156
+ "animation",
170157
+ "app_info",
170158
+ "clipboard",
170159
+ "file_picker",
170160
+ "haptics",
170161
+ "keyboard",
170162
+ "media_playback",
170163
+ "motion",
170164
+ "on_device_ai",
170165
+ "open_url",
170166
+ "pdf",
170167
+ "share",
170168
+ "stream",
170169
+ "theme",
170170
+ "ui",
170171
+ "wix_api"
170172
+ ];
170137
170173
  APP_ID3 = /^[a-z0-9][a-z0-9._-]{0,127}$/i;
170138
170174
  }
170139
170175
  });
@@ -174440,7 +174476,7 @@ var ServeCliClient = class {
174440
174476
  const headers2 = { ...this.ctrlHeaders(), ...gzip ? { "content-encoding": "gzip" } : {} };
174441
174477
  const res = await this.request("control", "POST", "/v1/admin/release", { rawBody: bytes2, headers: headers2 });
174442
174478
  if (gzip && res.status === 400 && res.json?.error === "bad_json") {
174443
- const json6 = { error: "compressed_publish_unsupported", hint: "this body is over the plain publish cap, and this serve plane does not accept a compressed one yet; it takes a serve deploy carrying gzip publish bodies" };
174479
+ const json6 = { code: "compressed_publish_unsupported", error: "compressed_publish_unsupported", hint: "this body is over the plain publish cap, and the plane did not accept it compressed: either the plane predates gzip publish bodies (it needs a serve deploy), or this is a self-serve credential, which keeps the plain 8 MB cap" };
174444
174480
  return { ...res, json: json6, text: JSON.stringify(json6) };
174445
174481
  }
174446
174482
  return res;
@@ -179820,7 +179856,8 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
179820
179856
  }
179821
179857
  if (!r2.ok) {
179822
179858
  const hint = releaseIdExistsHint(r2.status, r2.json);
179823
- print({ ok: false, status: r2.status, body: r2.json ?? r2.text, ...hint ? { hint } : {} });
179859
+ const code = r2.json?.code === "compressed_publish_unsupported" ? "compressed_publish_unsupported" : void 0;
179860
+ print({ ok: false, ...code ? { code } : {}, status: r2.status, body: r2.json ?? r2.text, ...hint ? { hint } : {} });
179824
179861
  return 1;
179825
179862
  }
179826
179863
  if (sendPayload.sourceGz && r2.json?.template !== true) {
@@ -106,6 +106,15 @@ failure codes. A forced push still follows the existing override rules.
106
106
  | `config_not_applied` | `--content` was given, but the binding is not in its `config.ts` (no config file, a dynamic or symlinked config, an edit `himi validate` rolled back, or no validator); the `config` report or `note` says what to add by hand. |
107
107
  | `connect_failed` | An otherwise unclassified error stopped connect (for example an unreadable manifest, or a failed `--out` write). The original message is preserved. |
108
108
 
109
+ ## `himi template publish` codes
110
+
111
+ `template publish` is still mostly legacy. It carries one code so far, on the path that sends the
112
+ whole body gzip-encoded because it is over the plain 8 MB cap:
113
+
114
+ | Code | Meaning |
115
+ |---|---|
116
+ | `compressed_publish_unsupported` | The publish body went out gzipped and the publishing service did not accept it compressed, so it read the bytes as malformed JSON. Either the service does not accept compressed bodies yet, or the credential is a self-serve one, which keeps the 8 MB uncompressed limit. Nothing was written. |
117
+
109
118
  ## `himi site member-app` codes
110
119
 
111
120
  `himi site member-app set|clear|show <site>` prints one envelope. A refusal from the publishing service
@@ -126,10 +135,12 @@ keeps the service's own `error` in `serverError` and its HTTP `status`; the CLI
126
135
 
127
136
  `show` succeeds with `opens` (what members get: the picked app or `himi-branded-lite`), `compatible`
128
137
  (whether the picked release fits the Spaces host manifest, judged with `checkHostCompatibility`), and —
129
- whenever members get Branded Lite instead of the pick — `reason`. `opens` is Spaces' own decision, so a
130
- compatible pick that this Spaces build cannot host yet reports `compatible: true` with `opens:
131
- "himi-branded-lite"` and that reason. An incompatible pick is not a failure: it is `ok: true` with
132
- `compatible: false`.
138
+ whenever members get Branded Lite instead of the pick — `reason`. `opens` is Spaces' own decision: a
139
+ compatible pick reports `compatible: true` with `opens` naming that app — except one that needs a
140
+ capability the hosted-app sandbox does not grant (on-device stores such as `local_database`,
141
+ `secure_storage` and `files`, or push, purchases, release control and the like), which reports
142
+ `compatible: true` with `opens: "himi-branded-lite"` and that reason. Read `opens`, not `compatible`, for
143
+ what members get. An incompatible pick is not a failure: it is `ok: true` with `compatible: false`.
133
144
 
134
145
  ## Follow-ups
135
146
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1366.0",
3
+ "version": "0.1368.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": "2252ba70fda9f2dd25a520a0ec7d75a7d716dcdcb74564bf1f929780"
74
+ "falconPackageHash": "b0dba7f9b4c5184e704a739e1f459e4930cc9b446af7d0866d9038ae"
75
75
  }