@akanjs/cli 3.0.0-alpha.4 → 3.0.0-alpha.6
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/.build-stamp +1 -1
- package/{abstractCompactor-rk6twzvj.js → abstractCompactor-e5yq60qz.js} +2 -2
- package/{agent.command-jfz8yfwy.js → agent.command-b0fcx3r2.js} +7 -7
- package/{application.command-mxyqtd6p.js → application.command-cezdnvtq.js} +5 -5
- package/{applicationBuildRunner-cwk52sb7.js → applicationBuildRunner-ha3y8ew8.js} +4 -4
- package/{applicationReleasePackager-yrrhbkv3.js → applicationReleasePackager-gg8ccbeh.js} +1 -1
- package/buildBatch.proc.js +4 -4
- package/{capacitorApp-j357ak1g.js → capacitorApp-jaksw4cy.js} +3 -3
- package/{cloud.command-f87dwe52.js → cloud.command-6xvsd487.js} +9 -9
- package/{context.command-z5bf8bn7.js → context.command-ajn1b683.js} +15 -15
- package/{guideline.command-1m1ctar3.js → guideline.command-9ew6aqhm.js} +5 -5
- package/guidelines/ssrRule/ssrRule.generate.json +31 -0
- package/guidelines/ssrRule/ssrRule.instruction.md +108 -0
- package/incrementalBuilder.proc.js +3 -3
- package/{index-3pgtw35d.js → index-0cj2zxbm.js} +1 -1
- package/{index-jtm86byd.js → index-47qxw1tz.js} +28 -22
- package/{index-vhv3xnjz.js → index-60a3jfcz.js} +6 -6
- package/{index-b978vs2e.js → index-6npsfpxr.js} +3 -3
- package/{index-csqk9z5j.js → index-c94nq3c1.js} +3 -3
- package/{index-cn24dcqn.js → index-exhpp31y.js} +2 -2
- package/{index-y0k42k04.js → index-hk9rbcsz.js} +1 -1
- package/{index-hjzr8ja1.js → index-hrwzz2wf.js} +1 -1
- package/{index-rh16j3c7.js → index-j9cxndc0.js} +3 -2
- package/{index-jk9q6pse.js → index-jkynkyfk.js} +1 -1
- package/{index-4yp06pn1.js → index-jn9vfpwz.js} +9 -31
- package/{index-4zgs8g1w.js → index-m4kpmmtj.js} +1 -1
- package/{index-e3qskyt2.js → index-meh7mmz9.js} +2 -2
- package/{index-6pz1j0zj.js → index-mxvakhsm.js} +6 -2
- package/{index-n0z3f2xg.js → index-nfxq39kj.js} +4 -4
- package/{index-r4w8cry5.js → index-pfrt7qwh.js} +4 -4
- package/{index-cap2k2ch.js → index-qb61h0k7.js} +52 -17
- package/{index-xwgm94zr.js → index-qp089jp0.js} +1 -1
- package/{index-tq1y56tp.js → index-r7nqv8qj.js} +35 -12
- package/{index-1s71fwrq.js → index-vkqxw0ek.js} +11 -11
- package/{index-fmgbwsr5.js → index-wrrb8rxk.js} +4 -4
- package/{index-xj8bks3p.js → index-zbx0jheb.js} +4 -4
- package/{index-ybybkec0.js → index-zr2wvx69.js} +6 -6
- package/index.js +19 -19
- package/{library.command-pwfx8dx2.js → library.command-aa1g8nsa.js} +4 -4
- package/{localRegistry.command-r4zjx5py.js → localRegistry.command-jha3sn50.js} +8 -8
- package/{module.command-0t3ewata.js → module.command-b1zzgqde.js} +8 -8
- package/{package.command-7hmkxvpa.js → package.command-9qv6vr9s.js} +4 -4
- package/package.json +2 -2
- package/{page.command-st6r4s0q.js → page.command-k16pw244.js} +4 -4
- package/{primitive.command-1qkxpzsn.js → primitive.command-s60dn1ae.js} +9 -9
- package/{quality.command-hy5vt1bh.js → quality.command-p3vaze52.js} +456 -71
- package/{repair.command-nakkq2zp.js → repair.command-mfv749ha.js} +6 -6
- package/{scalar.command-fjq272gs.js → scalar.command-hs3nwzv1.js} +7 -7
- package/templates/lib/db.ts +3 -1
- package/templates/lib/useClient.ts +9 -3
- package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +3 -2
- package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +1 -0
- package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +59 -0
- package/templates/workspaceRoot/AGENTS.md.template +155 -15
- package/templates/workspaceRoot/biome.json.template +22 -0
- package/{workflow.command-jswbgk90.js → workflow.command-z0e0fk0z.js} +12 -12
- package/{workspace.command-h9wwcjpt.js → workspace.command-3ydyy991.js} +21 -21
- package/templates/libRoot/base/baseLogic.ts +0 -14
- package/templates/libRoot/base/index.ts +0 -8
package/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
474303da5b9e0b19ac13326096bbf0527aa6a2ed71915d1eb65c33af084338b4
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AiSession
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-0cj2zxbm.js";
|
|
5
5
|
import {
|
|
6
6
|
AbstractDoc
|
|
7
7
|
} from "./index-0wae5ebk.js";
|
|
8
|
-
import"./index-
|
|
8
|
+
import"./index-mxvakhsm.js";
|
|
9
9
|
import"./index-67546d0j.js";
|
|
10
10
|
import"./index-r24hmh0q.js";
|
|
11
11
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AgentScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
4
|
+
} from "./index-nfxq39kj.js";
|
|
5
|
+
import"./index-jn9vfpwz.js";
|
|
6
|
+
import"./index-m4kpmmtj.js";
|
|
7
|
+
import"./index-qp089jp0.js";
|
|
8
8
|
import {
|
|
9
9
|
Workspace,
|
|
10
10
|
command
|
|
11
|
-
} from "./index-
|
|
12
|
-
import"./index-
|
|
13
|
-
import"./index-
|
|
11
|
+
} from "./index-jkynkyfk.js";
|
|
12
|
+
import"./index-47qxw1tz.js";
|
|
13
|
+
import"./index-mxvakhsm.js";
|
|
14
14
|
import"./index-xys926f2.js";
|
|
15
15
|
import"./index-67546d0j.js";
|
|
16
16
|
import"./index-r24hmh0q.js";
|
|
@@ -4,22 +4,22 @@ import {
|
|
|
4
4
|
} from "./index-0wae5ebk.js";
|
|
5
5
|
import {
|
|
6
6
|
ApplicationScript
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-r7nqv8qj.js";
|
|
8
8
|
import {
|
|
9
9
|
getMobileTargetChoices
|
|
10
10
|
} from "./index-76rn3g2c.js";
|
|
11
|
-
import"./index-
|
|
11
|
+
import"./index-exhpp31y.js";
|
|
12
12
|
import {
|
|
13
13
|
App,
|
|
14
14
|
Exec,
|
|
15
15
|
Sys,
|
|
16
16
|
Workspace,
|
|
17
17
|
command
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-jkynkyfk.js";
|
|
19
19
|
import"./index-fgc8r6dj.js";
|
|
20
20
|
import"./index-bjpxzr6s.js";
|
|
21
|
-
import"./index-
|
|
22
|
-
import"./index-
|
|
21
|
+
import"./index-47qxw1tz.js";
|
|
22
|
+
import"./index-mxvakhsm.js";
|
|
23
23
|
import"./index-67546d0j.js";
|
|
24
24
|
import"./index-r24hmh0q.js";
|
|
25
25
|
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
CsrArtifactBuilder,
|
|
5
5
|
SsrBaseArtifactBuilder,
|
|
6
6
|
precompressArtifacts
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-qb61h0k7.js";
|
|
8
8
|
import"./index-xjd3rqzj.js";
|
|
9
|
-
import"./index-
|
|
9
|
+
import"./index-j9cxndc0.js";
|
|
10
10
|
import"./index-bjpxzr6s.js";
|
|
11
11
|
import {
|
|
12
12
|
Spinner
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-mxvakhsm.js";
|
|
14
14
|
import"./index-r24hmh0q.js";
|
|
15
15
|
|
|
16
16
|
// pkgs/@akanjs/devkit/applicationBuildRunner.ts
|
|
@@ -66,7 +66,7 @@ class ApplicationBuildRunner {
|
|
|
66
66
|
await this.#runPhase("backend", "Compiling backend", () => this.#buildBackend(), (result) => `${result.entrypoints} entrypoints, ${result.outputs} outputs`, phaseOptions);
|
|
67
67
|
await this.#runPhase("ssr", "Building SSR route artifacts", () => this.#buildSsr(), (result) => result ? `${result.allRoutes.manifest.routeIds.length} routes, ${result.allRoutes.manifest.knownEntries.length} entries` : "skipped", phaseOptions);
|
|
68
68
|
await this.#runPhase("csr", "Building CSR assets", () => this.#buildCsr(), (result) => result?.outputDir ?? "skipped", phaseOptions);
|
|
69
|
-
await this.#runPhase("compress", "Compressing static assets", () => precompressArtifacts(this.#app), (result) => result.files > 0 ? `${result.files} files, ${ApplicationBuildRunner.formatBytes(result.inputBytes)} -> ${ApplicationBuildRunner.formatBytes(result.outputBytes)}` : "no files", phaseOptions);
|
|
69
|
+
await this.#runPhase("compress", "Compressing static assets", () => precompressArtifacts(this.#app), (result) => result.files > 0 ? `${result.files} files, ${ApplicationBuildRunner.formatBytes(result.inputBytes)} -> gzip ${ApplicationBuildRunner.formatBytes(result.outputBytes)} / br ${ApplicationBuildRunner.formatBytes(result.brotliBytes)}` : "no files", phaseOptions);
|
|
70
70
|
await this.#runPhase("metadata", "Writing production metadata", () => this.#buildAppMeta(), undefined, {
|
|
71
71
|
spinner
|
|
72
72
|
});
|
package/buildBatch.proc.js
CHANGED
|
@@ -5,15 +5,15 @@ import {
|
|
|
5
5
|
FontOptimizer,
|
|
6
6
|
PagesBundleBuilder,
|
|
7
7
|
SsrBaseArtifactBuilder
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-qb61h0k7.js";
|
|
9
9
|
import"./index-xjd3rqzj.js";
|
|
10
|
-
import"./index-
|
|
10
|
+
import"./index-j9cxndc0.js";
|
|
11
11
|
import"./index-bjpxzr6s.js";
|
|
12
12
|
import {
|
|
13
13
|
AppExecutor,
|
|
14
14
|
WorkspaceExecutor
|
|
15
|
-
} from "./index-
|
|
16
|
-
import"./index-
|
|
15
|
+
} from "./index-47qxw1tz.js";
|
|
16
|
+
import"./index-mxvakhsm.js";
|
|
17
17
|
import"./index-67546d0j.js";
|
|
18
18
|
import"./index-r24hmh0q.js";
|
|
19
19
|
|
|
@@ -25,10 +25,10 @@ import {
|
|
|
25
25
|
selectLocalDevHost,
|
|
26
26
|
sortIosRunTargets,
|
|
27
27
|
writeRootCapacitorConfig
|
|
28
|
-
} from "./index-
|
|
28
|
+
} from "./index-hk9rbcsz.js";
|
|
29
29
|
import"./index-76rn3g2c.js";
|
|
30
|
-
import"./index-
|
|
31
|
-
import"./index-
|
|
30
|
+
import"./index-47qxw1tz.js";
|
|
31
|
+
import"./index-mxvakhsm.js";
|
|
32
32
|
import"./index-67546d0j.js";
|
|
33
33
|
import"./index-r24hmh0q.js";
|
|
34
34
|
export {
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
CloudScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
4
|
+
} from "./index-zr2wvx69.js";
|
|
5
|
+
import"./index-zbx0jheb.js";
|
|
6
|
+
import"./index-meh7mmz9.js";
|
|
7
7
|
import {
|
|
8
8
|
GlobalConfig
|
|
9
|
-
} from "./index-
|
|
10
|
-
import"./index-
|
|
9
|
+
} from "./index-0cj2zxbm.js";
|
|
10
|
+
import"./index-r7nqv8qj.js";
|
|
11
11
|
import"./index-76rn3g2c.js";
|
|
12
|
-
import"./index-
|
|
12
|
+
import"./index-exhpp31y.js";
|
|
13
13
|
import {
|
|
14
14
|
Workspace,
|
|
15
15
|
command
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-jkynkyfk.js";
|
|
17
17
|
import"./index-fgc8r6dj.js";
|
|
18
18
|
import"./index-bjpxzr6s.js";
|
|
19
|
-
import"./index-
|
|
20
|
-
import"./index-
|
|
19
|
+
import"./index-47qxw1tz.js";
|
|
20
|
+
import"./index-mxvakhsm.js";
|
|
21
21
|
import"./index-46tjzh6s.js";
|
|
22
22
|
import"./index-67546d0j.js";
|
|
23
23
|
import"./index-r24hmh0q.js";
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
ContextScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
8
|
-
import"./index-
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-
|
|
4
|
+
} from "./index-vkqxw0ek.js";
|
|
5
|
+
import"./index-6npsfpxr.js";
|
|
6
|
+
import"./index-c94nq3c1.js";
|
|
7
|
+
import"./index-pfrt7qwh.js";
|
|
8
|
+
import"./index-60a3jfcz.js";
|
|
9
|
+
import"./index-hrwzz2wf.js";
|
|
10
|
+
import"./index-wrrb8rxk.js";
|
|
11
11
|
import"./index-ss469dec.js";
|
|
12
|
-
import"./index-
|
|
13
|
-
import"./index-
|
|
14
|
-
import"./index-
|
|
15
|
-
import"./index-
|
|
16
|
-
import"./index-
|
|
12
|
+
import"./index-hk9rbcsz.js";
|
|
13
|
+
import"./index-0cj2zxbm.js";
|
|
14
|
+
import"./index-jn9vfpwz.js";
|
|
15
|
+
import"./index-m4kpmmtj.js";
|
|
16
|
+
import"./index-qp089jp0.js";
|
|
17
17
|
import"./index-76rn3g2c.js";
|
|
18
18
|
import {
|
|
19
19
|
Workspace,
|
|
20
20
|
command
|
|
21
|
-
} from "./index-
|
|
22
|
-
import"./index-
|
|
23
|
-
import"./index-
|
|
21
|
+
} from "./index-jkynkyfk.js";
|
|
22
|
+
import"./index-47qxw1tz.js";
|
|
23
|
+
import"./index-mxvakhsm.js";
|
|
24
24
|
import"./index-xys926f2.js";
|
|
25
25
|
import"./index-67546d0j.js";
|
|
26
26
|
import"./index-r24hmh0q.js";
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AiSession
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-0cj2zxbm.js";
|
|
5
5
|
import {
|
|
6
6
|
Prompter
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-qp089jp0.js";
|
|
8
8
|
import {
|
|
9
9
|
Workspace,
|
|
10
10
|
command,
|
|
11
11
|
runner,
|
|
12
12
|
script
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-jkynkyfk.js";
|
|
14
14
|
import {
|
|
15
15
|
getDirname
|
|
16
|
-
} from "./index-
|
|
17
|
-
import"./index-
|
|
16
|
+
} from "./index-47qxw1tz.js";
|
|
17
|
+
import"./index-mxvakhsm.js";
|
|
18
18
|
import {
|
|
19
19
|
FileSys
|
|
20
20
|
} from "./index-67546d0j.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "SSR Rule",
|
|
3
|
+
"description": "Akan SSR-first rendering rules — keep JSX on the server and justify every client boundary",
|
|
4
|
+
"group": "core",
|
|
5
|
+
"codegenPriority": 3,
|
|
6
|
+
"deprecated": false,
|
|
7
|
+
"scans": [
|
|
8
|
+
{
|
|
9
|
+
"type": "example",
|
|
10
|
+
"description": "Client boundary shells that render server children untouched",
|
|
11
|
+
"path": "{apps,libs}/*/ui/**/*.tsx",
|
|
12
|
+
"sample": 4
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"type": "example",
|
|
16
|
+
"description": "Module UI split across client Zone/Template/Util and server Unit/View",
|
|
17
|
+
"path": "{apps,libs}/*/lib/*/*.tsx",
|
|
18
|
+
"sample": 4
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"update": {
|
|
22
|
+
"filePath": "./ssrRule.instruction.md",
|
|
23
|
+
"contents": ["purpose", "when a client boundary is earned", "quality rules", "implementation playbook"],
|
|
24
|
+
"rules": [
|
|
25
|
+
"Use current Akan APIs only",
|
|
26
|
+
"Keep output parseable for codegen",
|
|
27
|
+
"Name the akan.ssr.* rule ids the quality scanner emits",
|
|
28
|
+
"Ground every pattern in a file that exists in the workspace"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Akan SSR Rule Guideline
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Use this when writing or reviewing any `.tsx` file. Akan is SSR-first: an element rendered on the server ships as
|
|
5
|
+
HTML and costs nothing to hydrate, while an element behind `"use client"` ships twice — as markup and as bundled JS
|
|
6
|
+
that re-runs in the browser. The boundary question is never "may this file be client", it is **how little ends up
|
|
7
|
+
on the client side**.
|
|
8
|
+
|
|
9
|
+
## When A Client Boundary Is Earned
|
|
10
|
+
- A component earns `"use client"` only by using a client-only capability: a React hook, a JSX event handler, the
|
|
11
|
+
store (`st.use.*` / `st.do.*`), a browser global (`window`, `document`, `navigator`, `localStorage`, …), or a
|
|
12
|
+
client-only third-party package.
|
|
13
|
+
- Rendering markup, mapping over data, reading a route param, and calling `l()` are server work. `usePage()` and
|
|
14
|
+
`getSelf()` are legal in server components and never force a boundary.
|
|
15
|
+
- In domain UI the file role fixes the directive: `Template`, `Zone`, and `Util` are client; `Unit` and `View` are
|
|
16
|
+
server. That decides *where* the boundary sits, not how much markup sits behind it — a `Zone` that hoards markup
|
|
17
|
+
is still an SSR regression.
|
|
18
|
+
- Measure with `akan quality ssr` (`--format json` for tooling). It reports the server render share per app and
|
|
19
|
+
lib as server-rendered JSX elements over total. Treat **50% server share as the floor** and a falling share as a
|
|
20
|
+
regression to justify or revert.
|
|
21
|
+
|
|
22
|
+
## Quality Rules
|
|
23
|
+
- `akan.ssr.unnecessary-use-client` — the directive is present but nothing in the file needs it. Delete it. If the
|
|
24
|
+
file exists only to wrap one client child, drop the wrapper and use the child directly.
|
|
25
|
+
- `akan.ssr.client-static-component` — a component inside a client file renders real markup with zero client-only
|
|
26
|
+
capability. Move it to a server file: a `<Model>.Unit.tsx` / `<Model>.View.tsx` for a module, or a `ui/` file with
|
|
27
|
+
no directive.
|
|
28
|
+
- `akan.ssr.client-static-markup` — a large subtree wraps one or two interactive touches. Keep the interactive
|
|
29
|
+
element in the client component and hoist the static subtree into a server component received as `children`.
|
|
30
|
+
- `akan.ssr.client-mount-load` — a `useEffect(…, [])` loads server data. Fetch it in the route and pass the
|
|
31
|
+
init/view object down.
|
|
32
|
+
- `akan.ssr.module-missing-server-view` — a module renders only from `Template`/`Zone`/`Util` and declares no
|
|
33
|
+
`Unit`/`View`. Add them and have the `Zone` delegate.
|
|
34
|
+
- `akan.ssr.template-client-state` — a `Template` holds form state in `useState`. Bind to the store instead:
|
|
35
|
+
`value={xForm.field}` with `onChange={st.do.setFieldOnX}`.
|
|
36
|
+
|
|
37
|
+
A third-party client package and the `ui/<Folder>/index_.tsx` + `lazy()` boundary both justify the directive and are
|
|
38
|
+
not flagged. Interaction-driven `fetch.*` inside an `onClick` is not flagged either — only mount-time loads are,
|
|
39
|
+
because those are the ones the server could have performed.
|
|
40
|
+
|
|
41
|
+
## Implementation Playbook
|
|
42
|
+
|
|
43
|
+
**① Wrap the interaction, not the UI.** The smallest useful client component adds one behaviour and renders
|
|
44
|
+
`children` untouched, so the markup inside never reaches the bundle.
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
"use client";
|
|
48
|
+
export const ClickWrapper = ({ children, onPick }: ClickWrapperProps) => <div onClick={onPick}>{children}</div>;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`libs/shared/ui/Only/User.tsx` is the same shape: it reads auth state on the client and returns `{children}`.
|
|
52
|
+
|
|
53
|
+
**② Split compound components so panels stay on the server.** A tab, accordion, or disclosure needs client state
|
|
54
|
+
only for *which* part is visible, never for what the parts contain. `Tab` / `Tab.Menus` / `Tab.Menu` / `Tab.Panel`
|
|
55
|
+
in `akanjs/ui` is the reference: only the provider and menu hold state, and `<Tab.Panel>` renders its children
|
|
56
|
+
as-is, so a server `Unit`/`View` passed in stays server-rendered.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<Tab defaultMenu="detail">
|
|
60
|
+
<Tab.Menus>
|
|
61
|
+
<Tab.Menu menu="detail">{l("post.detail")}</Tab.Menu>
|
|
62
|
+
<Tab.Menu menu="history">{l("post.history")}</Tab.Menu>
|
|
63
|
+
</Tab.Menus>
|
|
64
|
+
<Tab.Panel menu="detail">
|
|
65
|
+
<Post.View.General post={post} />
|
|
66
|
+
</Tab.Panel>
|
|
67
|
+
</Tab>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Never collapse this into one client file with a mode `useState` and every panel body inlined.
|
|
71
|
+
|
|
72
|
+
**③ Sync state instead of fetching it.** A server component cannot hold state, so render the initial data on the
|
|
73
|
+
server and hand it across as a serializable object. The route calls `fetch.initXInY(...)` / `fetch.viewX(...)` and
|
|
74
|
+
passes the result into a `Zone`; `Load.Units` / `Load.View` hydrate the store from it. A `useEffect(…, [])` that
|
|
75
|
+
fetches on mount renders an empty shell, hydrates, then round-trips for data the server already had.
|
|
76
|
+
|
|
77
|
+
**④ Push the boundary down to the leaf that needs it.** A store-reading `Zone` should hold zero markup and delegate
|
|
78
|
+
to a server `View` — `User.Zone.Self` is one line, `st.use.self()` into `<User.View.General user={self} />`, so the
|
|
79
|
+
whole detail surface renders server-side wherever a route uses the `View` directly.
|
|
80
|
+
|
|
81
|
+
**⑤ Hand the promise across, not the awaited value.** `ClientInit` / `ClientView` are `PromiseOrObject<T>`, so a
|
|
82
|
+
route may pass an unawaited `fetch.initX(...)` and `Load.*` resolves it behind a skeleton. `await` blocks the shell
|
|
83
|
+
for data the page needs immediately; the promise streams the rest. Independent fetches still go through one
|
|
84
|
+
`Promise.all`.
|
|
85
|
+
|
|
86
|
+
**⑥ Use named `ReactNode` slots, not just `children`.** `Layout.Navbar` accepts `title`, `back`, `left`, `right`,
|
|
87
|
+
and `children`, so a client shell composes server-rendered content in five places instead of absorbing it.
|
|
88
|
+
|
|
89
|
+
**⑦ Let the server do the derived work.** Display and predicate logic belongs on `Light<Model>` (`isNew()`,
|
|
90
|
+
`canWrite(user?)`, `formatTimes()`), and enum→class lookups belong in a module-scope `as const` map. Both sides call
|
|
91
|
+
the same method, so a client component that exists only to compute a label is markup in the wrong place.
|
|
92
|
+
|
|
93
|
+
**⑧ Gate auth on the server.** `getSelf({ unauthorize: "/signin" })` in `_layout.tsx` redirects before any HTML is
|
|
94
|
+
sent. A client-side check costs a hydration round-trip and flashes the wrong UI first.
|
|
95
|
+
|
|
96
|
+
**⑨ Prefer CSS over client state for pure visibility.** A `data-*` attribute plus `group-data-[…]` variants (see
|
|
97
|
+
`libs/util/ui/Grid/*`) or `<details>`/`<summary>` keeps both branches server-rendered. Reach for `useState` when the
|
|
98
|
+
state is real, not when a Tailwind variant would do.
|
|
99
|
+
|
|
100
|
+
**⑩ Keep the heavy island out of the first load.** A large client-only widget goes behind the
|
|
101
|
+
`ui/<Folder>/index_.tsx` + `lazy()` pair so the server renders the page around it.
|
|
102
|
+
|
|
103
|
+
## Review Checklist
|
|
104
|
+
- Does every `"use client"` in the diff name a capability that requires it?
|
|
105
|
+
- Does each client component hold only interaction, with markup delegated to `children`, a slot prop, or a
|
|
106
|
+
`Unit`/`View`?
|
|
107
|
+
- Is initial data fetched in the route and passed as `init`/`view`, with no mount-only load effect?
|
|
108
|
+
- Did `akan quality ssr` hold or improve the server share for every touched app and lib?
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
DevGeneratedIndexSync,
|
|
9
9
|
GraphClientEntryDiscovery,
|
|
10
10
|
RouteClientBuilder
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-j9cxndc0.js";
|
|
12
12
|
import {
|
|
13
13
|
HmrWatcher,
|
|
14
14
|
WatchRootResolver
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
import {
|
|
17
17
|
AppExecutor,
|
|
18
18
|
WorkspaceExecutor
|
|
19
|
-
} from "./index-
|
|
20
|
-
import"./index-
|
|
19
|
+
} from "./index-47qxw1tz.js";
|
|
20
|
+
import"./index-mxvakhsm.js";
|
|
21
21
|
import"./index-67546d0j.js";
|
|
22
22
|
import"./index-r24hmh0q.js";
|
|
23
23
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
Spinner
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-mxvakhsm.js";
|
|
5
5
|
import {
|
|
6
6
|
FileSys
|
|
7
7
|
} from "./index-67546d0j.js";
|
|
@@ -913,19 +913,8 @@ ${errorText}, ${warningText} found`];
|
|
|
913
913
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
914
914
|
import { rm } from "fs/promises";
|
|
915
915
|
import path4 from "path";
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
"dictionary",
|
|
919
|
-
"document",
|
|
920
|
-
"service",
|
|
921
|
-
"signal",
|
|
922
|
-
"store",
|
|
923
|
-
"template",
|
|
924
|
-
"unit",
|
|
925
|
-
"util",
|
|
926
|
-
"view",
|
|
927
|
-
"zone"
|
|
928
|
-
];
|
|
916
|
+
|
|
917
|
+
// pkgs/@akanjs/devkit/workspaceLayout.ts
|
|
929
918
|
var appRootAllowedFiles = new Set([
|
|
930
919
|
"AGENTS.md",
|
|
931
920
|
"CLAUDE.md",
|
|
@@ -939,25 +928,25 @@ var appRootAllowedFiles = new Set([
|
|
|
939
928
|
"tsconfig.json",
|
|
940
929
|
"tsconfig.tsbuildinfo"
|
|
941
930
|
]);
|
|
942
|
-
var generatedRootCapacitorConfigFiles = ["capacitor.config.js", "capacitor.config.json"];
|
|
943
931
|
var appRootAllowedDirs = new Set([
|
|
944
932
|
".akan",
|
|
945
933
|
"android",
|
|
934
|
+
"common",
|
|
946
935
|
"env",
|
|
947
936
|
"ios",
|
|
948
937
|
"lib",
|
|
949
938
|
"mobile",
|
|
950
939
|
"page",
|
|
940
|
+
"plugin",
|
|
951
941
|
"private",
|
|
952
942
|
"public",
|
|
953
943
|
"script",
|
|
954
|
-
"
|
|
944
|
+
"secrets",
|
|
955
945
|
"srvkit",
|
|
956
|
-
"
|
|
957
|
-
"
|
|
958
|
-
"secrets"
|
|
946
|
+
"ui",
|
|
947
|
+
"webkit"
|
|
959
948
|
]);
|
|
960
|
-
var
|
|
949
|
+
var libFacetRootAllowedFiles = new Set([
|
|
961
950
|
"cnst.ts",
|
|
962
951
|
"db.ts",
|
|
963
952
|
"dict.ts",
|
|
@@ -968,6 +957,23 @@ var libRootAllowedFiles = new Set([
|
|
|
968
957
|
"useClient.ts",
|
|
969
958
|
"useServer.ts"
|
|
970
959
|
]);
|
|
960
|
+
var isScannedAppRootEntry = (name) => !name.startsWith(".") || appRootAllowedDirs.has(name);
|
|
961
|
+
|
|
962
|
+
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
963
|
+
var databaseFileTypes = [
|
|
964
|
+
"constant",
|
|
965
|
+
"dictionary",
|
|
966
|
+
"document",
|
|
967
|
+
"service",
|
|
968
|
+
"signal",
|
|
969
|
+
"store",
|
|
970
|
+
"template",
|
|
971
|
+
"unit",
|
|
972
|
+
"util",
|
|
973
|
+
"view",
|
|
974
|
+
"zone"
|
|
975
|
+
];
|
|
976
|
+
var generatedRootCapacitorConfigFiles = ["capacitor.config.js", "capacitor.config.json"];
|
|
971
977
|
var internalLibDirs = new Set(["__lib", "__scalar"]);
|
|
972
978
|
var moduleNonUiFileTypes = {
|
|
973
979
|
database: new Set(["constant", "dictionary", "document", "service", "signal", "store"]),
|
|
@@ -983,7 +989,7 @@ var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
|
|
|
983
989
|
var rootSignalTestFilePattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
|
|
984
990
|
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-f6grrep3.js")).TypeScriptDependencyScanner.from(exec);
|
|
985
991
|
var isAllowedTestFile = (filename) => testFilePattern.test(filename);
|
|
986
|
-
var isAllowedLibRootFile = (filename) =>
|
|
992
|
+
var isAllowedLibRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
|
|
987
993
|
var getScanPath = (exec, relativePath) => path4.posix.join(`${exec.type}s`, exec.name, relativePath.split(path4.sep).join("/"));
|
|
988
994
|
async function clearGeneratedRootCapacitorConfigs(exec) {
|
|
989
995
|
if (exec.type !== "app")
|
|
@@ -3003,4 +3009,4 @@ class ModuleExecutor extends Executor {
|
|
|
3003
3009
|
}
|
|
3004
3010
|
}
|
|
3005
3011
|
|
|
3006
|
-
export { AGENT_BLOCK_START, AGENT_BLOCK_END, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, getDirname, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|
|
3012
|
+
export { AGENT_BLOCK_START, AGENT_BLOCK_END, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, getDirname, appRootAllowedFiles, appRootAllowedDirs, libFacetRootAllowedFiles, isScannedAppRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
PageScript
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-hrwzz2wf.js";
|
|
5
5
|
import {
|
|
6
6
|
pluralizeName
|
|
7
7
|
} from "./index-ss469dec.js";
|
|
8
8
|
import {
|
|
9
9
|
AiSession
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-0cj2zxbm.js";
|
|
11
11
|
import {
|
|
12
12
|
bilingualDescriptionForField,
|
|
13
13
|
bilingualLabelForField,
|
|
@@ -15,17 +15,17 @@ import {
|
|
|
15
15
|
generatedFilesForSync,
|
|
16
16
|
moduleSourcePaths,
|
|
17
17
|
sourceFile
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-m4kpmmtj.js";
|
|
19
19
|
import {
|
|
20
20
|
Prompter
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-qp089jp0.js";
|
|
22
22
|
import {
|
|
23
23
|
runner,
|
|
24
24
|
script
|
|
25
|
-
} from "./index-
|
|
25
|
+
} from "./index-jkynkyfk.js";
|
|
26
26
|
import {
|
|
27
27
|
ModuleExecutor
|
|
28
|
-
} from "./index-
|
|
28
|
+
} from "./index-47qxw1tz.js";
|
|
29
29
|
import {
|
|
30
30
|
FileSys
|
|
31
31
|
} from "./index-67546d0j.js";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AkanContextAnalyzer
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-jn9vfpwz.js";
|
|
5
5
|
import {
|
|
6
6
|
createRepairReport,
|
|
7
7
|
generatedFilePathsForTarget,
|
|
8
8
|
renderRepairReport,
|
|
9
9
|
writeGeneratedSyncState,
|
|
10
10
|
writeWorkflowRunArtifact
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-m4kpmmtj.js";
|
|
12
12
|
import {
|
|
13
13
|
runner
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-jkynkyfk.js";
|
|
15
15
|
|
|
16
16
|
// pkgs/@akanjs/cli/repair/repair.runner.ts
|
|
17
17
|
var commandForShell = (command) => command.startsWith("akan ") ? `bun run ${command}` : command;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AkanContextAnalyzer
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-jn9vfpwz.js";
|
|
5
5
|
import {
|
|
6
6
|
WorkflowExecutor,
|
|
7
7
|
compactWorkflowInputs,
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
workflowCommandsForPlan,
|
|
24
24
|
workflowPlanApproval,
|
|
25
25
|
writeWorkflowRunArtifact
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-m4kpmmtj.js";
|
|
27
27
|
import {
|
|
28
28
|
runner
|
|
29
|
-
} from "./index-
|
|
29
|
+
} from "./index-jkynkyfk.js";
|
|
30
30
|
|
|
31
31
|
// pkgs/@akanjs/cli/workflow/workflow.runner.ts
|
|
32
32
|
import { mkdir, readFile, writeFile } from "fs/promises";
|