@akanjs/cli 3.0.0-alpha.71 → 3.0.0-alpha.73
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-20e0cwbs.js → abstractCompactor-8yjc9sj4.js} +1 -1
- package/{agent.command-xdvw642m.js → agent.command-z0cam80t.js} +6 -6
- package/{application.command-g3f7xj25.js → application.command-2dct57za.js} +11 -12
- package/{applicationBuildRunner-af0wtspv.js → applicationBuildRunner-ds8acdfz.js} +3 -3
- package/{applicationReleasePackager-93nzdfsy.js → applicationReleasePackager-0jf6ejr4.js} +2 -2
- package/buildBatch.proc.js +4 -4
- package/{capacitorApp-b0ppke3m.js → capacitorApp-md7dnt25.js} +2 -2
- package/{cloud.command-0hmsv44q.js → cloud.command-8j7xrxsm.js} +10 -10
- package/{context.command-x92afrnf.js → context.command-xjf4y7em.js} +14 -14
- package/{dependencyScanner-rbs2407b.js → dependencyScanner-aqg3dkks.js} +1 -1
- package/{guideline.command-hpq08q66.js → guideline.command-yzm0qevv.js} +4 -4
- package/guidelines/conventions/conventions.instruction.md +17 -9
- package/guidelines/ssrRule/ssrRule.instruction.md +49 -5
- package/incrementalBuilder.proc.js +5 -5
- package/{index-737aj4fm.js → index-116w1dap.js} +4 -4
- package/{index-cp00yns2.js → index-5r4e65hb.js} +65 -62
- package/{index-abyjt72y.js → index-61x7qthy.js} +17 -21
- package/{index-m5gfc86a.js → index-763h7h9g.js} +1 -1
- package/{index-wnp7hwq7.js → index-94hdqqka.js} +1 -1
- package/{index-r691v756.js → index-9gqzgfsd.js} +4 -4
- package/{index-pehn44hr.js → index-a341yqdh.js} +3 -3
- package/{index-gvq17wqn.js → index-akz5xvyw.js} +17 -5
- package/{index-6d5r8q6k.js → index-bmz9crym.js} +13 -6
- package/{index-nq3avsf6.js → index-eed7vc38.js} +66 -33
- package/{index-46tjzh6s.js → index-h5sr2nnj.js} +24 -24
- package/{index-5f4gnt4c.js → index-h9cybjep.js} +91 -19
- package/{index-sqsfv8wg.js → index-hvbdre8z.js} +4 -10
- package/{index-qnv0aqmm.js → index-jcm6zr20.js} +3 -1
- package/{index-j37qq1f2.js → index-k7731a4v.js} +4 -4
- package/{index-8besc14m.js → index-q0s2dp3y.js} +1 -1
- package/{index-ety6takb.js → index-q13s3e01.js} +3 -3
- package/{index-jybbmwed.js → index-qge1hc70.js} +5 -5
- package/{index-sh01r3pm.js → index-safgeq9a.js} +3 -2
- package/{index-xjd3rqzj.js → index-scemmfpj.js} +6 -15
- package/{index-wbbswwqt.js → index-te6r1b79.js} +5 -5
- package/{index-p27h7535.js → index-vrra4ttx.js} +6 -6
- package/{index-hs70d8ed.js → index-y3wyqcsp.js} +6 -6
- package/{index-cbfp5wyp.js → index-ym9g9ggs.js} +21 -21
- package/{index-fgc8r6dj.js → index-ynf37b66.js} +3 -1
- package/{index-wybbcgxn.js → index-z52nhkjs.js} +4 -4
- package/index.js +18 -18
- package/{library.command-8vgrdtwy.js → library.command-w8b53vtt.js} +4 -4
- package/{localRegistry.command-0gtqj0r0.js → localRegistry.command-ymrgda7e.js} +9 -9
- package/{module.command-rama4zya.js → module.command-7pje37dv.js} +7 -7
- package/{package.command-6jxapdsg.js → package.command-jg4qk8ts.js} +4 -4
- package/package.json +3 -4
- package/{page.command-hxy7x525.js → page.command-abbpj96j.js} +3 -3
- package/{primitive.command-4bf6xcc3.js → primitive.command-jw4yv918.js} +8 -8
- package/{quality.command-h5edwegz.js → quality.command-06j6qy6n.js} +34 -4
- package/{repair.command-rgqf6px6.js → repair.command-x6resn10.js} +5 -5
- package/{scalar.command-6krkz6tw.js → scalar.command-mj2vx6rj.js} +6 -6
- package/templates/appSample/lib/task/task.signal.ts +11 -6
- package/templates/crudPages/[__model__Id]/edit/page.tsx +5 -5
- package/templates/crudPages/[__model__Id]/page.tsx +10 -13
- package/templates/crudPages/new/page.tsx +5 -5
- package/templates/crudPages/page.tsx +9 -9
- package/templates/crudSinglePage/page.tsx +11 -7
- package/templates/module/__model__.dictionary.ts +4 -1
- package/templates/module/__model__.signal.ts +2 -3
- package/templates/module/__model__.store.ts +1 -2
- package/{typeChecker-g6bh0xfv.js → typeChecker-yhs4eht8.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/{workflow.command-dwhwrqhd.js → workflow.command-pmw2tere.js} +11 -11
- package/{workspace.command-f5h11gjn.js → workspace.command-x32k2vma.js} +29 -26
package/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
a9d70ff91464d4b82a980a78c9674659fc1f17c40d66e5b20089f065bd4f2212
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AgentScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
4
|
+
} from "./index-te6r1b79.js";
|
|
5
|
+
import"./index-bmz9crym.js";
|
|
6
|
+
import"./index-q0s2dp3y.js";
|
|
7
|
+
import"./index-k7731a4v.js";
|
|
8
8
|
import {
|
|
9
9
|
Workspace,
|
|
10
10
|
command
|
|
11
|
-
} from "./index-
|
|
12
|
-
import"./index-
|
|
11
|
+
} from "./index-akz5xvyw.js";
|
|
12
|
+
import"./index-h9cybjep.js";
|
|
13
13
|
import"./index-f39512t6.js";
|
|
14
14
|
import"./index-mxvakhsm.js";
|
|
15
15
|
import"./index-xys926f2.js";
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
} from "./index-0wae5ebk.js";
|
|
5
5
|
import {
|
|
6
6
|
ApplicationScript
|
|
7
|
-
} from "./index-
|
|
8
|
-
import"./index-
|
|
7
|
+
} from "./index-5r4e65hb.js";
|
|
8
|
+
import"./index-hvbdre8z.js";
|
|
9
9
|
import {
|
|
10
10
|
getMobileTargetChoices
|
|
11
11
|
} from "./index-76rn3g2c.js";
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
Sys,
|
|
16
16
|
Workspace,
|
|
17
17
|
command
|
|
18
|
-
} from "./index-
|
|
19
|
-
import"./index-
|
|
18
|
+
} from "./index-akz5xvyw.js";
|
|
19
|
+
import"./index-ynf37b66.js";
|
|
20
20
|
import"./index-5vy2jzar.js";
|
|
21
|
-
import"./index-
|
|
21
|
+
import"./index-h9cybjep.js";
|
|
22
22
|
import"./index-f39512t6.js";
|
|
23
23
|
import"./index-mxvakhsm.js";
|
|
24
24
|
import"./index-1577bej2.js";
|
|
@@ -27,7 +27,6 @@ import"./index-yb2wsc7f.js";
|
|
|
27
27
|
|
|
28
28
|
// pkgs/@akanjs/cli/application/application.command.ts
|
|
29
29
|
import { select } from "@inquirer/prompts";
|
|
30
|
-
var asMobileEnv = (env) => env;
|
|
31
30
|
var mobileTargetOption = {
|
|
32
31
|
desc: "mobile target name or all",
|
|
33
32
|
ask: "Select mobile target",
|
|
@@ -94,14 +93,14 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
|
|
|
94
93
|
desc: "backend environment",
|
|
95
94
|
default: "debug"
|
|
96
95
|
}).option("write", Boolean, { desc: "write code generation", default: true }).option("regenerate", Boolean, { flag: "g", desc: "delete and regenerate native project", default: false }).exec(async function(app, target2, env, write, regenerate) {
|
|
97
|
-
await this.applicationScript.buildIos(app, { target: target2, env
|
|
96
|
+
await this.applicationScript.buildIos(app, { target: target2, env, write, regenerate });
|
|
98
97
|
}),
|
|
99
98
|
buildAndroid: target({ short: true, desc: "Build Android app with Capacitor" }).with(App).option("target", String, mobileTargetOption).option("env", String, {
|
|
100
99
|
enum: ["local", "debug", "develop", "main"],
|
|
101
100
|
desc: "backend environment",
|
|
102
101
|
default: "debug"
|
|
103
102
|
}).option("write", Boolean, { desc: "write code generation", default: true }).option("regenerate", Boolean, { flag: "g", desc: "delete and regenerate native project", default: false }).exec(async function(app, target2, env, write, regenerate) {
|
|
104
|
-
await this.applicationScript.buildAndroid(app, { target: target2, env
|
|
103
|
+
await this.applicationScript.buildAndroid(app, { target: target2, env, write, regenerate });
|
|
105
104
|
}),
|
|
106
105
|
start: target({ short: true, desc: "Start development server (frontend SSR + backend)" }).with(App).option("open", Boolean, { desc: "open web browser?", default: false }).option("write", Boolean, { desc: "write code generation", default: true }).exec(async function(app, open, write) {
|
|
107
106
|
await this.applicationScript.start(app, { open, write });
|
|
@@ -119,7 +118,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
|
|
|
119
118
|
}).exec(async function(app, target2, env, open, release, write, regenerate, noAllowProvisioningUpdates, device) {
|
|
120
119
|
await this.applicationScript.startIos(app, {
|
|
121
120
|
target: target2,
|
|
122
|
-
env
|
|
121
|
+
env,
|
|
123
122
|
open,
|
|
124
123
|
operation: release ? "release" : "local",
|
|
125
124
|
write,
|
|
@@ -135,7 +134,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
|
|
|
135
134
|
}).option("release", Boolean, { desc: "release mode", default: false }).option("open", Boolean, { desc: "open android simulator", default: false }).option("write", Boolean, { desc: "write code generation", default: true }).option("regenerate", Boolean, { flag: "g", desc: "delete and regenerate native project", default: false }).exec(async function(app, target2, env, release, open, write, regenerate) {
|
|
136
135
|
await this.applicationScript.startAndroid(app, {
|
|
137
136
|
target: target2,
|
|
138
|
-
env
|
|
137
|
+
env,
|
|
139
138
|
open,
|
|
140
139
|
operation: release ? "release" : "local",
|
|
141
140
|
write,
|
|
@@ -149,7 +148,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
|
|
|
149
148
|
}).option("write", Boolean, { desc: "write code generation", default: true }).option("regenerate", Boolean, { flag: "g", desc: "delete and regenerate native project", default: false }).option("allowLocalRelease", Boolean, { flag: "l", desc: "allow release with --env local", default: false }).exec(async function(app, target2, env, write, regenerate, allowLocalRelease) {
|
|
150
149
|
await this.applicationScript.releaseIos(app, {
|
|
151
150
|
target: target2,
|
|
152
|
-
env
|
|
151
|
+
env,
|
|
153
152
|
write,
|
|
154
153
|
regenerate,
|
|
155
154
|
allowLocalRelease
|
|
@@ -162,7 +161,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
|
|
|
162
161
|
}).option("write", Boolean, { desc: "write code generation", default: true }).option("regenerate", Boolean, { flag: "g", desc: "delete and regenerate native project", default: false }).option("allowLocalRelease", Boolean, { flag: "l", desc: "allow release with --env local", default: false }).exec(async function(app, assembleType, target2, env, write, regenerate, allowLocalRelease) {
|
|
163
162
|
await this.applicationScript.releaseAndroid(app, assembleType, {
|
|
164
163
|
target: target2,
|
|
165
|
-
env
|
|
164
|
+
env,
|
|
166
165
|
write,
|
|
167
166
|
regenerate,
|
|
168
167
|
allowLocalRelease
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
FontPruner,
|
|
6
6
|
SsrBaseArtifactBuilder,
|
|
7
7
|
precompressArtifacts
|
|
8
|
-
} from "./index-
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-
|
|
8
|
+
} from "./index-61x7qthy.js";
|
|
9
|
+
import"./index-scemmfpj.js";
|
|
10
|
+
import"./index-jcm6zr20.js";
|
|
11
11
|
import"./index-5vy2jzar.js";
|
|
12
12
|
import"./index-f39512t6.js";
|
|
13
13
|
import {
|
|
@@ -12,7 +12,7 @@ import { cp, mkdir, rm } from "fs/promises";
|
|
|
12
12
|
import path from "path";
|
|
13
13
|
|
|
14
14
|
// pkgs/@akanjs/devkit/uploadRelease.ts
|
|
15
|
-
import {
|
|
15
|
+
import { Logger, RestClient } from "akanjs/common";
|
|
16
16
|
var spinning = (message) => {
|
|
17
17
|
const spinner = new Spinner(message, { prefix: message, enableSpin: true }).start();
|
|
18
18
|
return spinner;
|
|
@@ -27,7 +27,7 @@ var uploadRelease = async (appName, {
|
|
|
27
27
|
}) => {
|
|
28
28
|
const logger = new Logger("uploadRelease");
|
|
29
29
|
const basePath = local ? "http://localhost:8282/backend" : "https://cloud.akanjs.com/backend";
|
|
30
|
-
const httpClient = new
|
|
30
|
+
const httpClient = new RestClient(basePath);
|
|
31
31
|
const buildPath = `${workspaceRoot}/releases/builds/${appName}-release.tar.gz`;
|
|
32
32
|
const appBuildPath = `${workspaceRoot}/releases/builds/${appName}-appBuild.zip`;
|
|
33
33
|
const sourcePath = `${workspaceRoot}/releases/sources/${appName}-source.tar.gz`;
|
package/buildBatch.proc.js
CHANGED
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
FontOptimizer,
|
|
6
6
|
PagesBundleBuilder,
|
|
7
7
|
SsrBaseArtifactBuilder
|
|
8
|
-
} from "./index-
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-
|
|
8
|
+
} from "./index-61x7qthy.js";
|
|
9
|
+
import"./index-scemmfpj.js";
|
|
10
|
+
import"./index-jcm6zr20.js";
|
|
11
11
|
import"./index-5vy2jzar.js";
|
|
12
12
|
import {
|
|
13
13
|
AppExecutor,
|
|
14
14
|
WorkspaceExecutor
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-h9cybjep.js";
|
|
16
16
|
import"./index-f39512t6.js";
|
|
17
17
|
import"./index-mxvakhsm.js";
|
|
18
18
|
import"./index-1577bej2.js";
|
|
@@ -25,9 +25,9 @@ import {
|
|
|
25
25
|
selectLocalDevHost,
|
|
26
26
|
sortIosRunTargets,
|
|
27
27
|
writeRootCapacitorConfig
|
|
28
|
-
} from "./index-
|
|
28
|
+
} from "./index-ym9g9ggs.js";
|
|
29
29
|
import"./index-76rn3g2c.js";
|
|
30
|
-
import"./index-
|
|
30
|
+
import"./index-h9cybjep.js";
|
|
31
31
|
import"./index-f39512t6.js";
|
|
32
32
|
import"./index-mxvakhsm.js";
|
|
33
33
|
import"./index-1577bej2.js";
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
CloudScript
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
4
|
+
} from "./index-y3wyqcsp.js";
|
|
5
|
+
import"./index-116w1dap.js";
|
|
6
|
+
import"./index-qge1hc70.js";
|
|
7
7
|
import {
|
|
8
8
|
GlobalConfig
|
|
9
|
-
} from "./index-
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
9
|
+
} from "./index-safgeq9a.js";
|
|
10
|
+
import"./index-5r4e65hb.js";
|
|
11
|
+
import"./index-hvbdre8z.js";
|
|
12
12
|
import"./index-76rn3g2c.js";
|
|
13
13
|
import {
|
|
14
14
|
Workspace,
|
|
15
15
|
command
|
|
16
|
-
} from "./index-
|
|
17
|
-
import"./index-
|
|
16
|
+
} from "./index-akz5xvyw.js";
|
|
17
|
+
import"./index-ynf37b66.js";
|
|
18
18
|
import"./index-5vy2jzar.js";
|
|
19
|
-
import"./index-
|
|
19
|
+
import"./index-h9cybjep.js";
|
|
20
20
|
import"./index-f39512t6.js";
|
|
21
21
|
import"./index-mxvakhsm.js";
|
|
22
22
|
import"./index-1577bej2.js";
|
|
23
|
-
import"./index-
|
|
23
|
+
import"./index-h5sr2nnj.js";
|
|
24
24
|
import"./index-67546d0j.js";
|
|
25
25
|
import"./index-yb2wsc7f.js";
|
|
26
26
|
|
|
@@ -1,25 +1,25 @@
|
|
|
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-
|
|
4
|
+
} from "./index-eed7vc38.js";
|
|
5
|
+
import"./index-q13s3e01.js";
|
|
6
|
+
import"./index-a341yqdh.js";
|
|
7
|
+
import"./index-9gqzgfsd.js";
|
|
8
|
+
import"./index-z52nhkjs.js";
|
|
9
|
+
import"./index-vrra4ttx.js";
|
|
10
10
|
import"./index-ss469dec.js";
|
|
11
|
-
import"./index-
|
|
12
|
-
import"./index-
|
|
13
|
-
import"./index-
|
|
14
|
-
import"./index-
|
|
15
|
-
import"./index-
|
|
16
|
-
import"./index-
|
|
11
|
+
import"./index-763h7h9g.js";
|
|
12
|
+
import"./index-ym9g9ggs.js";
|
|
13
|
+
import"./index-safgeq9a.js";
|
|
14
|
+
import"./index-bmz9crym.js";
|
|
15
|
+
import"./index-q0s2dp3y.js";
|
|
16
|
+
import"./index-k7731a4v.js";
|
|
17
17
|
import"./index-76rn3g2c.js";
|
|
18
18
|
import {
|
|
19
19
|
Workspace,
|
|
20
20
|
command
|
|
21
|
-
} from "./index-
|
|
22
|
-
import"./index-
|
|
21
|
+
} from "./index-akz5xvyw.js";
|
|
22
|
+
import"./index-h9cybjep.js";
|
|
23
23
|
import"./index-f39512t6.js";
|
|
24
24
|
import"./index-mxvakhsm.js";
|
|
25
25
|
import"./index-xys926f2.js";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
AiSession
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-safgeq9a.js";
|
|
5
5
|
import {
|
|
6
6
|
Prompter
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-k7731a4v.js";
|
|
8
8
|
import {
|
|
9
9
|
Workspace,
|
|
10
10
|
command,
|
|
11
11
|
runner,
|
|
12
12
|
script
|
|
13
|
-
} from "./index-
|
|
14
|
-
import"./index-
|
|
13
|
+
} from "./index-akz5xvyw.js";
|
|
14
|
+
import"./index-h9cybjep.js";
|
|
15
15
|
import"./index-f39512t6.js";
|
|
16
16
|
import"./index-mxvakhsm.js";
|
|
17
17
|
import {
|
|
@@ -108,16 +108,18 @@ back.
|
|
|
108
108
|
- **Never write an async component outside `page/`** (`no-async-component-in-ui.grit`, scoped to
|
|
109
109
|
`{apps,libs}/**/ui/**/*.tsx`). React has no async client component, so a `ui/` component that awaits breaks as
|
|
110
110
|
soon as a client parent renders it, and the load drops below the route, which could have started it before the
|
|
111
|
-
first byte. Await in the page — or hand an unawaited `fetch.*` to a `Zone` as an `init` / `view` prop
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
first byte. Await in the page — or hand an unawaited `fetch.*` field to a `Zone` as an `init` / `view` prop, or
|
|
112
|
+
to a `<Load.Stream of={…}>` that awaits it behind a boundary of its own — and take the resolved data as a prop.
|
|
113
|
+
Only a PascalCase binding whose own initializer is `async` is matched, so an async handler inside a synchronous
|
|
114
|
+
component and `lazy(async () => import(…))` are untouched.
|
|
114
115
|
- **Never call `fetch.init*` from a client file** (`no-init-fetch-in-client.grit`). `fetch.init<Model><Suffix>` and
|
|
115
116
|
`fetch.get<Model>Init<Suffix>` compose the slice's list and insight queries into the hydration snapshot that
|
|
116
117
|
`Load.Units` / `Load.View` seed the store from. From a route it resolves before the first byte; after hydration
|
|
117
118
|
it is two extra round-trips for a shell the browser already painted. Load it in the page and pass the result
|
|
118
|
-
down as an `init` prop — or hand the unawaited promise across — and reload from the client
|
|
119
|
-
`st.do.init<Model><Suffix>()`. Gated on the real `"use client"` directive plus
|
|
120
|
-
(`init` + `Capitalize<refName>` + `Capitalize<suffix>`), so a hand-written
|
|
119
|
+
down as an `init` prop — or hand the unawaited `x<Model>Init<Suffix>` promise across — and reload from the client
|
|
120
|
+
through the generated `st.do.init<Model><Suffix>()`. Gated on the real `"use client"` directive plus
|
|
121
|
+
`*.store.ts`, and matched by shape (`init` + `Capitalize<refName>` + `Capitalize<suffix>`), so a hand-written
|
|
122
|
+
`initPayment` is out.
|
|
121
123
|
- `noArrayIndexKey` and `useExhaustiveDependencies` are **off** on purpose: `key={idx}` for embedded scalars and
|
|
122
124
|
short dependency arrays are intentional, not oversights.
|
|
123
125
|
- **A grit plugin diagnostic is suppressed as `lint/plugin`, not `plugin`** — `// biome-ignore lint/plugin: <reason>`
|
|
@@ -263,8 +265,14 @@ are, because those are the ones the server could have done.
|
|
|
263
265
|
`useEffect(…, [])` that fetches on mount.
|
|
264
266
|
4. **Push the boundary down to the leaf that needs it.** A store-reading `Zone` should hold zero markup and
|
|
265
267
|
delegate to a server `View`.
|
|
266
|
-
5. **Hand
|
|
267
|
-
|
|
268
|
+
5. **Hand each promise across, not the awaited value.** `fetch.init<Model><Suffix>` / `view<Model>` / `edit<Model>`
|
|
269
|
+
are awaitable *and* destructurable: `const { xInitInY, xListInY } = fetch.initXInY(id)` hands out one promise
|
|
270
|
+
per field with both queries already in flight. Give `xInitInY` to a `Zone` and `xListInY` to a
|
|
271
|
+
`<Load.Stream of={…}>`; each renders behind its own boundary as its own data lands, so the page never waits
|
|
272
|
+
for the slowest. `await` still returns the old shape and keeps the whole section in the shell — which is what
|
|
273
|
+
SEO snapshots, prerendering and pre-hydration E2E read, so await what the page needs immediately and stream
|
|
274
|
+
the rest. `xListInY` / `xInsightInY` hold hydrated model instances that React Flight refuses as client props:
|
|
275
|
+
consume them in a server component, never as a `Zone` prop.
|
|
268
276
|
6. **Use named `ReactNode` slots, not just `children`** — `Layout.Navbar` takes `title`, `back`, `left`, `right`,
|
|
269
277
|
and `children`, so a client shell composes server content in five places instead of absorbing it.
|
|
270
278
|
7. **Let the server do the derived work.** Display and predicate logic belongs on `Light<Model>`; enum→class
|
|
@@ -326,7 +334,7 @@ Full contract: `get_guideline` with `runtimeRule`, or `akan guideline show runti
|
|
|
326
334
|
- Never `React.FC`, never `defaultProps`, never `PropsWithChildren`. Defaults go in the destructuring (`prefix = ""`); children are typed `children: ReactNode`.
|
|
327
335
|
- `"use client"` on line 1 above the imports is mechanical by file role: every `.Zone.tsx`, `.Template.tsx`, and `.Util.tsx` has it; no `.Unit.tsx` or `.View.tsx` ever does. `usePage()` is legal in server files.
|
|
328
336
|
- Conditional render is `cond ? <X/> : null`. Never `{cond && <X/>}` — in a `className` context it renders the literal string `"false"`. Early `return null` is for guard clauses only.
|
|
329
|
-
- Never hand-roll loading, empty, or list states. Use `Load.Units` / `Load.View` / `Load.Edit` with `renderItem`, `renderList`, `renderView`, and `renderEmpty`; `<Empty />` for a bare placeholder; and `Model.New` / `Model.Edit` / `Model.SureToRemove` for CRUD modals.
|
|
337
|
+
- Never hand-roll loading, empty, or list states. Use `Load.Units` / `Load.View` / `Load.Edit` with `renderItem`, `renderList`, `renderView`, and `renderEmpty`; `<Empty />` for a bare placeholder; and `Model.New` / `Model.Edit` / `Model.SureToRemove` for CRUD modals. For data no `Load.*` covers, `<Load.Stream of={promise} fallback={…}>{(value) => …}</Load.Stream>` awaits one promise behind its own Suspense boundary; a resolved value renders in the shell with no boundary at all, so the same call site works either way.
|
|
330
338
|
- Avoid hooks. `useState` is for modal-open, tab, draft-input, and drag state only — never for server data. `useEffect` must be a genuine effect such as subscribe-with-cleanup or one-shot init. Prefer `Tab` over a `useState` mode switch. `.Template.tsx` files contain zero `useState`.
|
|
331
339
|
- Forms are entirely store-driven: `value={xForm.field}` with `onChange={st.do.setFieldOnX}`, the setter passed by reference. Always use `Field.*`, never a bare `<input>` for a model field. Nested rows use `st.do.writeOnX("payments.3.name", v)` plus the generated `add<Field>OnX` / `sub<Field>OnX`. **Passing the setter by reference is also what makes the framework emit `data-akan-action` / `data-akan-state`** on the control — the annotation an in-page agent, an E2E selector, and an external browser agent all read. Wrapping it in an inline arrow (`onChange={(v) => st.do.setFieldOnX(v)}`) silently drops that: a closure the caller wrote says nothing about what it does. Never hand-write a `data-akan-*` attribute.
|
|
332
340
|
- Read with `st.use.*` and write with `st.do.*`. Client components do not call `fetch.*`.
|
|
@@ -71,18 +71,62 @@ Never collapse this into one client file with a mode `useState` and every panel
|
|
|
71
71
|
|
|
72
72
|
**③ Sync state instead of fetching it.** A server component cannot hold state, so render the initial data on the
|
|
73
73
|
server and hand it across as a serializable object. The route calls `fetch.initXInY(...)` / `fetch.viewX(...)` and
|
|
74
|
-
passes
|
|
75
|
-
fetches on mount renders an empty shell, hydrates, then round-trips for data the server
|
|
74
|
+
passes `xInitInY` / `xView` into a `Zone`; `Load.Units` / `Load.View` hydrate the store from it. A
|
|
75
|
+
`useEffect(…, [])` that fetches on mount renders an empty shell, hydrates, then round-trips for data the server
|
|
76
|
+
already had.
|
|
76
77
|
|
|
77
78
|
**④ Push the boundary down to the leaf that needs it.** A store-reading `Zone` should hold zero markup and delegate
|
|
78
79
|
to a server `View` — `User.Zone.Self` is one line, `st.use.self()` into `<User.View.General user={self} />`, so the
|
|
79
80
|
whole detail surface renders server-side wherever a route uses the `View` directly.
|
|
80
81
|
|
|
81
|
-
**⑤ Hand
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
**⑤ Hand each promise across, not the awaited value.** `fetch.init<Model><Suffix>`, `fetch.view<Model>` and
|
|
83
|
+
`fetch.edit<Model>` are awaitable *and* destructurable, so a route can split one call into the promises its
|
|
84
|
+
sections actually need:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
export default async function Page({ params: { orgId } }: PageProps) {
|
|
88
|
+
const { taskInitInOrg, taskListInOrg } = fetch.initTaskInOrg(orgId);
|
|
89
|
+
const { orgView } = fetch.viewOrg(orgId);
|
|
90
|
+
return (
|
|
91
|
+
<>
|
|
92
|
+
<Org.Zone.Header view={orgView} />
|
|
93
|
+
<Task.Zone.Card init={taskInitInOrg} />
|
|
94
|
+
<Load.Stream of={taskListInOrg} fallback={<Loading.Skeleton active />}>
|
|
95
|
+
{(taskList) => taskList.map((task) => <Task.Unit.Row key={task.id} task={task} />)}
|
|
96
|
+
</Load.Stream>
|
|
97
|
+
</>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Both queries leave immediately — splitting the result never serializes them — and each section renders behind its
|
|
103
|
+
own boundary as its own data lands, so one slow query no longer holds the page. `x<Slice>List` does not wait for
|
|
104
|
+
the aggregate the way `x<Slice>Init` must.
|
|
105
|
+
|
|
106
|
+
**`await` is still the right call for what the page needs immediately.** It returns the shape the helper always
|
|
107
|
+
gave and keeps that markup in the shell, which is what SEO snapshots, prerendering and pre-hydration E2E read; a
|
|
108
|
+
boundary moves its subtree out of the shell and into the stream. Independent awaited fetches still go through one
|
|
84
109
|
`Promise.all`.
|
|
85
110
|
|
|
111
|
+
Three rules the shape enforces:
|
|
112
|
+
|
|
113
|
+
- **`x<Slice>List` and `x<Slice>Insight` are server-only.** They hold hydrated model instances, which React Flight
|
|
114
|
+
refuses as props to a client component. Consume them in a server component; `x<Slice>Init` (plain data) is the
|
|
115
|
+
one that crosses into a `Zone`.
|
|
116
|
+
- **Never hand the whole handle to a component** — pass the field. `<Zone init={xInitInY} />`, not
|
|
117
|
+
`<Zone init={fetch.initXInY(id)} />`.
|
|
118
|
+
- **Rendering the list on the server costs one extra hydration.** `Load.Stream` builds the model instances on the
|
|
119
|
+
server and `Load.Units` builds them again after hydration, so a large list is still better off going through
|
|
120
|
+
`x<Slice>Init` → `Zone` alone. Reach for `Load.Stream` when the markup is small and static enough that having
|
|
121
|
+
it in the HTML is worth more than the second pass.
|
|
122
|
+
|
|
123
|
+
**A failure now surfaces where it happened.** One `Promise.all` in the page body reports nothing about which of
|
|
124
|
+
eight queries threw; per-section boundaries put each rejection at its own boundary.
|
|
125
|
+
|
|
126
|
+
**Keep the auth gate in the shell.** A redirect thrown after the shell has flushed can only be delivered as a
|
|
127
|
+
soft-redirect script, so `getSelf({ unauthorize: "/signin" })` stays in `_layout.tsx` or the page body — never
|
|
128
|
+
inside a streamed section.
|
|
129
|
+
|
|
86
130
|
**⑥ Use named `ReactNode` slots, not just `children`.** `Layout.Navbar` accepts `title`, `back`, `left`, `right`,
|
|
87
131
|
and `children`, so a client shell composes server-rendered content in five places instead of absorbing it.
|
|
88
132
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
prepareDevWatchBatch
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-ynf37b66.js";
|
|
5
5
|
import {
|
|
6
6
|
AutoImportSync,
|
|
7
7
|
DevChangePlanner,
|
|
8
8
|
DevGeneratedIndexSync,
|
|
9
9
|
GraphClientEntryDiscovery,
|
|
10
10
|
RouteClientBuilder
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-jcm6zr20.js";
|
|
12
12
|
import {
|
|
13
13
|
HmrWatcher,
|
|
14
14
|
WatchRootResolver
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import {
|
|
17
17
|
AppExecutor,
|
|
18
18
|
WorkspaceExecutor
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-h9cybjep.js";
|
|
20
20
|
import"./index-f39512t6.js";
|
|
21
21
|
import"./index-mxvakhsm.js";
|
|
22
22
|
import"./index-1577bej2.js";
|
|
@@ -252,6 +252,7 @@ class IncrementalBuilder {
|
|
|
252
252
|
this.#shuttingDown = true;
|
|
253
253
|
const started = Date.now();
|
|
254
254
|
this.#logger.debug(`shutdown requested (${reason}); draining ${this.#inFlight} work item(s)`);
|
|
255
|
+
this.#watcher?.stop();
|
|
255
256
|
if (this.#cssRebuildTimer) {
|
|
256
257
|
clearTimeout(this.#cssRebuildTimer);
|
|
257
258
|
this.#cssRebuildTimer = null;
|
|
@@ -361,13 +362,12 @@ class IncrementalBuilder {
|
|
|
361
362
|
this.#logger.verbose(`[auto-import] inserted imports into ${autoImport.changedFiles.length} file(s)`);
|
|
362
363
|
const indexSync = await this.#generatedIndexSync.syncForBatch(batch.files);
|
|
363
364
|
await this.#watcher?.absorb([...autoImport.changedFiles, ...indexSync.changedFiles]);
|
|
364
|
-
const { files, kinds, expandedBatch, event, hasSyncErrors } = prepareDevWatchBatch({
|
|
365
|
+
const { files, kinds, expandedBatch, devPlan, event, hasSyncErrors } = prepareDevWatchBatch({
|
|
365
366
|
generation,
|
|
366
367
|
batch,
|
|
367
368
|
indexSync,
|
|
368
369
|
changePlanner: this.#changePlanner
|
|
369
370
|
});
|
|
370
|
-
const devPlan = event.devPlan;
|
|
371
371
|
this.#logger.verbose(`[hmr] batch generation=${generation} kinds=${kinds.join(",")} files=${files.length} generated=${indexSync.changedFiles.length} roles=${devPlan.roles.join(",") || "(none)"} actions=${devPlan.actions.join(",") || "(none)"}`);
|
|
372
372
|
for (const error of indexSync.errors)
|
|
373
373
|
this.#logger.error(error);
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
CloudApi,
|
|
5
5
|
GlobalConfig,
|
|
6
6
|
getDefaultHostConfig
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-safgeq9a.js";
|
|
8
8
|
import {
|
|
9
9
|
openBrowser
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-5r4e65hb.js";
|
|
11
11
|
import {
|
|
12
12
|
runner
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-akz5xvyw.js";
|
|
14
14
|
import {
|
|
15
15
|
AppExecutor,
|
|
16
16
|
WorkspaceExecutor
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-h9cybjep.js";
|
|
18
18
|
|
|
19
19
|
// pkgs/@akanjs/cli/npmRegistry.ts
|
|
20
20
|
var defaultNpmRegistry = "https://registry.npmjs.org";
|