@akanjs/devkit 3.0.0-alpha.53 → 3.0.0-alpha.55
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/biome.base.json +11 -0
- package/lint/no-init-fetch-in-client.grit +47 -0
- package/package.json +2 -2
package/biome.base.json
CHANGED
|
@@ -186,6 +186,17 @@
|
|
|
186
186
|
"includes": ["{apps,libs}/**/*.tsx", "!**/*.test.tsx", "!**/*.spec.tsx"],
|
|
187
187
|
"plugins": ["./node_modules/@akanjs/devkit/lint/no-unpublished-form-setter.grit"]
|
|
188
188
|
},
|
|
189
|
+
{
|
|
190
|
+
"includes": [
|
|
191
|
+
"{apps,libs}/**/*.ts",
|
|
192
|
+
"{apps,libs}/**/*.tsx",
|
|
193
|
+
"!**/*.test.ts",
|
|
194
|
+
"!**/*.test.tsx",
|
|
195
|
+
"!**/*.spec.ts",
|
|
196
|
+
"!**/*.spec.tsx"
|
|
197
|
+
],
|
|
198
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-init-fetch-in-client.grit"]
|
|
199
|
+
},
|
|
189
200
|
{
|
|
190
201
|
"includes": [
|
|
191
202
|
"**/ui/**/*.ts",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
engine biome(1.0)
|
|
2
|
+
language js(typescript, jsx)
|
|
3
|
+
|
|
4
|
+
// `fetch.init<Model><Suffix>` is not a request, it is a hydration snapshot. `#registerSlice`
|
|
5
|
+
// (pkgs/akanjs/fetch/client/fetchClient.ts) composes it out of the slice's list and insight queries and
|
|
6
|
+
// returns a `ServerInit` whose only consumer is the `init` prop of `Load.Units` / `Load.View`, which
|
|
7
|
+
// writes it into the store before React ever renders. `fetch.get<Model>Init<Suffix>` is the same call
|
|
8
|
+
// returning the payload alone. Run from a route they resolve before the first byte and the markup ships
|
|
9
|
+
// populated; run after hydration they are two extra round-trips for a shell the browser already painted
|
|
10
|
+
// empty, landing in a local variable no store reads — `Load.*` seeds state, so a value held in a client
|
|
11
|
+
// closure reaches nothing.
|
|
12
|
+
//
|
|
13
|
+
// The client is not missing the load, only this spelling of it: every slice also generates
|
|
14
|
+
// `st.do.init<Model><Suffix>` (pkgs/akanjs/store/action.ts), which runs the same two queries and commits
|
|
15
|
+
// them to state.
|
|
16
|
+
//
|
|
17
|
+
// Both names are matched by shape, since a lint rule cannot know which slices exist. The generated one is
|
|
18
|
+
// `init` + `Capitalize<refName>` + `Capitalize<suffix>`, so it always carries two capital-led segments —
|
|
19
|
+
// requiring the second one is what keeps a hand-written `initPayment` / `initSession` endpoint out, while
|
|
20
|
+
// `initializeSomething` was never at risk (`init` is followed by a lowercase letter). What is left over is a
|
|
21
|
+
// custom endpoint that happens to spell the generated shape exactly, `initPaymentSession` or
|
|
22
|
+
// `get<X>Init<Y>`; suppress that one with `// biome-ignore lint/plugin: <reason>`.
|
|
23
|
+
//
|
|
24
|
+
// `view`/`edit` hydrate the same way but are not matched here: `edit<X>` is a plausible custom endpoint
|
|
25
|
+
// name, whereas the two shapes above are not.
|
|
26
|
+
//
|
|
27
|
+
// The gate is the file. `JsDirective` anchors `"use client"` to the real directive — docs pages carry the
|
|
28
|
+
// same text as an ordinary string literal and inside sample code, and neither is one. `*.store.ts` is
|
|
29
|
+
// added by name because a store is client-only by role and carries no directive.
|
|
30
|
+
JsCallExpression() as $call where {
|
|
31
|
+
$call <: `fetch.$endpoint($...)`,
|
|
32
|
+
$endpoint <: or {
|
|
33
|
+
r"init[A-Z][A-Za-z0-9_$]*[A-Z][A-Za-z0-9_$]*",
|
|
34
|
+
r"get[A-Z][A-Za-z0-9_$]*Init[A-Z][A-Za-z0-9_$]*"
|
|
35
|
+
},
|
|
36
|
+
or {
|
|
37
|
+
$filename <: r".*\.store\.ts",
|
|
38
|
+
$call <: within JsModule() as $module where {
|
|
39
|
+
$module <: contains JsDirective() as $directive where { $directive <: r"[\s\S]*use client[\s\S]*" }
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
register_diagnostic(
|
|
43
|
+
span = $call,
|
|
44
|
+
message = "This is a server-side hydration call. It composes the slice's list and insight queries into a snapshot whose only consumer is the init prop of Load.Units / Load.View, so on the client it costs two extra round-trips for a shell the browser already painted, and the result lands in a value nothing reads. Load it in the route — await fetch.initXInY(...) in page/** and pass the result down as an init prop, or hand the unawaited promise to a Zone and let Load.* resolve it behind a skeleton. To reload from the client, call the generated store action st.do.initXInY() instead, which writes the same data into state.",
|
|
45
|
+
severity = "error"
|
|
46
|
+
)
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/devkit",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.55",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@langchain/openai": "^1.4.6",
|
|
46
46
|
"@tailwindcss/node": "^4.3.0",
|
|
47
47
|
"@trapezedev/project": "^7.1.4",
|
|
48
|
-
"akanjs": "3.0.0-alpha.
|
|
48
|
+
"akanjs": "3.0.0-alpha.55",
|
|
49
49
|
"chalk": "^5.6.2",
|
|
50
50
|
"commander": "^14.0.3",
|
|
51
51
|
"dayjs": "^1.11.20",
|