@wix/himalaya-cli 0.1321.0 → 0.1322.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview/src/index.d.ts +4 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/index.d.ts +16 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/display.d.ts +21 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/webview-page.mjs +78 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/webview.mjs +16 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores.mjs +13 -4
- package/dist/cli.mjs +25 -0
- package/guides/sdk-reference.json +33 -3
- package/guides/web-page-native-sdk.md +154 -33
- package/guides/webview-page-sdk.md +11 -0
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +492 -0
- package/templates/beauty-salon/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
- package/templates/branded-lite/dev/index.ts +492 -0
- package/templates/branded-lite/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
- package/templates/gym-fitness/dev/index.ts +492 -0
- package/templates/gym-fitness/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
- package/templates/portfolio-creative/dev/index.ts +492 -0
- package/templates/portfolio-creative/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
- package/templates/retail-store/dev/index.ts +492 -0
- package/templates/retail-store/tier5-src/wix-spaces-collection-detail/index.ts +146 -30
|
@@ -31,19 +31,30 @@ Your page can only use capabilities the **app owner** turned on for your site. I
|
|
|
31
31
|
|
|
32
32
|
- `capabilities` — the capability ids your page will call (see the
|
|
33
33
|
[Web page SDK reference](https://apps.wix.com/_api/himi-serve/docs/web-page-sdk-reference.md) for every id and method).
|
|
34
|
-
- `permissionCopy` — the sentence the phone shows when it asks the user for permission
|
|
35
|
-
for the end user, about what *they* get.
|
|
34
|
+
- `permissionCopy` — optional: the sentence the phone shows when it asks the user for permission,
|
|
35
|
+
at most 500 characters. Write it for the end user, about what *they* get. Only capabilities that
|
|
36
|
+
prompt need one (Health, camera, photos, location, microphone…); `haptic` and `share` never ask,
|
|
37
|
+
and a capability left out gets the app's built-in generic sentence.
|
|
36
38
|
- No worker code is needed. Brandy generates the companion worker that answers your page from
|
|
37
|
-
`capabilities`, allowing every method the capability's page lists — except
|
|
39
|
+
`capabilities`, allowing **every** method the capability's page lists — except
|
|
38
40
|
`presigned_upload.putFile`, which reads a device file and is allowed only when `files` is enabled
|
|
39
|
-
too.
|
|
40
|
-
narrower allowlist can still name their own worker in `bundle`.)
|
|
41
|
+
too. So enabling a capability is enough; the owner does not list methods.
|
|
41
42
|
- Enabling a capability changes the app's native permissions, so the owner ships a **new app
|
|
42
43
|
build** with it before your page can call it. Until then the call times out.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
**You cannot enable anything from the page, or with any public command.** The app owner is
|
|
46
|
+
whoever builds the app (for an app Wix builds for a customer, the team that ships it). Hand them a
|
|
47
|
+
request they can act on without asking you anything back — for example:
|
|
48
|
+
|
|
49
|
+
> Please enable these web page capabilities for `https://www.example.com` in the app's `webSdk`
|
|
50
|
+
> provisioning and ship a new build: `["health", "haptic", "share"]`, with
|
|
51
|
+
> `permissionCopy.health` = "Show your step count for today." The page checks what is enabled and
|
|
52
|
+
> hides the rest, so it is safe to ship before the build.
|
|
53
|
+
|
|
54
|
+
An owner who wrote their own companion worker (named in `webSdk.bundle`) chooses methods one by
|
|
55
|
+
one: for that app only, add the exact `capability.method` pairs your page calls, for example
|
|
56
|
+
`health.availability`, `health.requestPermission`, `health.query`, `haptic.play`. A method that
|
|
57
|
+
worker does not allow never answers — your call times out (see *Errors*).
|
|
47
58
|
|
|
48
59
|
Your page must be served from the site origin the app was built for. Pages in iframes, and pages
|
|
49
60
|
reached through a redirect to another origin, do not get the bridge.
|
|
@@ -100,7 +111,12 @@ export function isInHimiApp(): boolean {
|
|
|
100
111
|
return bridge() !== undefined;
|
|
101
112
|
}
|
|
102
113
|
|
|
103
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Call one native method, e.g. call("health", "query", [{ type: "steps", from, to }]).
|
|
116
|
+
* A call that shows native UI (a permission prompt, the share sheet) answers only when the user is
|
|
117
|
+
* done: give it a long timeoutMs, such as 120_000. Never wait without a deadline — a message the app
|
|
118
|
+
* drops (see "Keep what you send small") gets no answer at all.
|
|
119
|
+
*/
|
|
104
120
|
export function call<T = unknown>(capability: string, method: string, args: unknown[] = [], timeoutMs = 30_000): Promise<T> {
|
|
105
121
|
const target = bridge();
|
|
106
122
|
if (!target) return Promise.reject(new HimalayaError("Not running inside a Himi app", "not_in_app"));
|
|
@@ -119,8 +135,86 @@ export function call<T = unknown>(capability: string, method: string, args: unkn
|
|
|
119
135
|
});
|
|
120
136
|
}
|
|
121
137
|
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
let manifest: { on: Bridge; list: Record<string, string[]> } | undefined;
|
|
139
|
+
|
|
140
|
+
let asking: { on: Bridge; until: number; answer: Promise<Record<string, string[]> | null> } | undefined;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* ONE question loop per bridge, however many callers wait on it: every message counts against the
|
|
144
|
+
* app's rate limit, so twenty gated controls must not ask twenty times a second. It asks every
|
|
145
|
+
* half second until the latest caller's deadline (a message sent before the app is ready is lost);
|
|
146
|
+
* each question listens for 2 s, so a slow answer still lands and at most four are in flight.
|
|
147
|
+
*/
|
|
148
|
+
function askShared(target: Bridge, budget: number): Promise<Record<string, string[]> | null> {
|
|
149
|
+
const until = Date.now() + budget;
|
|
150
|
+
if (asking?.on === target) {
|
|
151
|
+
asking.until = Math.max(asking.until, until);
|
|
152
|
+
return asking.answer;
|
|
153
|
+
}
|
|
154
|
+
const state = { on: target, until, answer: Promise.resolve<Record<string, string[]> | null>(null) };
|
|
155
|
+
asking = state; // before the first ask: a loop that ends at once must clear itself
|
|
156
|
+
state.answer = new Promise((resolve) => {
|
|
157
|
+
let done = false;
|
|
158
|
+
const finish = (list: Record<string, string[]> | null) => {
|
|
159
|
+
if (done) return;
|
|
160
|
+
done = true;
|
|
161
|
+
clearInterval(again);
|
|
162
|
+
if (asking === state) asking = undefined;
|
|
163
|
+
if (list) manifest = { on: target, list };
|
|
164
|
+
resolve(list);
|
|
165
|
+
};
|
|
166
|
+
const ask = () => {
|
|
167
|
+
if (done) return;
|
|
168
|
+
const left = state.until - Date.now();
|
|
169
|
+
if (left <= 0 || bridge() !== target) return finish(null); // deadline, or the page's bridge changed
|
|
170
|
+
call<{ capabilities?: Record<string, string[]> }>("himalaya", "capabilities", [], Math.max(1, Math.min(2_000, left))).then(
|
|
171
|
+
(reply) => finish(reply?.capabilities ?? null),
|
|
172
|
+
// A timed-out question is not an answer; the deadline decides. Anything else is final.
|
|
173
|
+
(error) => { if (!(error instanceof HimalayaError && error.code === "timeout")) finish(null); },
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
const again = setInterval(ask, 500);
|
|
177
|
+
ask();
|
|
178
|
+
});
|
|
179
|
+
return state.answer;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* What this app lets the page call, as { capability: [method, …] }. null outside the app, in an app
|
|
184
|
+
* build older than this question, or when nothing answered within timeoutMs. A list is remembered
|
|
185
|
+
* (and returned at once, whatever timeoutMs); a miss is not, because an app that is still starting
|
|
186
|
+
* drops the first messages.
|
|
187
|
+
*/
|
|
188
|
+
export async function enabledCapabilities(timeoutMs = 3_000): Promise<Record<string, string[]> | null> {
|
|
189
|
+
const target = bridge();
|
|
190
|
+
if (!target) return null;
|
|
191
|
+
if (manifest?.on === target) return manifest.list;
|
|
192
|
+
if (!(timeoutMs > 0)) return null; // no time to ask: nothing can answer
|
|
193
|
+
// setTimeout cannot wait longer than 2^31-1 ms (a longer delay fires at once), so clamp it.
|
|
194
|
+
const budget = Math.min(timeoutMs, 2_147_483_647);
|
|
195
|
+
const answer = askShared(target, budget);
|
|
196
|
+
// This caller's own deadline; the shared question may keep going for a caller who waits longer.
|
|
197
|
+
return new Promise((resolve) => {
|
|
198
|
+
const stop = setTimeout(() => resolve(manifest?.on === target ? manifest.list : null), budget);
|
|
199
|
+
void answer.then((list) => { clearTimeout(stop); resolve(list); });
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* True when the app lets the page call `capability.method`, read from enabledCapabilities(): nothing
|
|
205
|
+
* is called and nothing happens on the phone. false when there is no list (outside the app, an app
|
|
206
|
+
* build older than the list, or no answer yet).
|
|
207
|
+
*/
|
|
208
|
+
export async function isEnabled(capability: string, method: string, timeoutMs = 3_000): Promise<boolean> {
|
|
209
|
+
const enabled = await enabledCapabilities(timeoutMs);
|
|
210
|
+
return enabled?.[capability]?.includes(method) ?? false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* For an app build older than enabledCapabilities(): CALL `capability.method` and report whether the
|
|
215
|
+
* app answered it (even with an error). It runs the method, so pass only a read-only one.
|
|
216
|
+
*/
|
|
217
|
+
export async function probe(capability: string, method: string, args: unknown[] = [], timeoutMs = 3_000): Promise<boolean> {
|
|
124
218
|
try {
|
|
125
219
|
await call(capability, method, args, timeoutMs);
|
|
126
220
|
return true;
|
|
@@ -154,15 +248,15 @@ Capability ids are snake_case (`health`, `haptic`, `secure_storage`, `local_data
|
|
|
154
248
|
names are exactly the SDK's function names. Arguments and results are plain JSON.
|
|
155
249
|
|
|
156
250
|
```ts
|
|
157
|
-
import { himalaya, HimalayaError } from "./lib/himalaya";
|
|
251
|
+
import { call, himalaya, HimalayaError } from "./lib/himalaya";
|
|
158
252
|
|
|
159
253
|
// Light, fire-and-forget feedback.
|
|
160
254
|
await himalaya.haptic.play("success");
|
|
161
255
|
|
|
162
|
-
// Health: check, ask (from a button tap), then read.
|
|
256
|
+
// Health: check, ask (from a button tap), then read. The prompt waits for the user: allow two minutes.
|
|
163
257
|
const { available } = await himalaya.health.availability();
|
|
164
258
|
if (available) {
|
|
165
|
-
await
|
|
259
|
+
await call("health", "requestPermission", [{ read: ["steps"] }], 120_000);
|
|
166
260
|
const midnight = new Date();
|
|
167
261
|
midnight.setHours(0, 0, 0, 0);
|
|
168
262
|
const { samples } = await himalaya.health.query({
|
|
@@ -174,13 +268,21 @@ if (available) {
|
|
|
174
268
|
```
|
|
175
269
|
|
|
176
270
|
`call("health", "availability")` is the same thing without the proxy, and is handy when the
|
|
177
|
-
capability or method name is a variable
|
|
271
|
+
capability or method name is a variable — or when you need a timeout other than the 30-second
|
|
272
|
+
default. **Give every call that shows native UI a long deadline** — `call(..., 120_000)` for a
|
|
273
|
+
permission prompt, the share sheet, the camera or a photo picker: it answers when the user is
|
|
274
|
+
done, and the 30-second default can turn a slow user into a `timeout` your page reads as "not
|
|
275
|
+
enabled". Keep a deadline even there: a message the app drops gets no answer at all.
|
|
276
|
+
|
|
277
|
+
`steps`, `activeEnergy` and `distance` come back summed (one sample for the whole range, or one
|
|
278
|
+
per `bucket: "hour" | "day"`), and `heartRate` averaged; summing `samples` for a total is right
|
|
279
|
+
either way.
|
|
178
280
|
|
|
179
281
|
## Step 3 — React pattern
|
|
180
282
|
|
|
181
283
|
```tsx
|
|
182
284
|
import { useEffect, useState } from "react";
|
|
183
|
-
import { call, himalaya, isInHimiApp, HimalayaError } from "./lib/himalaya";
|
|
285
|
+
import { call, himalaya, isEnabled, isInHimiApp, HimalayaError } from "./lib/himalaya";
|
|
184
286
|
|
|
185
287
|
export function StepsCard() {
|
|
186
288
|
const [state, setState] = useState<"checking" | "browser" | "off" | "ready" | "denied" | "failed">("checking");
|
|
@@ -188,8 +290,10 @@ export function StepsCard() {
|
|
|
188
290
|
|
|
189
291
|
useEffect(() => {
|
|
190
292
|
if (!isInHimiApp()) return setState("browser");
|
|
191
|
-
//
|
|
192
|
-
|
|
293
|
+
// Enabled for this site? Answered from the app's list, without calling anything.
|
|
294
|
+
isEnabled("health", "availability")
|
|
295
|
+
.then((on) => (on ? call<{ available: boolean }>("health", "availability", [], 3_000) : { available: false }))
|
|
296
|
+
// Enabled is not enough: a phone without a health store answers { available: false }.
|
|
193
297
|
.then(({ available }) => setState(available ? "ready" : "off"))
|
|
194
298
|
// Not enabled for this site (timeout) hides the feature; any other failure offers a retry.
|
|
195
299
|
.catch((error) => setState(error instanceof HimalayaError && error.code === "timeout" ? "off" : "failed"));
|
|
@@ -197,7 +301,7 @@ export function StepsCard() {
|
|
|
197
301
|
|
|
198
302
|
async function connect() {
|
|
199
303
|
try {
|
|
200
|
-
await
|
|
304
|
+
await call("health", "requestPermission", [{ read: ["steps"] }], 120_000); // waits for the user
|
|
201
305
|
const from = new Date(); from.setHours(0, 0, 0, 0);
|
|
202
306
|
const { samples } = await himalaya.health.query({ type: "steps", from: from.toISOString(), to: new Date().toISOString() });
|
|
203
307
|
setSteps(samples.reduce((sum: number, s: { value: number }) => sum + s.value, 0));
|
|
@@ -232,9 +336,21 @@ The same page must keep working in an ordinary browser (and in Base44 / Lovable
|
|
|
232
336
|
device (`availability()` tells you). Show a calm fallback, not an error. On iOS a denied Health
|
|
233
337
|
**read** is not reported as `not_authorized`: the read succeeds with no samples, exactly like a
|
|
234
338
|
day with no data. Word an empty result so it also covers "access is off".
|
|
235
|
-
- **Hide features the app doesn't enable.**
|
|
236
|
-
|
|
237
|
-
|
|
339
|
+
- **Hide features the app doesn't enable.** Check with `isEnabled(capability, method)` and hide the
|
|
340
|
+
UI when it is `false`. The app answers from its list of enabled capabilities
|
|
341
|
+
(`enabledCapabilities()`), so nothing is called and nothing happens on the phone — this works
|
|
342
|
+
for `haptic.play` too. An app build older than that list has none, so `isEnabled` answers
|
|
343
|
+
`false` there. To support such a build, fall back to `probe(capability, method)`, which **calls**
|
|
344
|
+
the method — use it only with a read-only one (`health.availability`, never `haptic.play`).
|
|
345
|
+
`true` only means the method is enabled — still read its answer (`availability()` can say
|
|
346
|
+
`{ available: false }`).
|
|
347
|
+
- **Ask for a permission once, then trust the result you read.** `health.requestPermission`
|
|
348
|
+
resolves with `{ granted }`, but on iOS a read type counts as granted once asked, whatever the
|
|
349
|
+
user chose — so read the data and treat an empty result as "no data or access off". The phone
|
|
350
|
+
shows each permission prompt once; asking again answers without showing anything.
|
|
351
|
+
- **Check for the app when you need it.** In current app builds the bridge exists before your
|
|
352
|
+
first script runs. On an older Android System WebView it is added as the page loads, so call
|
|
353
|
+
`isInHimiApp()` where you use it (for example in `useEffect`), not once at module load.
|
|
238
354
|
- **Plain JSON only.** Arguments and results cross as JSON: no functions, `Date` objects (use ISO
|
|
239
355
|
strings), `Blob`s or class instances.
|
|
240
356
|
- **Keep what you send small.** The app checks every message a page sends and silently drops one
|
|
@@ -258,7 +374,7 @@ Every failure rejects with a `HimalayaError` that has a `code`:
|
|
|
258
374
|
| `code` | Meaning | What to do |
|
|
259
375
|
|---|---|---|
|
|
260
376
|
| `not_in_app` | Ordinary browser or preview, no bridge | Render the browser fallback |
|
|
261
|
-
| `timeout` | No answer
|
|
377
|
+
| `timeout` | No answer within `timeoutMs`: capability or method not enabled for this site, not on this app build, or the message broke a size rule (see *Keep what you send small*). A call that shows native UI can also time out while the user is still looking at it — give it a long `timeoutMs` (`120_000`) | Check your arguments; otherwise hide the feature and ask the app owner to enable the capability |
|
|
262
378
|
| `bridge_refused` | The app's bridge refused the message outright | Retry later; send less often |
|
|
263
379
|
| `not_authorized` | The user denied permission | Explain how to enable it in Settings |
|
|
264
380
|
| `unavailable` | Not supported on this device | Hide the feature |
|
|
@@ -275,6 +391,8 @@ Codes other than the first three come from the capability itself; its reference
|
|
|
275
391
|
|
|
276
392
|
```ts
|
|
277
393
|
const answers: Record<string, unknown> = {
|
|
394
|
+
// What the app answers when the page asks which capabilities it may call.
|
|
395
|
+
"himalaya.capabilities": { v: 1, capabilities: { health: ["availability", "query", "requestPermission"], haptic: ["play"] } },
|
|
278
396
|
"health.availability": { available: true },
|
|
279
397
|
"health.requestPermission": undefined,
|
|
280
398
|
"health.query": { samples: [{ value: 4200 }] },
|
|
@@ -289,21 +407,24 @@ Codes other than the first three come from the capability itself; its reference
|
|
|
289
407
|
|
|
290
408
|
Never ship the fake: a page that defines `HimalayaWorker` itself is lying to its own feature
|
|
291
409
|
checks.
|
|
292
|
-
- **On a phone** —
|
|
293
|
-
|
|
410
|
+
- **On a phone** — there is no public preview app that carries your site's capabilities: ask the
|
|
411
|
+
app owner for an installable test build of the app with your capabilities enabled, open your
|
|
412
|
+
page inside it, and check each feature once with permission granted and once denied. Until then,
|
|
413
|
+
the fake bridge above is the test.
|
|
294
414
|
|
|
295
415
|
## More recipes
|
|
296
416
|
|
|
297
417
|
Each uses the client from Step 1. The exact types are on each capability's page (see *Reference*).
|
|
298
418
|
|
|
299
419
|
```ts
|
|
300
|
-
import {
|
|
420
|
+
import { call, himalaya } from "./lib/himalaya";
|
|
301
421
|
|
|
302
|
-
// Share a link through the phone's share sheet (from a tap).
|
|
303
|
-
|
|
422
|
+
// Share a link through the phone's share sheet (from a tap). The sheet waits for the user: allow two minutes.
|
|
423
|
+
// Outside the app, fall back to the browser's own share (or copy the link).
|
|
424
|
+
const { completed } = await call<{ completed: boolean }>("share", "share", [{ text: "Join me on Friday", url: "https://example.com/e/42" }], 120_000);
|
|
304
425
|
|
|
305
426
|
// Where am I? Ask first, then read once. getCurrent answers null when no fix arrives in time.
|
|
306
|
-
const status = await
|
|
427
|
+
const status = await call("location", "requestPermission", [], 120_000);
|
|
307
428
|
if (status === "granted") {
|
|
308
429
|
const here = await himalaya.location.getCurrent({ timeoutMs: 10_000 });
|
|
309
430
|
if (here) console.log(here.lat, here.lng, `±${here.accuracy}m`);
|
|
@@ -315,7 +436,7 @@ const saved = await himalaya.secure_storage.read("refresh-token"); // string | n
|
|
|
315
436
|
|
|
316
437
|
// Scan a QR code with the camera (iOS). null when the user cancels — and always on Android,
|
|
317
438
|
// which has no built-in QR decoder — so keep a way to type the code in.
|
|
318
|
-
const code = (await
|
|
439
|
+
const code = (await call<string | null>("camera", "scanQR", [], 120_000)) ?? window.prompt("Enter the code");
|
|
319
440
|
```
|
|
320
441
|
|
|
321
442
|
**Files arrive as handles.** Methods that return a photo, recording or file give you a
|
|
@@ -324,15 +445,15 @@ You cannot put it in an `<img>` directly. Hand it to another call that takes one
|
|
|
324
445
|
save it to the photo library:
|
|
325
446
|
|
|
326
447
|
```ts
|
|
327
|
-
const [photo] = await
|
|
328
|
-
if (photo) await
|
|
448
|
+
const [photo] = await call<any[]>("photos", "pick", [{ limit: 1 }], 120_000);
|
|
449
|
+
if (photo) await call("share", "share", [{ files: [photo] }], 120_000);
|
|
329
450
|
```
|
|
330
451
|
|
|
331
452
|
To get the bytes into the page, read them with the `files` capability (the app owner must enable
|
|
332
453
|
it too). `files.readBase64` returns the contents as base64, up to 8 MiB:
|
|
333
454
|
|
|
334
455
|
```ts
|
|
335
|
-
const [photo] = await
|
|
456
|
+
const [photo] = await call<any[]>("photos", "pick", [{ limit: 1 }], 120_000);
|
|
336
457
|
if (photo) {
|
|
337
458
|
const base64 = await himalaya.files.readBase64(photo);
|
|
338
459
|
const img = document.createElement("img");
|
|
@@ -70,6 +70,17 @@ logicBundle: {
|
|
|
70
70
|
}
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
Every worker built on `exposeCapabilitiesToPage` also answers the page's handshake,
|
|
74
|
+
`call("himalaya", "capabilities")`, with exactly the allowlist it was given
|
|
75
|
+
(`{ v: 1, capabilities: { health: ["availability", …] } }`); the page client's
|
|
76
|
+
`enabledCapabilities()` and `isEnabled()` (in both the pasted guide client and
|
|
77
|
+
`@wix/himalaya/webview-page`) read it, so a page hides what is off without calling a method or
|
|
78
|
+
waiting out a timeout. They share one question per page, re-asked every 0.5 s until answered or the latest caller's deadline (at most two messages a second, however many controls check), since a worker that is still
|
|
79
|
+
booting drops the first messages. `isEnabled()` never calls the method: with no list (an app built
|
|
80
|
+
before the handshake) it answers `false`, and a page that must support such a build calls
|
|
81
|
+
`probe()` — which does call the method — with a read-only one. `himalaya` is reserved: exposing a capability under that name
|
|
82
|
+
throws.
|
|
83
|
+
|
|
73
84
|
Do not build one worker that imports every SDK. Static bundle scanning would correctly conclude
|
|
74
85
|
that the release uses every capability, forcing unrelated permissions and native modules into the
|
|
75
86
|
binary. One app-specific worker imports exactly the app’s selected subset.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1322.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": "
|
|
74
|
+
"falconPackageHash": "bb7cc4c5d0d0841cd11950b890b11f51d812396f8f4a0649727b0501"
|
|
75
75
|
}
|