create-hozu 0.1.0 → 0.3.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/README.md +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +25 -35
- package/skill/changing.md +81 -27
- package/skill/patterns.md +2 -1
- package/skill/reference.md +6 -1
- package/templates/guide.md +9 -4
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;AAChD,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AAE1D,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EAAiC,CAAA;AAGpE,eAAO,MAAM,YAAY,QAAsB,CAAA;AAiB/C,eAAO,MAAM,QAAQ,cAAe,MAAM,GAAG,SAAS,KAAG,MAGxD,CAAA;AAWD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBzG;AAYD,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,WAAW,SAAU,MAAM,WAAW,MAAM;;;;;QAKrD,KAAK;QACL,KAAK;QACL,KAAK;;;QAGL,oBAAoB;QACpB,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,sBAAsB;QACtB,kBAAkB;QAClB,GAAG;;;QAGH,WAAW;QACX,aAAa;QACb,UAAU;;;QAED,IAAI;;CACf,CAAA;AAEF,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBtF"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;AAChD,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AAE1D,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EAAiC,CAAA;AAGpE,eAAO,MAAM,YAAY,QAAsB,CAAA;AAiB/C,eAAO,MAAM,QAAQ,cAAe,MAAM,GAAG,SAAS,KAAG,MAGxD,CAAA;AAWD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBzG;AAYD,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,WAAW,SAAU,MAAM,WAAW,MAAM;;;;;QAKrD,KAAK;QACL,KAAK;QACL,KAAK;;;QAGL,oBAAoB;QACpB,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,sBAAsB;QACtB,kBAAkB;QAClB,GAAG;;;QAGH,WAAW;QACX,eAAe;QACf,aAAa;QACb,UAAU;;;QAED,IAAI;;CACf,CAAA;AAEF,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBtF"}
|
package/dist/index.js
CHANGED
|
@@ -64,7 +64,7 @@ export const packageJson = (name, version) => ({
|
|
|
64
64
|
private: true,
|
|
65
65
|
type: 'module',
|
|
66
66
|
scripts: {
|
|
67
|
-
check: '
|
|
67
|
+
check: 'hozu check',
|
|
68
68
|
start: 'node serve.ts',
|
|
69
69
|
build: 'hozu build',
|
|
70
70
|
},
|
|
@@ -79,6 +79,7 @@ export const packageJson = (name, version) => ({
|
|
|
79
79
|
},
|
|
80
80
|
devDependencies: {
|
|
81
81
|
'@hozu/cli': `^${version}`,
|
|
82
|
+
'@hozu/testing': `^${version}`,
|
|
82
83
|
'@types/node': '^22.20.4',
|
|
83
84
|
typescript: '^7.0.2',
|
|
84
85
|
},
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -5,9 +5,10 @@ description: Build or change an app with the Hozu framework (packages @hozu/*, f
|
|
|
5
5
|
|
|
6
6
|
# Hozu authoring guide
|
|
7
7
|
|
|
8
|
-
Hozu is not in your training data. These files are the whole API;
|
|
8
|
+
Hozu is not in your training data. These files are the whole API; skip `node_modules/@hozu`.
|
|
9
9
|
- **Changing an app:** read `changing.md` first, then only the app's own files.
|
|
10
|
-
- **Building an app:** read this file
|
|
10
|
+
- **Building an app:** read this file, run `hozu add feature <name> --page / --with auth,detail,toggle,filter,remove`
|
|
11
|
+
(auth = sign-in, per-user data) and edit the texts it lists; don't print the generated files.
|
|
11
12
|
- **`reference.md`** when the task needs it: routes, DOM fields, no-JS forms, `head`, 404/500, field errors,
|
|
12
13
|
sessions, languages, env, HTTP, Markdown, images, preview, PWA, page tests, deployment.
|
|
13
14
|
- **A diagnostic you do not understand:** `diagnostics.md`.
|
|
@@ -26,25 +27,27 @@ Hozu is not in your training data. These files are the whole API; do not read `n
|
|
|
26
27
|
|
|
27
28
|
## Files
|
|
28
29
|
```
|
|
29
|
-
hozu.config.ts
|
|
30
|
-
routes.ts
|
|
31
|
-
server.ts
|
|
32
|
-
serve.ts
|
|
33
|
-
app.css
|
|
30
|
+
hozu.config.ts project(): schema adapter, site, routes, pages, features
|
|
31
|
+
routes.ts route() declarations
|
|
32
|
+
server.ts resolvers(project, implement => [...]): query/mutation implementations
|
|
33
|
+
serve.ts createServer({ build, styles, resolvers }).listen(PORT)
|
|
34
|
+
app.css @import "tailwindcss";
|
|
34
35
|
features/<name>/
|
|
35
|
-
model.ts
|
|
36
|
-
views.ts
|
|
36
|
+
model.ts schemas, events, query / mutation / tag / fn, the machine
|
|
37
|
+
views.ts views, contracts, feature()
|
|
37
38
|
```
|
|
38
|
-
Relative imports end in `.ts`. Any other split works too.
|
|
39
39
|
|
|
40
|
-
##
|
|
40
|
+
## Commands (from the app directory)
|
|
41
41
|
```
|
|
42
|
-
pnpm exec
|
|
43
|
-
pnpm exec hozu
|
|
44
|
-
pnpm exec hozu
|
|
45
|
-
|
|
42
|
+
pnpm exec hozu check # after every edit: types, rules, contracts
|
|
43
|
+
pnpm exec hozu check --update-lock # accept an intended behaviour change
|
|
44
|
+
pnpm exec hozu add feature items --page / --with detail,toggle # a working feature, wired in
|
|
45
|
+
pnpm exec hozu map # outline of the app with file:line
|
|
46
|
+
pnpm exec hozu get / --select button --forms # pages without a server: text, attributes, forms
|
|
47
|
+
pnpm exec hozu post / --field title=A --next 'POST / title=a' --next / # submit a form like a browser
|
|
46
48
|
```
|
|
47
|
-
|
|
49
|
+
Diagnostics give `file:line`, cause and fix: apply the fix. `get` / `post` start from fresh in-memory data;
|
|
50
|
+
chain steps with `--next`. Run `node serve.ts` only to use the app. Relative imports end in `.ts`.
|
|
48
51
|
|
|
49
52
|
## model.ts
|
|
50
53
|
```ts
|
|
@@ -125,12 +128,11 @@ export const Board = ui.view({
|
|
|
125
128
|
]),
|
|
126
129
|
})
|
|
127
130
|
```
|
|
128
|
-
- `ui.<tag>(attrs, children)`;
|
|
131
|
+
- `ui.<tag>(attrs, children)`; values are literals, references or guards. `ui.each(list, 'id', (item) => node)`.
|
|
129
132
|
- `class` is a static string of Tailwind classes that must exist (HZ026). Conditional classes:
|
|
130
133
|
`toggle: { 'bg-indigo-600 text-white': op.eq(ctx.tab, t) }`. CSS variables: `vars: { '--hue': item.hue }`.
|
|
131
134
|
- Events: `on: { click: ui.send(Event, payload) }`. Payload fields: literals, references, `ui.dom.value`,
|
|
132
135
|
`ui.dom.form('name')`, `ui.dom.checked`, `ui.dom.valueAsNumber`, `ui.dom.key`.
|
|
133
|
-
- `ui.each(list, 'id', (item) => node)` (key `null` for primitives).
|
|
134
136
|
- Links: `ui.link(route, params, search)`, never a string path (HZ032). The third argument exists only when the
|
|
135
137
|
route declares `search` (`null` = all defaults). Filters that belong in the URL are `search` links, not context.
|
|
136
138
|
- A form whose submit reads only `ui.dom.form(...)`, literals, context, params and search also works without JS.
|
|
@@ -165,14 +167,9 @@ Every declaration goes in `declarations` once, under its name. Optional: `import
|
|
|
165
167
|
`exports: [Event, query, …]` (all other features may use), `styles: [new URL('./x.css', import.meta.url)]`.
|
|
166
168
|
|
|
167
169
|
## hozu.config.ts
|
|
170
|
+
`project({ schema: zodAdapter, styles, site: { url, name, lang }, routes: { home, itemPage }, pages, features })`;
|
|
171
|
+
`hozu add feature --page` adds static pages. A page with params:
|
|
168
172
|
```ts
|
|
169
|
-
export default project({
|
|
170
|
-
schema: zodAdapter,
|
|
171
|
-
styles: new URL('./app.css', import.meta.url),
|
|
172
|
-
site: { url: 'http://localhost:3000', name: 'Items', lang: 'en' },
|
|
173
|
-
routes: { home, itemPage },
|
|
174
|
-
pages: [
|
|
175
|
-
ui.page(home, { views: [Board], head: { render: () => ({ title: 'Items', description: 'All items.' }) } }),
|
|
176
173
|
ui.page(itemPage, {
|
|
177
174
|
views: [Detail],
|
|
178
175
|
head: {
|
|
@@ -182,9 +179,6 @@ export default project({
|
|
|
182
179
|
},
|
|
183
180
|
entries: { query: listItems, input: {}, params: (item) => ({ id: item.id }) }, // sitemap
|
|
184
181
|
}),
|
|
185
|
-
],
|
|
186
|
-
features: [items],
|
|
187
|
-
})
|
|
188
182
|
```
|
|
189
183
|
```ts
|
|
190
184
|
// routes.ts
|
|
@@ -193,10 +187,6 @@ export const itemPage = route({ path: '/items/:id', params: z.object({ id: z.str
|
|
|
193
187
|
```
|
|
194
188
|
|
|
195
189
|
## server.ts
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
implement(addItem, ({ title }, { fail }) => /* … */ fail('Duplicate', { title })), // → failed.Duplicate
|
|
200
|
-
])
|
|
201
|
-
```
|
|
202
|
-
Input failing its schema returns the error `Invalid` (`{ message, fields }`; see `reference.md`).
|
|
190
|
+
`export const createResolvers = () => resolvers(project, (implement) => [...])`, one
|
|
191
|
+
`implement(getItem, ({ id }, { fail }) => item ?? fail('NotFound', { id }))` per query / mutation. `hozu add feature` puts a feature's resolvers in `features/<name>/server.ts`.
|
|
192
|
+
Input failing its schema returns `Invalid` (`{ message, fields }`; `reference.md`).
|
package/skill/changing.md
CHANGED
|
@@ -1,40 +1,94 @@
|
|
|
1
1
|
# Changing a Hozu app
|
|
2
2
|
|
|
3
|
-
Keep the loop short:
|
|
3
|
+
Keep the loop short: map once, edit everything, check once, verify once.
|
|
4
4
|
|
|
5
5
|
## 1. Read
|
|
6
6
|
- The change request.
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
where it keeps views, contracts and `feature()`.
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## 2.
|
|
14
|
-
|
|
7
|
+
- `pnpm exec hozu map`: every route, query, mutation, event, state, view and contract, each with its `file:line`.
|
|
8
|
+
Open only the lines the change touches. Below, *model* is where the app keeps schemas, events, effects and
|
|
9
|
+
the machine (`model.ts`), and *views* where it keeps views, contracts and `feature()`.
|
|
10
|
+
- The API is in `SKILL.md`. Use a recipe below when one fits; open `patterns.md` / `reference.md` only for
|
|
11
|
+
something else.
|
|
12
|
+
|
|
13
|
+
## 2. Recipes
|
|
14
|
+
Names follow `hozu add feature items`: `Item`, `NewItem`, `Add`, `addItem`, `itemsMachine`, `ItemsBoard`.
|
|
15
|
+
|
|
16
|
+
### A field chosen in the add form (an enum)
|
|
17
|
+
- **model:**
|
|
18
|
+
- `export const Priority = z.enum(['low', 'normal', 'high'])`;
|
|
19
|
+
- add `priority: Priority` to `Item`, `NewItem` and the `Add` payload;
|
|
20
|
+
- context: `priority: Priority`, with `priority: 'normal'` in `initialContext`;
|
|
21
|
+
- `fields` gets `priority: z.string().nullable()`, with `priority: null` in `initialContext` and in the `Add`
|
|
22
|
+
assign that resets it;
|
|
23
|
+
- the `Add` assign also gets `op.set(ctx.priority, e.priority)`, and the add `invoke` input becomes
|
|
24
|
+
`{ title: ctx.draft, priority: ctx.priority }`.
|
|
25
|
+
- **views:**
|
|
26
|
+
- the form's submit sends `{ title: ui.dom.form('title'), priority: ui.dom.form('priority') }`;
|
|
27
|
+
- inside the form add
|
|
28
|
+
`ui.select({ name: 'priority', 'aria-label': 'Priority', class: 'rounded border px-2' }, ['low', 'normal', 'high'].map((p) => ui.option({ value: p, selected: p === 'normal' }, [p])))`;
|
|
29
|
+
- in the item: `ui.span({ class: 'text-xs' }, [item.priority])`.
|
|
30
|
+
- **Contracts:**
|
|
31
|
+
- add `priority: 'normal'` to every `Add` payload, to the add effect's input, and to the `done` result;
|
|
32
|
+
- `rejectsInvalid`'s `data.fields` and `changes.fields` get `priority: null`.
|
|
33
|
+
- **server:** store `priority` (seed items included) and return it.
|
|
34
|
+
|
|
35
|
+
### An action button that works on many items (e.g. "Clear done")
|
|
36
|
+
- **model:**
|
|
37
|
+
- `export const ClearDone = event({ payload: z.object({}) })`;
|
|
38
|
+
- `export const clearDone = mutation({ input: z.object({}), output: z.object({ removed: z.number() }), invalidates: () => [itemsTag()] })`;
|
|
39
|
+
- in `idle`: `on(ClearDone, { target: 'clearing', assign: () => [op.set(ctx.error, null)] })`;
|
|
40
|
+
- a state
|
|
41
|
+
`clearing: { ignore: [...], invoke: invoke(clearDone, { input: {}, done: [{ target: 'idle' }], failed: { Unexpected: [{ target: 'idle', assign: (e) => [op.set(ctx.error, e.message)] }] } }) }`;
|
|
42
|
+
- add `ClearDone` to every busy state's `ignore`, and give `clearing` the same list.
|
|
43
|
+
- **views:** the control
|
|
44
|
+
`ui.form({ on: { submit: ui.send(ClearDone, {}) } }, [ui.button({ type: 'submit', class: 'text-sm underline' }, ['Clear done'])])`.
|
|
45
|
+
- **Contracts:**
|
|
46
|
+
- `given: { state: 'idle' }`, when `[{ send: ClearDone, payload: {} }, { done: clearDone, result: { removed: 1 } }]`,
|
|
47
|
+
expect `{ state: 'idle', effects: [{ effect: clearDone, input: {} }] }`;
|
|
48
|
+
- a second one for `failed … 'Unexpected'` from `clearing`;
|
|
49
|
+
- add `ClearDone`, `clearDone` and both contracts to `declarations`.
|
|
50
|
+
- **server:**
|
|
51
|
+
`implement(clearDone, () => { const before = items.length; items.splice(0, items.length, ...items.filter((i) => !i.done)); return { removed: before - items.length } })`.
|
|
52
|
+
- **Try it:** `hozu post / --button 'Clear done' --next /`.
|
|
53
|
+
|
|
54
|
+
### A field shown on the detail page
|
|
55
|
+
In the detail view's `ready`: `ui.p({}, ['Priority: ', item.priority])`. The detail query already returns the whole
|
|
56
|
+
item.
|
|
57
|
+
|
|
58
|
+
### A detail page, when the feature has none
|
|
59
|
+
Run a fresh scaffold into a scratch app with `--with detail`, and copy the parts it prints:
|
|
60
|
+
- the route with params;
|
|
61
|
+
- the `get` query and its resolver;
|
|
62
|
+
- the detail view;
|
|
63
|
+
- the link in the list;
|
|
64
|
+
- `ui.page(...)` with `head` and `entries`.
|
|
65
|
+
|
|
66
|
+
### Other changes
|
|
67
|
+
| Change | Touch |
|
|
15
68
|
|---|---|
|
|
16
|
-
| New
|
|
17
|
-
|
|
|
18
|
-
| New
|
|
19
|
-
| New page | `routes.ts` (`params`, `search`) → a view with `route`, added to `declarations` → `ui.page(...)` in `hozu.config.ts` (with `head`, and `entries` when the route has params). |
|
|
20
|
-
| New filter / sort / page number that should be in the URL | the route's `search` schema (with a default) → links with `ui.link(route, params, { key: value })` → read `search.key` in the view. No machine change. |
|
|
69
|
+
| New UI-only state (a tab) | model: the context field and its initial value, an event, an `on` that `op.set`s it (add the event to every busy state's `ignore`) → views: the control, a contract, the event in `declarations`. |
|
|
70
|
+
| Filter / sort / page in the URL | the route's `search` schema (with a default) → links with `ui.link(route, params, { key: value })` → read `search.key` in the view. No machine change. |
|
|
71
|
+
| New page | `routes.ts` → a view with `route`, in `declarations` → `ui.page(...)` in `hozu.config.ts` (`head`, and `entries` when the route has params). |
|
|
21
72
|
|
|
22
73
|
Whenever the machine changes:
|
|
23
|
-
- Add one contract per new transition; HZ016 prints each missing one ready to paste.
|
|
24
|
-
|
|
25
|
-
- Every busy state `ignore`s every event its visible controls can send. HZ005 prints the missing `ignore` entries.
|
|
74
|
+
- Add one contract per new transition; HZ016 prints each missing one ready to paste.
|
|
75
|
+
- Every busy state `ignore`s every event its visible controls can send; HZ005 prints the missing entries.
|
|
26
76
|
|
|
27
77
|
## 3. Check (once, after all edits)
|
|
28
78
|
```
|
|
29
|
-
pnpm exec
|
|
79
|
+
pnpm exec hozu check
|
|
30
80
|
```
|
|
31
|
-
Fix what
|
|
32
|
-
`pnpm exec hozu
|
|
33
|
-
|
|
34
|
-
## 4. Verify (once)
|
|
35
|
-
Start the server with `PORT=4700 node serve.ts & echo $!`, then use one curl script:
|
|
36
|
-
- pages: `curl -s localhost:4700/…`;
|
|
37
|
-
- mutations:
|
|
38
|
-
`curl -s -X POST localhost:4700/_hozu/effect -H 'content-type: application/json' -d '{"effect":"<feature>.<mutation>","input":{…},"keys":[]}'`.
|
|
81
|
+
Fix what it reports. When the behaviour change is intended and everything is clean, run
|
|
82
|
+
`pnpm exec hozu check --update-lock`. HZ018 asks for this.
|
|
39
83
|
|
|
40
|
-
|
|
84
|
+
## 4. Verify (once, no server needed)
|
|
85
|
+
- **Pages:** `pnpm exec hozu get / /items/i1` prints the status, title, alerts and visible text.
|
|
86
|
+
- **Attributes and forms:** `--select button` (or `'[role=alert]'`, `a[href]`, `#id`) prints elements with their
|
|
87
|
+
attributes, e.g. `aria-pressed`; `--forms` lists each form's fields and buttons. Never start a server for this.
|
|
88
|
+
- **Forms:** `pnpm exec hozu post / --field title=A --field priority=high --next /items` fills the form like a
|
|
89
|
+
browser (other fields keep their defaults). It follows the redirect, then runs the next steps in the same
|
|
90
|
+
process.
|
|
91
|
+
- **Chaining:** chain what must share data, e.g. `--next 'POST / title=a'` (fields as `a=1&b=2`) or
|
|
92
|
+
`--next /items/i3`.
|
|
93
|
+
- **A form with only a button:** `--button 'Clear done'`, or `--next 'POST / @Clear done'`. With one form per item,
|
|
94
|
+
`--field id=t2` picks the item's form.
|
package/skill/patterns.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Hozu patterns
|
|
2
2
|
|
|
3
|
-
Patterns marked *(example)* are used in `example
|
|
3
|
+
Patterns marked *(example)* are used in `example/features/bookmarks/model.ts` and `views.ts`, next to this file;
|
|
4
|
+
read only the part you need.
|
|
4
5
|
|
|
5
6
|
- **Form with a server-side error** *(example)*:
|
|
6
7
|
- `ui.form({ on: { submit: ui.send(Add, { title: ui.dom.form('title') }) } }, [label, input, button])`.
|
package/skill/reference.md
CHANGED
|
@@ -51,6 +51,10 @@ Every mutation also has the framework error `Invalid` = `{ message, fields }`: o
|
|
|
51
51
|
(see `patterns.md`).
|
|
52
52
|
|
|
53
53
|
## Sessions
|
|
54
|
+
- **Start from the scaffold:** `hozu add feature notes --page / --with auth` writes `features/account`
|
|
55
|
+
(sign-in page, sign-out, `me`), the session cookie in `serve.ts`, per-user resolvers, and a redirect to `/login`
|
|
56
|
+
when signed out. Replace the name-only sign-in with real credentials before production; set `SESSION_SECRET`
|
|
57
|
+
(and `SESSION_SECURE=true` behind HTTPS).
|
|
54
58
|
- `project({ session: z.object({ user: z.string() }) })` declares the identity. Queries with `scope: 'user'` and
|
|
55
59
|
mutations receive `session`; public resolvers never do.
|
|
56
60
|
- `createServer({ session: (request) => value })`, or `sessionCookie({ name, secret })` from
|
|
@@ -122,7 +126,8 @@ shown when the network is down; a service worker is generated (HZ043: no params,
|
|
|
122
126
|
|
|
123
127
|
## Testing rendered pages
|
|
124
128
|
`const app = testApp({ build, resolvers })` from `@hozu/testing`; `await app.get('/')` gives
|
|
125
|
-
`{ status, headers, html, text, payload }`; `app.post(path, fields)` submits a native form.
|
|
129
|
+
`{ status, headers, html, text, payload }`; `app.post(path, fields)` submits a native form. In a browser test (Playwright),
|
|
130
|
+
wait for `html[data-hozu-ready]` before clicking: it is set when the page has hydrated.
|
|
126
131
|
|
|
127
132
|
## Deployment
|
|
128
133
|
`hozu build` writes `dist/public/` (static files for any host or CDN) and `dist/manifest.json`. On Node:
|
package/templates/guide.md
CHANGED
|
@@ -7,14 +7,19 @@ A web app built with Hozu (`@hozu/*`). Hozu is not in your training data.
|
|
|
7
7
|
- Changing existing code: read `__SKILL__/changing.md` first.
|
|
8
8
|
- The files in `__SKILL__/` are the whole API. Do not read the framework source in `node_modules/@hozu`.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## The loop
|
|
11
11
|
```
|
|
12
|
-
__RUN__
|
|
13
|
-
|
|
14
|
-
__RUN__ hozu
|
|
12
|
+
__RUN__ hozu add feature tasks --page / --with detail,toggle,filter,remove # then edit the texts it lists
|
|
13
|
+
# add auth to the list for sign-in and per-user data
|
|
14
|
+
__RUN__ hozu map # outline of the app with file:line, before a change
|
|
15
|
+
__RUN__ hozu check # after every change: types, rules, contracts
|
|
16
|
+
__RUN__ hozu check --update-lock # only to accept a clean, intended behaviour change
|
|
17
|
+
__RUN__ hozu get / --select button --forms # try pages without a server: text, attributes, forms
|
|
18
|
+
__RUN__ hozu post / --field title=Ship --next / # submit a form like a browser
|
|
15
19
|
```
|
|
16
20
|
__NOTE__
|
|
17
21
|
## Rules
|
|
22
|
+
- After `hozu add feature`, do not print the generated files: edit the texts it lists; `hozu map` shows the rest.
|
|
18
23
|
- Apply the fix each diagnostic gives; do not work around a rule.
|
|
19
24
|
- Every behaviour change comes with a contract change.
|
|
20
25
|
- Do not edit `__SKILL__/`: `__RUN__ hozu skill` rewrites it for the installed Hozu version.
|