create-hozu 0.5.0 → 0.6.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/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -34,9 +34,10 @@ npx hozu add feature items --page / --with auth,detail,toggle,filter,remove
|
|
|
34
34
|
npx hozu map # outline with file:line
|
|
35
35
|
npx hozu get / --select button --forms # a page, no server needed
|
|
36
36
|
npx hozu post / --field title=A --next / # a no-JS form post, cookies shown
|
|
37
|
+
npx hozu browse / --do 'fill Search=a' --do 'click Save' # real browser: errors, widgets, text
|
|
37
38
|
npx hozu docs views # one topic
|
|
38
39
|
```
|
|
39
|
-
`get` / `post` replace a running server for checks; `npm start` runs the app. Relative imports end in `.ts`.
|
|
40
|
+
`get` / `post` / `browse` replace a running server for checks; `npm start` runs the app. Relative imports end in `.ts`.
|
|
40
41
|
|
|
41
42
|
## A feature in one screen
|
|
42
43
|
```ts
|
package/skill/topics/data.md
CHANGED
|
@@ -15,7 +15,7 @@ export const addItem = mutation({
|
|
|
15
15
|
errors: { Duplicate: z.object({ title: z.string() }) }, // optional: declared failures
|
|
16
16
|
invalidates: () => [itemsTag()], // refreshes queries with these tags
|
|
17
17
|
})
|
|
18
|
-
export const visible = fn({ // computation: pure JS, self-contained (no imports, no
|
|
18
|
+
export const visible = fn({ // computation: pure JS, self-contained (no imports, no helpers outside impl: HZ047)
|
|
19
19
|
input: z.object({ items: z.array(Item), show: Show }), output: z.array(Item),
|
|
20
20
|
impl: ({ items, show }) => items.filter((i) => show === 'all' || !i.done),
|
|
21
21
|
})
|
|
@@ -39,4 +39,5 @@ around the rule.
|
|
|
39
39
|
| HZ044 | a feature file was loaded without the Hozu transform | run node with `--import @hozu/transform/register` (`npm start` does), or add `hozuTransform()` to Vite / Vitest |
|
|
40
40
|
| HZ045 | `serve.ts` misses the widget bundle or the session store | add `widgets: await bundleWidgets(build)` / `session: sessionCookie(…)` |
|
|
41
41
|
| HZ046 | an endpoint path is reserved, has params, or collides with a page, redirect or endpoint | use a static path such as `/api/…` (patch) |
|
|
42
|
+
| HZ047 | a `fn` body uses a helper or constant defined outside `impl` (it is sent to the browser as source) | write the helper inside `impl`, or pass the value as input |
|
|
42
43
|
| HZ042 | `site.locales` empty / missing `site.lang` / not a canonical tag, or `ui.alternate` of an undeclared locale | fix the list (`'zh-TW'`, not `'zh_tw'`) |
|
package/skill/topics/testing.md
CHANGED
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
- Each step prints its status, redirect and `set-cookie` attributes (`HttpOnly`, `SameSite`); the session cookie
|
|
7
7
|
is kept across `--next` steps. Two users: run two commands.
|
|
8
8
|
- Endpoints: `hozu get '/api/items?x=1'`.
|
|
9
|
+
- **In a real browser, still without a server:** `hozu browse / --do 'fill Search=park' --do 'click Tech Park'`.
|
|
10
|
+
- It uses the installed Chrome / Chromium / Edge (`HOZU_CHROME=/path` to choose), loads the page, waits for
|
|
11
|
+
hydration and runs the steps in order: `fill <label>=<value>`, `select <label>=<option>`, `check <label>`,
|
|
12
|
+
`click <name>`, `press <key>`, `wait <ms>`, `goto <path>`. Labels and names are what a user reads (aria-label,
|
|
13
|
+
`<label>`, placeholder, button text, `title`).
|
|
14
|
+
- It prints the uncaught exceptions, `console.error`s and failed requests, every widget on the page (mounted,
|
|
15
|
+
failed, size, canvases), the visible text and `--select <css>` elements; exit code 1 when anything failed.
|
|
16
|
+
- `--screenshot shot.png` saves the viewport (open it to look); `--reduced-motion` emulates reduced motion.
|
|
17
|
+
- Use it once after client-side work (widgets, islands); `get` / `post` stay the fast checks.
|
|
9
18
|
- In code: `const app = testApp({ build, resolvers })` from `@hozu/testing`; `await app.get('/')` →
|
|
10
19
|
`{ status, headers, html, text, payload }`; `app.post(path, fields)` submits a native form.
|
|
11
20
|
- Vitest: add `hozuTransform()` from `@hozu/transform/vite` to `plugins`.
|
package/skill/topics/widgets.md
CHANGED
|
@@ -23,3 +23,6 @@ export default implement<typeof Map>(({ el, props, emit, signal }) => {
|
|
|
23
23
|
- `serve.ts` passes `widgets: await bundleWidgets(build)` (the server refuses to start without it; `hozu build` bundles
|
|
24
24
|
them itself). A library's CSS goes in `app.css` (`@import "leaflet/dist/leaflet.css";`); a map or chart host needs a
|
|
25
25
|
height class.
|
|
26
|
+
- Check it with `hozu browse /` (no server): each widget is listed as mounted / failed / not mounted with its size
|
|
27
|
+
and canvases, next to any error it threw. A mounted host carries `data-hozu-widget="<feature>.<Name>"` and
|
|
28
|
+
`data-hozu-widget-state="mounted"` for your own browser tests.
|
package/templates/guide.md
CHANGED
|
@@ -16,6 +16,7 @@ __RUN__ hozu check # after every change: types, rules, c
|
|
|
16
16
|
__RUN__ hozu check --update-lock # only to accept a clean, intended behaviour change
|
|
17
17
|
__RUN__ hozu get / --select button --forms # try pages without a server: text, attributes, forms
|
|
18
18
|
__RUN__ hozu post / --field title=Ship --next / # submit a form like a browser
|
|
19
|
+
__RUN__ hozu browse / --do 'click Save' # real browser, no server: errors, widgets, text after steps
|
|
19
20
|
```
|
|
20
21
|
__NOTE__
|
|
21
22
|
## Rules
|