@wix/himalaya-cli 0.1573.0 → 0.1575.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/dev-server/src/app-config.d.ts +16 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +6 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/message-format.d.ts +59 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/telemetry/wix-bi/src/index.d.ts +15 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/telemetry/wix-bi/src/oneapp.d.ts +90 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +3 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/l10n.mjs +8 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +3 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-bi.mjs +165 -5
- package/dist/cli.mjs +5261 -2937
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/designing-himi-screens.md +7 -1
- package/guides/hhp.md +2 -2
- package/guides/himi-json-output.md +53 -2
- package/guides/himi-mcp.md +1 -1
- package/guides/himi-test.md +3 -2
- package/guides/iap-products.md +1 -1
- package/guides/importing-oneapp-translations.md +115 -0
- package/guides/index.json +6 -0
- package/guides/one-app-section-mappings.md +16 -4
- package/guides/one-app-to-himi-app.md +167 -10
- package/guides/push-cli-onboarding.md +10 -0
- package/guides/qa-builds.md +21 -1
- package/guides/templates.md +3 -2
- package/guides/testing-himi-apps.md +1 -1
- package/package.json +3 -3
- package/templates/beauty-salon/dev/index.ts +96 -133
- package/templates/beauty-salon/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/beauty-salon-owner/dev/index.ts +27 -6
- package/templates/beauty-salon-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/branded-lite/dev/index.ts +136 -142
- package/templates/branded-lite/l10n/en.json +570 -0
- package/templates/branded-lite/l10n/he.json +200 -0
- package/templates/branded-lite/tier5-src/_shared/business-chat-copy.ts +40 -0
- package/templates/branded-lite/tier5-src/_shared/business-chat-message-model.ts +1 -1
- package/templates/branded-lite/tier5-src/_shared/business-chat-model.ts +3 -2
- package/templates/branded-lite/tier5-src/_shared/business-chat-presenter.ts +26 -21
- package/templates/branded-lite/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/branded-lite/tier5-src/business-chat/index.ts +184 -63
- package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/community-club/dev/index.ts +22 -6
- package/templates/community-club-owner/dev/index.ts +27 -6
- package/templates/community-club-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/events-meetups/dev/index.ts +22 -6
- package/templates/events-meetups-owner/dev/index.ts +25 -6
- package/templates/events-meetups-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/gym-fitness/dev/index.ts +96 -133
- package/templates/gym-fitness/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/gym-fitness-owner/dev/index.ts +28 -6
- package/templates/gym-fitness-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/himi-chat/dev/index.ts +22 -6
- package/templates/nonprofit-cause/dev/index.ts +22 -6
- package/templates/nonprofit-cause-owner/dev/index.ts +26 -6
- package/templates/nonprofit-cause-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/owner-lite/dev/index.ts +28 -6
- package/templates/owner-lite/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/podcast-creator/dev/index.ts +22 -6
- package/templates/podcast-creator-owner/dev/index.ts +27 -6
- package/templates/podcast-creator-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/portfolio-creative/dev/index.ts +96 -133
- package/templates/portfolio-creative/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/portfolio-creative-owner/dev/index.ts +27 -6
- package/templates/portfolio-creative-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/restaurant/dev/index.ts +22 -6
- package/templates/restaurant-owner/dev/index.ts +28 -6
- package/templates/restaurant-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/retail-store/dev/index.ts +96 -133
- package/templates/retail-store/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/retail-store-owner/dev/index.ts +26 -6
- package/templates/retail-store-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/surface-showcase/dev/index.ts +22 -6
- package/templates/yoga-studio/dev/index.ts +22 -6
- package/templates/yoga-studio-owner/dev/index.ts +26 -6
- package/templates/yoga-studio-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
|
Binary file
|
|
@@ -331,7 +331,13 @@ build/validate/render cycles because the failure looks like a content bug rather
|
|
|
331
331
|
of the scrolling `VStack`. Put the action row in `stickyFooter` with its own
|
|
332
332
|
`padding` + `background: { token: "surfacePrimary" }` so it reads as a bar rather than as floating
|
|
333
333
|
content, and keep the scroll root's `padding.bottom` generous enough that the last row is not
|
|
334
|
-
hidden behind it.
|
|
334
|
+
hidden behind it. Buttons in `stickyHeader` and `stickyFooter` use the same action-binding
|
|
335
|
+
contract as the body: non-worker actions resolve `$service:` values in `params` and `args`
|
|
336
|
+
against live state when tapped. Native iOS, macOS and Android also resolve `$app:` values
|
|
337
|
+
through the app service scope. Missing/null bindings are dropped; `params` accepts scalars
|
|
338
|
+
only, while `args` preserves typed values. `tier5.*` actions keep their
|
|
339
|
+
params/args as authored (read the state in the reducer); their declared `nav` resolves
|
|
340
|
+
through the existing navigation contract.
|
|
335
341
|
|
|
336
342
|
---
|
|
337
343
|
|
package/guides/hhp.md
CHANGED
|
@@ -121,8 +121,8 @@ The portable compiler stores its generated catalog as a deterministic gzip/base6
|
|
|
121
121
|
envelope with a SHA-256 check. `himi hhp profile --json` returns the complete decoded
|
|
122
122
|
metadata; the installed component guides and support decision source remain readable.
|
|
123
123
|
`gen-v2.ts` builds the envelope from the canonical schemas and SDK exports, and refuses while any
|
|
124
|
-
new field or export lacks a decision in `v2-support-decisions.json`. The catalog itself is
|
|
125
|
-
|
|
124
|
+
new field or export lacks a decision in `v2-support-decisions.json`. The catalog itself is gitignored
|
|
125
|
+
and generated before use, so a PR commits the decisions file and there is no catalog to commit.
|
|
126
126
|
|
|
127
127
|
## CSS
|
|
128
128
|
|
|
@@ -6,7 +6,7 @@ repurposed when human wording changes. New codes may be added; consumers must
|
|
|
6
6
|
handle an unknown code as a failure, without parsing prose.
|
|
7
7
|
|
|
8
8
|
**Rollout:** this contract is enforced for **`himi push`**, including `--only`,
|
|
9
|
-
first, for **`himi store iap connect`**, for **`himi site member-app`**, for **`himi fidelity`**,
|
|
9
|
+
first, for **`himi store iap connect`**, for **`himi site member-app`**, for **`himi fidelity`**, for the **`himi base44`** entity and function verbs, and for **`himi l10n import`**. Other subcommands still have legacy failures without codes and are a
|
|
10
10
|
follow-up migration. This is an additive change: existing `error`, `errors`,
|
|
11
11
|
`message`, `hint`, status, body, and gate-specific fields stay as they were.
|
|
12
12
|
Some legacy envelopes have no singular `error` or `hint`; consumers must not
|
|
@@ -105,6 +105,18 @@ then carries a `ring_pinned` entry in `warnings` (also printed to stderr) and
|
|
|
105
105
|
that moves the ring to the new release. When the push passed `--control-url`, `promote` repeats it. It stays `ok: true`. When the rings cannot be read, push
|
|
106
106
|
prints neither.
|
|
107
107
|
|
|
108
|
+
## `himi notify` owner-login codes
|
|
109
|
+
|
|
110
|
+
`himi notify setup|status` and `himi notify send --provider ping` carry `code` on these refusals
|
|
111
|
+
only; their other refusals keep the legacy `error`-only envelope for now. Login hints name the
|
|
112
|
+
target the command read, e.g. `himi login --browser --target wix`.
|
|
113
|
+
|
|
114
|
+
| Code | Meaning |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `control_token_expired` | The stored control token is past its `exp`. Decided locally before any network call; run `himi login`. |
|
|
117
|
+
| `owner_login_required` | No usable owner login: the control token is missing or has no subject, or the plane answered 401/403 to the owner-apps read (`GET /v1/owner/apps`). Run `himi login`. Other failures of that read stay `app_ownership_unknown`. |
|
|
118
|
+
| `flag_not_supported_with_ping` | A local-sender flag was passed with `--provider ping`; `flag` names it. `--badge` is one: Ping has no badge field, and for a Branded app Ping sets the iOS badge itself from the member's unseen Ping feed items. |
|
|
119
|
+
|
|
108
120
|
## `himi cms seed` codes
|
|
109
121
|
|
|
110
122
|
| Code | Meaning |
|
|
@@ -114,6 +126,34 @@ prints neither.
|
|
|
114
126
|
|
|
115
127
|
This is not a whole-command migration: the command's other refusals still have no code.
|
|
116
128
|
|
|
129
|
+
## `himi l10n import` codes
|
|
130
|
+
|
|
131
|
+
Every refusal from `himi l10n import` carries one of these. Usage-grammar refusals exit 2;
|
|
132
|
+
operational refusals exit 1. A successful import (exit 0) reports `unsupported`,
|
|
133
|
+
`missingInSource`, `converted`, `duplicateSources`, `keyConflicts`, `staleKeys`, `invalidKeys` and `warnings` inside
|
|
134
|
+
its `ok: true` envelope — those are findings, not failures.
|
|
135
|
+
|
|
136
|
+
| Code | Meaning |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `invalid_usage` | The subcommand, `<dir>` positional, app selector (`--app`/`--content`) or `--locales`/`--source` value is missing or malformed (a bare `--locales` is refused, not read as "all"). Nothing was read or written. Exit 2. |
|
|
139
|
+
| `unsupported_format` | `--format` is missing or names a format other than `oneapp`; `formats` lists what exists. Exit 2. |
|
|
140
|
+
| `app_not_found` | `--app <slug>` is not a slug, or `apps/<slug>/config.ts` does not exist under the current directory. Exit 2. |
|
|
141
|
+
| `messages_dir_not_found` | `<dir>` does not exist or is not a directory. Exit 1. |
|
|
142
|
+
| `no_messages_found` | `<dir>` holds no `messages_<locale>.json` file. Exit 1. |
|
|
143
|
+
| `source_locale_missing` | There is no `messages_<source>.json` — the source locale supplies every row's `source` string, so nothing can be converted without it. `found` lists the tags that do exist. Exit 1. |
|
|
144
|
+
| `locale_file_missing` | A `--locales` tag has no `messages_<tag>.json`; `missing` and `found` name them. Exit 1. |
|
|
145
|
+
| `messages_not_utf8` | A messages file is not valid UTF-8, has a UTF-16 byte-order mark, or contains NUL bytes (a UTF-16 export, even an ASCII-only one, is the usual cause). A UTF-8 BOM is tolerated and stripped. Exit 1. |
|
|
146
|
+
| `messages_unreadable` | The messages directory cannot be listed, or a messages file cannot be read (a directory or a FIFO in its place is refused up front, so the import never blocks on one), is not JSON, is not an object, or has non-string values (`keys` names up to five offenders). Exit 1. |
|
|
147
|
+
| `catalog_unreadable` | An existing `apps/<app>/l10n/<tag>.json` cannot be parsed, or holds a message that is not an object. The import refuses rather than overwrite translations it could not read; the file is left untouched. Exit 1. |
|
|
148
|
+
| `unsafe_path` | A `messages_<locale>.json` inside the messages directory, the app's `l10n` directory, or one of its catalogs is a symbolic link. The import never follows one: it would read a file the translation directory points at into the generated catalog, or write outside the app. Nothing was written. (The directory named on the command line may itself be a link — that is the caller's choice.) Exit 1. |
|
|
149
|
+
| `catalog_write_failed` | Writing a catalog failed, or the app's `l10n` path cannot be inspected or created (for example `l10n` is a regular file); `written` lists what landed before the failure. Exit 1. |
|
|
150
|
+
| `import_failed` | The conversion itself threw on input the earlier checks accepted. Nothing was written. Exit 1. |
|
|
151
|
+
| `invalid_flag_value` | The CLI's global flag grammar refused a flag before the command ran (for example `--overwrite=false`: a switch takes no value). `problems` lists each one. Exit 2. |
|
|
152
|
+
|
|
153
|
+
This is not a whole-command-group migration: only `l10n import` exists today, and all of
|
|
154
|
+
its refusals are coded — including the global flag-grammar refusal, which carries a `code`
|
|
155
|
+
for `l10n` only.
|
|
156
|
+
|
|
117
157
|
## `himi store iap status` codes
|
|
118
158
|
|
|
119
159
|
Status adds these stable codes to incomplete JSON results. Existing result fields and exit
|
|
@@ -143,7 +183,7 @@ existing `problems` list.
|
|
|
143
183
|
| Code | Meaning |
|
|
144
184
|
|---|---|
|
|
145
185
|
| `screenshots_incomplete` | At least one selected item has no screenshot. Each one in `items` carries a `skipped` reason: no purchase screen, no Apple price yet, an existing screenshot kept without `--force`, a screen that did not show the Apple price, or a failed read of the item. The screenshots that were made are saved and named in the manifest. Exit 1. |
|
|
146
|
-
| `browser_unavailable` | The headless Chromium the screenshots are taken in is not installed. Run
|
|
186
|
+
| `browser_unavailable` | The headless Chromium the screenshots are taken in is not installed. Run the install command the error names once (it uses the CLI's own Playwright, so it installs the Chromium revision the CLI launches). Nothing was rendered or written. Exit 2. |
|
|
147
187
|
|
|
148
188
|
An invalid manifest fails with `manifest_invalid`, like the other `store iap` commands.
|
|
149
189
|
|
|
@@ -217,6 +257,17 @@ whole body gzip-encoded because it is over the plain 8 MB cap:
|
|
|
217
257
|
|---|---|
|
|
218
258
|
| `compressed_publish_unsupported` | The publish body went out gzipped and the publishing service did not accept it compressed. It either read the bytes as malformed JSON, or measured the decompressed body against the 8 MB uncompressed limit (HTTP 413). 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. |
|
|
219
259
|
|
|
260
|
+
## `himi template screens --upsert` codes
|
|
261
|
+
|
|
262
|
+
`--upsert` writes many generated screens at once. Its refusals carry a code; nothing is written
|
|
263
|
+
on any of them (a failed batch restores every file). Other `template screens` paths stay legacy.
|
|
264
|
+
|
|
265
|
+
| Code | Meaning |
|
|
266
|
+
|---|---|
|
|
267
|
+
| `invalid_usage` | `--upsert` was given without `--from <file>`. Exit 2. |
|
|
268
|
+
| `invalid_input` | The `--from` file cannot be read or is not JSON. Exit 2. |
|
|
269
|
+
| `upsert_refused` | The JSON is not `{ "<screenId>": <ScreenDescriptor> }`, an id or `screenId` does not match, the result would not parse as plain SCREENS entries, or a target file is a symlink. `error` names which. Exit 2. |
|
|
270
|
+
|
|
220
271
|
## `himi site member-app` codes
|
|
221
272
|
|
|
222
273
|
`himi site member-app set|clear|show <site>` prints one envelope. A refusal from the publishing service
|
package/guides/himi-mcp.md
CHANGED
|
@@ -112,7 +112,7 @@ runs a session with it.
|
|
|
112
112
|
| `himi_build` | Compile the app's worker bundles. |
|
|
113
113
|
| `himi_validate` | Lint the app without publishing anything. |
|
|
114
114
|
| `himi_test` | The behavioral crawl — every action each screen declares, against the app's mocked network. Never reaches live data. |
|
|
115
|
-
| `himi_render` | Render one screen and return the PNG to the agent (needs Playwright's Chromium:
|
|
115
|
+
| `himi_render` | Render one screen and return the PNG to the agent (needs Playwright's Chromium: run the install command `himi render --png` prints). |
|
|
116
116
|
| `himi_progress` | Read or add to the build journal the owner follows. |
|
|
117
117
|
| `himi_preview_start` / `_status` / `_stop` | The live preview — see below. |
|
|
118
118
|
| `himi_whoami` | Which account the stored sign-in belongs to. |
|
package/guides/himi-test.md
CHANGED
|
@@ -492,8 +492,9 @@ behavior. This instruction does not add an automatic suppression or retry gate t
|
|
|
492
492
|
|
|
493
493
|
**Screenshots** are on by default when a headless browser is installed: one PNG per screen
|
|
494
494
|
to `.himi/shots/`, showing the settled state at phone width. Absent browser ⇒ the report
|
|
495
|
-
carries `shots.unavailable` and the ledger names the one-time
|
|
496
|
-
|
|
495
|
+
carries `shots.unavailable` and the ledger names the one-time install command for the
|
|
496
|
+
CLI's own Playwright (`node '<CLI>/node_modules/playwright/cli.js' install chromium`; a bare
|
|
497
|
+
`npx playwright install chromium` can install another revision). Fully hermetic; `--no-shots` opts out.
|
|
497
498
|
|
|
498
499
|
### Exit codes
|
|
499
500
|
|
package/guides/iap-products.md
CHANGED
|
@@ -411,7 +411,7 @@ product's review screenshot from the app's own purchase screen, so nobody has to
|
|
|
411
411
|
|
|
412
412
|
**One-time setup.** The screenshots are taken in a headless Chromium on your machine, so no phone,
|
|
413
413
|
simulator or Xcode is needed. The Playwright library comes with himi; the browser is a separate
|
|
414
|
-
download (~170MB) that you run once
|
|
414
|
+
download (~170MB) that you run once, with the install command the CLI prints (`node '<CLI>/node_modules/playwright/cli.js' install chromium`). Without it the command stops
|
|
415
415
|
before rendering anything and says so (`browser_unavailable`). A `--dry-run` doesn't need it.
|
|
416
416
|
|
|
417
417
|
1. **It renders the screen.** For each item it opens that Wix item's detail screen: `himi_product_<id>`,
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Importing OneApp translations
|
|
2
|
+
|
|
3
|
+
An app moving to Himi from the OneApp engine already has its copy translated: one flat
|
|
4
|
+
JSON file per locale, `messages_<locale>.json`, mapping an engine key to an ICU
|
|
5
|
+
MessageFormat string (`{ "DOWNLOAD_BTN": "Download", … }`). Himi's per-app catalog
|
|
6
|
+
(`l10n/<tag>.json` in the app's content directory) is a different shape, and re-keying
|
|
7
|
+
thousands of strings by hand is error-prone. `himi l10n import` does the conversion:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
himi l10n import --format oneapp ./strings --app my-app --locales en,he --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
reads `./strings/messages_en.json` + `./strings/messages_he.json` and writes the app's
|
|
14
|
+
`l10n/en.json` + `l10n/he.json` (`--app <slug>` names an app in a checkout; off-repo,
|
|
15
|
+
point `--content` at the app's directory). After the import, a descriptor (or a worker,
|
|
16
|
+
via `t()`) references each message by its OneApp key: `$t:DOWNLOAD_BTN`.
|
|
17
|
+
|
|
18
|
+
## What it does
|
|
19
|
+
|
|
20
|
+
- **One catalog per locale**, in the existing shape: rows keyed by the extractor's
|
|
21
|
+
content hash of the **source-locale** string, each carrying `source` (the `--source`
|
|
22
|
+
locale's text, default `en`), `key` (the OneApp key — what `$t:<KEY>` resolves) and
|
|
23
|
+
`translation` (that locale's text; empty in the source locale's own catalog).
|
|
24
|
+
- **Default locales: every `messages_<tag>.json` found** in the directory. `--locales`
|
|
25
|
+
narrows the list; a requested tag with no file is a refusal, not a silent skip.
|
|
26
|
+
- **Placeholders**: OneApp's legacy `{{name}}` spelling (spaces and hyphens allowed:
|
|
27
|
+
`{{ name }}`, `{{user-name}}`) becomes ICU `{name}` and is listed under `converted`. A
|
|
28
|
+
double brace that is not a plain name (`{{first name}}`) is kept verbatim and listed under
|
|
29
|
+
`unsupported`, because the runtime would paint it literally; so is a `{{name}}` inside an
|
|
30
|
+
ICU quoted span (`'{{name}}'`), whose braces ICU makes literal. The rewrite walks the
|
|
31
|
+
pattern with the runtime's own ICU tokenizer and edits the original text in place, so branch
|
|
32
|
+
order and spacing are preserved (the row id is a hash of that text) and a genuine ICU double brace (`one {{count}} other {{count} files}` — branch brace plus
|
|
33
|
+
argument brace) is never corrupted.
|
|
34
|
+
- **ICU subset**: each message is parsed with the subset the runtime formats — simple
|
|
35
|
+
arguments, `plural` with `=N`/`#` (the Hebrew dual included) and `select`. Anything
|
|
36
|
+
outside it — `selectordinal`, number/date skeletons, plural `offset:`, a plural nested
|
|
37
|
+
in another plural, a quoted `'#'` inside a plural branch, branch text the tokenizer cannot
|
|
38
|
+
parse (a stray comma between branches, a quoted brace), a branch selector the runtime can
|
|
39
|
+
never select (`one {a};other {b}` — the `;other` is part of the key — or a non-canonical
|
|
40
|
+
`=01`/`=1.0`, which never equals the number), a plural or select
|
|
41
|
+
with no `other` branch, HTML tags — is kept **verbatim**
|
|
42
|
+
(the runtime degrades to visible text by contract) and listed under `unsupported` with key
|
|
43
|
+
and locale.
|
|
44
|
+
- **Merging**: an existing catalog's manual translations and keys survive a re-import
|
|
45
|
+
unless `--overwrite`; provenance fields and rows the import does not touch survive the
|
|
46
|
+
import. An existing catalog that cannot be parsed is refused, never clobbered.
|
|
47
|
+
- **Changed source text**: row ids are content hashes, so editing a source string moves its
|
|
48
|
+
key to a new row. The old row keeps its text (for the source-string swap) but loses the
|
|
49
|
+
key, so exactly one row answers each `$t:` key; the dropped keys are listed under
|
|
50
|
+
`staleKeys`. This happens with or without `--overwrite`, and in a target locale whose file
|
|
51
|
+
has no entry for the key yet. When only the row id moved (the text did not change), the
|
|
52
|
+
manual translation moves with the key.
|
|
53
|
+
- **The source-string extractor** keeps a prior row only while a descriptor still contains
|
|
54
|
+
its text or references its key as `$t:`. A key used only from a worker through `t()`
|
|
55
|
+
therefore needs the import re-run after an extract.
|
|
56
|
+
- **Keys a descriptor cannot reference**: a `$t:` binding accepts letters, digits, `_`, `.`
|
|
57
|
+
and `-`. A OneApp key outside that (`settings:title`, `Home Header`) is still written —
|
|
58
|
+
a worker's `t()` takes any string — but listed under `invalidKeys`, since no `$t:<key>`
|
|
59
|
+
can reach it.
|
|
60
|
+
- **Native rows**: when the app lives inside the Himalaya source checkout, its English
|
|
61
|
+
catalog also receives the native login-gate rows (the same rows the extractor adds), so
|
|
62
|
+
the derived-output check stays green; other locales hold translations only.
|
|
63
|
+
- **Symbolic links are never followed**: a `messages_<locale>.json` that is a link, a linked
|
|
64
|
+
`l10n` directory, or a linked catalog is refused (`unsafe_path`) before anything is read
|
|
65
|
+
or written, so an untrusted translation package cannot pull another local file into a
|
|
66
|
+
catalog or redirect a write outside the app. Catalogs are written through a temporary
|
|
67
|
+
file and a rename, never in place.
|
|
68
|
+
- **Deterministic output**: ids sorted, no timestamp — re-running over the same inputs
|
|
69
|
+
produces no diff.
|
|
70
|
+
- **Edge cases reported, never silent**: a key present in a target locale but missing in
|
|
71
|
+
the source is skipped and listed under `missingInSource`; OneApp keys sharing one source
|
|
72
|
+
string all survive, each on its own row id, and the group is listed under
|
|
73
|
+
`duplicateSources` (no key keeps the plain id, so a key added later cannot take an id
|
|
74
|
+
from one already imported).
|
|
75
|
+
|
|
76
|
+
## The report
|
|
77
|
+
|
|
78
|
+
`--json` prints one envelope:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"ok": true,
|
|
83
|
+
"written": [{ "tag": "he", "path": "my-app/l10n/he.json", "count": 412 }],
|
|
84
|
+
"unsupported": [{ "key": "UPDATED_AT", "locale": "he", "construct": "date argument \"when\" (short)" }],
|
|
85
|
+
"missingInSource": [{ "key": "ONLY_IN_HE", "locales": ["he"] }]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
plus `converted`, `duplicateSources`, `keyConflicts`, `staleKeys`, `invalidKeys` and
|
|
90
|
+
`warnings` when non-empty.
|
|
91
|
+
Failures carry a stable `code` — see
|
|
92
|
+
[the JSON failure contract](himi-json-output.md#himi-l10n-import-codes).
|
|
93
|
+
|
|
94
|
+
## Declare the locales
|
|
95
|
+
|
|
96
|
+
A catalog only bakes and serves for a locale the app declares, and only `en`, `he` and
|
|
97
|
+
`es` can be declared. The import checks each imported tag against the app's `locale`
|
|
98
|
+
config and warns with the line to add to its `locale` block:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
translations: ["es", "he"]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
A tag outside those three (`fr`, or a region tag like `es-MX`) still gets its catalog
|
|
105
|
+
written, but is warned about separately and is never offered as config — declaring it would
|
|
106
|
+
make the config fail.
|
|
107
|
+
|
|
108
|
+
`--source` should be the app's default locale: the runtime falls back to a row's source text
|
|
109
|
+
only for the default locale, so importing another locale as the source warns.
|
|
110
|
+
|
|
111
|
+
## Scope
|
|
112
|
+
|
|
113
|
+
The importer is generic for any OneApp-format catalog (flat key → ICU string). Fetching
|
|
114
|
+
messages from a translation service, exporting back, and other source formats are out of
|
|
115
|
+
scope — adapters can be added behind `--format` later.
|
package/guides/index.json
CHANGED
|
@@ -74,6 +74,12 @@
|
|
|
74
74
|
"category": "CLI & Loop",
|
|
75
75
|
"file": "himi-json-output.md"
|
|
76
76
|
},
|
|
77
|
+
{
|
|
78
|
+
"id": "importing-oneapp-translations",
|
|
79
|
+
"title": "Importing OneApp translations",
|
|
80
|
+
"category": "CLI & Loop",
|
|
81
|
+
"file": "importing-oneapp-translations.md"
|
|
82
|
+
},
|
|
77
83
|
{
|
|
78
84
|
"id": "himi-mcp",
|
|
79
85
|
"title": "himi in your coding agent (MCP)",
|
|
@@ -110,8 +110,8 @@ The **Himalaya implementation** cell is blank for every unassigned row. Notes on
|
|
|
110
110
|
|
|
111
111
|
| Source sectionDefinitionId | Source viewer component | Himalaya implementation | Placement / reuse | Class | Settings, actions and gaps |
|
|
112
112
|
| --- | --- | --- | --- | --- | --- |
|
|
113
|
-
| `referrals_refer_section` | `referrals.components.ReferWidget` | | | Empty | No consumer referral-code/link sharing and referral-status feature was found. Do not map to Loyalty or generic sharing without a user decision. |
|
|
114
|
-
| `referrals_description_section` | `referrals.components.DescriptionWidget` | | | Empty | No referral-program description/data implementation was found. Text primitives alone do not resolve the business-bound referral content. |
|
|
113
|
+
| `referrals_refer_section` | `referrals.components.ReferWidget` | | | Empty | No consumer referral-code/link sharing and referral-status feature was found. Do not map to Loyalty or generic sharing without a user decision. **Probe first:** `GET /_api/referral-programs/v1/program` answered the One App visitor identity in a 2026-11 migration, and the program copy was built live in an app-local section. The member's own referral link/code was not generated; resolve it before you mark the Refer action supported. |
|
|
114
|
+
| `referrals_description_section` | `referrals.components.DescriptionWidget` | | | Empty | No referral-program description/data implementation was found. Text primitives alone do not resolve the business-bound referral content. **Probe first:** `GET /_api/referral-programs/v1/program` answered the One App visitor identity in a 2026-11 migration, and the program copy was built live in an app-local section. The member's own referral link/code was not generated; resolve it before you mark the Refer action supported. |
|
|
115
115
|
|
|
116
116
|
### 9. member-list-section-definitions.json
|
|
117
117
|
|
|
@@ -330,8 +330,8 @@ These are the exact definitions whose target cells above remain empty. “Not fo
|
|
|
330
330
|
| `events-section-definitions.json` | `events_guests_section` | The Events detail has only a best-effort attendee summary/avatar strip using an owner-scoped guest query. It is not a full consumer guest-list section; leave the mapping unassigned. |
|
|
331
331
|
| `groups-section-definitions.json` | `single_group_feed_section` | A feed exists, but it selects a relevant/home group internally and does not accept the configured fixed-group selector. No verified single-group feed adapter exists; keep this target empty until a policy/implementation is chosen. |
|
|
332
332
|
| `loyalty-section-definitions.json` | `loyalty_status_section` | The existing Loyalty worker lists the program and rewards but does not load this member's points balance/tier/status. A rewards catalog is not a loyalty-status widget. |
|
|
333
|
-
| `referrals-section-definitions.json` | `referrals_refer_section` | No consumer referral-code/link sharing and referral-status feature was found. Do not map to Loyalty or generic sharing without a user decision. |
|
|
334
|
-
| `referrals-section-definitions.json` | `referrals_description_section` | No referral-program description/data implementation was found. Text primitives alone do not resolve the business-bound referral content. |
|
|
333
|
+
| `referrals-section-definitions.json` | `referrals_refer_section` | No consumer referral-code/link sharing and referral-status feature was found. Do not map to Loyalty or generic sharing without a user decision. A visitor-readable program read exists; see the row above. |
|
|
334
|
+
| `referrals-section-definitions.json` | `referrals_description_section` | No referral-program description/data implementation was found. Text primitives alone do not resolve the business-bound referral content. A visitor-readable program read exists; see the row above. |
|
|
335
335
|
| `pages-section-definitions.json` | `pages_section` | No matching Wix Pages content fetch/render adapter was found. Generic CMS or RichContent renderers do not identify the original page entity or its data contract. |
|
|
336
336
|
| `photoalbum-section-definitions.json` | `photoAlbums_list_section` | Existing Photo Albums code is an empty-state placeholder with no album API wired. Pro Gallery uses a different data source and is not a substitute; choose an implementation explicitly. |
|
|
337
337
|
| `photoalbum-section-definitions.json` | `photoAlbums_photos_list` | Existing Photo Albums code is an empty-state placeholder with no album API wired. Pro Gallery uses a different data source and is not a substitute; choose an implementation explicitly. |
|
|
@@ -377,3 +377,15 @@ These rows have reusable code, but their remaining requirements must not disappe
|
|
|
377
377
|
## GitHub implementation references
|
|
378
378
|
|
|
379
379
|
The linked sources are in private Wix repositories. The inventory and gap decisions above are usable as historical capability evidence without local filesystem references. Links identify implementation code, not production deployment or exact feature parity.
|
|
380
|
+
|
|
381
|
+
## Definitions outside the pinned inventory
|
|
382
|
+
|
|
383
|
+
Migrated apps contain section definitions that the pinned inventory above does not list. They are
|
|
384
|
+
outside its 77 definitions and have no verified mapping. Resolve each one with the workflow's probe
|
|
385
|
+
procedure (`himi docs one-app-to-himi-app`, "Probe an unmapped section") and record the result.
|
|
386
|
+
|
|
387
|
+
| Source sectionDefinitionId | Seen in | Status and leads |
|
|
388
|
+
| --- | --- | --- |
|
|
389
|
+
| `forum_post_list_section` | A 2026-11 Branded migration | Unmapped. A single-section page can point at the Forum template screen; an inline post list needs an app-local section over the Forum posts read. |
|
|
390
|
+
| `shared_gallery_list_section` | A 2026-11 Branded migration | Unmapped and left unresolved in that migration. Do not substitute Pro Gallery or Photo Albums without verifying the source data contract. |
|
|
391
|
+
| `woa_member_restaurants_reservation` | A 2026-11 Branded migration | Unmapped. That migration adapted it to a "Reserve a Table" button that opens the template reservation screen; record it as an adaptation, not as the source section. |
|
|
@@ -259,6 +259,16 @@ Apply these interpretation rules:
|
|
|
259
259
|
a feature to account for; they do not alone prove visibility or access for every
|
|
260
260
|
visitor or member. Resolve those rules separately. This check is specific to this
|
|
261
261
|
migration workflow; it does not change the behavior of `himi validate`.
|
|
262
|
+
The check maps a source screen to its target **only** through that screen's `route`
|
|
263
|
+
row (`source: "/screens/<id>"`) in `ONE-APP-COVERAGE.json`, through `target.screenId`;
|
|
264
|
+
a row of any other kind does not map a screen, and an unmapped source screen is checked
|
|
265
|
+
under its own id. A control counts only as an entry of `actions`; a matching `topBar.items`
|
|
266
|
+
entry (a leading profile avatar, for example) does not, because iOS draws no toolbar items
|
|
267
|
+
yet and web/Android draw only some trailing ones. A `branded-lite` screen
|
|
268
|
+
that declares its own `topBar` replaces `topBarDefault`, so the shared controls are
|
|
269
|
+
missing on it: `himi_account`, `himi_shop`, `himi_services`, `himi_agenda`, `himi_events`,
|
|
270
|
+
`himi_blog` and the CMS collection screens do. Delete that `topBar` so the screen inherits
|
|
271
|
+
the default, or add every source control to its `actions`.
|
|
262
272
|
- Apply the collected app theme before the first build: run
|
|
263
273
|
`himi one-app validate-design --evidence-dir .himi/one-app --content . --fix`,
|
|
264
274
|
resolve any remaining mismatches/unresolved values, then rebuild. The source is
|
|
@@ -486,7 +496,7 @@ reference's top-tabs row in R04 and its top-tabs acceptance case:
|
|
|
486
496
|
- `missing_icon`: choose an icon that matches the page content and record it as a
|
|
487
497
|
target adaptation. `missing_label`: use a label from the page content and record it.
|
|
488
498
|
- `tab_overflow`: more than five tabs need the explicit overflow arrangement of
|
|
489
|
-
viewer rule R05. Do not drop tabs to fit the bar.
|
|
499
|
+
viewer rule R05. Do not drop tabs to fit the bar. See [Large top-tab apps](#large-top-tab-apps).
|
|
490
500
|
- `free_instance_converted`: the source editor offers bottom tabs to Branded apps
|
|
491
501
|
only. Record the converted navigation as a target adaptation in the report.
|
|
492
502
|
- `nested_top_tabs`: a bottom entry holds a `TOP_TABS` screen. It is out of this
|
|
@@ -495,12 +505,53 @@ reference's top-tabs row in R04 and its top-tabs acceptance case:
|
|
|
495
505
|
With `--top-tabs keep`, the plan has `reason: "policy-keep"` and the viewer
|
|
496
506
|
reference's top-tabs rules apply.
|
|
497
507
|
|
|
508
|
+
#### Large top-tab apps
|
|
509
|
+
|
|
510
|
+
A source with many top-tab pages (33 in one migration) converts to this arrangement:
|
|
511
|
+
|
|
512
|
+
- The first four pages in source order are tabs; a fifth **More** tab lists every other
|
|
513
|
+
visible page in source order, and each row pushes its page. Hidden pages get no row.
|
|
514
|
+
- `appEditor.outline.*` icons with no Himi name (lightning, rocket, light bulb, megaphone,
|
|
515
|
+
brochure, content card) need a fallback icon from `himi icons`, such as `star`,
|
|
516
|
+
`bell` or `doc`. Record each fallback as an adaptation.
|
|
517
|
+
- A source `goToScreen` to a page that is now a **tab** must select that tab. A descriptor
|
|
518
|
+
`himi.open` pushes a second copy of the page instead, so give static pages a small nav
|
|
519
|
+
worker whose action calls `navigate(s, { tab: "<tabId>" })`. A `goToScreen` to a page
|
|
520
|
+
in More can use `himi.open`.
|
|
521
|
+
- A `goToScreen` whose layout item does not exist does nothing in the source. Keep it a
|
|
522
|
+
no-op (a worker action that returns the state unchanged) and list it as an unresolved
|
|
523
|
+
route.
|
|
524
|
+
- A page whose only section is one vertical (Pricing, Groups, Forum, Events, Programs,
|
|
525
|
+
Loyalty, Galleries, Shop, Services, Forms) can point at that vertical's template screen
|
|
526
|
+
instead of a copy. Record its route row against the template screen id.
|
|
527
|
+
- Only the first tab keeps the source header; the others take the compact default bar.
|
|
528
|
+
|
|
498
529
|
The current [viewer reference](https://apps.wix.com/_api/himi-serve/docs/one-app-viewer.md)
|
|
499
530
|
supersedes simplified historical ordering, routing and layout examples. Pinned
|
|
500
531
|
mapping rows are research leads: inspect the current CLI's component, SDK and
|
|
501
532
|
template contracts before using them. A previously empty row does not prove the
|
|
502
533
|
feature is impossible today.
|
|
503
534
|
|
|
535
|
+
### Probe an unmapped section
|
|
536
|
+
|
|
537
|
+
A section whose catalogue row is "Empty", or whose definition is not in the catalogue at
|
|
538
|
+
all, is not unresolved until you probe it:
|
|
539
|
+
|
|
540
|
+
1. Find the section's data contract: its `sectionDefinitionId`, the source viewer component
|
|
541
|
+
in the catalogue, and the Wix REST API of that domain (Wix docs or `@himalaya/wix-*`).
|
|
542
|
+
2. Choose a read-only call. Confirm in the service contract that it does not write on read
|
|
543
|
+
(see the announcement getter above).
|
|
544
|
+
3. Send it through the target transport with the app's One App visitor identity
|
|
545
|
+
(`himi render --live`, or the hosted preview), not with an owner credential.
|
|
546
|
+
4. A 2xx with the source content means you can build the section app-locally. Record the
|
|
547
|
+
call, the response shape and the identity in the migration report, and mark the row
|
|
548
|
+
`supported` or `adapted`. A 401/403/428 for the visitor is an access result: keep the
|
|
549
|
+
row `unresolved` and record the status.
|
|
550
|
+
|
|
551
|
+
For example, `GET /_api/referral-programs/v1/program` answers the visitor identity, so
|
|
552
|
+
the referral program copy can be built live. The member's own referral link is a
|
|
553
|
+
separate, member-scoped contract.
|
|
554
|
+
|
|
504
555
|
### Standalone launch tab
|
|
505
556
|
|
|
506
557
|
When the reconstructed navigation has a tab bar, preserve the app's actual tab
|
|
@@ -708,6 +759,22 @@ For a marked One App migration, `himi validate --strict` fails when the icon is
|
|
|
708
759
|
missing, still byte-identical to a bundled template, or its pixel checks cannot run. A passing mechanical check
|
|
709
760
|
cannot establish ownership of arbitrary custom artwork; compare the real mark too.
|
|
710
761
|
|
|
762
|
+
Expect a large ledger: a 33-page app had 796 rows, 396 of them top-bar controls. Map it
|
|
763
|
+
in batches with the executable ledger mapping recipe above, not by hand. Each row's
|
|
764
|
+
`source` is a JSON pointer into `raw-structure.json`, and the shape says what to set:
|
|
765
|
+
|
|
766
|
+
| `source` shape | `target` |
|
|
767
|
+
| --- | --- |
|
|
768
|
+
| `/screens/<id>` (`route`) | `{ "screenId": "<target>" }`. `validate-topbar` maps screens only through these rows. |
|
|
769
|
+
| `/screens/<id>/layout/items/<i>` | the target screen of that layout item (a top-tab page). |
|
|
770
|
+
| `…/layout/items/<i>/elements/<j>` | that page's screen; an `interaction` row also names the `control` (the section's element id). |
|
|
771
|
+
| `/screens/<id>/topBar/…` | the screen, and the `control` id of the matching top-bar action (`cart`, `notifications`, `chat`, `profile`). |
|
|
772
|
+
| `/sections/<id>` | the screen of the page that holds that section. |
|
|
773
|
+
| `/businessProfile…` | the business-profile screen. |
|
|
774
|
+
|
|
775
|
+
Decide per row, and let the recipe list every row it could not map or decide. Never
|
|
776
|
+
invent a status for an undecided row. Run `coverage check` after each run.
|
|
777
|
+
|
|
711
778
|
Map each row to a target screen and, for interactions or top-bar controls, a
|
|
712
779
|
target control. A `design` row is app-wide, so it needs no screen or control: it is
|
|
713
780
|
satisfied by the design check instead. Set its `status` to `supported`, `adapted`, `conditional`, or
|
|
@@ -843,6 +910,31 @@ not share mutable filters accidentally. Keep static authored content in the app,
|
|
|
843
910
|
and products, services, availability, posts and member records live on the same site.
|
|
844
911
|
Refresh data after operations without reconnecting layout to the One App editor.
|
|
845
912
|
|
|
913
|
+
### Write generated screens as static SCREENS entries
|
|
914
|
+
|
|
915
|
+
`himi template trim`, `himi template screens --show/--write` and
|
|
916
|
+
`himi one-app validate-topbar` read `dev/index.ts` statically. They see only plain
|
|
917
|
+
`"<screenId>": { "screenId": "<screenId>", … },` entries inside the `SCREENS` literal.
|
|
918
|
+
A screen merged in at runtime (`Object.assign`, an imported module), a spread, or a
|
|
919
|
+
function call in the literal makes them fail with "expected a `"<screenId>": {` entry",
|
|
920
|
+
"homeScreenId … is not a screen in the SCREENS map" or "no target screen mapping to an
|
|
921
|
+
authored descriptor". Blank lines and whole-line `//` comments between entries are
|
|
922
|
+
accepted.
|
|
923
|
+
|
|
924
|
+
So generate descriptors as data and write them with the CLI:
|
|
925
|
+
|
|
926
|
+
```sh
|
|
927
|
+
himi template screens --upsert --from .himi/one-app/gen/screens.json
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
The file is one JSON object, `{ "<screenId>": <ScreenDescriptor>, … }`. Each existing
|
|
931
|
+
id is replaced in place; each new id is added and registered in
|
|
932
|
+
`navigation.linkableScreens`. One invalid entry refuses the batch and restores every
|
|
933
|
+
file. A builder call such as `detailedHeader(...)` written inline in `dev/index.ts`
|
|
934
|
+
cannot be inspected: call the builder in your generator and serialize the value it
|
|
935
|
+
returns. Run the generator inside the app (after `npm install`), so
|
|
936
|
+
`@wix/himalaya/screens` resolves to the app's own dependency.
|
|
937
|
+
|
|
846
938
|
### Screen-content contract
|
|
847
939
|
|
|
848
940
|
Use the current [screen design guide](https://apps.wix.com/_api/himi-serve/docs/designing-himi-screens.md) and the app's
|
|
@@ -942,7 +1034,12 @@ a new destination to read the site's current data; never invent or retain a temp
|
|
|
942
1034
|
Use `siteUrl` from the successful collection's manifest for the auth binding. It is
|
|
943
1035
|
the first usable value from `website.publicUrl`, then legacy `website.url`: an HTTPS
|
|
944
1036
|
origin and optional base path, with no credentials, custom port, query or fragment.
|
|
945
|
-
`site client ensure` does not return it.
|
|
1037
|
+
`site client ensure` does not return it.
|
|
1038
|
+
With the One App binding, `himi push` bakes the current product and service detail
|
|
1039
|
+
screens through the site's One App visitor instance. A `dev/index.ts` scaffolded by an
|
|
1040
|
+
older CLI reads only `clientId` for this, so it bakes no detail screens; the preview
|
|
1041
|
+
still resolves them live.
|
|
1042
|
+
Keep visitor/member gates from the reconstruction plan. Verify that the
|
|
946
1043
|
built app reads the intended site (and, with a client, uses the exact registered
|
|
947
1044
|
redirect). The MetaSite and a public client ID are app configuration; the collection
|
|
948
1045
|
credential is not.
|
|
@@ -987,8 +1084,15 @@ as unverified in the migration report.
|
|
|
987
1084
|
|
|
988
1085
|
The UX audit requires app-specific network fixtures. `himi test --record` records
|
|
989
1086
|
only boot-time reads with the app's visitor identity, then crawls hermetically.
|
|
990
|
-
|
|
991
|
-
|
|
1087
|
+
Before you run it, run `himi template inspect` and read `.himi/adopt.json`
|
|
1088
|
+
`bootRequests[]`: every entry is a screen that can request when it appears. An entry
|
|
1089
|
+
with `trigger: "module-load"` is a worker that calls an action while its module
|
|
1090
|
+
evaluates (`svc.load();` at the bottom of the file — the pattern every migration
|
|
1091
|
+
worker uses); the screen descriptor names nothing, but the read runs as soon as the
|
|
1092
|
+
screen boots the worker. Each boot path must be a catalogue or directory read.
|
|
1093
|
+
Stop if one submits, orders, books, pays, or calls a getter known to mutate on read
|
|
1094
|
+
(such as the legacy announcement default getter). Then review the recorded and
|
|
1095
|
+
refused requests. Keep actual recordings
|
|
992
1096
|
under `.himi/one-app/fixtures/net-mocks.json`. For local test/render discovery,
|
|
993
1097
|
make `dev/net-mocks.json` a relative symlink to that private file: the source
|
|
994
1098
|
archiver skips symlinks as well as `.himi/`. Verify the archive excludes both
|
|
@@ -996,19 +1100,56 @@ before publishing. Portable fixtures committed as regular files must instead be
|
|
|
996
1100
|
synthetic test data; do not publish source catalogs, member records or credentials
|
|
997
1101
|
as test evidence. Re-run affected checks after changing fixtures.
|
|
998
1102
|
|
|
1103
|
+
`himi push` refuses with `headless_run_failed` while `himi test` has an error finding,
|
|
1104
|
+
including one on an inherited template screen. Boot-only fixtures cannot cover a read
|
|
1105
|
+
that a tap starts (for example, choosing a category on `himi_shop`), so the hermetic
|
|
1106
|
+
crawl reports it stuck on loading although it works live. Reproduce it live first
|
|
1107
|
+
(`himi run` or the hosted preview). If it works, add a fixture for that read, or add a
|
|
1108
|
+
`himi-test.json` `skip[]` entry with the `screen`, `action`, `invariant` and a `reason`
|
|
1109
|
+
that states the live evidence (date, data shown). If it fails live, fix it. Never push
|
|
1110
|
+
with `--force` to pass this gate.
|
|
1111
|
+
|
|
1112
|
+
In `SPEC.md` `## Data access`, name an inherited template write the way `himi test`
|
|
1113
|
+
reads it: its action (`selectCategory` or `tier5.himiBrandedShop.selectCategory`), its
|
|
1114
|
+
endpoint (`POST /stores/v3/products/query`, with `*` for one path segment), or its
|
|
1115
|
+
capability or kind (`payment`, `signup`). Prose approves nothing.
|
|
1116
|
+
|
|
999
1117
|
Render and inspect actual reconstructed screens at compact and wider widths,
|
|
1000
1118
|
including loading, empty, error and denied states. Compare the source's resolved
|
|
1001
1119
|
design and composition; when source visual evidence is available compare matched
|
|
1002
1120
|
locale, platform and data state. Record actual visual evidence and any native
|
|
1003
1121
|
platform not exercised; never infer native parity from a web screenshot.
|
|
1004
1122
|
|
|
1123
|
+
Known web limits:
|
|
1124
|
+
|
|
1125
|
+
- A short screen paints its root background only as tall as its content; below it the
|
|
1126
|
+
web host shows its own (light) background. On a dark source, check a short page and
|
|
1127
|
+
record the difference; native fills the screen.
|
|
1128
|
+
- `himi render --png` needs the Chromium of the Playwright that `himi` bundles. Run the
|
|
1129
|
+
install command the render hint prints. A bare `npx playwright install chromium`
|
|
1130
|
+
from the app directory can install another revision.
|
|
1131
|
+
- A Detailed header (`CollapsingHeader`) scrolls with the page in current releases. An
|
|
1132
|
+
older CLI drew it in a 640px scroll box, so the page scrolled inside it and
|
|
1133
|
+
`himi render --png` showed only the first viewport; update the CLI before you compare.
|
|
1134
|
+
- The One App editor preview shows demo data for member widgets ("This is a demo image
|
|
1135
|
+
and won't appear live") and draws some vertical pages blank. It is not a live baseline:
|
|
1136
|
+
compare against the published app or the source evidence instead.
|
|
1137
|
+
|
|
1138
|
+
Fonts follow the typography rules of the design check in step 1: a source family Himi
|
|
1139
|
+
does not ship is replaced only with the owner's explicit instruction, recorded as an
|
|
1140
|
+
`adapted` design row. Also resolve every other pointer the report lists under
|
|
1141
|
+
`notCompared` (button `uppercase`, for example); a passing design check does not cover them.
|
|
1142
|
+
|
|
1005
1143
|
Record actual mobile UX checks for the current release, then audit them. For each
|
|
1006
1144
|
platform driven, use `himi ux record --platform ios --status passed --checks <actual-checks>`
|
|
1007
1145
|
(or `android`, and `failed` for a real failure). An unavailable platform requires
|
|
1008
1146
|
`himi ux record --platform android --status unavailable --reason "<actual limitation>"`
|
|
1009
1147
|
and no fabricated checks. Resolve failures, run `himi ux audit --strict`, and keep
|
|
1010
1148
|
these records bound to the final content immediately before push. An edit changes
|
|
1011
|
-
the release; repeat the affected checks and record that content.
|
|
1149
|
+
the release; repeat the affected checks and record that content. Any content change
|
|
1150
|
+
(a fixture, a trimmed screen, a recompressed icon) makes a new release hash, so redo
|
|
1151
|
+
`himi ux record` and `himi one-app validate-design --record --release-hash <new>` as
|
|
1152
|
+
the last step before `himi push`, after every size or test fix. Never bypass this
|
|
1012
1153
|
gate with `--force` or claim an unavailable native platform passed.
|
|
1013
1154
|
|
|
1014
1155
|
Once the implemented app passes its available checks, publish only a draft:
|
|
@@ -1017,11 +1158,27 @@ Once the implemented app passes its available checks, publish only a draft:
|
|
|
1017
1158
|
himi push --draft --target bo
|
|
1018
1159
|
```
|
|
1019
1160
|
|
|
1020
|
-
Keep the editable source archive included.
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1161
|
+
Keep the editable source archive included. The publish body is limited to 8,388,608
|
|
1162
|
+
bytes. It is about base64(source archive + worker bundles + assets + icons) plus the
|
|
1163
|
+
descriptor JSON, so a large app can exceed it: one 33-page migration measured
|
|
1164
|
+
11,259,935 bytes. Measure early, not at the end: after `himi build`, add up
|
|
1165
|
+
`dist/bundles/*`, the icons and a zip of the content directory without the excluded
|
|
1166
|
+
paths below. `himi push` refuses an oversized body locally, before it sends anything,
|
|
1167
|
+
with `publish_body_too_large`; its `breakdown`
|
|
1168
|
+
gives each part's bytes (`appSource`, `screens`, `bundles`, `assets`, `icon`, `other`)
|
|
1169
|
+
and the largest entries by name. Reduce it in this order, and repeat affected
|
|
1170
|
+
validation after each step:
|
|
1171
|
+
|
|
1172
|
+
1. Trim the template screens the plan does not use, and the ones a reconstructed page
|
|
1173
|
+
replaced (`himi template trim --keep …`). Their descriptors and workers ride the body.
|
|
1174
|
+
2. Recompress images losslessly (the 1024 icon is in the body and in the archive). Prove
|
|
1175
|
+
the decoded pixels are unchanged.
|
|
1176
|
+
3. Remove unused generated definitions.
|
|
1177
|
+
|
|
1178
|
+
The archive already leaves out `.himi/`, `.claude/`, `.agents/`, `HIMALAYA.md`,
|
|
1179
|
+
`node_modules/`, `dist/` and symlinks. Do not use `--no-source` or remove authored
|
|
1180
|
+
features to fit the upload limit; report a remaining size blocker with the breakdown
|
|
1181
|
+
instead.
|
|
1025
1182
|
|
|
1026
1183
|
Use the target's existing authentication flow when needed. Capture the returned
|
|
1027
1184
|
release and hosted preview URL, then open that exact URL in the browser and verify
|
|
@@ -343,6 +343,16 @@ goes to the member's subscribed devices for this site's Branded-family app, whic
|
|
|
343
343
|
than one device. It does not go to their other Wix apps. Confirm receipt and the tap on the
|
|
344
344
|
device itself.
|
|
345
345
|
|
|
346
|
+
**There is no `--badge`.** Ping's send request has no badge field. For a Branded app, Ping sets
|
|
347
|
+
the iOS app-icon badge itself from the member's unseen items in their Ping feed, so the CLI refuses
|
|
348
|
+
`--badge` (`flag_not_supported_with_ping`) rather than send a number Ping would ignore.
|
|
349
|
+
|
|
350
|
+
**An expired login is named as one.** When the stored control token has expired, `notify send`
|
|
351
|
+
and `notify setup|status` refuse with `control_token_expired` before any network call; when the
|
|
352
|
+
plane rejects the token, they refuse with `owner_login_required`. Both mean log in again, not
|
|
353
|
+
an ownership problem: the hint names the target the command read (`himi login --browser --target
|
|
354
|
+
<target>`), because a bare `himi login` renews the default target instead.
|
|
355
|
+
|
|
346
356
|
Every send carries a request ID. If the outcome is unknown (`send_outcome_unknown`, or a lost
|
|
347
357
|
response), the CLI prints the ID and never retries on its own. Re-run the same command with
|
|
348
358
|
`--request-id <id>`: Ping runs one request at most once per site for 24 hours, so a retry
|