@hozu/cli 0.25.0 → 0.26.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/CHANGELOG.md +1510 -0
- package/dist/commands/browse-page.d.ts.map +1 -1
- package/dist/commands/browse-page.js +7 -1
- package/dist/commands/browse-page.js.map +1 -1
- package/dist/commands/browse-tab.d.ts +1 -1
- package/dist/commands/browse-tab.d.ts.map +1 -1
- package/dist/commands/browse-tab.js +20 -9
- package/dist/commands/browse-tab.js.map +1 -1
- package/dist/commands/browse-world.d.ts.map +1 -1
- package/dist/commands/browse-world.js +73 -9
- package/dist/commands/browse-world.js.map +1 -1
- package/dist/commands/browse.d.ts +2 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +4 -3
- package/dist/commands/browse.js.map +1 -1
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +17 -3
- package/dist/commands/explain.js.map +1 -1
- package/dist/commands/request.d.ts +1 -0
- package/dist/commands/request.d.ts.map +1 -1
- package/dist/commands/request.js +14 -4
- package/dist/commands/request.js.map +1 -1
- package/dist/commands/scaffold.js +1 -1
- package/dist/commands/scaffold.js.map +1 -1
- package/dist/commands/target.d.ts +17 -0
- package/dist/commands/target.d.ts.map +1 -0
- package/dist/commands/target.js +168 -0
- package/dist/commands/target.js.map +1 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +10 -3
- package/dist/commands/validate.js.map +1 -1
- package/dist/contract.d.ts +2 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +17 -1
- package/dist/main.js.map +1 -1
- package/dist/migrate/steps.d.ts.map +1 -1
- package/dist/migrate/steps.js +20 -0
- package/dist/migrate/steps.js.map +1 -1
- package/package.json +9 -8
- package/schema/inspect.schema.json +0 -7
- package/schema/why.schema.json +6 -1
- package/skill/example/features/bookmarks/views.ts +3 -1
- package/skill/topics/components.md +2 -2
- package/skill/topics/deploy.md +14 -12
- package/skill/topics/machine.md +3 -2
- package/skill/topics/testing.md +3 -1
- package/skill/topics/views.md +7 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hozu/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "The hozu command: check, map, why, show, get, browse, call, plan, add, build, export, gen, dev, serve, docs, migrate and skill (all with --json)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hozu",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"bin",
|
|
39
|
+
"CHANGELOG.md",
|
|
39
40
|
"dist",
|
|
40
41
|
"schema",
|
|
41
42
|
"skill",
|
|
@@ -48,14 +49,14 @@
|
|
|
48
49
|
"access": "public"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
51
|
-
"@hozu/core": "0.
|
|
52
|
-
"@hozu/
|
|
53
|
-
"@hozu/machine": "0.
|
|
54
|
-
"@hozu/
|
|
55
|
-
"@hozu/transform": "0.
|
|
56
|
-
"@hozu/
|
|
52
|
+
"@hozu/core": "0.26.0",
|
|
53
|
+
"@hozu/validator": "0.26.0",
|
|
54
|
+
"@hozu/machine": "0.26.0",
|
|
55
|
+
"@hozu/devtools": "0.26.0",
|
|
56
|
+
"@hozu/transform": "0.26.0",
|
|
57
|
+
"@hozu/compiler": "0.26.0"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"create-hozu": "0.
|
|
60
|
+
"create-hozu": "0.26.0"
|
|
60
61
|
}
|
|
61
62
|
}
|
|
@@ -1429,13 +1429,6 @@
|
|
|
1429
1429
|
},
|
|
1430
1430
|
"payload": {
|
|
1431
1431
|
"$ref": "#/definitions/ValueExpr"
|
|
1432
|
-
},
|
|
1433
|
-
"keys": {
|
|
1434
|
-
"type": "array",
|
|
1435
|
-
"items": {
|
|
1436
|
-
"type": "string"
|
|
1437
|
-
},
|
|
1438
|
-
"description": "Only these key presses send it, and they do not reach the browser's own shortcuts (ADR 0072 B)."
|
|
1439
1432
|
}
|
|
1440
1433
|
},
|
|
1441
1434
|
"required": [
|
package/schema/why.schema.json
CHANGED
|
@@ -224,6 +224,10 @@
|
|
|
224
224
|
"items": {
|
|
225
225
|
"type": "string"
|
|
226
226
|
}
|
|
227
|
+
},
|
|
228
|
+
"decides": {
|
|
229
|
+
"type": "boolean",
|
|
230
|
+
"description": "Whether it decides, so a contract must cover it; otherwise the lock reviews it (ADR 0037)."
|
|
227
231
|
}
|
|
228
232
|
},
|
|
229
233
|
"required": [
|
|
@@ -234,7 +238,8 @@
|
|
|
234
238
|
"guard",
|
|
235
239
|
"assign",
|
|
236
240
|
"navigate",
|
|
237
|
-
"coveredBy"
|
|
241
|
+
"coveredBy",
|
|
242
|
+
"decides"
|
|
238
243
|
],
|
|
239
244
|
"additionalProperties": false
|
|
240
245
|
},
|
|
@@ -55,7 +55,9 @@ export const Board = ui.view({
|
|
|
55
55
|
{ name: 'kind', 'aria-label': 'Kind', class: 'rounded border px-2 py-2' },
|
|
56
56
|
kinds.map((k) => ui.option({ value: k, selected: ctx.kind === k }, [k])),
|
|
57
57
|
),
|
|
58
|
-
ui.use(Button, { props: { type: 'submit', disabled: is(['adding']) }
|
|
58
|
+
ui.use(Button, { props: { type: 'submit', disabled: is(['adding']) }, keys: ['Mod+Enter'] }, [
|
|
59
|
+
'Add',
|
|
60
|
+
]),
|
|
59
61
|
],
|
|
60
62
|
),
|
|
61
63
|
ctx.error !== null && ui.p({ role: 'alert', class: 'text-rose-600' }, [ctx.error]),
|
|
@@ -20,8 +20,8 @@ export const Button = ui.component({
|
|
|
20
20
|
ui.use(Button, { variant: { tone: 'ghost' }, props: { busy: ctx.saving }, slots: { icon: ui.span({}, ['+']) },
|
|
21
21
|
on: { press: ui.send(Save, {}) }, class: 'w-full' }, ['Save']) // in a view; its id is ui.Button
|
|
22
22
|
```
|
|
23
|
-
- **`ui.use` keys** (all optional): `variant` (literals only, HZ071), `props` (
|
|
24
|
-
|
|
23
|
+
- **`ui.use` keys** (all optional): `variant` (literals only, HZ071), `props` (what changes at run time), `slots`,
|
|
24
|
+
`on`, `class`, `keys` (a control root); children only with `children: true`.
|
|
25
25
|
- **Render** reads only `props`, `slots`, `children`, `on` and `classes`; the caller passes sends, links and text
|
|
26
26
|
in (HZ070).
|
|
27
27
|
- **`class`** may only add classes that set none of the component's properties (`w-full`, `md:hidden`); to change
|
package/skill/topics/deploy.md
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
`app({ resolvers, session?, components?, … })` from `@hozu/runtime-server`. `hozu serve`, `hozu check`, `hozu get`,
|
|
5
5
|
`hozu browse` and `testApp(app)` all run it, so what the tools verify is what production serves.
|
|
6
6
|
- **Which host:** nobody marks pages static. `npx hozu export` writes every page for a static host (GitHub Pages,
|
|
7
|
-
Netlify, Cloudflare Pages
|
|
8
|
-
|
|
9
|
-
- **Node:** `npm start` is `hozu serve` (
|
|
10
|
-
--omit=dev`, `CMD ["npx", "hozu", "serve"]`.
|
|
7
|
+
Netlify, Cloudflare Pages) to `dist/` and exits 1 naming each page or effect that needs a server; then
|
|
8
|
+
`npx hozu build --target node | workers | vercel` writes what that platform deploys as is and lists what it needs.
|
|
9
|
+
- **Node:** `npm start` is `hozu serve` (`PORT`, `HOST`); `--target node` writes its `Dockerfile`.
|
|
11
10
|
- Set `SESSION_SECRET` when the app has sessions: `npm start` (`hozu serve`) runs as production unless `NODE_ENV` is set, and production refuses to start without it. `hozu dev`, `get`, `browse` and `call` do not need it.
|
|
12
11
|
- Workers, several instances, sessions in KV, upgrading: see --more.
|
|
13
12
|
|
|
@@ -24,14 +23,16 @@
|
|
|
24
23
|
`dist/public/`, `dist/manifest.json` and `dist/server/render.js`. It compresses answers as they stream (gzip),
|
|
25
24
|
and framework files with brotli or gzip from the `.br` / `.gz` that `hozu build` writes. Live streams are not
|
|
26
25
|
compressed. The edge handler leaves compression to the platform.
|
|
27
|
-
- **
|
|
28
|
-
`
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
- **Workers and Vercel:** `npx hozu build --target workers` writes `dist/workers/` (`worker.mjs`, `assets/`,
|
|
27
|
+
`wrangler.jsonc`; then `npx wrangler deploy` there); `--target vercel` writes `.vercel/output/` (an Edge Function;
|
|
28
|
+
then `npx vercel deploy --prebuilt`). Both need `@hozu/bundle`, bundle the app with its resolvers (a resolver that
|
|
29
|
+
imports Node-only code fails the build there) and print what the platform needs: env, `SESSION_SECRET`, a KV
|
|
30
|
+
namespace bound as `SESSIONS` on Workers, a shared session store on Vercel. Workers keep no memory between
|
|
31
|
+
requests: data goes in a database. Check the bundle before deploying: `npx hozu browse / --build dist/workers`
|
|
32
|
+
(env from your shell; `--session` signs in through its KV).
|
|
33
|
+
- **Another edge (Bun, Deno):** `hozu build --out build`, then an entry that calls
|
|
34
|
+
`createHandler(app, { manifest, render, env })` with `import * as render from './build/server/render.js'`,
|
|
35
|
+
bundled with `hozuTransform()` from `@hozu/transform/esbuild` (the target's entry is the model).
|
|
35
36
|
- **Static host:** `npx hozu export [--out dist]` (`@hozu/adapter-static`, in new apps) empties the folder, writes
|
|
36
37
|
every page without per-request server data plus `.nojekyll`, and prints what it skipped. Pages whose data runs in
|
|
37
38
|
the browser (`runs: 'browser'` / `'either'`) export completely; a page that calls a server effect is listed
|
|
@@ -75,3 +76,4 @@
|
|
|
75
76
|
## Upgrading Hozu
|
|
76
77
|
`npx -p @hozu/cli@latest hozu migrate` (preview with `--dry-run`), then run the `next:` lines it prints: install, and
|
|
77
78
|
`npx hozu migrate` again, which checks the IR is unchanged and runs `hozu check`. Never raise `@hozu/*` by hand.
|
|
79
|
+
Each release's notes are in `node_modules/@hozu/cli/CHANGELOG.md`.
|
package/skill/topics/machine.md
CHANGED
|
@@ -71,8 +71,9 @@ export const m = machine({
|
|
|
71
71
|
- **Across pages:** the calm state (the last state without `invoke`, with its context) is kept in `sessionStorage`
|
|
72
72
|
and resumed on a page that shows the same machine view, or on the same address; a reload or a page without that
|
|
73
73
|
view starts from `initialContext` (or `seed`).
|
|
74
|
-
- `Unexpected`'s `message` is `Internal error (call <id>)` in production (the real one reaches `onError`)
|
|
75
|
-
code or a fixed text
|
|
74
|
+
- `Unexpected`'s `message` is `Internal error (call <id>)` in production (the real one reaches `onError`). A page
|
|
75
|
+
for customers stores a code or a fixed text; a staff tool may show `e.message`, whose call id matches the server
|
|
76
|
+
log line.
|
|
76
77
|
- **assign** values are event (`e`), result (`r`) or error fields, context, literals, operators and `fn()` calls.
|
|
77
78
|
- **guard** conditions: a field (`() => ctx.auto`), comparisons, `&&`, `||`, `!`, or a boolean `fn()`.
|
|
78
79
|
- **navigate** sends the browser to `ui.link(route, params, search?)` after the transition. It returns one link: to
|
package/skill/topics/testing.md
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
<!-- more -->
|
|
31
31
|
|
|
32
|
+
- `press Mod+s` (with `Mod`, `Ctrl`, `Meta`, `Alt`, `Shift`) presses the control whose `keys` match, as a person would; with `--js off` it reports that a shortcut needs JavaScript.
|
|
32
33
|
- **Server errors:** what the app's `onError` receives (a resolver that threw, an invalid input) is listed under the
|
|
33
34
|
step or the `get` request that caused it, `server error: <message> (<feature.effect>)`; `--json` `serverErrors`.
|
|
34
35
|
- **A calm page:** a step that rebuilds elements unchanged says `N elements rebuilt unchanged (a flash: main > form >
|
|
@@ -83,7 +84,8 @@
|
|
|
83
84
|
- **More checks in a step:**
|
|
84
85
|
- A click that would land on another element fails the step: `the click would land on <h3>, which contains it, above
|
|
85
86
|
<a href="/x">: a person cannot click it` (an overlay, a card covering its link).
|
|
86
|
-
- A navigation shows how it arrived: `→ /x (loaded, 32 ms)
|
|
87
|
+
- A navigation shows how it arrived: `→ /x (loaded, 32 ms)`; with `--js both`, per mode. Browse always shows
|
|
88
|
+
`loaded`: Chrome turns prerendering off under DevTools request interception, so this is the worst case.
|
|
87
89
|
- `--select` prints each element's `class` too. An element moved to another parent is not a flash.
|
|
88
90
|
- A server error that `get` or `browse` lists is noted once with `a production server shows "Internal error" here`:
|
|
89
91
|
the visitor sees that text and the call id; `onError` gets the message.
|
package/skill/topics/views.md
CHANGED
|
@@ -55,10 +55,13 @@ export const Board = ui.view({
|
|
|
55
55
|
`row(item)`; it is inlined, so the IR equals the inline form. A plain function that receives data is HZ059.
|
|
56
56
|
- **Shared UI:** use the kit component, not a styled `ui.button` per page (`example/` uses a kit).
|
|
57
57
|
- **More events:** any DOM event name plus `visible` (entered the viewport). Payload fields also:
|
|
58
|
-
`ui.dom.formAll('name')`, `ui.dom.checked`, `ui.dom.valueAsNumber`, `ui.dom.key`. Keyboard shortcuts
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
`ui.dom.formAll('name')`, `ui.dom.checked`, `ui.dom.valueAsNumber`, `ui.dom.key`. Keyboard shortcuts
|
|
59
|
+
belong to the control they press: `ui.input({ name: 'q', keys: ['/'] })` focuses the field, `ui.button({ type:
|
|
60
|
+
'submit', keys: ['Mod+s'] }, ['Save'])` clicks it (so the form submits; no machine needed); a kit control takes
|
|
61
|
+
them too: `ui.use(Button, { props, keys: ['Mod+Enter'] }, ['Add'])`. `Mod` is ⌘ on Apple,
|
|
62
|
+
Ctrl elsewhere; also `Ctrl`, `Meta`, `Alt`, `Shift`. A printable key without a modifier waits while the person types
|
|
63
|
+
in another field (`Escape` does not); inside an open modal only its controls count. The page loads a small module
|
|
64
|
+
for it and writes `aria-keyshortcuts`; two controls always shown together with one key is HZ014. `ui.dom.value` / `ui.dom.form`
|
|
62
65
|
fill an enum field only from a `<select>`, radios or submit buttons whose literal values are all members (HZ033).
|
|
63
66
|
- **Search in links:** the third argument of `ui.link` is optional and exists only when the route declares `search`:
|
|
64
67
|
omitted means every default, and a search lists only the fields that differ: `ui.link(home, null, { show: 'done' })`.
|