@wix/himalaya-cli 0.1431.0 → 0.1433.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/base44/src/index.d.ts +17 -9
- package/dist/cli.mjs +3245 -2430
- package/guides/base44-app-context.md +2 -2
- package/guides/base44-app-to-himi-app.md +94 -31
- package/guides/base44-entities.md +0 -1
- package/guides/himi-json-output.md +18 -0
- package/guides/himi-test.md +10 -0
- package/guides/sdk-reference.json +4 -4
- package/package.json +2 -2
|
@@ -108,7 +108,7 @@ read-only, but it writes the book folder, so it is not annotated read-only to th
|
|
|
108
108
|
],
|
|
109
109
|
"functions": [
|
|
110
110
|
{ "name": "sendReport", "sourcePath": "base44/functions/sendReport/entry.ts", "kind": "http",
|
|
111
|
-
"methods": ["POST"], "invoke": "
|
|
111
|
+
"methods": ["POST"], "invoke": "functions.invoke(\"sendReport\", payload)",
|
|
112
112
|
"automations": [{ "name": "weekly", "type": "scheduled", "schedule": "0 9 * * 1" }] }
|
|
113
113
|
],
|
|
114
114
|
"agents": [{ "name": "job_helper", "tools": [{ "entity": "Job", "operations": ["read"] }] }],
|
|
@@ -128,7 +128,7 @@ app's own project files) or `rest` (the owner-authenticated API). Treat an opera
|
|
|
128
128
|
empty.
|
|
129
129
|
|
|
130
130
|
`BOOK.md` is the same content, summarised for an agent. For each entity it lists the worker calls
|
|
131
|
-
the Himi app would make through the `@himalaya/base44` capability: `
|
|
131
|
+
the Himi app would make through the `@himalaya/base44` capability: `entities("<Name>").list()`,
|
|
132
132
|
`.filter({…})`, `.get(id)`, and the writes (`create`, `update`, `delete`) that the entity's rules do
|
|
133
133
|
not forbid outright.
|
|
134
134
|
|
|
@@ -61,8 +61,8 @@ whose `Task` entity anyone may read and write:
|
|
|
61
61
|
|
|
62
62
|
| Tab | Screen | Worker | Pattern it shows |
|
|
63
63
|
|---|---|---|---|
|
|
64
|
-
| Tasks | `b44_tasks` | `
|
|
65
|
-
| (pushed) | `b44_task` | `task` | read one row by its id (a nav param), edit, delete then go back |
|
|
64
|
+
| Tasks | `b44_tasks` | `b44-task-list` | **generated** by `himi base44 screens`: list, create, delete; loading / empty / error / ready; pull to refresh |
|
|
65
|
+
| (pushed) | `b44_task` | `b44-task` | **generated**: read one row by its id (a nav param), edit, delete then go back |
|
|
66
66
|
| Functions | `b44_functions` | `functions` | `functions.invoke(name, payload)` with the reply and the error painted |
|
|
67
67
|
| Account | `b44_account` | `account` | Native Google sign-in (requires tenant app-link associations), email + password and emailed-code sign-in, register, reset, profile, sign out |
|
|
68
68
|
|
|
@@ -89,27 +89,48 @@ Turn the book's entities and functions into an adopted declaration, then wire it
|
|
|
89
89
|
himi base44 adopt --content . --book ../.himi/base44-book --write # the book step 1 wrote, one level up → base44-entities.ts (never overwrites)
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
+
The starter's `config.ts` declares the sample `Task` as a local `const base44Entities = [...]`.
|
|
93
|
+
Delete that declaration, then import yours in its place (keeping both fails with "Identifier
|
|
94
|
+
'base44Entities' has already been declared"):
|
|
95
|
+
|
|
92
96
|
```ts
|
|
93
97
|
import { base44Entities, base44Functions } from "./base44-entities.js";
|
|
94
98
|
// …
|
|
95
|
-
base44: { appId:
|
|
99
|
+
base44: { appId: base44AppId, entities: base44Entities, functions: base44Functions },
|
|
96
100
|
```
|
|
97
101
|
|
|
98
102
|
`himi validate` then lints the declaration (`pass: "base44"`), and `himi base44 entities query`
|
|
99
103
|
reports row counts and schema drift against the live app. See
|
|
100
104
|
[`base44-entities`](base44-entities.md) (`himi docs base44-entities`).
|
|
101
105
|
|
|
106
|
+
Then generate typed handles from the declaration, and import them in the workers instead of
|
|
107
|
+
spelling entity names:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
himi base44 types --content . # → tier5-src/_shared/base44-entities.ts (commit it)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
A field typo on a typed row (`row.titel`) is then a `himi validate` type error rather than a blank
|
|
114
|
+
cell on device. Re-run it after editing the block — `himi validate` reports `base44-types-stale`
|
|
115
|
+
until you do. See [`base44-sdk`](base44-sdk.md#typed-rows).
|
|
116
|
+
|
|
102
117
|
## 3. Plan the screens from the book
|
|
103
118
|
|
|
119
|
+
`himi base44 screens` (step 4) applies the rules below for you, so this step is about choosing
|
|
120
|
+
**what to declare**: which entities, in what order (with up to three entities each gets a tab; with
|
|
121
|
+
four or more, the first two get tabs and the rest go under More), which fields and which `rls`. The rules describe what the generator emits. Read them to predict the result, and to
|
|
122
|
+
know what to customise afterwards.
|
|
123
|
+
|
|
104
124
|
Write `.himi/screen-plan.md` before editing code. For each entity in `book.entities`:
|
|
105
125
|
|
|
106
126
|
1. **Decide whether it gets a tab.** An entity that a top-level route reads (`routes[].entities`)
|
|
107
127
|
and that a user browses gets a tab. A child entity (one whose rows only make sense under a
|
|
108
128
|
parent, such as `OrderItem` under `Order`) gets a section on the parent's detail screen
|
|
109
129
|
instead. Keep to 3–5 tabs. Account always takes one when the app is not public (step 5).
|
|
110
|
-
2. **Pick the list row.** The title is the
|
|
111
|
-
`title`, `name` or `label`. The subtitle is
|
|
112
|
-
number). Never put a long text field in a
|
|
130
|
+
2. **Pick the list row.** The title is the entity's `displayField` if it declares one, else the
|
|
131
|
+
first `required` string field, preferring one named `title`, `name` or `label`. The subtitle is
|
|
132
|
+
one or two short fields (a status `enum`, a date, a number). Never put a long text field in a
|
|
133
|
+
row.
|
|
113
134
|
3. **Pick the detail and form fields** from each field's JSON Schema type:
|
|
114
135
|
|
|
115
136
|
| Field (`type` / `format` / `enum`) | Detail shows | Form control |
|
|
@@ -118,20 +139,28 @@ Write `.himi/screen-plan.md` before editing code. For each entity in `book.entit
|
|
|
118
139
|
| `string` + long text (`description`, `notes`, `body`, …) | `Text` with `maxLines` | `TextField` with `multilineMaxLines` |
|
|
119
140
|
| `string` + `enum` | `Badge` / `Text` | `SegmentedControl` (≤ 4 values) or `Picker` |
|
|
120
141
|
| `string` + `format: date` / `date-time` | formatted `Text` | `DatePicker` |
|
|
121
|
-
| `string` + `format: email` / `uri` | `Text
|
|
142
|
+
| `string` + `format: email` / `uri` | `Text` (the generator does not make it tappable yet) | `TextField` with `keyboard: "email"` / `"url"` |
|
|
122
143
|
| `string` holding an image URL (`image`, `photo`, `avatar`, `*_url`) | `Image` | read-only, see [file upload](#what-the-sdk-cannot-do) |
|
|
123
144
|
| `number` / `integer` | `Text` (with unit) | `Stepper` (small ranges) or numeric `TextField` |
|
|
124
145
|
| `boolean` | `Badge` or `Text` | `Toggle` |
|
|
125
|
-
| `array` of strings |
|
|
126
|
-
| `object` / nested `array` of objects | a sub-section of rows | none
|
|
146
|
+
| `array` of strings | comma-joined `Text` | `ChipsInput` |
|
|
147
|
+
| `object` / nested `array` of objects | its JSON as `Text` (a sub-section of rows is yours to build) | none. Edit it on the web app |
|
|
127
148
|
| built-ins `id`, `created_date`, `updated_date`, `created_by` | "Created …" metadata row | never editable |
|
|
128
149
|
|
|
129
150
|
4. **Respect the entity's rules.** `rls` (and field-level `rls`) decide what the signed-in user
|
|
130
|
-
may do.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
151
|
+
may do. Declare the `rls` `BOOK.md` lists for the entity. The generator gates each write
|
|
152
|
+
control on its operation's rule (falling back to the entity-level `write` rule):
|
|
153
|
+
|
|
154
|
+
| Rule | Control |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `false`, or absent | not emitted at all |
|
|
157
|
+
| `true` | always shown |
|
|
158
|
+
| exactly `{ "created_by": "{{user.email}}" }` or `{ "created_by_id": "{{user.id}}" }` | shown only on the signed-in user's own rows |
|
|
159
|
+
| any other condition | shown only when signed in |
|
|
160
|
+
|
|
161
|
+
A field whose field-level `rls.write` is not `true` is read-only in the form. The gate is
|
|
162
|
+
advisory: a denied call still fails with Base44's message, and every screen paints that error
|
|
163
|
+
rather than swallowing it.
|
|
135
164
|
5. **Use the sample rows** (`sampleRows`, already redacted) to size rows and choose the subtitle,
|
|
136
165
|
never as data the app ships.
|
|
137
166
|
|
|
@@ -140,22 +169,48 @@ Compose each screen with [`designing-himi-screens`](designing-himi-screens.md)
|
|
|
140
169
|
|
|
141
170
|
## 4. Build one list + detail per entity
|
|
142
171
|
|
|
143
|
-
|
|
172
|
+
Declare the entity, then generate its screens:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
himi base44 adopt --content . --book ../.himi/base44-book --write # or declare by hand (step 2)
|
|
176
|
+
himi base44 screens --content . --json
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
For each entity in `config.ts` `base44.entities`, `himi base44 screens` writes a list screen
|
|
180
|
+
(`b44_<plural>`, e.g. `b44_projects`) and a detail screen (`b44_<name>`, e.g. `b44_project`):
|
|
181
|
+
|
|
182
|
+
- `tier5-src/_shared/b44-<entity>-plan.ts`: the plan (row title and subtitle, facts, form
|
|
183
|
+
controls, write gates) the rules in step 3 produce. The list, the detail and the descriptors all
|
|
184
|
+
read it, so this is the file to customise.
|
|
185
|
+
- `tier5-src/b44-<entity>-list/index.ts` and `tier5-src/b44-<entity>/index.ts`: one-line worker
|
|
186
|
+
entries over the template's shared engine (`_shared/entity-list.ts`, `_shared/entity-detail.ts`).
|
|
187
|
+
Each entity gets its own bundle and service, so two entity tabs never share state.
|
|
188
|
+
- `dev/entities.generated.ts` and `config.entities.generated.ts`: the screen registrations and the
|
|
189
|
+
`linkableScreens` / `tabBar` items. `dev/index.ts` and `config.ts` already import them.
|
|
190
|
+
|
|
191
|
+
The first three entities in config order get a tab, in front of Functions and Account. With more,
|
|
192
|
+
the last entity slot becomes a generated `b44_more` screen listing the rest, so the bar never has
|
|
193
|
+
more than five items. Ids pluralise naively (`Category` → `b44_categories`, `Person` →
|
|
194
|
+
`b44_persons`); give the entity a `title` for the visible name. Two entities that would share an id
|
|
195
|
+
are refused with `code: "entity_id_collision"`.
|
|
196
|
+
|
|
197
|
+
Re-running is safe. Each generated file starts with
|
|
198
|
+
`// @generated by himi base44 screens — sha256:<hash>`:
|
|
199
|
+
|
|
200
|
+
- an unchanged config reports every file `unchanged` and writes nothing;
|
|
201
|
+
- a generated file you edited by hand (its body no longer matches the hash) is reported
|
|
202
|
+
`skipped-edited` and left alone, and the command still exits 0. Pass `--force` to overwrite it;
|
|
203
|
+
- files for an entity you removed from `config.ts` are reported in `orphaned[]` and never deleted.
|
|
204
|
+
|
|
205
|
+
`--dry-run` reports the same outcomes without writing. Failures carry a top-level `code`
|
|
206
|
+
(`no_entities_block`, `entity_id_collision`, `content_dir_not_base44_starter`), per
|
|
207
|
+
[`himi-json-output`](himi-json-output.md). The generator never calls Base44.
|
|
144
208
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
guard, and `derive()` producing the `hide*` flags.
|
|
149
|
-
- `tier5-src/project/index.ts` from `tier5-src/task/index.ts`. `inputId()` reads the row id from
|
|
150
|
-
the nav param, `get(id)` loads it, and `remove` returns `navigate(…, { presentation: "back" })`
|
|
151
|
-
from the action the host dispatched.
|
|
152
|
-
- In `dev/index.ts`, a `projects()` and a `project()` builder (copy `tasks()` and `task()`), each
|
|
153
|
-
bound with `bundle: "<worker dir>"` and `declaredCapabilities: ["base44"]`. Register both in
|
|
154
|
-
`screens.exact` and the tab root in `seed.screens`.
|
|
155
|
-
- In `config.ts`, a `linkableScreens` entry for each (the detail with `paramKeys: ["id"]` and its
|
|
156
|
-
list as `parentScreenId`) and a `tabBar` item for the list.
|
|
209
|
+
To change a screen beyond what the plan expresses (a filtered list, a child section, a custom
|
|
210
|
+
action), edit its generated entry or plan. The edit makes the file `skipped-edited`, so the
|
|
211
|
+
generator leaves it alone from then on.
|
|
157
212
|
|
|
158
|
-
The calls a worker
|
|
213
|
+
The calls the engine makes (and a customised worker can make), all on `entities("<Name>")`:
|
|
159
214
|
|
|
160
215
|
| Need | Call |
|
|
161
216
|
|---|---|
|
|
@@ -176,7 +231,9 @@ Rules that keep it correct:
|
|
|
176
231
|
`$item.openLabel`. `himi validate` flags this as an error.
|
|
177
232
|
- **Every write re-lists**, and a failed write keeps the list on screen with the error above it.
|
|
178
233
|
Only a failed *first* list is the error state.
|
|
179
|
-
-
|
|
234
|
+
- Replace the sample `Task` declaration with your own entities and re-run `himi base44 screens`.
|
|
235
|
+
The home screen is the first entity's list. The generator reports the sample's files as
|
|
236
|
+
`orphaned`; delete them by hand.
|
|
180
237
|
|
|
181
238
|
## 5. Auth: the Account tab
|
|
182
239
|
|
|
@@ -285,8 +342,14 @@ himi run --content . # web preview against the live Base
|
|
|
285
342
|
```
|
|
286
343
|
|
|
287
344
|
`himi test` crawls every action against the real workers with hermetic transport, so it proves
|
|
288
|
-
the wiring, not your data.
|
|
289
|
-
|
|
345
|
+
the wiring, not your data. Base44 reads are served from rows you already have: an owned entity's
|
|
346
|
+
`seed:` rows in the `base44.entities` block, then an adopted entity's redacted `sampleRows` from
|
|
347
|
+
`.himi/base44-book/book.json` in the content directory (copy the book in, or re-run analyze with
|
|
348
|
+
`--out .himi/base44-book`). So a list screen crawls populated, its row actions get a row to act on,
|
|
349
|
+
and a typo'd entity name fails loudly instead of rendering empty. Writes and `functions.invoke` are
|
|
350
|
+
refused in the crawl by design, so their error paths are what it exercises. With no seed and no
|
|
351
|
+
book, a declared Base44 read answers nothing and the list crawls empty, as before. Its gap ledger
|
|
352
|
+
names what the hermetic crawl could not reach (rows that only exist on the live app, for instance). Close a gap with the remedy it names, or accept it.
|
|
290
353
|
Then drive the real flow in `himi run`: list, create, edit, delete a row of each entity, and
|
|
291
354
|
sign in when the app is not public.
|
|
292
355
|
|
|
@@ -147,4 +147,3 @@ Failure codes are listed in [`himi-json-output`](himi-json-output.md#himi-base44
|
|
|
147
147
|
full-set sync, which is why it is a separate, deliberate step.
|
|
148
148
|
- **Typed clients and hermetic test data**: `entities<"X">()` typed from the declaration, with
|
|
149
149
|
`seed` rows as mocks.
|
|
150
|
-
- **Generated screens**: list and detail screens per declared entity.
|
|
@@ -249,6 +249,24 @@ branch on them without parsing prose:
|
|
|
249
249
|
- `source_unavailable`: the project download (the eject read) failed, so no drift was
|
|
250
250
|
computed. Row counts still ran; `sourceRead` is `"unavailable"` and `sourceError` says why.
|
|
251
251
|
|
|
252
|
+
## `himi base44 screens` codes
|
|
253
|
+
|
|
254
|
+
`himi base44 screens` (#4560, [base44-app-to-himi-app](base44-app-to-himi-app.md)) generates one
|
|
255
|
+
list + detail screen per declared `base44.entities` entity. Failures print `ok: false` and `code`
|
|
256
|
+
on stderr (exit 1):
|
|
257
|
+
|
|
258
|
+
- `content_dir_not_base44_starter`: the directory lacks the shared engine the generated files
|
|
259
|
+
import (`missing[]` names the files). Scaffold with `himi init --template base44-starter`.
|
|
260
|
+
- `no_entities_block`: `config.ts` declares no `base44.entities`, so there is nothing to generate.
|
|
261
|
+
- `entity_id_collision`: two entities would generate the same screen id (or one would shadow
|
|
262
|
+
`b44_functions` / `b44_account` / `b44_more`); `entity`, `screenId` and `with` name the clash.
|
|
263
|
+
- `config_unloadable` / `invalid_config`: as for `himi base44 entities` above.
|
|
264
|
+
|
|
265
|
+
On success (`ok: true`, stdout, exit 0) `files[]` gives every generated path with its `outcome`:
|
|
266
|
+
`written`, `unchanged`, or `skipped-edited` (the file was edited by hand and was left alone; pass
|
|
267
|
+
`--force` to overwrite it). A skipped file is not a failure. `orphaned[]`, when present, lists
|
|
268
|
+
generated files for entities no longer declared. They are never deleted.
|
|
269
|
+
|
|
252
270
|
## Follow-ups
|
|
253
271
|
|
|
254
272
|
- Migrate failure envelopes in subcommands other than `push`, keeping this contract.
|
package/guides/himi-test.md
CHANGED
|
@@ -201,6 +201,16 @@ assembles it from four layers in priority order, **none of which touches the wir
|
|
|
201
201
|
4. **offline reject** — the floor that always exists; see the failure UI head-on
|
|
202
202
|
(`--offline`).
|
|
203
203
|
|
|
204
|
+
**Base44 apps have a fifth, beside these.** Base44 reads are `capability.base44.*` calls on the
|
|
205
|
+
host bus, not HTTP, so the layers above never see them. The crawl serves them from the
|
|
206
|
+
`base44.entities` block's `seed:` rows (owned entities, keyed by the physical `Himi<App><Name>`),
|
|
207
|
+
then from `.himi/base44-book/book.json`'s redacted `sampleRows` (adopted entities, keyed by the
|
|
208
|
+
Base44 name). `list` honours `sort` / `skip` / `limit` / `fields`, `filter` matches top-level
|
|
209
|
+
equality only, `get` finds by `id`. An entity neither knows is an error (`http_404`) naming it,
|
|
210
|
+
never `[]`; writes and `functions.invoke` are refused by design. The transport line says
|
|
211
|
+
`+ base44 (N entities …)` when the layer is on. With neither seed nor book it is off, and a
|
|
212
|
+
declared Base44 read answers `null` (the SDK's empty list) as it always did. `--offline` strips it.
|
|
213
|
+
|
|
204
214
|
**Need your site's real shapes?** `himi test --record` refreshes layer 1 from live reads —
|
|
205
215
|
`load()` and `onAppear` **only**, read-path-only by construction (GET and read-shaped POST;
|
|
206
216
|
every write refused at the transport) — then crawls hermetically on what it froze. Explicit
|
|
@@ -468,14 +468,14 @@
|
|
|
468
468
|
{
|
|
469
469
|
"name": "EntityHandle",
|
|
470
470
|
"kind": "interface",
|
|
471
|
-
"jsdoc": "",
|
|
472
|
-
"decl": "export interface EntityHandle {\n list(opts?: ListOptions): Promise<
|
|
471
|
+
"jsdoc": "/**\n * One entity's verbs. `T` is the row shape: `Base44Row` (untyped) unless the caller names one,\n * e.g. a row type generated by `himi base44 types`. A row type must be a type alias, not an\n * `interface` — only an alias satisfies `Base44Row`'s `JsonObject` index signature.\n */",
|
|
472
|
+
"decl": "export interface EntityHandle<T extends Base44Row = Base44Row> {\n list(opts?: ListOptions): Promise<T[]>;\n filter(query: JsonObject, opts?: ListOptions): Promise<T[]>;\n get(id: string): Promise<T>;\n create(data: Partial<T>): Promise<T>;\n update(id: string, patch: Partial<T>): Promise<T>;\n delete(id: string): Promise<void>;\n bulkCreate(rows: Partial<T>[]): Promise<T[]>;\n}"
|
|
473
473
|
},
|
|
474
474
|
{
|
|
475
475
|
"name": "entities",
|
|
476
476
|
"kind": "function",
|
|
477
|
-
"jsdoc": "
|
|
478
|
-
"decl": "export function entities(name: string): EntityHandle
|
|
477
|
+
"jsdoc": "/**\n * Typed access to one entity of the configured Base44 app, e.g. `entities(\"Task\").list()`.\n * Pass a row type to type the rows: `entities<TaskRow>(\"Task\")`. Types only — runtime is identical.\n */",
|
|
478
|
+
"decl": "export function entities<T extends Base44Row = Base44Row>(name: string): EntityHandle<T>;"
|
|
479
479
|
},
|
|
480
480
|
{
|
|
481
481
|
"name": "functions",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1433.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": "f0352e9dd51208b098564413b02976840565ff1539e321ae4ea327f5"
|
|
75
75
|
}
|