@hozu/cli 0.21.1 → 0.22.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/bin/hozu.js +2 -2
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +10 -7
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/app.d.ts +3 -0
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +23 -0
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/browse-tab.d.ts +4 -2
- package/dist/commands/browse-tab.d.ts.map +1 -1
- package/dist/commands/browse-tab.js +36 -5
- package/dist/commands/browse-tab.js.map +1 -1
- package/dist/commands/browse-world.d.ts +3 -0
- package/dist/commands/browse-world.d.ts.map +1 -1
- package/dist/commands/browse-world.js +2 -1
- package/dist/commands/browse-world.js.map +1 -1
- package/dist/commands/browse.d.ts +1 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +50 -11
- package/dist/commands/browse.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +6 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/gen.d.ts +6 -0
- package/dist/commands/gen.d.ts.map +1 -0
- package/dist/commands/gen.js +53 -0
- package/dist/commands/gen.js.map +1 -0
- package/dist/commands/request.d.ts +6 -1
- package/dist/commands/request.d.ts.map +1 -1
- package/dist/commands/request.js +60 -6
- package/dist/commands/request.js.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +11 -3
- package/dist/commands/serve.js.map +1 -1
- package/dist/contract.d.ts +40 -3
- package/dist/contract.d.ts.map +1 -1
- package/dist/gen/go.d.ts +5 -0
- package/dist/gen/go.d.ts.map +1 -0
- package/dist/gen/go.js +369 -0
- package/dist/gen/go.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +28 -2
- package/dist/main.js.map +1 -1
- package/dist/migrate/steps.d.ts.map +1 -1
- package/dist/migrate/steps.js +17 -0
- package/dist/migrate/steps.js.map +1 -1
- package/dist/remote.d.ts +15 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +58 -0
- package/dist/remote.js.map +1 -0
- package/package.json +8 -8
- package/schema/browse.schema.json +55 -4
- package/schema/check.schema.json +2 -1
- package/schema/gen.schema.json +61 -0
- package/schema/inspect.schema.json +20 -0
- package/schema/migrate.schema.json +2 -1
- package/schema/render.schema.json +2 -1
- package/schema/request.schema.json +35 -1
- package/skill/example/features/bookmarks/views.ts +1 -2
- package/skill/topics/data.md +49 -0
- package/skill/topics/diagnostics.md +1 -0
- package/skill/topics/http.md +2 -1
- package/skill/topics/machine.md +4 -5
- package/skill/topics/pages.md +1 -1
- package/skill/topics/recipes.md +22 -0
- package/skill/topics/testing.md +8 -4
- package/skill/topics/views.md +13 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"steps.js","sourceRoot":"","sources":["../../src/migrate/steps.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"steps.js","sourceRoot":"","sources":["../../src/migrate/steps.ts"],"names":[],"mappings":"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"}
|
package/dist/remote.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type BuildResult, type Diagnostic, type RemoteContract } from '@hozu/core/ir';
|
|
2
|
+
import type { Loaded } from './load.ts';
|
|
3
|
+
export interface RemoteGroup {
|
|
4
|
+
/** The generated contract file, absolute. */
|
|
5
|
+
file: string;
|
|
6
|
+
/** The Go package: the contract's folder name. */
|
|
7
|
+
pkg: string;
|
|
8
|
+
contract: RemoteContract;
|
|
9
|
+
}
|
|
10
|
+
export declare const packageOf: (file: string) => string;
|
|
11
|
+
/** Every `remote()` group of the app's resolvers with its contract (ADR 0068). */
|
|
12
|
+
export declare function remoteGroups(loaded: Loaded, build: BuildResult, resolvers: unknown): Promise<RemoteGroup[]>;
|
|
13
|
+
/** HZ093 for a contract that is missing, not Go, or generated from other declarations. */
|
|
14
|
+
export declare function remoteDiagnostics(loaded: Loaded, groups: RemoteGroup[], app: string): Diagnostic[];
|
|
15
|
+
//# sourceMappingURL=remote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAS,KAAK,UAAU,EAAE,KAAK,cAAc,EAAkB,MAAM,eAAe,CAAA;AAG7G,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAEvC,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,cAAc,CAAA;CACzB;AASD,eAAO,MAAM,SAAS,SAAU,MAAM,WAGG,CAAA;AAEzC,kFAAkF;AAClF,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAQxB;AAaD,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,CAsClG"}
|
package/dist/remote.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, extname, relative } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { codes, remoteContract } from '@hozu/core/ir';
|
|
5
|
+
import { importer } from './commands/app.js';
|
|
6
|
+
import { goFingerprint } from './gen/go.js';
|
|
7
|
+
export const packageOf = (file) => basename(dirname(file))
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.replace(/[^a-z0-9_]/g, '') || 'hozu';
|
|
10
|
+
/** Every `remote()` group of the app's resolvers with its contract (ADR 0068). */
|
|
11
|
+
export async function remoteGroups(loaded, build, resolvers) {
|
|
12
|
+
const data = await importer(loaded, 'gen')('@hozu/data');
|
|
13
|
+
return data
|
|
14
|
+
.remotesOf(resolvers, (decl) => build.bindings.refs.get(decl))
|
|
15
|
+
.map(({ options, refs }) => {
|
|
16
|
+
const file = fileURLToPath(options.contract.href);
|
|
17
|
+
return { file, pkg: packageOf(file), contract: remoteContract(build.ir, refs) };
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const appLine = (app) => {
|
|
21
|
+
try {
|
|
22
|
+
const at = readFileSync(app, 'utf8')
|
|
23
|
+
.split('\n')
|
|
24
|
+
.findIndex((l) => /\bremote\(/.test(l));
|
|
25
|
+
return { file: app, line: at + 1, column: 1 };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/** HZ093 for a contract that is missing, not Go, or generated from other declarations. */
|
|
32
|
+
export function remoteDiagnostics(loaded, groups, app) {
|
|
33
|
+
const shown = (file) => relative(dirname(loaded.path), file);
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const g of groups) {
|
|
36
|
+
const problem = (message, cause, summary) => out.push({
|
|
37
|
+
code: 'HZ093',
|
|
38
|
+
severity: codes.HZ093.severity,
|
|
39
|
+
message,
|
|
40
|
+
location: { feature: null, pointer: '/app', source: appLine(app) },
|
|
41
|
+
cause,
|
|
42
|
+
fix: { summary, snippet: 'npx hozu gen', patch: null },
|
|
43
|
+
});
|
|
44
|
+
if (extname(g.file) !== '.go') {
|
|
45
|
+
problem(`remote() names the contract ${shown(g.file)}, but hozu gen writes Go contracts only`, 'The contract is the generated file the service compiles against.', "Name a .go file: contract: new URL('./service/hozu/contract.go', import.meta.url)");
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!existsSync(g.file)) {
|
|
49
|
+
problem(`The remote contract ${shown(g.file)} does not exist`, 'hozu gen writes it from the declarations remote() lists.', 'Run hozu gen, then implement the Resolvers interface it prints in the service');
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const found = goFingerprint(readFileSync(g.file, 'utf8'));
|
|
53
|
+
if (found !== g.contract.fingerprint)
|
|
54
|
+
problem(`The remote contract ${shown(g.file)} is stale (${found ?? 'no fingerprint'}, the declarations are ${g.contract.fingerprint})`, 'A declaration remote() lists changed after hozu gen wrote the contract, so the service would answer 409.', 'Run hozu gen, fix the service until go build passes, and rebuild it');
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hozu/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "The hozu command: check, map, why, show, get, browse, call, plan, add, build, dev, serve, docs, migrate and skill (all with --json)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hozu",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
"access": "public"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@hozu/core": "0.
|
|
52
|
-
"@hozu/
|
|
53
|
-
"@hozu/
|
|
54
|
-
"@hozu/
|
|
55
|
-
"@hozu/
|
|
56
|
-
"@hozu/transform": "0.
|
|
51
|
+
"@hozu/core": "0.22.0",
|
|
52
|
+
"@hozu/devtools": "0.22.0",
|
|
53
|
+
"@hozu/validator": "0.22.0",
|
|
54
|
+
"@hozu/machine": "0.22.0",
|
|
55
|
+
"@hozu/compiler": "0.22.0",
|
|
56
|
+
"@hozu/transform": "0.22.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"create-hozu": "0.
|
|
59
|
+
"create-hozu": "0.22.0"
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -167,13 +167,36 @@
|
|
|
167
167
|
"description": "With the document kept: how many elements are new after the step (a region drawn again)."
|
|
168
168
|
},
|
|
169
169
|
"flashes": {
|
|
170
|
-
"type": "
|
|
171
|
-
"
|
|
170
|
+
"type": "object",
|
|
171
|
+
"properties": {
|
|
172
|
+
"count": {
|
|
173
|
+
"type": "number"
|
|
174
|
+
},
|
|
175
|
+
"elements": {
|
|
176
|
+
"type": "array",
|
|
177
|
+
"items": {
|
|
178
|
+
"type": "string"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"required": [
|
|
183
|
+
"count",
|
|
184
|
+
"elements"
|
|
185
|
+
],
|
|
186
|
+
"additionalProperties": false,
|
|
187
|
+
"description": "Elements the step removed and built again unchanged: same tag, class, text, `name`, `id`, `href`, `src`, `type` and parent path (ADR 0067 C2, ADR 0069 A3). `count` counts every such element, `elements` names the outermost ones as CSS-like paths (`main > form > input[name=card]`)."
|
|
172
188
|
},
|
|
173
189
|
"shift": {
|
|
174
190
|
"type": "number",
|
|
175
191
|
"description": "Layout shift no input explains (layout-shift entries without recent input, summed, as CLS counts them)."
|
|
176
192
|
},
|
|
193
|
+
"serverErrors": {
|
|
194
|
+
"type": "array",
|
|
195
|
+
"items": {
|
|
196
|
+
"$ref": "#/definitions/ServerError"
|
|
197
|
+
},
|
|
198
|
+
"description": "What the app's `onError` received during the step (ADR 0069 A2)."
|
|
199
|
+
},
|
|
177
200
|
"url": {
|
|
178
201
|
"type": "string"
|
|
179
202
|
},
|
|
@@ -214,6 +237,32 @@
|
|
|
214
237
|
"off"
|
|
215
238
|
]
|
|
216
239
|
},
|
|
240
|
+
"ServerError": {
|
|
241
|
+
"type": "object",
|
|
242
|
+
"properties": {
|
|
243
|
+
"message": {
|
|
244
|
+
"type": "string"
|
|
245
|
+
},
|
|
246
|
+
"effect": {
|
|
247
|
+
"type": "string",
|
|
248
|
+
"description": "The effect (`feature.symbol`) whose resolver or input failed, when known."
|
|
249
|
+
},
|
|
250
|
+
"path": {
|
|
251
|
+
"type": "string",
|
|
252
|
+
"description": "The request path, when known."
|
|
253
|
+
},
|
|
254
|
+
"details": {
|
|
255
|
+
"type": "object",
|
|
256
|
+
"additionalProperties": {},
|
|
257
|
+
"description": "The other fields `onError` received, such as the schema issues of an invalid input and where it came from."
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
"required": [
|
|
261
|
+
"message"
|
|
262
|
+
],
|
|
263
|
+
"additionalProperties": false,
|
|
264
|
+
"description": "One call of the app's `onError` (ADR 0069 A2): a resolver that threw, an invalid input, a failed stream."
|
|
265
|
+
},
|
|
217
266
|
"BrowseElsewhere": {
|
|
218
267
|
"type": "object",
|
|
219
268
|
"properties": {
|
|
@@ -252,8 +301,10 @@
|
|
|
252
301
|
"enum": [
|
|
253
302
|
"exception",
|
|
254
303
|
"console",
|
|
255
|
-
"request"
|
|
256
|
-
|
|
304
|
+
"request",
|
|
305
|
+
"server"
|
|
306
|
+
],
|
|
307
|
+
"description": "`server`: the app's `onError` was called outside any step (opening the page); a step lists its own."
|
|
257
308
|
},
|
|
258
309
|
"text": {
|
|
259
310
|
"type": "string"
|
package/schema/check.schema.json
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$ref": "#/definitions/GenOutput",
|
|
4
|
+
"definitions": {
|
|
5
|
+
"GenOutput": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"contracts": {
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"file": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The contract file, relative to the working directory."
|
|
16
|
+
},
|
|
17
|
+
"package": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"fingerprint": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"effects": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"description": "The effects it implements: feature.symbol."
|
|
29
|
+
},
|
|
30
|
+
"written": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"description": "False when the file already held this contract."
|
|
33
|
+
},
|
|
34
|
+
"problems": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": {
|
|
37
|
+
"type": "string"
|
|
38
|
+
},
|
|
39
|
+
"description": "Effects that cannot be remote (the server refuses to start with them, HZ093)."
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"required": [
|
|
43
|
+
"file",
|
|
44
|
+
"package",
|
|
45
|
+
"fingerprint",
|
|
46
|
+
"effects",
|
|
47
|
+
"written",
|
|
48
|
+
"problems"
|
|
49
|
+
],
|
|
50
|
+
"additionalProperties": false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"required": [
|
|
55
|
+
"contracts"
|
|
56
|
+
],
|
|
57
|
+
"additionalProperties": false,
|
|
58
|
+
"description": "`hozu gen` (ADR 0068)."
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1284,6 +1284,26 @@
|
|
|
1284
1284
|
}
|
|
1285
1285
|
]
|
|
1286
1286
|
},
|
|
1287
|
+
"seedQueries": {
|
|
1288
|
+
"type": "array",
|
|
1289
|
+
"items": {
|
|
1290
|
+
"type": "object",
|
|
1291
|
+
"properties": {
|
|
1292
|
+
"ref": {
|
|
1293
|
+
"type": "string"
|
|
1294
|
+
},
|
|
1295
|
+
"input": {
|
|
1296
|
+
"$ref": "#/definitions/ValueExpr"
|
|
1297
|
+
}
|
|
1298
|
+
},
|
|
1299
|
+
"required": [
|
|
1300
|
+
"ref",
|
|
1301
|
+
"input"
|
|
1302
|
+
],
|
|
1303
|
+
"additionalProperties": false
|
|
1304
|
+
},
|
|
1305
|
+
"description": "Queries the seed reads (ADR 0069 B2), in order: the seed's values read result i as `{ ref: 'binding', depth: i }`. A query that fails leaves the fields reading it at initialContext. Absent when the seed reads none."
|
|
1306
|
+
},
|
|
1287
1307
|
"root": {
|
|
1288
1308
|
"$ref": "#/definitions/ViewNode"
|
|
1289
1309
|
}
|
|
@@ -74,6 +74,13 @@
|
|
|
74
74
|
"items": {
|
|
75
75
|
"$ref": "#/definitions/RequestForm"
|
|
76
76
|
}
|
|
77
|
+
},
|
|
78
|
+
"serverErrors": {
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": {
|
|
81
|
+
"$ref": "#/definitions/ServerError"
|
|
82
|
+
},
|
|
83
|
+
"description": "What the app's `onError` received while answering this request (ADR 0069 A2)."
|
|
77
84
|
}
|
|
78
85
|
},
|
|
79
86
|
"required": [
|
|
@@ -87,7 +94,8 @@
|
|
|
87
94
|
"text",
|
|
88
95
|
"truncated",
|
|
89
96
|
"elements",
|
|
90
|
-
"forms"
|
|
97
|
+
"forms",
|
|
98
|
+
"serverErrors"
|
|
91
99
|
],
|
|
92
100
|
"additionalProperties": false
|
|
93
101
|
},
|
|
@@ -271,6 +279,32 @@
|
|
|
271
279
|
"outside"
|
|
272
280
|
],
|
|
273
281
|
"additionalProperties": false
|
|
282
|
+
},
|
|
283
|
+
"ServerError": {
|
|
284
|
+
"type": "object",
|
|
285
|
+
"properties": {
|
|
286
|
+
"message": {
|
|
287
|
+
"type": "string"
|
|
288
|
+
},
|
|
289
|
+
"effect": {
|
|
290
|
+
"type": "string",
|
|
291
|
+
"description": "The effect (`feature.symbol`) whose resolver or input failed, when known."
|
|
292
|
+
},
|
|
293
|
+
"path": {
|
|
294
|
+
"type": "string",
|
|
295
|
+
"description": "The request path, when known."
|
|
296
|
+
},
|
|
297
|
+
"details": {
|
|
298
|
+
"type": "object",
|
|
299
|
+
"additionalProperties": {},
|
|
300
|
+
"description": "The other fields `onError` received, such as the schema issues of an invalid input and where it came from."
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
"required": [
|
|
304
|
+
"message"
|
|
305
|
+
],
|
|
306
|
+
"additionalProperties": false,
|
|
307
|
+
"description": "One call of the app's `onError` (ADR 0069 A2): a resolver that threw, an invalid input, a failed stream."
|
|
274
308
|
}
|
|
275
309
|
}
|
|
276
310
|
}
|
|
@@ -75,9 +75,8 @@ export const Board = ui.view({
|
|
|
75
75
|
ui.a(
|
|
76
76
|
{
|
|
77
77
|
href: ui.link(home, null, { show: s.value }),
|
|
78
|
-
'aria-current': search.show === s.value,
|
|
79
78
|
class:
|
|
80
|
-
'rounded-full border px-3 py-1 aria-[current=
|
|
79
|
+
'rounded-full border px-3 py-1 aria-[current=page]:bg-indigo-600 aria-[current=page]:text-white',
|
|
81
80
|
},
|
|
82
81
|
[s.label],
|
|
83
82
|
),
|
package/skill/topics/data.md
CHANGED
|
@@ -50,6 +50,7 @@ export default app({ resolvers: resolvers(project, (implement) => [
|
|
|
50
50
|
shows it, also from the browser. `'live'` is for data your own mutations change. A refresh the visitor controls
|
|
51
51
|
(a button, Pause / Resume) is `refresh: () => [tag()]` on a machine transition (`hozu docs machine`).
|
|
52
52
|
- Call a `fn` from views or machines: `ui.each(visible({ items, show: ctx.show }), 'id', …)`.
|
|
53
|
+
- **A database** (pool, migrations, numeric ids): see --more.
|
|
53
54
|
|
|
54
55
|
<!-- more -->
|
|
55
56
|
|
|
@@ -73,3 +74,51 @@ export default app({ resolvers: resolvers(project, (implement) => [
|
|
|
73
74
|
defaults and transforms applied.
|
|
74
75
|
- Every mutation also has `Invalid` = `{ message, fields }` (input failing its schema, or
|
|
75
76
|
`fail('Invalid', { message, fields: { title: 'Taken' } })`); never declare `Invalid` or `Unexpected` yourself.
|
|
77
|
+
|
|
78
|
+
## Resolvers in another language (Go)
|
|
79
|
+
Only when the person asks for it or the service already exists in Go: TypeScript resolvers are the default and need
|
|
80
|
+
no second process. `remote()` sends server effects to a service over HTTP; everything else (access, caching, tags,
|
|
81
|
+
the output schema check) stays in the Hozu server, so a wrong answer is `Unexpected`, never a wrong page.
|
|
82
|
+
```ts
|
|
83
|
+
import { remote, resolvers } from '@hozu/data'
|
|
84
|
+
export default app({
|
|
85
|
+
resolvers: resolvers(project, (implement) => [
|
|
86
|
+
implement(me, (_, { session }) => ({ name: session?.user ?? '' })),
|
|
87
|
+
...remote(
|
|
88
|
+
{
|
|
89
|
+
url: { env: 'NOTES_SERVICE_URL' },
|
|
90
|
+
secret: { env: 'NOTES_SERVICE_SECRET' },
|
|
91
|
+
contract: new URL('./service/hozu/contract.go', import.meta.url),
|
|
92
|
+
},
|
|
93
|
+
[listNotes, addNote],
|
|
94
|
+
),
|
|
95
|
+
]),
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
- The loop: change the declaration in TypeScript → `npx hozu gen` (writes the contract: types, the `Resolvers`
|
|
99
|
+
interface, `Handler`) → implement the interface until `go test ./...` passes → restart the service → `hozu check`.
|
|
100
|
+
A contract older than the declarations is HZ093; the service answers 409 to calls from other declarations.
|
|
101
|
+
- In Go: return a declared error as the error value (`hozu.NotesAddNoteDuplicate{Text: t}`), `hozu.Invalid{…}` for
|
|
102
|
+
input problems; `ctx.Session` is nil when signed out; `ctx.SetSession(…)` / `ctx.SignOut()` in mutations. Public
|
|
103
|
+
queries never receive the session. `ctx.File(token)` reads an upload, `ctx.Header` an endpoint's request headers
|
|
104
|
+
(no cookie), `ctx.Preview` preview mode. The secret is required (16+ characters, the same value on both sides,
|
|
105
|
+
HZ093): the service trusts the session it is sent, so serve `hozu.Handler(r, hozu.Options{Secret: …})` on a private
|
|
106
|
+
address (it refuses to start without one).
|
|
107
|
+
- `.meta({ title: 'Note' })` on a schema makes it one Go type wherever it appears; `z.int()` is `int64`, a plain
|
|
108
|
+
number `float64`. Only `runs: 'server'` effects and JSON endpoints can be remote (HZ093).
|
|
109
|
+
- `examples/notes-go` is the reference: the notes app with every resolver in Go.
|
|
110
|
+
|
|
111
|
+
## A database
|
|
112
|
+
- One pool per process, made in `app.ts`; close it in `app({ dispose: () => pool.end() })` so `hozu get`, `call` and
|
|
113
|
+
`browse` exit and `hozu serve` stops cleanly. Transactions belong in one mutation resolver (`BEGIN` … `COMMIT`).
|
|
114
|
+
- Migrations and seed data are scripts in `package.json` (`"db:migrate": "node db/migrate.ts"`), idempotent, run
|
|
115
|
+
before `npm start`; the URL and password are server env (`project({ env: { server } })`, `hozu docs env`).
|
|
116
|
+
- Route params and form fields are strings: a numeric id is `z.coerce.number()` in the query or mutation input
|
|
117
|
+
(a query input that fails its schema is a program error, reported to `onError` with the field).
|
|
118
|
+
- Data the whole staff shares but only staff may read is `scope: 'user'` with `access` (it is never cached across
|
|
119
|
+
requests). Share one rule: `const staffOnly = part(({ session }) => session.role !== 'editor')`, then
|
|
120
|
+
`access: { allow: staffOnly }` on each effect.
|
|
121
|
+
- A resolver may answer `fail('Forbidden', { message })` (a row deleted meanwhile, a check `access` cannot make);
|
|
122
|
+
with `access: 'signedIn'` its `session` is never null.
|
|
123
|
+
- Another app writing the same database: give the reading app a signed `endpoint` that `invalidates` the tags, and
|
|
124
|
+
call it after a write (`hozu docs endpoints`).
|
|
@@ -97,3 +97,4 @@ around the rule. `npx hozu docs HZ083` prints one code: its cause, its fix and t
|
|
|
97
97
|
| HZ090 (warning) | `access: 'anyone'` on a `scope: 'user'` query: every visitor, signed in or not, may read it | say who may read it (`'signedIn'`, `{ owner: { row, session } }`), or accept the warning with a reason |
|
|
98
98
|
| HZ091 | a query with `owner` access returned rows the visitor does not own (reported at run time) | read only the visitor's rows in the resolver (filter by the session); production drops the extra rows and logs this |
|
|
99
99
|
| HZ092 | a preview in `project({ previews })` no longer fits the app: data off its query output schema, an error the query does not declare, a route without a page, or a component use that does not build | update the preview to the current schema, error, page or component (previews are for people: they never ship) |
|
|
100
|
+
| HZ093 | a `remote()` resolver that cannot answer: its generated contract is missing or stale, or it lists an effect the browser runs or a non-JSON endpoint | run `hozu gen` and rebuild the service; implement browser-run effects in fetch.ts and non-JSON endpoints in TypeScript |
|
package/skill/topics/http.md
CHANGED
|
@@ -18,4 +18,5 @@ http: {
|
|
|
18
18
|
},
|
|
19
19
|
```
|
|
20
20
|
Server options live in the app module: `app({ resolvers, session?, components?, onError?, csp?, og?, preview? })`.
|
|
21
|
-
A strict CSP, `nosniff` and a cross-site POST check are on by default; `csp: {
|
|
21
|
+
A strict CSP, `nosniff` and a cross-site POST check are on by default; `csp: { img: ['https://…'] }` adds sources
|
|
22
|
+
(`script style img font connect frame media`).
|
package/skill/topics/machine.md
CHANGED
|
@@ -68,8 +68,7 @@ export const m = machine({
|
|
|
68
68
|
}),
|
|
69
69
|
})
|
|
70
70
|
```
|
|
71
|
-
-
|
|
72
|
-
seeds come from the address).
|
|
71
|
+
- Calm state follows the visitor to a page that shows the same view, and back to the same address.
|
|
73
72
|
- **assign** values are event (`e`), result (`r`) or error fields, context, literals, operators and `fn()` calls.
|
|
74
73
|
- **guard** conditions: a field (`() => ctx.auto`), comparisons, `&&`, `||`, `!`, or a boolean `fn()`.
|
|
75
74
|
- **navigate** sends the browser to `ui.link(route, params, search?)` after the transition. It returns one link: to
|
|
@@ -79,9 +78,9 @@ export const m = machine({
|
|
|
79
78
|
- **Shared transitions:** `machine({ on })` entries are copied into every state that has no `invoke`, is not final,
|
|
80
79
|
and neither handles nor ignores the event itself. Without `target` they stay in the state they fire in; one
|
|
81
80
|
contract covers every copy.
|
|
82
|
-
- **Start from the URL:** a view with a `route` may declare
|
|
83
|
-
|
|
84
|
-
per page may seed a machine (HZ048).
|
|
81
|
+
- **Start from the URL or server data:** a view with a `route` may declare
|
|
82
|
+
`seed: ({ params, search, query }) => ({ q: search.q, email: query(me, {}).email })` (server render, hydration and
|
|
83
|
+
no-JS posts alike; a failed query leaves `initialContext`). One view per page may seed a machine (HZ048).
|
|
85
84
|
- In an app with `site.locales`, machines never hold
|
|
86
85
|
translated text (HZ041): store a code (`ctx.error = 'duplicate'`) and choose the message in the view. The
|
|
87
86
|
scaffold does this in every app.
|
package/skill/topics/pages.md
CHANGED
|
@@ -11,7 +11,7 @@ export const docs = route({ path: '/docs/:path+', params: z.object({ path: z.arr
|
|
|
11
11
|
- **Pages** go in `project({ routes: { home, itemPage }, pages: [...] })` (the whole config: see --more):
|
|
12
12
|
`ui.page(home, { views: [Board], head: { render: () => ({ title: 'Items' }) } })`.
|
|
13
13
|
- **Head from a query:** `head: { query: getItem, input: (params, locale) => ({ id: params.id }), render: (item) => ({ title:
|
|
14
|
-
item.title }), failed: { NotFound: 404 } }`. `failed` maps every declared error of the query (HZ051) to a route
|
|
14
|
+
item.title }), failed: { NotFound: 404 } }`. Both also get `search`. `failed` maps every declared error of the query (HZ051) to a route
|
|
15
15
|
without params (303) or to `403`, `404` or `410`.
|
|
16
16
|
- `head.render` fields: `title`, `description`, `type` (`'website' | 'article'`), `image`, `published`, `noindex`;
|
|
17
17
|
any other is HZ014 (Open Graph, `twitter:card` and the JSON-LD are derived from these).
|
package/skill/topics/recipes.md
CHANGED
|
@@ -81,3 +81,25 @@ Run a fresh scaffold into a scratch app with `--with detail`, and copy the parts
|
|
|
81
81
|
- Following the system needs no code: Tailwind's `dark:` classes (`bg-white dark:bg-slate-900`).
|
|
82
82
|
- A switch the visitor chooses: a client component (`hozu docs components`) puts `dark` on `<html>` and keeps the
|
|
83
83
|
choice in `localStorage`; `app.css` adds `@custom-variant dark (&:where(.dark, .dark *));`.
|
|
84
|
+
|
|
85
|
+
## A shell shared by many pages (a back office)
|
|
86
|
+
Pages are config, so a helper is the layout:
|
|
87
|
+
```ts
|
|
88
|
+
const staffHead = { query: me, render: (m) => ({ title: `${m.name} · Admin` }), failed: { Forbidden: signIn } }
|
|
89
|
+
const staff = (route, View) => ui.page(route, { views: [Sidebar, View], head: staffHead })
|
|
90
|
+
export default project({ /* … */ pages: [staff(orders, OrderList), staff(orderDetail, OrderPage), …] })
|
|
91
|
+
```
|
|
92
|
+
The sidebar's links mark the page shown with `aria-current` by themselves (`aria-[current]:font-bold`).
|
|
93
|
+
|
|
94
|
+
## Screens with different state
|
|
95
|
+
One machine per feature: an order list (filters, selection) and an order page (shipping, refund) are two features,
|
|
96
|
+
`orders` and `order`, sharing declarations through `exports`. Each machine stays small and its contracts few.
|
|
97
|
+
|
|
98
|
+
## A multi-step checkout that also works without JavaScript
|
|
99
|
+
Each step is a state; the server runs the machine per request, so without JS a step's form posts every earlier field
|
|
100
|
+
again as hidden inputs (`ui.input({ type: 'hidden', name: 'line1', value: ctx.line1 })`), and the last step's
|
|
101
|
+
mutation receives them all. Prefill from the member with `seed: ({ query }) => ({ email: query(me, {}).email })`.
|
|
102
|
+
|
|
103
|
+
## A notice after saving
|
|
104
|
+
A `notice` context field set in `done` and cleared by `after: [{ ms: 4000, target: 'idle' }]` on a `saved` state;
|
|
105
|
+
the view shows `ctx.notice !== null && ui.p({ role: 'status' }, [ctx.notice])`. There is no global toast store.
|
package/skill/topics/testing.md
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
`hozu call api.who --input '{"room":"a"}' --header 'Authorization: Bearer t'` (a POST needs `--write`).
|
|
8
8
|
- **Drive the app in a real browser, still without a server:**
|
|
9
9
|
`hozu browse / --session '{"user":"ada"}' --do 'fill New note=Milk' --do 'press Enter' --do 'click Pin in "Milk"'`.
|
|
10
|
-
- Steps: `fill <label>=<value
|
|
11
|
-
`submit "<form>"`, `press <key>`, `wait <ms>`, `goto <path>`, `post <path> a=1&b=2`,
|
|
10
|
+
- Steps: `fill <label>=<value>` (`\n`, `\t` work), `select <label>=<option>`, `check` / `uncheck <label>`,
|
|
11
|
+
`click <name>`, `submit "<form>"`, `press <key>`, `wait <ms>`, `goto <path>`, `post <path> a=1&b=2`,
|
|
12
12
|
`remember <name> from url|<selector> [@attr]` (later steps read `$name`); a target may end with `in "<text>"`
|
|
13
13
|
(for fill and select, before or after `=value`).
|
|
14
14
|
- Labels are what `hozu get <page> --forms` lists; a missing one prints `Did you mean "…"?`. One `--do` may hold
|
|
@@ -29,8 +29,12 @@
|
|
|
29
29
|
|
|
30
30
|
<!-- more -->
|
|
31
31
|
|
|
32
|
-
- **
|
|
33
|
-
|
|
32
|
+
- **Server errors:** what the app's `onError` receives (a resolver that threw, an invalid input) is listed under the
|
|
33
|
+
step or the `get` request that caused it, `server error: <message> (<feature.effect>)`; `--json` `serverErrors`.
|
|
34
|
+
- **A calm page:** a step that rebuilds elements unchanged says `N elements rebuilt unchanged (a flash: main > form >
|
|
35
|
+
button[type=submit])`, naming up to five (`--json` `flashes.elements` has all; a control hidden while busy: disable
|
|
36
|
+
it instead). Equal means tag, class, text, `name`, `id`, `href`, `src`, `type` and parent path; a node that moved is
|
|
37
|
+
no flash. Layout that moves without input says `layout shift X`. Both are
|
|
34
38
|
problems to fix; a calm step prints neither. An address changed with `replace` stays `in place`.
|
|
35
39
|
- **`hozu get`** prints the status, redirect, `set-cookie` attributes (`HttpOnly`, `SameSite`), title, alerts and
|
|
36
40
|
visible text.
|
package/skill/topics/views.md
CHANGED
|
@@ -23,10 +23,10 @@ export const Board = ui.view({
|
|
|
23
23
|
- **Events:** `on: { click: ui.send(Event, payload) }`; payload fields are literals, data, `ui.dom.value`,
|
|
24
24
|
`ui.dom.form('name')` (submit; `hozu docs forms`). A control that only sets a context field:
|
|
25
25
|
`on: { click: ui.set(ctx.open, !ctx.open) }`, `on: { input: ui.set(ctx.q, ui.dom.value) }` (no event to declare).
|
|
26
|
-
- **Links:** `ui.a({ href: ui.link(itemPage, { id: item.id }) }, [...])`; never a string path (HZ032).
|
|
26
|
+
- **Links:** `ui.a({ href: ui.link(itemPage, { id: item.id }) }, [...])`; never a string path (HZ032). Menus,
|
|
27
|
+
dialogs, plurals: --more.
|
|
27
28
|
- **Data:** `ui.query(listItems, input, { ready: (items) => …, failed: { NotFound: () => …, Unexpected: () => … } })`;
|
|
28
|
-
`failed` lists every declared error plus `Unexpected`.
|
|
29
|
-
parent) and update by key; `pending` shows only before the first answer.
|
|
29
|
+
`failed` lists every declared error plus `Unexpected`.
|
|
30
30
|
- **Shared UI** (buttons, inputs, fields): `ui.use(Button, { variant, props, on }, ['Save'])` of a kit component
|
|
31
31
|
(`hozu docs components`).
|
|
32
32
|
|
|
@@ -63,3 +63,13 @@ export const Board = ui.view({
|
|
|
63
63
|
(`hozu docs components`; `examples/showcase` has a Chart.js one).
|
|
64
64
|
- **Also:** `ui.html(post.html)` (trusted HTML from query data only, HZ030), `ui.asset(new URL('./x.png',
|
|
65
65
|
import.meta.url))`, `ui.window({ on })` / `ui.document({ on })`, `ui.embed(OtherView)`.
|
|
66
|
+
|
|
67
|
+
## Menus, dialogs, counting
|
|
68
|
+
- When a query's input changes, the rows stay (`aria-busy` on the parent) and update by key; `pending` shows only
|
|
69
|
+
before the first answer.
|
|
70
|
+
- A link to the page shown gets `aria-current="page"` (`"true"` for its section): `aria-[current]:font-bold`.
|
|
71
|
+
- `ui.dialog({ open: is(['editing']), on: { close: ui.send(Cancel, {}) } }, [...])` opens as a modal and closes with
|
|
72
|
+
the machine; Escape sends `close`.
|
|
73
|
+
- `ui.format.plural(n, { one: '# item', other: '# items' })` picks the case for the page's language (`=0` works).
|
|
74
|
+
- `null` and `false` render nothing, also inside a constant list:
|
|
75
|
+
`ui.ul({}, [...kinds.map((k) => (k === 'draft' ? null : ui.li({}, [k])))])`.
|