@hozu/cli 0.21.0 → 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/scaffold.d.ts.map +1 -1
- package/dist/commands/scaffold.js +6 -7
- package/dist/commands/scaffold.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/model.ts +0 -7
- package/skill/example/features/bookmarks/views.ts +3 -5
- package/skill/topics/data.md +49 -0
- package/skill/topics/diagnostics.md +1 -0
- package/skill/topics/forms.md +2 -2
- package/skill/topics/http.md +2 -1
- package/skill/topics/machine.md +5 -6
- package/skill/topics/pages.md +1 -1
- package/skill/topics/patterns.md +9 -8
- 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/
|
|
52
|
-
"@hozu/
|
|
53
|
-
"@hozu/validator": "0.
|
|
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
|
}
|
|
@@ -11,7 +11,6 @@ const NewBookmark = z.object({
|
|
|
11
11
|
kind: Kind,
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
export const Draft = event({ payload: z.object({ text: z.string() }) })
|
|
15
14
|
export const Add = event({ payload: z.object({ title: z.string(), kind: Kind }) })
|
|
16
15
|
export const ToggleRead = event({ payload: BookmarkKey })
|
|
17
16
|
|
|
@@ -89,12 +88,6 @@ export const bookmarksMachine = machine({
|
|
|
89
88
|
states: ({ ctx }) => ({
|
|
90
89
|
idle: {
|
|
91
90
|
on: [
|
|
92
|
-
on(Draft, {
|
|
93
|
-
target: 'idle',
|
|
94
|
-
assign: (e) => {
|
|
95
|
-
ctx.draft = e.text
|
|
96
|
-
},
|
|
97
|
-
}),
|
|
98
91
|
on(Add, {
|
|
99
92
|
target: 'adding',
|
|
100
93
|
assign: (e) => {
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
Add,
|
|
9
9
|
addBookmark,
|
|
10
10
|
bookmarksMachine,
|
|
11
|
-
Draft,
|
|
12
11
|
getBookmark,
|
|
13
12
|
isEmpty,
|
|
14
13
|
listBookmarks,
|
|
@@ -48,7 +47,7 @@ export const Board = ui.view({
|
|
|
48
47
|
invalid: ctx.fields.title !== null,
|
|
49
48
|
describedby: 'title-error',
|
|
50
49
|
},
|
|
51
|
-
on: { input: ui.
|
|
50
|
+
on: { input: ui.set(ctx.draft, ui.dom.value) },
|
|
52
51
|
}),
|
|
53
52
|
},
|
|
54
53
|
}),
|
|
@@ -76,9 +75,8 @@ export const Board = ui.view({
|
|
|
76
75
|
ui.a(
|
|
77
76
|
{
|
|
78
77
|
href: ui.link(home, null, { show: s.value }),
|
|
79
|
-
'aria-current': search.show === s.value,
|
|
80
78
|
class:
|
|
81
|
-
'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',
|
|
82
80
|
},
|
|
83
81
|
[s.label],
|
|
84
82
|
),
|
|
@@ -142,7 +140,7 @@ export const addsBookmark = contract(bookmarksMachine, {
|
|
|
142
140
|
given: { state: 'idle' },
|
|
143
141
|
when: [
|
|
144
142
|
{ send: Add, payload: { title: 'Hozu talk', kind: 'podcast' } },
|
|
145
|
-
{ send:
|
|
143
|
+
{ send: ToggleRead, payload: { id: 'b1' } },
|
|
146
144
|
{ done: addBookmark, result: { id: 'b3', title: 'Hozu talk', kind: 'podcast', read: false } },
|
|
147
145
|
],
|
|
148
146
|
expect: {
|
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/forms.md
CHANGED
|
@@ -7,7 +7,7 @@ ui.form({ on: { submit: ui.send(Add, { title: ui.dom.form('title'), kind: ui.dom
|
|
|
7
7
|
ui.label({ for: 'title' }, ['Title']),
|
|
8
8
|
ui.input({ id: 'title', name: 'title', required: true, minlength: 2, value: ctx.draft,
|
|
9
9
|
'aria-invalid': ctx.fields.title !== null, 'aria-describedby': 'title-error',
|
|
10
|
-
on: { input: ui.
|
|
10
|
+
on: { input: ui.set(ctx.draft, ui.dom.value) } }),
|
|
11
11
|
ui.select({ name: 'kind', 'aria-label': 'Kind' }, kinds.map((k) => ui.option({ value: k, selected: ctx.kind === k }, [k]))),
|
|
12
12
|
ui.button({ type: 'submit' }, ['Add']),
|
|
13
13
|
])
|
|
@@ -27,7 +27,7 @@ ui.p({ id: 'title-error', class: 'text-sm text-rose-600' }, [ctx.fields.title])
|
|
|
27
27
|
```ts
|
|
28
28
|
ui.use(Field, { props: { for: 'title', label: 'Title', error: ctx.fields.title, errorId: 'title-error' },
|
|
29
29
|
slots: { control: ui.use(Input, { props: { id: 'title', name: 'title', value: ctx.draft, required: true,
|
|
30
|
-
invalid: ctx.fields.title !== null, describedby: 'title-error' }, on: { input: ui.
|
|
30
|
+
invalid: ctx.fields.title !== null, describedby: 'title-error' }, on: { input: ui.set(ctx.draft, ui.dom.value) } }) } }),
|
|
31
31
|
ui.use(Button, { props: { type: 'submit' } }, ['Add']),
|
|
32
32
|
```
|
|
33
33
|
- **Limit messages:** `z.string().min(2, 'Use at least 2 characters')`.
|
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
|
@@ -44,7 +44,7 @@ export const m = machine({
|
|
|
44
44
|
context: z.object({ draft: z.string(), error: z.string().nullable(), target: z.string() }),
|
|
45
45
|
initialContext: { draft: '', error: null, target: '' },
|
|
46
46
|
initial: 'idle',
|
|
47
|
-
on: ({ ctx }) => [on(Draft, { assign: (e) => { ctx.draft = e.text } })], //
|
|
47
|
+
on: ({ ctx }) => [on(Draft, { assign: (e) => { ctx.draft = e.text; ctx.error = null } })], // every state without invoke
|
|
48
48
|
states: ({ ctx }) => ({
|
|
49
49
|
idle: {
|
|
50
50
|
on: [
|
|
@@ -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).
|