@wix/himalaya-cli 0.1433.0 → 0.1434.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +1517 -634
- package/guides/base44-app-context.md +1 -1
- package/guides/base44-entities.md +117 -7
- package/guides/himi-json-output.md +66 -2
- package/package.json +2 -2
|
@@ -55,7 +55,7 @@ listed in `gaps[]`.
|
|
|
55
55
|
|
|
56
56
|
| Mode | How | Stored where |
|
|
57
57
|
|---|---|---|
|
|
58
|
-
| Interactive | `himi base44 login` runs Base44's device sign-in. You approve a code in the browser, and only read access (`apps:read`) is asked for | `~/.himi/base44/session.json`, mode 0600 |
|
|
58
|
+
| Interactive | `himi base44 login` runs Base44's device sign-in. You approve a code in the browser, and only read access (`apps:read`) is asked for. `--write` also asks for `apps:write`, which only the provisioning verbs need ([base44-entities](base44-entities.md#provisioning-create-seed-deploy)) | `~/.himi/base44/session.json`, mode 0600 |
|
|
59
59
|
| Reuse the Base44 CLI's session | `himi base44 login --from-base44-cli` imports what `npx base44 login` stored | the same file |
|
|
60
60
|
| CI | `BASE44_ACCESS_TOKEN=<token>` in the environment | nowhere, it is read from the environment |
|
|
61
61
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Base44 entities and functions (declare, lint, adopt, query)
|
|
1
|
+
# Base44 entities and functions (declare, lint, adopt, query, provision)
|
|
2
2
|
|
|
3
3
|
A Himi app on [Base44](https://base44.com) names the entities and backend functions it depends on
|
|
4
4
|
in `config.ts`. With that declaration, `himi validate` lints it, `himi base44 adopt` writes it from
|
|
@@ -8,8 +8,9 @@ This is the Base44 sibling of [`cms-collections`](cms-collections.md) (`himi doc
|
|
|
8
8
|
It reuses the same ideas (owned versus adopted, an offline lint, a read-only drift report) but not
|
|
9
9
|
the same block: Base44 field types, access rules and naming differ from Wix Data.
|
|
10
10
|
|
|
11
|
-
> **
|
|
12
|
-
> rows and deploying functions
|
|
11
|
+
> **Writes are separate and deliberate.** `adopt`, `query` and the lint never write to a Base44
|
|
12
|
+
> app. Creating schemas, seeding rows and deploying functions are their own verbs. Each one prints
|
|
13
|
+
> a plan and writes only with `--yes` (see [Provisioning](#provisioning-create-seed-deploy)).
|
|
13
14
|
|
|
14
15
|
## The block
|
|
15
16
|
|
|
@@ -35,7 +36,7 @@ Each entity is one of two kinds:
|
|
|
35
36
|
|
|
36
37
|
| Kind | Declared by | Physical entity | himi may |
|
|
37
38
|
|---|---|---|---|
|
|
38
|
-
| **Owned** | `name: "Note"` (alphanumeric) | `Himi<AppPascal>Note`. For app `todo` that is `HimiTodoNote`, and for `video-courses` it is `HimiVideoCoursesNote` | create, seed
|
|
39
|
+
| **Owned** | `name: "Note"` (alphanumeric) | `Himi<AppPascal>Note`. For app `todo` that is `HimiTodoNote`, and for `video-courses` it is `HimiVideoCoursesNote` | create, seed |
|
|
39
40
|
| **Adopted** | `base44Name: "Customer"` | `Customer`, verbatim | read only |
|
|
40
41
|
|
|
41
42
|
Base44 entity names are alphanumeric only, so the CMS `himi_<app>_` prefix cannot be used. The
|
|
@@ -140,10 +141,119 @@ makes is a `GET`.
|
|
|
140
141
|
|
|
141
142
|
Failure codes are listed in [`himi-json-output`](himi-json-output.md#himi-base44-entities-codes).
|
|
142
143
|
|
|
144
|
+
## Provisioning: create, seed, deploy
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
himi base44 login --write # once: a session with apps:read apps:write
|
|
148
|
+
himi base44 entities create --app todo # the plan: create / update / unchanged / refused per entity
|
|
149
|
+
himi base44 entities create --app todo --yes # send it
|
|
150
|
+
himi base44 entities seed --app todo --yes # fill EMPTY owned entities
|
|
151
|
+
himi base44 functions deploy --app todo --yes # ship owned functions
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`--app <slug>` resolves to `apps/<slug>/`, and `--content <dir>` points anywhere. Without `--yes`
|
|
155
|
+
each verb makes only reads and sends no write.
|
|
156
|
+
|
|
157
|
+
**Base44's schema write is a destructive full-set sync.** `PUT /api/apps/<id>/entity-schemas`
|
|
158
|
+
with `{ entityNameToSchema }` **deletes every entity the body leaves out**, along with its rows.
|
|
159
|
+
Base44 has no read for schemas. So `entities create` downloads the live project (the same eject
|
|
160
|
+
read as `query`) and builds the body from every entity in it:
|
|
161
|
+
|
|
162
|
+
- Owned entities are built from `config.ts`.
|
|
163
|
+
- Every other entity is passed through as the exact schema object the download holds. It is never
|
|
164
|
+
rebuilt, renamed, changed or dropped.
|
|
165
|
+
|
|
166
|
+
A **live** entity counts as owned only if `base44-provisioned.json`, beside `config.ts`, records
|
|
167
|
+
that this app provisioned it. `entities create` keeps that file up to date. **Commit it** like a
|
|
168
|
+
lockfile, so every machine and CI agrees on what the app owns. A bare prefix is not enough on its
|
|
169
|
+
own. If app `todo` (`HimiTodo…`) declares `ListNote`, that names the entity app `todo-list` owns
|
|
170
|
+
as `Note` (`HimiTodoListNote`). So:
|
|
171
|
+
|
|
172
|
+
- A declared entity that already exists but is not in the file is refused with
|
|
173
|
+
`owned_entity_unclaimed`. If it really is this app's, record it in the file; otherwise rename the
|
|
174
|
+
declaration.
|
|
175
|
+
- An undeclared entity in the namespace that the file does not list is left untouched and listed
|
|
176
|
+
in `warnings`.
|
|
177
|
+
- When a sync's outcome is uncertain (a lost reply, a 5xx, a reply with no `deleted[]`),
|
|
178
|
+
`entities create` re-reads the app and records only the creates that are live, and keeps every
|
|
179
|
+
name the file already held. If that re-read fails too, nothing new is recorded, and the next run
|
|
180
|
+
refuses the entity with `owned_entity_unclaimed`, which you fix by recording it by hand.
|
|
181
|
+
- `entities seed` only writes entities the file lists.
|
|
182
|
+
|
|
183
|
+
If any entity file in the download fails to parse, or the source walk drops it (a symlink, a
|
|
184
|
+
denied name), the snapshot counts as unreadable. A sync without that file would delete the
|
|
185
|
+
entity.
|
|
186
|
+
|
|
187
|
+
```mermaid
|
|
188
|
+
flowchart TD
|
|
189
|
+
A[entities create] --> Y{--yes?}
|
|
190
|
+
Y -- yes --> S{token has apps:write?}
|
|
191
|
+
S -- no --> R1[write_scope_missing<br/>no request]
|
|
192
|
+
S -- yes --> C
|
|
193
|
+
Y -- no --> C["GET …/eject → every live entity, verbatim"]
|
|
194
|
+
C -- failed --> R2[schema_snapshot_unavailable]
|
|
195
|
+
C -- no entities, no --empty-app-ok --> R3[schema_snapshot_empty]
|
|
196
|
+
C --> P["plan: foreign as-is + owned from config"]
|
|
197
|
+
P -- a foreign entity missing or altered --> R4[would_delete_foreign_entity]
|
|
198
|
+
P -- owned entity / field dropped, no --allow-destructive --> R5[owned_*_removal_needs_flag]
|
|
199
|
+
P -- no --yes --> D[print the plan, exit 0]
|
|
200
|
+
P -- --yes --> H[re-read the eject, re-plan]
|
|
201
|
+
H -- plan differs --> R6[snapshot_changed]
|
|
202
|
+
H -- same --> I["one PUT …/entity-schemas"]
|
|
203
|
+
I -- deleted[] names an entity the plan kept --> R7[foreign_entity_deleted]
|
|
204
|
+
I --> K[created / updated / unchanged]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Every refusal except the last one happens before the `PUT`.
|
|
208
|
+
|
|
209
|
+
- `--allow-destructive` lets an **owned** entity or field be removed. It only reaches entities this
|
|
210
|
+
app provisioned, never another app's.
|
|
211
|
+
- `--apply-permissions` writes a changed owned `rls` (entity- or field-level). Without it the live
|
|
212
|
+
rules are kept and the difference is reported as `permissions` drift. A rule the declaration
|
|
213
|
+
does not state never clears a live one.
|
|
214
|
+
- `--empty-app-ok` accepts a download with no entities. An empty app cannot be told apart from a
|
|
215
|
+
failed read, so this has to be opted into.
|
|
216
|
+
|
|
217
|
+
Because this is a full-set sync, an entity added in the Base44 builder between the plan and the
|
|
218
|
+
`PUT` is caught by the re-read (`snapshot_changed`). Whether the eject download always reflects
|
|
219
|
+
builder edits that were never exported is not yet proven against a live app. Before the first
|
|
220
|
+
live `--yes`, check it on a throwaway app: add an entity in the builder and confirm `entities
|
|
221
|
+
create` lists it.
|
|
222
|
+
|
|
223
|
+
**`entities seed`** checks each owned entity with `GET …/entities/<E>?limit=1`:
|
|
224
|
+
|
|
225
|
+
- An empty entity gets one `POST …/entities/<E>/bulk` with its rows.
|
|
226
|
+
- An entity that already has rows is skipped with `skipped: "not-empty"`.
|
|
227
|
+
- An adopted entity is never read or written.
|
|
228
|
+
|
|
229
|
+
Rows from `base44-seed.json` take precedence over `config.ts` `seed`. Only declared keys are sent,
|
|
230
|
+
so a row cannot set `id` or `created_by`. `--ai` writes placeholder rows to `base44-seed.json`
|
|
231
|
+
offline and returns an `agentPrompt` for the agent to rewrite them, exactly like `himi cms seed
|
|
232
|
+
--ai`.
|
|
233
|
+
|
|
234
|
+
**`functions deploy`** reads each owned function from `base44/functions/<name>/`. The entry file is
|
|
235
|
+
`entry.ts` or `entry.js`, or the one `function.jsonc`'s `entry` names. The folder is read with
|
|
236
|
+
`himi push`'s own walk: symlinks are never followed, the deny-list applies, and the secret scan
|
|
237
|
+
runs. Anything those flag refuses the deploy with `function_source_unsafe`. Each function is sent
|
|
238
|
+
with
|
|
239
|
+
one `PUT …/backend-functions/<name>` and body `{ entry, files, automations? }`. It never uses the
|
|
240
|
+
bulk `PUT …/backend-functions`, which deletes the functions it omits, and never sends `DELETE`.
|
|
241
|
+
|
|
242
|
+
Owned functions keep their plain `name`, so every deploy adds a `.himi-owned` marker file naming
|
|
243
|
+
the app. A deployed function with a declared name that lacks this app's marker is refused with
|
|
244
|
+
`function_name_taken` and nothing is deployed. That covers a function built in the builder,
|
|
245
|
+
another himi app's function, or a listing that returns no files. A listing with no `functions`
|
|
246
|
+
array is refused outright and is never read as "nothing deployed".
|
|
247
|
+
|
|
248
|
+
**Scope.** The default `himi base44 login` stays `apps:read`, so the analyzer and `query` keep
|
|
249
|
+
least privilege. `--yes` on any of these verbs needs a token whose `scope` claim includes
|
|
250
|
+
`apps:write`. A token whose claims cannot be read (an opaque `BASE44_ACCESS_TOKEN`) is refused
|
|
251
|
+
rather than guessed.
|
|
252
|
+
|
|
253
|
+
Failure codes are listed in
|
|
254
|
+
[`himi-json-output`](himi-json-output.md#himi-base44-entities--functions-provisioning-codes).
|
|
255
|
+
|
|
143
256
|
## Coming next
|
|
144
257
|
|
|
145
|
-
- **Provisioning**: `create`, `seed` and `functions deploy` for owned entities and functions. It
|
|
146
|
-
consumes `diffEntityFields` and the `Base44QueryReport`. Base44's schema write is a destructive
|
|
147
|
-
full-set sync, which is why it is a separate, deliberate step.
|
|
148
258
|
- **Typed clients and hermetic test data**: `entities<"X">()` typed from the declaration, with
|
|
149
259
|
`seed` rows as mocks.
|
|
@@ -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`**,
|
|
9
|
+
first, for **`himi store iap connect`**, for **`himi site member-app`**, and for the **`himi base44`** entity and function verbs. 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
|
|
@@ -234,7 +234,7 @@ Covers `himi base44 adopt` and `himi base44 entities query` (#4557,
|
|
|
234
234
|
carries each `ruleCode`. Adopt only emits what the lint accepts, so this means a bug in
|
|
235
235
|
`adopt` (exit 1).
|
|
236
236
|
- `unknown_subcommand`: `himi base44 entities` was given no subcommand, or one other than
|
|
237
|
-
`query` (exit 2).
|
|
237
|
+
`query`, `create` or `seed` (exit 2).
|
|
238
238
|
- `config_unloadable`: `entities query` could not load `config.ts` (exit 1).
|
|
239
239
|
- `invalid_config`: the `base44` block has lint errors; `issues[]` carries each one's
|
|
240
240
|
`ruleCode` (exit 1). `himi validate` reports the same findings with `pass: "base44"`.
|
|
@@ -249,6 +249,70 @@ 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 entities | functions` provisioning codes
|
|
253
|
+
|
|
254
|
+
Covers `himi base44 entities create`, `himi base44 entities seed` and `himi base44 functions
|
|
255
|
+
deploy` (#4558, [base44-entities](base44-entities.md#provisioning-create-seed-deploy)). Failures
|
|
256
|
+
print `ok: false` and `code` on stderr. Every code below that refuses a write does so **before**
|
|
257
|
+
the write request is sent.
|
|
258
|
+
|
|
259
|
+
- `invalid_usage`: an unknown `functions` subcommand, a bare `--only`, `--only` on `entities
|
|
260
|
+
create` (always a full-set sync), an `--app` with no `apps/<slug>/config.ts`, or nothing to
|
|
261
|
+
deploy (no owned function, or `--only` matched none) (exit 2).
|
|
262
|
+
- `unknown_subcommand`: `himi base44 entities` was given no subcommand, or one other than `query`,
|
|
263
|
+
`create` or `seed` (exit 2).
|
|
264
|
+
- `config_unloadable`: `config.ts` could not be loaded (exit 1).
|
|
265
|
+
- `invalid_config`: the `base44` block has lint errors; `issues[]` carries each `ruleCode` (exit 1).
|
|
266
|
+
- `no_app_id`: the config has no `base44` block, or no `base44.appId` (exit 1).
|
|
267
|
+
- `not_signed_in`: there is no session and no `BASE44_ACCESS_TOKEN`. Run `himi base44 login
|
|
268
|
+
--write` (exit 2).
|
|
269
|
+
- `write_scope_missing`: `--yes` was given, but the token's `scope` claim lacks `apps:write` or
|
|
270
|
+
cannot be read. Nothing is sent, not even a read. Run `himi base44 login --write` (exit 2).
|
|
271
|
+
- `schema_snapshot_unavailable`: the project download (`GET …/eject`) failed, or one of its entity
|
|
272
|
+
files does not parse or was dropped by the source walk. The current entity set is unknown, and
|
|
273
|
+
a sync without that file would delete the entity (exit 1).
|
|
274
|
+
- `schema_snapshot_empty`: the download has no entity schemas. That cannot be told apart from a
|
|
275
|
+
failed read, so the run refuses unless `--empty-app-ok` is passed (exit 1).
|
|
276
|
+
- `would_delete_foreign_entity`: the sync body would omit or alter an entity himi does not own.
|
|
277
|
+
The guard, which should never trip (exit 1).
|
|
278
|
+
- `owned_entity_removal_needs_flag`: an entity this app provisioned (recorded in
|
|
279
|
+
`base44-provisioned.json`) is no longer declared. Dropping it deletes its rows; pass
|
|
280
|
+
`--allow-destructive`. An entity in the namespace that this app never provisioned is left
|
|
281
|
+
untouched and only warned about (exit 1).
|
|
282
|
+
- `owned_field_removal_needs_flag`: an owned entity lost a declared field. Pass
|
|
283
|
+
`--allow-destructive` (exit 1).
|
|
284
|
+
- `owned_entity_unclaimed`: a declared owned entity already exists on the app, but
|
|
285
|
+
`base44-provisioned.json` does not record this app provisioning it, so it may belong to another
|
|
286
|
+
himi app whose slug shares the prefix. If it is this app's, record it in that file; otherwise
|
|
287
|
+
rename the declaration (exit 1).
|
|
288
|
+
- `snapshot_changed`: the entities changed between the plan and the re-read just before the
|
|
289
|
+
`PUT`. Nothing was sent; re-run (exit 1).
|
|
290
|
+
- `ledger_unreadable`: `base44-provisioned.json` exists but is not a JSON object (a merge
|
|
291
|
+
conflict, say). himi will not rewrite it from scratch, because that would drop other app ids'
|
|
292
|
+
records, so fix the file. The same code means the sync was sent but the file could not be
|
|
293
|
+
written afterwards; `error` names the entities to record by hand (exit 1).
|
|
294
|
+
- `foreign_entity_deleted`: after the `PUT`, Base44's `deleted[]` named an entity the plan did not
|
|
295
|
+
drop on purpose; `foreignDeleted` lists them. Defence in depth: the guard should make this
|
|
296
|
+
unreachable (exit 1).
|
|
297
|
+
- `nothing_to_seed`: `seed` found no owned entity (adopted ones are never seeded), or `--ai`
|
|
298
|
+
had none to write (exit 1).
|
|
299
|
+
- `seed_incomplete`: one or more owned entities were not seeded because they are missing from
|
|
300
|
+
the app, unrecorded in `base44-provisioned.json` (`skipped: "unclaimed"`), or their rows could
|
|
301
|
+
not be read; `skipped[]` names each one. Not-empty entities are
|
|
302
|
+
skipped (`skipped: "not-empty"`) without failing (exit 1).
|
|
303
|
+
- `seed_file_invalid`: `base44-seed.json` is not a JSON object keyed by entity name, one of
|
|
304
|
+
its entries is not an array of row objects, or a row has no declared field left once undeclared
|
|
305
|
+
keys are dropped (a blank record would make the entity non-empty for good) (exit 1).
|
|
306
|
+
- `function_name_taken`: a declared function name is already deployed and does not carry this
|
|
307
|
+
app's `.himi-owned` marker. Nothing was deployed (exit 1).
|
|
308
|
+
- `function_source_missing`: an owned function has no `base44/functions/<name>/` folder or no
|
|
309
|
+
entry file (exit 1).
|
|
310
|
+
- `function_source_unsafe`: the function folder contains a symlink or a denied path, the secret
|
|
311
|
+
scan flags a file, or the folder is over the file or byte cap. Nothing is uploaded (exit 1).
|
|
312
|
+
- `request_failed`: any other refused request, or a reply himi cannot read. That includes a sync
|
|
313
|
+
response with no `deleted[]` and a function listing with no `functions` array. `status` and
|
|
314
|
+
`serverError` are included when the server answered (exit 1).
|
|
315
|
+
|
|
252
316
|
## `himi base44 screens` codes
|
|
253
317
|
|
|
254
318
|
`himi base44 screens` (#4560, [base44-app-to-himi-app](base44-app-to-himi-app.md)) generates one
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1434.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": "cb5b7712df9ddebe73b144d2897a1f0c22f171a5e4e2f908546c7509"
|
|
75
75
|
}
|