@akanjs/cli 3.0.0-alpha.103 → 3.0.0-alpha.104

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.
Files changed (68) hide show
  1. package/.build-stamp +1 -1
  2. package/{abstractCompactor-byytxs22.js → abstractCompactor-mjh5ppsq.js} +1 -1
  3. package/{agent.command-v1a4746v.js → agent.command-d2gfxfck.js} +5 -5
  4. package/{application.command-fzdcnzhg.js → application.command-xgphqs7k.js} +5 -5
  5. package/{applicationBuildRunner-s4gsk728.js → applicationBuildRunner-3d5q1yn7.js} +2 -2
  6. package/{applicationReleasePackager-28v9vbzk.js → applicationReleasePackager-4yasxwv9.js} +1 -1
  7. package/buildBatch.proc.js +2 -2
  8. package/{capacitorApp-8d6d4zkm.js → capacitorApp-36rbr858.js} +2 -2
  9. package/{cloud.command-wygy2z05.js → cloud.command-abgkk73f.js} +9 -9
  10. package/{context.command-4vdt1aqq.js → context.command-ez8a0zyz.js} +13 -13
  11. package/{devTui-qnf1txdz.js → devTui-70cjjtaw.js} +1 -1
  12. package/{devTuiView-yzct2cq6.js → devTuiView-71wnkjft.js} +1 -1
  13. package/{guideline.command-p92dq6ts.js → guideline.command-xmqwx8zm.js} +11 -7
  14. package/guidelines/agentRule/agentRule.instruction.md +6 -14
  15. package/guidelines/conventions/conventions.instruction.md +40 -25
  16. package/guidelines/mcpRule/mcpRule.instruction.md +61 -39
  17. package/guidelines/ssrRule/ssrRule.instruction.md +15 -13
  18. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +4 -3
  19. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +68 -3
  20. package/incrementalBuilder.proc.js +1 -1
  21. package/{index-p5neav9b.js → index-0vh9rgxz.js} +1 -1
  22. package/{index-gq44bqjt.js → index-259dsnz3.js} +2 -2
  23. package/{index-qsq3q8fy.js → index-2tv3fdx4.js} +21 -10
  24. package/{index-yks023mb.js → index-4c9ykbfq.js} +6 -6
  25. package/{index-qkk27bk6.js → index-4edzf1gr.js} +4 -4
  26. package/{index-yza7zkpt.js → index-600zhnve.js} +10 -10
  27. package/{index-srdssqj7.js → index-7737gxcp.js} +3 -3
  28. package/{index-zmjppp25.js → index-8pm30m73.js} +5 -5
  29. package/{index-0amdxycf.js → index-fz5q3gd7.js} +3 -3
  30. package/{index-fc1bh0a7.js → index-gyd220p2.js} +1 -1
  31. package/{index-5svjba73.js → index-j9yhg404.js} +1 -1
  32. package/{index-c69j78kk.js → index-kn1h7p1x.js} +1 -1
  33. package/{index-gtmz74tj.js → index-ktb5njgy.js} +2 -2
  34. package/{index-znynzt5w.js → index-mak3cd28.js} +1 -1
  35. package/{index-29sxqfaw.js → index-ne2qy0nk.js} +3 -3
  36. package/{index-hyywke0f.js → index-pnqbkf5p.js} +1 -1
  37. package/{index-8p8p0cf8.js → index-rwg2aa4f.js} +3 -3
  38. package/{index-7d6vny25.js → index-ws5e0j51.js} +2 -2
  39. package/{index-1yxtbmbj.js → index-wt7qrtd4.js} +1 -1
  40. package/{index-zz5jyd94.js → index-yecdrt9a.js} +9 -9
  41. package/{index-zxgr3s8s.js → index-yw4xj7pa.js} +4 -4
  42. package/index.js +19 -19
  43. package/{library.command-s4fszngs.js → library.command-nbsky672.js} +3 -3
  44. package/{localRegistry.command-gyw4da9z.js → localRegistry.command-namg61k1.js} +8 -8
  45. package/{module.command-6n7dwvav.js → module.command-29vqzrh8.js} +6 -6
  46. package/{package.command-gr82ypnr.js → package.command-axv0abmn.js} +3 -3
  47. package/package.json +2 -2
  48. package/{page.command-7gvgb3jb.js → page.command-vs9s3zrh.js} +3 -3
  49. package/{primitive.command-tk5ckw38.js → primitive.command-cbxmqbtc.js} +7 -7
  50. package/{quality.command-38v81baf.js → quality.command-gmbs7nws.js} +2 -2
  51. package/{repair.command-5xbwvsxp.js → repair.command-bqsjptsj.js} +5 -5
  52. package/{routeSourceValidator-ze6x894c.js → routeSourceValidator-apyqw7wk.js} +90 -17
  53. package/{scalar.command-0epwcr5k.js → scalar.command-6k1vhe9s.js} +5 -5
  54. package/{subspace.command-e2t36xb2.js → subspace.command-35a3t6vv.js} +3 -3
  55. package/templates/app/page/_index.tsx +3 -3
  56. package/templates/app/page/_layout.tsx +31 -32
  57. package/templates/appSample/page/task/[taskId]/_index.tsx +22 -27
  58. package/templates/appSample/page/task/[taskId]/edit.tsx +25 -30
  59. package/templates/appSample/page/task/_index.tsx +3 -7
  60. package/templates/appSample/page/task/_layout.tsx +4 -15
  61. package/templates/appSample/page/task/new.tsx +4 -10
  62. package/templates/crudPages/[__model__Id]/edit/page.tsx +26 -28
  63. package/templates/crudPages/[__model__Id]/page.tsx +20 -25
  64. package/templates/crudPages/new/page.tsx +24 -23
  65. package/templates/crudPages/page.tsx +25 -24
  66. package/templates/crudSinglePage/page.tsx +25 -24
  67. package/{workflow.command-kphbr7eh.js → workflow.command-nwpcdc8p.js} +10 -10
  68. package/{workspace.command-j1gatz3d.js → workspace.command-kah5jgg5.js} +20 -20
package/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getTargetMetas,
5
5
  getTargetCommandNames,
6
6
  runCommands
7
- } from "./index-znynzt5w.js";
7
+ } from "./index-mak3cd28.js";
8
8
  import"./index-q0y2jq9j.js";
9
- import"./index-qsq3q8fy.js";
9
+ import"./index-2tv3fdx4.js";
10
10
  import"./index-6wwzs1bc.js";
11
11
 
12
12
  // pkgs/@akanjs/cli/commandManifest.ts
@@ -14,23 +14,23 @@ import path from "path";
14
14
 
15
15
  // pkgs/@akanjs/cli/commandModules.ts
16
16
  var commandModules = {
17
- workspace: async () => (await import("./workspace.command-j1gatz3d.js")).WorkspaceCommand,
18
- agent: async () => (await import("./agent.command-v1a4746v.js")).AgentCommand,
19
- application: async () => (await import("./application.command-fzdcnzhg.js")).ApplicationCommand,
20
- library: async () => (await import("./library.command-s4fszngs.js")).LibraryCommand,
21
- localRegistry: async () => (await import("./localRegistry.command-gyw4da9z.js")).LocalRegistryCommand,
22
- package: async () => (await import("./package.command-gr82ypnr.js")).PackageCommand,
23
- module: async () => (await import("./module.command-6n7dwvav.js")).ModuleCommand,
24
- page: async () => (await import("./page.command-7gvgb3jb.js")).PageCommand,
25
- context: async () => (await import("./context.command-4vdt1aqq.js")).ContextCommand,
26
- cloud: async () => (await import("./cloud.command-wygy2z05.js")).CloudCommand,
27
- subspace: async () => (await import("./subspace.command-e2t36xb2.js")).SubspaceCommand,
28
- guideline: async () => (await import("./guideline.command-p92dq6ts.js")).GuidelineCommand,
29
- scalar: async () => (await import("./scalar.command-0epwcr5k.js")).ScalarCommand,
30
- primitive: async () => (await import("./primitive.command-tk5ckw38.js")).PrimitiveCommand,
31
- quality: async () => (await import("./quality.command-38v81baf.js")).QualityCommand,
32
- repair: async () => (await import("./repair.command-5xbwvsxp.js")).RepairCommand,
33
- workflow: async () => (await import("./workflow.command-kphbr7eh.js")).WorkflowCommand
17
+ workspace: async () => (await import("./workspace.command-kah5jgg5.js")).WorkspaceCommand,
18
+ agent: async () => (await import("./agent.command-d2gfxfck.js")).AgentCommand,
19
+ application: async () => (await import("./application.command-xgphqs7k.js")).ApplicationCommand,
20
+ library: async () => (await import("./library.command-nbsky672.js")).LibraryCommand,
21
+ localRegistry: async () => (await import("./localRegistry.command-namg61k1.js")).LocalRegistryCommand,
22
+ package: async () => (await import("./package.command-axv0abmn.js")).PackageCommand,
23
+ module: async () => (await import("./module.command-29vqzrh8.js")).ModuleCommand,
24
+ page: async () => (await import("./page.command-vs9s3zrh.js")).PageCommand,
25
+ context: async () => (await import("./context.command-ez8a0zyz.js")).ContextCommand,
26
+ cloud: async () => (await import("./cloud.command-abgkk73f.js")).CloudCommand,
27
+ subspace: async () => (await import("./subspace.command-35a3t6vv.js")).SubspaceCommand,
28
+ guideline: async () => (await import("./guideline.command-xmqwx8zm.js")).GuidelineCommand,
29
+ scalar: async () => (await import("./scalar.command-6k1vhe9s.js")).ScalarCommand,
30
+ primitive: async () => (await import("./primitive.command-cbxmqbtc.js")).PrimitiveCommand,
31
+ quality: async () => (await import("./quality.command-gmbs7nws.js")).QualityCommand,
32
+ repair: async () => (await import("./repair.command-bqsjptsj.js")).RepairCommand,
33
+ workflow: async () => (await import("./workflow.command-nwpcdc8p.js")).WorkflowCommand
34
34
  };
35
35
  var commandModuleIds = Object.keys(commandModules);
36
36
 
@@ -3,13 +3,13 @@ import {
3
3
  Lib,
4
4
  Workspace,
5
5
  command
6
- } from "./index-znynzt5w.js";
6
+ } from "./index-mak3cd28.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-qsq3q8fy.js";
8
+ import"./index-2tv3fdx4.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import {
11
11
  LibraryScript
12
- } from "./index-gq44bqjt.js";
12
+ } from "./index-259dsnz3.js";
13
13
 
14
14
  // pkgs/@akanjs/cli/library/library.command.ts
15
15
  class LibraryCommand extends command("library", [LibraryScript], ({ public: target }) => ({
@@ -4,27 +4,27 @@ import {
4
4
  runner,
5
5
  script,
6
6
  command
7
- } from "./index-znynzt5w.js";
7
+ } from "./index-mak3cd28.js";
8
8
  import"./index-q0y2jq9j.js";
9
9
  import {
10
10
  PkgExecutor
11
- } from "./index-qsq3q8fy.js";
11
+ } from "./index-2tv3fdx4.js";
12
12
  import"./index-6wwzs1bc.js";
13
13
  import {
14
14
  ApplicationScript
15
- } from "./index-zz5jyd94.js";
16
- import"./index-gq44bqjt.js";
15
+ } from "./index-yecdrt9a.js";
16
+ import"./index-259dsnz3.js";
17
17
  import"./index-hwkygn9s.js";
18
- import"./index-c69j78kk.js";
18
+ import"./index-kn1h7p1x.js";
19
19
  import {
20
20
  getNpmRegistryUrl,
21
21
  CloudRunner
22
- } from "./index-zxgr3s8s.js";
22
+ } from "./index-yw4xj7pa.js";
23
23
  import"./index-kcxmv48c.js";
24
24
  import {
25
25
  PackageScript
26
- } from "./index-7d6vny25.js";
27
- import"./index-5svjba73.js";
26
+ } from "./index-ws5e0j51.js";
27
+ import"./index-j9yhg404.js";
28
28
 
29
29
  // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
30
30
  import { mkdir, rm } from "fs/promises";
@@ -3,18 +3,18 @@ import {
3
3
  Sys,
4
4
  Module,
5
5
  command
6
- } from "./index-znynzt5w.js";
6
+ } from "./index-mak3cd28.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-qsq3q8fy.js";
8
+ import"./index-2tv3fdx4.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import {
11
11
  renderPrimitiveReport
12
- } from "./index-fc1bh0a7.js";
13
- import"./index-c69j78kk.js";
12
+ } from "./index-gyd220p2.js";
13
+ import"./index-kn1h7p1x.js";
14
14
  import {
15
15
  ModuleScript
16
- } from "./index-zmjppp25.js";
17
- import"./index-hyywke0f.js";
16
+ } from "./index-8pm30m73.js";
17
+ import"./index-pnqbkf5p.js";
18
18
  import"./index-h7yw2z9n.js";
19
19
 
20
20
  // pkgs/@akanjs/cli/module/module.command.ts
@@ -3,14 +3,14 @@ import {
3
3
  Pkg,
4
4
  Workspace,
5
5
  command
6
- } from "./index-znynzt5w.js";
6
+ } from "./index-mak3cd28.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-qsq3q8fy.js";
8
+ import"./index-2tv3fdx4.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import"./index-kcxmv48c.js";
11
11
  import {
12
12
  PackageScript
13
- } from "./index-7d6vny25.js";
13
+ } from "./index-ws5e0j51.js";
14
14
 
15
15
  // pkgs/@akanjs/cli/package/package.command.ts
16
16
  class PackageCommand extends command("package", [PackageScript], ({ public: target }) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/cli",
3
- "version": "3.0.0-alpha.103",
3
+ "version": "3.0.0-alpha.104",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -33,7 +33,7 @@
33
33
  "@langchain/openai": "^1.4.6",
34
34
  "@tailwindcss/node": "^4.3.0",
35
35
  "@trapezedev/project": "^7.1.4",
36
- "akanjs": "3.0.0-alpha.103",
36
+ "akanjs": "3.0.0-alpha.104",
37
37
  "chalk": "^5.6.2",
38
38
  "commander": "^14.0.3",
39
39
  "dayjs": "^1.11.20",
@@ -3,13 +3,13 @@ import {
3
3
  App,
4
4
  Module,
5
5
  command
6
- } from "./index-znynzt5w.js";
6
+ } from "./index-mak3cd28.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-qsq3q8fy.js";
8
+ import"./index-2tv3fdx4.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import {
11
11
  PageScript
12
- } from "./index-hyywke0f.js";
12
+ } from "./index-pnqbkf5p.js";
13
13
 
14
14
  // pkgs/@akanjs/cli/page/page.command.ts
15
15
  class PageCommand extends command("page", [PageScript], ({ public: target }) => ({
@@ -2,20 +2,20 @@
2
2
  import {
3
3
  Workspace,
4
4
  command
5
- } from "./index-znynzt5w.js";
5
+ } from "./index-mak3cd28.js";
6
6
  import"./index-q0y2jq9j.js";
7
- import"./index-qsq3q8fy.js";
7
+ import"./index-2tv3fdx4.js";
8
8
  import"./index-6wwzs1bc.js";
9
9
  import {
10
10
  renderPrimitiveReport
11
- } from "./index-fc1bh0a7.js";
12
- import"./index-c69j78kk.js";
13
- import"./index-zmjppp25.js";
14
- import"./index-hyywke0f.js";
11
+ } from "./index-gyd220p2.js";
12
+ import"./index-kn1h7p1x.js";
13
+ import"./index-8pm30m73.js";
14
+ import"./index-pnqbkf5p.js";
15
15
  import"./index-h7yw2z9n.js";
16
16
  import {
17
17
  PrimitiveScript
18
- } from "./index-qkk27bk6.js";
18
+ } from "./index-4edzf1gr.js";
19
19
 
20
20
  // pkgs/@akanjs/cli/primitive/primitive.command.ts
21
21
  import { Logger } from "akanjs/common";
@@ -4,13 +4,13 @@ import {
4
4
  runner,
5
5
  script,
6
6
  command
7
- } from "./index-znynzt5w.js";
7
+ } from "./index-mak3cd28.js";
8
8
  import"./index-q0y2jq9j.js";
9
9
  import {
10
10
  rootAllowedFiles,
11
11
  rootAllowedDirs,
12
12
  isAllowedLibFacetRootFile
13
- } from "./index-qsq3q8fy.js";
13
+ } from "./index-2tv3fdx4.js";
14
14
  import"./index-6wwzs1bc.js";
15
15
  import {
16
16
  AbstractDoc
@@ -3,16 +3,16 @@ import {
3
3
  Workspace,
4
4
  script,
5
5
  command
6
- } from "./index-znynzt5w.js";
6
+ } from "./index-mak3cd28.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-qsq3q8fy.js";
8
+ import"./index-2tv3fdx4.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import"./index-by5gpp8x.js";
11
- import"./index-fc1bh0a7.js";
12
- import"./index-gtmz74tj.js";
11
+ import"./index-gyd220p2.js";
12
+ import"./index-ktb5njgy.js";
13
13
  import {
14
14
  RepairRunner
15
- } from "./index-0amdxycf.js";
15
+ } from "./index-fz5q3gd7.js";
16
16
 
17
17
  // pkgs/@akanjs/cli/repair/repair.script.ts
18
18
  import { Logger } from "akanjs/common";
@@ -2,6 +2,7 @@
2
2
  // pkgs/@akanjs/devkit/routeSourceValidator.ts
3
3
  import { getRouteExports } from "akanjs/common";
4
4
  import ts from "typescript";
5
+ var chainRoots = new Set(["page", "layout", "rootLayout"]);
5
6
 
6
7
  class RouteSourceValidator {
7
8
  static validateRouteSourceExports(source, filePath, kind, options = {}) {
@@ -62,7 +63,74 @@ class RouteSourceValidator {
62
63
  if (exported.has("metadata") && exported.has("generateMetadata")) {
63
64
  throw new Error(`[route-convention] metadata and generateMetadata cannot both be exported in ${filePath}`);
64
65
  }
65
- return { devOnly: RouteSourceValidator.#readDevOnly(sourceFile, filePath) };
66
+ const chain = RouteSourceValidator.#readChain(sourceFile, filePath);
67
+ if (!chain)
68
+ return { devOnly: RouteSourceValidator.#readDevOnly(sourceFile, filePath) };
69
+ const named = [...exported].filter((name) => name !== "default");
70
+ if (named.length)
71
+ throw new Error(`[route-convention] ${filePath} exports ${named.join(", ")} beside its ${chain.kind}() chain \u2014 every route setting is a stage of the chain`);
72
+ if (kind === "page" && chain.kind !== "page")
73
+ throw new Error(`[route-convention] ${filePath} is a page file but exports ${chain.kind}()`);
74
+ if (kind === "layout" && chain.kind === "page")
75
+ throw new Error(`[route-convention] ${filePath} is a layout file but exports page()`);
76
+ if (options.pattern)
77
+ RouteSourceValidator.#assertChainParams(chain, options.pattern, filePath);
78
+ return {
79
+ devOnly: chain.devOnly,
80
+ chain: { kind: chain.kind, params: chain.params, ...chain.prompt ? { prompt: chain.prompt } : {} }
81
+ };
82
+ }
83
+ static #readChain(sourceFile, filePath) {
84
+ for (const statement of sourceFile.statements) {
85
+ if (!ts.isExportAssignment(statement) || statement.isExportEquals)
86
+ continue;
87
+ let node = RouteSourceValidator.#unwrapExpression(statement.expression);
88
+ const stages = [];
89
+ while (node && ts.isCallExpression(node)) {
90
+ const callee = node.expression;
91
+ if (ts.isPropertyAccessExpression(callee)) {
92
+ stages.unshift({ name: callee.name.text, args: node.arguments });
93
+ node = callee.expression;
94
+ continue;
95
+ }
96
+ if (ts.isIdentifier(callee) && chainRoots.has(callee.text))
97
+ return RouteSourceValidator.#chainOf(callee.text, stages, filePath);
98
+ return null;
99
+ }
100
+ return null;
101
+ }
102
+ return null;
103
+ }
104
+ static #chainOf(kind, stages, filePath) {
105
+ const params = [];
106
+ let prompt;
107
+ let devOnly = false;
108
+ const literal = (stage) => {
109
+ const first = stage.args[0];
110
+ if (!first || !ts.isStringLiteralLike(first))
111
+ throw new Error(`[route-convention] .${stage.name}() takes a string literal first in ${filePath} \u2014 the build reads it without evaluating the module`);
112
+ return first.text;
113
+ };
114
+ for (const stage of stages) {
115
+ if (stage.name === "param")
116
+ params.push(literal(stage));
117
+ else if (stage.name === "prompt")
118
+ prompt = literal(stage);
119
+ else if (stage.name === "config")
120
+ devOnly = RouteSourceValidator.#devOnlyOf(RouteSourceValidator.#unwrapExpression(stage.args[0]), filePath);
121
+ }
122
+ return { kind, params, prompt, devOnly };
123
+ }
124
+ static #assertChainParams(chain, pattern, filePath) {
125
+ const inPath = pattern.split("/").filter((part) => part.startsWith(":")).map((part) => part.slice(1)).filter((name) => name !== "lang");
126
+ if (chain.params.includes("lang"))
127
+ throw new Error(`[route-convention] ${filePath} declares .param("lang"), which every route receives undeclared`);
128
+ const unknown = chain.params.find((name) => !inPath.includes(name));
129
+ if (unknown)
130
+ throw new Error(`[route-convention] ${filePath} declares .param("${unknown}") but no [${unknown}] segment is in its path`);
131
+ const undeclared = inPath.find((name) => !chain.params.includes(name));
132
+ if (chain.kind === "page" && undeclared)
133
+ throw new Error(`[route-convention] ${filePath} sits under [${undeclared}] but declares no .param("${undeclared}") \u2014 a page reads only what it declares`);
66
134
  }
67
135
  static #readDevOnly(sourceFile, filePath) {
68
136
  for (const statement of sourceFile.statements) {
@@ -75,26 +143,31 @@ class RouteSourceValidator {
75
143
  if (!ts.isIdentifier(declaration.name) || declaration.name.text !== "pageConfig")
76
144
  continue;
77
145
  const initializer = RouteSourceValidator.#unwrapExpression(declaration.initializer);
78
- if (!initializer || !ts.isObjectLiteralExpression(initializer))
79
- continue;
80
- for (const property of initializer.properties) {
81
- if (!ts.isPropertyAssignment(property))
82
- continue;
83
- const name = property.name;
84
- const key = ts.isIdentifier(name) ? name.text : ts.isStringLiteral(name) ? name.text : null;
85
- if (key !== "devOnly")
86
- continue;
87
- const value = RouteSourceValidator.#unwrapExpression(property.initializer);
88
- if (value?.kind === ts.SyntaxKind.TrueKeyword)
89
- return true;
90
- if (value?.kind === ts.SyntaxKind.FalseKeyword)
91
- return false;
92
- throw new Error(`[route-convention] pageConfig.devOnly must be a literal true or false in ${filePath} \u2014 the build reads it without evaluating the module`);
93
- }
146
+ if (initializer && ts.isObjectLiteralExpression(initializer))
147
+ return RouteSourceValidator.#devOnlyOf(initializer, filePath);
94
148
  }
95
149
  }
96
150
  return false;
97
151
  }
152
+ static #devOnlyOf(config, filePath) {
153
+ if (!config || !ts.isObjectLiteralExpression(config))
154
+ return false;
155
+ for (const property of config.properties) {
156
+ if (!ts.isPropertyAssignment(property))
157
+ continue;
158
+ const name = property.name;
159
+ const key = ts.isIdentifier(name) ? name.text : ts.isStringLiteral(name) ? name.text : null;
160
+ if (key !== "devOnly")
161
+ continue;
162
+ const value = RouteSourceValidator.#unwrapExpression(property.initializer);
163
+ if (value?.kind === ts.SyntaxKind.TrueKeyword)
164
+ return true;
165
+ if (value?.kind === ts.SyntaxKind.FalseKeyword)
166
+ return false;
167
+ throw new Error(`[route-convention] devOnly must be a literal true or false in ${filePath} \u2014 the build reads it without evaluating the module`);
168
+ }
169
+ return false;
170
+ }
98
171
  static #unwrapExpression(expression) {
99
172
  let current = expression;
100
173
  while (current && (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current))) {
@@ -2,18 +2,18 @@
2
2
  import {
3
3
  Sys,
4
4
  command
5
- } from "./index-znynzt5w.js";
5
+ } from "./index-mak3cd28.js";
6
6
  import"./index-q0y2jq9j.js";
7
- import"./index-qsq3q8fy.js";
7
+ import"./index-2tv3fdx4.js";
8
8
  import"./index-6wwzs1bc.js";
9
9
  import {
10
10
  renderPrimitiveReport
11
- } from "./index-fc1bh0a7.js";
12
- import"./index-c69j78kk.js";
11
+ } from "./index-gyd220p2.js";
12
+ import"./index-kn1h7p1x.js";
13
13
  import"./index-h7yw2z9n.js";
14
14
  import {
15
15
  ScalarScript
16
- } from "./index-8p8p0cf8.js";
16
+ } from "./index-rwg2aa4f.js";
17
17
 
18
18
  // pkgs/@akanjs/cli/scalar/scalar.command.ts
19
19
  import { Logger, lowerlize } from "akanjs/common";
@@ -4,7 +4,7 @@ import {
4
4
  runner,
5
5
  script,
6
6
  command
7
- } from "./index-znynzt5w.js";
7
+ } from "./index-mak3cd28.js";
8
8
  import {
9
9
  FileSys
10
10
  } from "./index-q0y2jq9j.js";
@@ -12,11 +12,11 @@ import {
12
12
  Executor,
13
13
  WorkspaceExecutor,
14
14
  AppExecutor
15
- } from "./index-qsq3q8fy.js";
15
+ } from "./index-2tv3fdx4.js";
16
16
  import"./index-6wwzs1bc.js";
17
17
  import {
18
18
  SlicePlanner
19
- } from "./index-5svjba73.js";
19
+ } from "./index-j9yhg404.js";
20
20
  import {
21
21
  LibSource
22
22
  } from "./index-3d9y066c.js";
@@ -8,7 +8,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
8
8
  filename: "_index.tsx",
9
9
  content: `
10
10
  import { getEnv } from "akanjs/base";
11
- import { usePage } from "akanjs/client";
11
+ import { page, usePage } from "akanjs/client";
12
12
  import { Link, System } from "akanjs/ui";
13
13
  import {
14
14
  FaBookOpen,
@@ -22,7 +22,7 @@ import {
22
22
  FaTerminal,
23
23
  } from "react-icons/fa";
24
24
 
25
- export default function Page() {
25
+ export default page().render(() => {
26
26
  const appName = getEnv().appName;
27
27
  const { l } = usePage();
28
28
  return (
@@ -294,6 +294,6 @@ export default function Page() {
294
294
  </section>
295
295
  </main>
296
296
  );
297
- }`,
297
+ });`,
298
298
  };
299
299
  }
@@ -9,41 +9,40 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
9
9
  filename: "_layout.tsx",
10
10
  content: `
11
11
  import "./styles.css";
12
- import type { Font, LayoutProps } from "akanjs/client";
12
+ import { rootLayout } from "akanjs/client";
13
13
  ${isUsingShared ? "import { Auth } from '@shared/ui';" : ""}
14
14
 
15
- export const fonts: Font[] = [
16
- {
17
- name: "pretendard",
18
- default: true,
19
- paths: [
20
- { src: "/fonts/Pretendard-Thin.woff2", weight: 100 },
21
- { src: "/fonts/Pretendard-ExtraLight.woff2", weight: 200 },
22
- { src: "/fonts/Pretendard-Light.woff2", weight: 300 },
23
- { src: "/fonts/Pretendard-Regular.woff2", weight: 400 },
24
- { src: "/fonts/Pretendard-Medium.woff2", weight: 500 },
25
- { src: "/fonts/Pretendard-SemiBold.woff2", weight: 600 },
26
- { src: "/fonts/Pretendard-Bold.woff2", weight: 700 },
27
- { src: "/fonts/Pretendard-ExtraBold.woff2", weight: 800 },
28
- { src: "/fonts/Pretendard-Black.woff2", weight: 900 },
29
- ],
30
- },
31
- ];
32
-
33
- export const head = (
34
- <>
35
- <title>${dict.appName}</title>
36
- <link rel="icon" href="/favicon.ico" />
37
- </>
38
- );
39
-
40
- export default function Layout({ children }: LayoutProps) {
41
- return (
15
+ export default rootLayout()
16
+ .fonts([
17
+ {
18
+ name: "pretendard",
19
+ default: true,
20
+ paths: [
21
+ { src: "/fonts/Pretendard-Thin.woff2", weight: 100 },
22
+ { src: "/fonts/Pretendard-ExtraLight.woff2", weight: 200 },
23
+ { src: "/fonts/Pretendard-Light.woff2", weight: 300 },
24
+ { src: "/fonts/Pretendard-Regular.woff2", weight: 400 },
25
+ { src: "/fonts/Pretendard-Medium.woff2", weight: 500 },
26
+ { src: "/fonts/Pretendard-SemiBold.woff2", weight: 600 },
27
+ { src: "/fonts/Pretendard-Bold.woff2", weight: 700 },
28
+ { src: "/fonts/Pretendard-ExtraBold.woff2", weight: 800 },
29
+ { src: "/fonts/Pretendard-Black.woff2", weight: 900 },
30
+ ],
31
+ },
32
+ ])
33
+ .head(
42
34
  <>
43
- {children}${isUsingShared ? "\n <Auth.User />\n <Auth.Admin />" : ""}
44
- </>
45
- );
46
- }
35
+ <title>${dict.appName}</title>
36
+ <link rel="icon" href="/favicon.ico" />
37
+ </>,
38
+ )
39
+ .render(({ children }) => {
40
+ return (
41
+ <>
42
+ {children}${isUsingShared ? "\n <Auth.User />\n <Auth.Admin />" : ""}
43
+ </>
44
+ );
45
+ });
47
46
  `,
48
47
  };
49
48
  }
@@ -3,37 +3,32 @@ import type { AppInfo, LibInfo } from "akanjs";
3
3
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
4
4
  return {
5
5
  filename: "_index.tsx",
6
- content: `
7
- import { fetch, usePage } from "@apps/${dict.appName}/client";
6
+ content: `import { fetch, usePage } from "@apps/${dict.appName}/client";
8
7
  import { Task } from "@apps/${dict.appName}/lib/task";
8
+ import { ID } from "akanjs/base";
9
+ import { page } from "akanjs/client";
9
10
  import { Link, buttonRecipe } from "akanjs/ui";
10
11
 
11
- // ===== page/task/[taskId]/_index.tsx =====
12
- // Convention: Akan.js file-based routing with dynamic segments.
13
- // [taskId] folder = URL path parameter extracted via useParams() from akanjs/client.
14
- // Uses usePage().l() for i18n — the framework convention for dictionary-based translations.
12
+ export default page()
13
+ .param("taskId", ID)
14
+ .render(async ({ taskId }) => {
15
+ const { l } = usePage();
16
+ const { taskView } = await fetch.viewTask(taskId);
17
+ return (
18
+ <main className="mx-auto max-w-4xl px-6 py-8">
19
+ <div className="mb-6 flex items-center justify-between">
20
+ <a href="/task" className={buttonRecipe({ variant: "ghost", size: "sm" })}>
21
+ {l("task.taskBackToTasks")}
22
+ </a>
23
+ <Link href={\`/task/\${taskId}/edit\`} className={buttonRecipe({ variant: "primary", size: "sm" })}>
24
+ {l("task.taskEdit")}
25
+ </Link>
26
+ </div>
15
27
 
16
- interface PageProps {
17
- params: { taskId: string };
18
- }
19
- export default async function Page({ params: { taskId } }: PageProps) {
20
- const { l } = usePage();
21
- const { taskView } = await fetch.viewTask(taskId);
22
- return (
23
- <main className="mx-auto max-w-4xl px-6 py-8">
24
- <div className="mb-6 flex items-center justify-between">
25
- <a href="/task" className={buttonRecipe({ variant: "ghost", size: "sm" })}>
26
- {l("task.taskBackToTasks")}
27
- </a>
28
- <Link href={\`/task/\${taskId}/edit\`} className={buttonRecipe({ variant: "primary", size: "sm" })}>
29
- {l("task.taskEdit")}
30
- </Link>
31
- </div>
32
-
33
- <Task.Zone.View className="max-w-2xl" view={taskView} />
34
- </main>
35
- );
36
- }
28
+ <Task.Zone.View className="max-w-2xl" view={taskView} />
29
+ </main>
30
+ );
31
+ });
37
32
  `,
38
33
  };
39
34
  }