@akanjs/cli 3.0.0-alpha.70 → 3.0.0-alpha.72
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-964bf8qg.js → agent.command-z0cam80t.js} +6 -6
- package/{application.command-n45n18sc.js → application.command-2dct57za.js} +34 -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-vnvnvdhf.js → capacitorApp-md7dnt25.js} +2 -2
- package/{cloud.command-kx1bh5yq.js → cloud.command-8j7xrxsm.js} +10 -10
- package/commandManifest.json +1 -1
- package/{context.command-g1a65x6j.js → context.command-xjf4y7em.js} +14 -14
- package/{dependencyScanner-rbs2407b.js → dependencyScanner-aqg3dkks.js} +1 -1
- package/{guideline.command-xphyhvwh.js → guideline.command-yzm0qevv.js} +4 -4
- package/guidelines/conventions/conventions.instruction.md +267 -440
- package/guidelines/framework/framework.generate.json +3 -2
- package/guidelines/framework/framework.instruction.md +0 -9
- package/guidelines/mcpRule/mcpRule.instruction.md +5 -8
- package/guidelines/queryRule/queryRule.generate.json +31 -0
- package/guidelines/queryRule/queryRule.instruction.md +143 -0
- package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
- package/guidelines/runtimeRule/runtimeRule.instruction.md +176 -0
- package/guidelines/ssrRule/ssrRule.instruction.md +49 -5
- package/guidelines/transportRule/transportRule.generate.json +31 -0
- package/guidelines/transportRule/transportRule.instruction.md +60 -0
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +17 -392
- package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
- package/incrementalBuilder.proc.js +5 -5
- package/{index-4rw4qhe6.js → index-116w1dap.js} +4 -4
- package/{index-mkn5qagt.js → index-5r4e65hb.js} +128 -59
- package/{index-abyjt72y.js → index-61x7qthy.js} +17 -21
- package/{index-bqqts262.js → index-763h7h9g.js} +1 -1
- package/{index-wnp7hwq7.js → index-94hdqqka.js} +1 -1
- package/{index-v5fdxdre.js → index-9gqzgfsd.js} +4 -4
- package/{index-fahkq20v.js → index-a341yqdh.js} +3 -3
- package/{index-e31ghfp5.js → index-akz5xvyw.js} +17 -5
- package/{index-va15r8h5.js → index-bmz9crym.js} +13 -6
- package/{index-qt4nfr0n.js → index-eed7vc38.js} +66 -33
- package/{index-46tjzh6s.js → index-h5sr2nnj.js} +24 -24
- package/{index-nkwmnqwn.js → index-h9cybjep.js} +92 -19
- package/{index-p681w089.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-ytaqtc04.js → index-q0s2dp3y.js} +1 -1
- package/{index-nj3w0r34.js → index-q13s3e01.js} +3 -3
- package/{index-0ngvvgry.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-rbnpe8cp.js → index-te6r1b79.js} +19 -23
- package/{index-yg3hxk2k.js → index-vrra4ttx.js} +6 -6
- package/{index-8gybxemv.js → index-y3wyqcsp.js} +6 -6
- package/{index-hee7egtm.js → index-ym9g9ggs.js} +21 -21
- package/{index-fgc8r6dj.js → index-ynf37b66.js} +3 -1
- package/{index-rb65xnw9.js → index-z52nhkjs.js} +4 -4
- package/index.js +18 -18
- package/{library.command-rfpd27yv.js → library.command-w8b53vtt.js} +4 -4
- package/{localRegistry.command-pyxfe0fs.js → localRegistry.command-ymrgda7e.js} +9 -9
- package/{module.command-qhaxad0p.js → module.command-7pje37dv.js} +7 -7
- package/{package.command-2k22q9nt.js → package.command-jg4qk8ts.js} +4 -4
- package/package.json +3 -4
- package/{page.command-ymk9dqh4.js → page.command-abbpj96j.js} +3 -3
- package/{primitive.command-9k45zpc1.js → primitive.command-jw4yv918.js} +8 -8
- package/{quality.command-bf6vkxe5.js → quality.command-06j6qy6n.js} +34 -4
- package/{repair.command-egvvm6xf.js → repair.command-x6resn10.js} +5 -5
- package/{scalar.command-bt1facyj.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/templates/workspaceRoot/AGENTS.md.template +4 -0
- package/{typeChecker-g6bh0xfv.js → typeChecker-yhs4eht8.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/{workflow.command-v1n3wg7v.js → workflow.command-pmw2tere.js} +11 -11
- package/{workspace.command-yvvqvhzz.js → workspace.command-x32k2vma.js} +29 -26
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
command,
|
|
8
8
|
runner,
|
|
9
9
|
script
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-akz5xvyw.js";
|
|
11
11
|
import {
|
|
12
12
|
isAllowedLibFacetRootFile,
|
|
13
13
|
rootAllowedDirs,
|
|
14
14
|
rootAllowedFiles
|
|
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";
|
|
@@ -496,6 +496,7 @@ var RULE_FIXES = {
|
|
|
496
496
|
"akan.file.max-lines": "Break the file into smaller focused modules; keep one primary responsibility per file.",
|
|
497
497
|
"akan.file.abstract-max-lines": "Run `akan compact <app-or-lib>` to rewrite the abstract with the AI editor, keeping only the invariants and workflows the source files cannot show.",
|
|
498
498
|
"akan.file.placeholder-export": "Remove the placeholder export; generated indexes should only re-export real modules.",
|
|
499
|
+
"akan.file.bang-comment-in-client": "Rewrite the marker as `// FIXME:` or `// TODO:`. Keep the bang form for server, srvkit, and CLI files.",
|
|
499
500
|
"akan.file.dictionary-stale-text": "Replace the scaffold text with real localized copy for this dictionary entry.",
|
|
500
501
|
"akan.file.global-declaration": "Move the global declaration into an approved low-level integration file (e.g. webkit) and keep it isolated.",
|
|
501
502
|
"akan.file.window-augmentation": "Move the Window augmentation into an approved browser integration file and keep it isolated.",
|
|
@@ -647,6 +648,7 @@ class AkanQualityScanner {
|
|
|
647
648
|
message: `File has ${lineCount} lines. Keep single files under ${MAX_FILE_LINES} lines.`
|
|
648
649
|
});
|
|
649
650
|
}
|
|
651
|
+
warnings.push(...getBangCommentWarnings(sourceFile));
|
|
650
652
|
warnings.push(...getPlaceholderExportWarnings(sourceFile));
|
|
651
653
|
warnings.push(...getDictionaryTextWarnings(sourceFile));
|
|
652
654
|
warnings.push(...getGlobalMutationWarnings(sourceFile));
|
|
@@ -909,7 +911,7 @@ function isEnumClassStatement(sourceFile, statement) {
|
|
|
909
911
|
return !!expression && expression.getText(sourceFile).startsWith("enumOf(");
|
|
910
912
|
}
|
|
911
913
|
function getExportedClassNames(sourceFile) {
|
|
912
|
-
return sourceFile.statements.filter((statement) => ts3.isClassDeclaration(statement)
|
|
914
|
+
return sourceFile.statements.filter((statement) => ts3.isClassDeclaration(statement)).filter((statement) => isExported(statement)).map((statement) => statement.name?.text).filter((name) => !!name);
|
|
913
915
|
}
|
|
914
916
|
function isComponentDeclarationFile(file) {
|
|
915
917
|
if (!file.endsWith(".tsx"))
|
|
@@ -989,7 +991,35 @@ function isPascalCaseName(name) {
|
|
|
989
991
|
function isDefaultExportStatement(statement) {
|
|
990
992
|
if (ts3.isExportAssignment(statement))
|
|
991
993
|
return !statement.isExportEquals;
|
|
992
|
-
|
|
994
|
+
if (!ts3.canHaveModifiers(statement))
|
|
995
|
+
return false;
|
|
996
|
+
return !!ts3.getModifiers(statement)?.some((modifier) => modifier.kind === ts3.SyntaxKind.DefaultKeyword);
|
|
997
|
+
}
|
|
998
|
+
function getBangCommentWarnings(sourceFile) {
|
|
999
|
+
if (!isClientReachableFile(sourceFile.file))
|
|
1000
|
+
return [];
|
|
1001
|
+
return findPatternLines(sourceFile.content, /(?:^|[^\s/][ \t]+)\/[*/]!/).map((line) => ({
|
|
1002
|
+
rule: "akan.file.bang-comment-in-client",
|
|
1003
|
+
scope: "file",
|
|
1004
|
+
severity: "warning",
|
|
1005
|
+
file: sourceFile.file,
|
|
1006
|
+
line,
|
|
1007
|
+
message: "A `//!` or `/*!` marker survives minification and ships to the browser."
|
|
1008
|
+
}));
|
|
1009
|
+
}
|
|
1010
|
+
function isClientReachableFile(file) {
|
|
1011
|
+
if (/\.(test|spec)\.tsx?$/.test(file))
|
|
1012
|
+
return false;
|
|
1013
|
+
if (/\.(constant|store)\.ts$/.test(file))
|
|
1014
|
+
return true;
|
|
1015
|
+
if (/\.(Template|Unit|Util|View|Zone)\.tsx$/.test(file))
|
|
1016
|
+
return true;
|
|
1017
|
+
const segments = file.split("/");
|
|
1018
|
+
if (segments.includes("ui") || segments.includes("webkit"))
|
|
1019
|
+
return /\.tsx?$/.test(file);
|
|
1020
|
+
if (segments.includes("common"))
|
|
1021
|
+
return file.endsWith(".ts");
|
|
1022
|
+
return segments.includes("page") && file.endsWith(".tsx");
|
|
993
1023
|
}
|
|
994
1024
|
function getPlaceholderExportWarnings(sourceFile) {
|
|
995
1025
|
if (!sourceFile.file.endsWith("/index.ts") && !sourceFile.file.endsWith("/index.tsx"))
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
RepairRunner
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
4
|
+
} from "./index-q13s3e01.js";
|
|
5
|
+
import"./index-bmz9crym.js";
|
|
6
|
+
import"./index-q0s2dp3y.js";
|
|
7
7
|
import {
|
|
8
8
|
Workspace,
|
|
9
9
|
command,
|
|
10
10
|
script
|
|
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";
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
ScalarScript
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-9gqzgfsd.js";
|
|
5
5
|
import"./index-ss469dec.js";
|
|
6
|
-
import"./index-
|
|
6
|
+
import"./index-safgeq9a.js";
|
|
7
7
|
import {
|
|
8
8
|
renderPrimitiveReport
|
|
9
|
-
} from "./index-
|
|
10
|
-
import"./index-
|
|
9
|
+
} from "./index-q0s2dp3y.js";
|
|
10
|
+
import"./index-k7731a4v.js";
|
|
11
11
|
import {
|
|
12
12
|
Sys,
|
|
13
13
|
command
|
|
14
|
-
} from "./index-
|
|
15
|
-
import"./index-
|
|
14
|
+
} from "./index-akz5xvyw.js";
|
|
15
|
+
import"./index-h9cybjep.js";
|
|
16
16
|
import"./index-f39512t6.js";
|
|
17
17
|
import"./index-mxvakhsm.js";
|
|
18
18
|
import"./index-1577bej2.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { AppInfo, LibInfo } from "akanjs";
|
|
2
2
|
|
|
3
3
|
export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
|
|
4
|
-
return `import {
|
|
4
|
+
return `import { SignedIn } from "@apps/${dict.appName}/srvkit";
|
|
5
|
+
import { endpoint, internal, None, Public, slice } from "akanjs/signal";
|
|
5
6
|
|
|
6
7
|
import * as cnst from "../cnst";
|
|
7
8
|
import * as srv from "../srv";
|
|
@@ -21,20 +22,24 @@ import * as srv from "../srv";
|
|
|
21
22
|
|
|
22
23
|
export class TaskInternal extends internal(srv.task, ({ interval }) => ({})) {}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
// Guards, per key: root = the generated admin API (runs any filter with caller-supplied args), get = reads,
|
|
26
|
+
// cru = create/update/remove. root and cru are never Public; None here means "nobody until you name a guard".
|
|
27
|
+
export class TaskSlice extends slice(srv.task, { guards: { root: None, get: Public, cru: SignedIn } }, (init) => ({
|
|
25
28
|
inPublic: init().exec(function () {
|
|
26
29
|
return this.taskService.queryAny();
|
|
27
30
|
}),
|
|
28
31
|
})) {}
|
|
29
32
|
|
|
33
|
+
// Every custom endpoint names its own guards array — the slice's map above only covers generated CRUD.
|
|
34
|
+
// It is also the MCP decision: an endpoint declaring no guard is not published to agents at all.
|
|
30
35
|
export class TaskEndpoint extends endpoint(srv.task, ({ mutation }) => ({
|
|
31
|
-
startTask: mutation(cnst.Task)
|
|
36
|
+
startTask: mutation(cnst.Task, { guards: [SignedIn] })
|
|
32
37
|
.param("taskId", String)
|
|
33
38
|
.exec(async function (taskId) {
|
|
34
39
|
return await this.taskService.startTask(taskId);
|
|
35
40
|
}),
|
|
36
41
|
|
|
37
|
-
completeTask: mutation(cnst.Task)
|
|
42
|
+
completeTask: mutation(cnst.Task, { guards: [SignedIn] })
|
|
38
43
|
.param("taskId", String)
|
|
39
44
|
.exec(async function (taskId) {
|
|
40
45
|
return await this.taskService.completeTask(taskId);
|
|
@@ -48,7 +53,7 @@ export class TaskEndpoint extends endpoint(srv.task, ({ mutation }) => ({
|
|
|
48
53
|
// taskEvent: pubsub(cnst.Task).exec(...),
|
|
49
54
|
// // search: search parameters (optional, URL query string)
|
|
50
55
|
// searchTask: query(cnst.LightTask).search("keyword", String).exec(...),
|
|
51
|
-
// //
|
|
52
|
-
//
|
|
56
|
+
// // mcp: false keeps a guarded endpoint off the agent shelf without changing its authorization
|
|
57
|
+
// startTask: mutation(cnst.Task, { guards: [SignedIn], mcp: false })...
|
|
53
58
|
`;
|
|
54
59
|
}
|
|
@@ -9,9 +9,9 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
9
9
|
return {
|
|
10
10
|
filename: "_index.tsx",
|
|
11
11
|
content: `
|
|
12
|
-
import {
|
|
13
|
-
import { fetch, usePage, ${dict.Model} } from "@apps/${dict.appName}/client";
|
|
12
|
+
import { ${dict.Model}, fetch, usePage } from "@apps/${dict.appName}/client";
|
|
14
13
|
import type { PageConfig } from "akanjs/client";
|
|
14
|
+
import { Load } from "akanjs/ui";
|
|
15
15
|
|
|
16
16
|
interface PageProps {
|
|
17
17
|
params: { ${dict.model}Id: string };
|
|
@@ -20,11 +20,11 @@ interface PageProps {
|
|
|
20
20
|
export default async function Page({ params }: PageProps) {
|
|
21
21
|
const { l } = usePage();
|
|
22
22
|
const { ${dict.model}Id } = params;
|
|
23
|
-
const { ${dict.model}
|
|
23
|
+
const [{ ${dict.model}Edit }] = await Promise.all([fetch.edit${dict.Model}(${dict.model}Id)]);
|
|
24
24
|
return (
|
|
25
25
|
<div className="container">
|
|
26
|
-
<div className="
|
|
27
|
-
<div className="
|
|
26
|
+
<div className="m-4 mt-8 flex justify-between">
|
|
27
|
+
<div className="flex items-center gap-2 text-primary text-xl">
|
|
28
28
|
{l("base.updateModel", { model: l("${dict.model}.modelName") })}
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
@@ -10,37 +10,34 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
10
10
|
filename: "_index.tsx",
|
|
11
11
|
content: `
|
|
12
12
|
import { ${dict.Model}, fetch, usePage } from "@apps/${dict.appName}/client";
|
|
13
|
-
import { Link } from "akanjs/ui";
|
|
14
13
|
import type { PageConfig } from "akanjs/client";
|
|
14
|
+
import { buttonRecipe, Link } from "akanjs/ui";
|
|
15
15
|
|
|
16
16
|
interface PageProps {
|
|
17
17
|
params: { ${dict.model}Id: string };
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export
|
|
20
|
+
export function generateHead({ params }: PageProps) {
|
|
21
21
|
const { ${dict.model}Id } = params;
|
|
22
|
-
const { ${dict.model} } = await fetch.view${dict.Model}(${dict.model}Id);
|
|
23
22
|
return (
|
|
24
23
|
<>
|
|
25
|
-
<title>{${dict.model}
|
|
26
|
-
<meta name="description" content={${dict.model}
|
|
27
|
-
<meta property="og:title" content={${dict.model}
|
|
28
|
-
<meta property="og:description" content={${dict.model}
|
|
24
|
+
<title>{${dict.model}Id}</title>
|
|
25
|
+
<meta name="description" content={${dict.model}Id} />
|
|
26
|
+
<meta property="og:title" content={${dict.model}Id} />
|
|
27
|
+
<meta property="og:description" content={${dict.model}Id} />
|
|
29
28
|
</>
|
|
30
29
|
);
|
|
31
30
|
}
|
|
32
31
|
export default async function Page({ params }: PageProps) {
|
|
33
32
|
const { l } = usePage();
|
|
34
33
|
const { ${dict.model}Id } = params;
|
|
35
|
-
const { ${dict.model}, ${dict.model}View } = await fetch.view${dict.Model}(${dict.model}Id);
|
|
34
|
+
const [{ ${dict.model}, ${dict.model}View }] = await Promise.all([fetch.view${dict.Model}(${dict.model}Id)]);
|
|
36
35
|
return (
|
|
37
36
|
<div className="container flex flex-col gap-4">
|
|
38
|
-
<div className="flex gap-4 font-bold text-lg
|
|
37
|
+
<div className="flex items-center gap-4 font-bold text-lg">
|
|
39
38
|
<${dict.Model}.Zone.View view={${dict.model}View} />
|
|
40
|
-
<Link href={\`/${dict.model}/\${${dict.model}.id}/edit\`}>
|
|
41
|
-
|
|
42
|
-
{l("base.updateModel", { model: l("${dict.model}.modelName") })}
|
|
43
|
-
</button>
|
|
39
|
+
<Link className={buttonRecipe()} href={\`/${dict.model}/\${${dict.model}.id}/edit\`}>
|
|
40
|
+
{l("base.updateModel", { model: l("${dict.model}.modelName") })}
|
|
44
41
|
</Link>
|
|
45
42
|
</div>
|
|
46
43
|
</div>
|
|
@@ -9,17 +9,17 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
9
9
|
return {
|
|
10
10
|
filename: "_index.tsx",
|
|
11
11
|
content: `
|
|
12
|
-
import {
|
|
13
|
-
import { cnst, fetch, usePage, ${dict.Model} } from "@apps/${dict.appName}/client";
|
|
12
|
+
import { type cnst, fetch, usePage, ${dict.Model} } from "@apps/${dict.appName}/client";
|
|
14
13
|
import type { PageConfig } from "akanjs/client";
|
|
14
|
+
import { Load } from "akanjs/ui";
|
|
15
15
|
|
|
16
16
|
export default function Page() {
|
|
17
17
|
const { l } = usePage();
|
|
18
18
|
const ${dict.model}Form: Partial<cnst.${dict.Model}> = {};
|
|
19
19
|
return (
|
|
20
20
|
<div className="container">
|
|
21
|
-
<div className="
|
|
22
|
-
<div className="
|
|
21
|
+
<div className="m-4 mt-8 flex justify-between">
|
|
22
|
+
<div className="flex items-center gap-2 text-primary text-xl">
|
|
23
23
|
+ {l("base.createModel", { model: l("${dict.model}.modelName") })}
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
@@ -37,6 +37,6 @@ export default function Page() {
|
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
39
|
export const pageConfig = { transition: "none" } satisfies PageConfig;
|
|
40
|
-
|
|
40
|
+
`,
|
|
41
41
|
};
|
|
42
42
|
}
|
|
@@ -10,26 +10,26 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
10
10
|
filename: "_index.tsx",
|
|
11
11
|
content: `
|
|
12
12
|
import { ${dict.Model}, fetch, usePage } from "@apps/${dict.appName}/client";
|
|
13
|
-
import { Link } from "akanjs/ui";
|
|
14
13
|
import type { PageConfig } from "akanjs/client";
|
|
14
|
+
import { buttonRecipe, Link } from "akanjs/ui";
|
|
15
15
|
|
|
16
16
|
export default async function Page() {
|
|
17
17
|
const { l } = usePage();
|
|
18
|
-
const { ${dict.model}InitInPublic } = await fetch.init${dict.Model}InPublic();
|
|
18
|
+
const [{ ${dict.model}InitInPublic }] = await Promise.all([fetch.init${dict.Model}InPublic()]);
|
|
19
19
|
return (
|
|
20
20
|
<div className="container flex flex-col gap-4">
|
|
21
|
-
<div className="
|
|
21
|
+
<div className="mt-5 h-full w-full px-5">
|
|
22
22
|
<div>{l("${dict.model}.modelName")}</div>
|
|
23
|
-
<div className="animate-fadeIn
|
|
23
|
+
<div className="flex animate-fadeIn items-center gap-4 px-4 pt-4">
|
|
24
24
|
<div className="font-bold text-lg md:text-4xl">${dict.Model}s</div>
|
|
25
|
-
<Link href={
|
|
26
|
-
|
|
25
|
+
<Link className={buttonRecipe()} href="/${dict.model}/new">
|
|
26
|
+
+ {l("base.createModel", { model: l("${dict.model}.modelName") })}
|
|
27
27
|
</Link>
|
|
28
28
|
</div>
|
|
29
29
|
<div>{l("${dict.model}.modelDesc")}</div>
|
|
30
|
-
<div className="
|
|
30
|
+
<div className="mt-3 flex gap-4 px-6">
|
|
31
31
|
<${dict.Model}.Zone.Card
|
|
32
|
-
className="animate-fadeIn grid
|
|
32
|
+
className="grid w-full animate-fadeIn grid-cols-1 justify-center gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"
|
|
33
33
|
init={${dict.model}InitInPublic}
|
|
34
34
|
/>
|
|
35
35
|
</div>
|
|
@@ -38,6 +38,6 @@ export default async function Page() {
|
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
export const pageConfig = { transition: "none" } satisfies PageConfig;
|
|
41
|
-
|
|
41
|
+
`,
|
|
42
42
|
};
|
|
43
43
|
}
|
|
@@ -9,23 +9,27 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
9
9
|
return {
|
|
10
10
|
filename: "_index.tsx",
|
|
11
11
|
content: `
|
|
12
|
-
import type { PageConfig } from "akanjs/client";
|
|
13
|
-
import { Model } from "akanjs/ui";
|
|
14
12
|
import { ${dict.Model}, fetch, usePage } from "@apps/${dict.appName}/client";
|
|
13
|
+
import type { PageConfig } from "akanjs/client";
|
|
14
|
+
import { buttonRecipe, Model } from "akanjs/ui";
|
|
15
15
|
|
|
16
16
|
export default async function Page() {
|
|
17
17
|
const { l } = usePage();
|
|
18
|
-
const { ${dict.model}InitInPublic } = await fetch.init${dict.Model}InPublic();
|
|
18
|
+
const [{ ${dict.model}InitInPublic }] = await Promise.all([fetch.init${dict.Model}InPublic()]);
|
|
19
19
|
return (
|
|
20
20
|
<>
|
|
21
|
-
<div className="animate-fadeIn
|
|
22
|
-
<div className="text-lg
|
|
23
|
-
<Model.New
|
|
21
|
+
<div className="flex animate-fadeIn items-center gap-4 px-4 pt-4">
|
|
22
|
+
<div className="font-bold text-lg md:text-4xl">{l("${dict.model}.modelName")}</div>
|
|
23
|
+
<Model.New
|
|
24
|
+
className={buttonRecipe({ size: "sm", variant: "ghost" })}
|
|
25
|
+
slice={fetch.slice.${dict.model}InPublic}
|
|
26
|
+
renderTitle="id"
|
|
27
|
+
>
|
|
24
28
|
<${dict.Model}.Template.General />
|
|
25
29
|
</Model.New>
|
|
26
30
|
</div>
|
|
27
31
|
<${dict.Model}.Zone.Card
|
|
28
|
-
className="
|
|
32
|
+
className="mt-2 grid w-full animate-fadeIn grid-cols-1 justify-center gap-4 md:grid-cols-2 xl:grid-cols-3"
|
|
29
33
|
init={${dict.model}InitInPublic}
|
|
30
34
|
/>
|
|
31
35
|
</>
|
|
@@ -18,6 +18,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
18
18
|
import { modelDictionary } from "akanjs/dictionary";
|
|
19
19
|
|
|
20
20
|
import type { ${dict.Model}, ${dict.Model}Insight } from "./${dict.model}.constant";
|
|
21
|
+
import type { ${dict.Model}Filter } from "./${dict.model}.document";
|
|
21
22
|
import type { ${dict.Model}Endpoint, ${dict.Model}Slice } from "./${dict.model}.signal";
|
|
22
23
|
|
|
23
24
|
export const dictionary = modelDictionary(["en", "ko"])
|
|
@@ -25,9 +26,11 @@ export const dictionary = modelDictionary(["en", "ko"])
|
|
|
25
26
|
t(["${modelLabelEn}", "${modelLabelKo}"]).desc(["${modelDescEn}", "${modelDescKo}"])
|
|
26
27
|
)
|
|
27
28
|
.model<${dict.Model}>((t) => ({
|
|
28
|
-
name: t(["Name", "이름"]),
|
|
29
|
+
name: t(["Name", "이름"]).desc(["Name", "이름"]),
|
|
29
30
|
}))
|
|
30
31
|
.insight<${dict.Model}Insight>((t) => ({}))
|
|
32
|
+
.query<${dict.Model}Filter>((fn) => ({}))
|
|
33
|
+
.sort<${dict.Model}Filter>((t) => ({}))
|
|
31
34
|
.slice<${dict.Model}Slice>((fn) => ({
|
|
32
35
|
inPublic: fn(["${dict.Model} In Public", "${dict.Model} 공개"]).arg((t) => ({})),
|
|
33
36
|
}))
|
|
@@ -8,14 +8,13 @@ interface Dict {
|
|
|
8
8
|
}
|
|
9
9
|
export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
|
|
10
10
|
return `
|
|
11
|
-
import { endpoint, internal, Public, slice } from "akanjs/signal";
|
|
11
|
+
import { endpoint, internal, None, Public, slice } from "akanjs/signal";
|
|
12
12
|
|
|
13
|
-
import * as cnst from "../cnst";
|
|
14
13
|
import * as srv from "../srv";
|
|
15
14
|
|
|
16
15
|
export class ${dict.Model}Internal extends internal(srv.${dict.model}, ({ interval }) => ({})) {}
|
|
17
16
|
|
|
18
|
-
export class ${dict.Model}Slice extends slice(srv.${dict.model}, { guards: { root:
|
|
17
|
+
export class ${dict.Model}Slice extends slice(srv.${dict.model}, { guards: { root: None, get: Public, cru: Public } }, (init) => ({
|
|
19
18
|
inPublic: init()
|
|
20
19
|
.exec(function () {
|
|
21
20
|
return this.${dict.model}Service.queryAny();
|
|
@@ -9,8 +9,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
9
9
|
return `
|
|
10
10
|
import { store } from "akanjs/store";
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
import { fetch, sig } from "../useClient";
|
|
12
|
+
import { sig } from "../useClient";
|
|
14
13
|
|
|
15
14
|
export class ${dict.Model}Store extends store(sig.${dict.model}, () => ({
|
|
16
15
|
// state
|
|
@@ -12,6 +12,10 @@ The section below is regenerated by `akan agent install` (run `bun run setup:age
|
|
|
12
12
|
workspace's apps, generated files, validation commands, and framework guide. Edit anything outside the
|
|
13
13
|
markers freely; content between them is overwritten on the next install.
|
|
14
14
|
|
|
15
|
+
It carries the rules only. The reasoning behind each area lives in deep-dive guidelines fetched on demand —
|
|
16
|
+
`akan guideline list` names them, `akan guideline show <name>` prints one, and an agent wired to `akan mcp`
|
|
17
|
+
calls `get_guideline` instead.
|
|
18
|
+
|
|
15
19
|
<!-- akan:agent:start -->
|
|
16
20
|
<!-- Populated by `akan agent install`. Run `bun run setup:agent` to refresh. -->
|
|
17
21
|
<!-- akan:agent:end -->
|
package/typecheck.proc.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
WorkflowRunner
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-a341yqdh.js";
|
|
5
5
|
import {
|
|
6
6
|
ScalarScript
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-9gqzgfsd.js";
|
|
8
8
|
import {
|
|
9
9
|
PrimitiveScript
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-z52nhkjs.js";
|
|
11
11
|
import {
|
|
12
12
|
ModuleScript
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-vrra4ttx.js";
|
|
14
14
|
import"./index-ss469dec.js";
|
|
15
|
-
import"./index-
|
|
16
|
-
import"./index-
|
|
17
|
-
import"./index-
|
|
15
|
+
import"./index-763h7h9g.js";
|
|
16
|
+
import"./index-safgeq9a.js";
|
|
17
|
+
import"./index-bmz9crym.js";
|
|
18
18
|
import {
|
|
19
19
|
createWorkflowStepRegistry
|
|
20
|
-
} from "./index-
|
|
21
|
-
import"./index-
|
|
20
|
+
} from "./index-q0s2dp3y.js";
|
|
21
|
+
import"./index-k7731a4v.js";
|
|
22
22
|
import {
|
|
23
23
|
Workspace,
|
|
24
24
|
command,
|
|
25
25
|
script
|
|
26
|
-
} from "./index-
|
|
27
|
-
import"./index-
|
|
26
|
+
} from "./index-akz5xvyw.js";
|
|
27
|
+
import"./index-h9cybjep.js";
|
|
28
28
|
import"./index-f39512t6.js";
|
|
29
29
|
import"./index-mxvakhsm.js";
|
|
30
30
|
import"./index-xys926f2.js";
|
|
@@ -1,40 +1,40 @@
|
|
|
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-
|
|
11
|
+
import"./index-763h7h9g.js";
|
|
12
12
|
import {
|
|
13
13
|
CloudScript
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-y3wyqcsp.js";
|
|
15
15
|
import {
|
|
16
16
|
getLatestPackageVersion,
|
|
17
17
|
getNpmRegistryUrl
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-116w1dap.js";
|
|
19
19
|
import {
|
|
20
20
|
PackageScript
|
|
21
|
-
} from "./index-
|
|
22
|
-
import"./index-
|
|
21
|
+
} from "./index-qge1hc70.js";
|
|
22
|
+
import"./index-ym9g9ggs.js";
|
|
23
23
|
import {
|
|
24
24
|
GlobalConfig
|
|
25
|
-
} from "./index-
|
|
25
|
+
} from "./index-safgeq9a.js";
|
|
26
26
|
import {
|
|
27
27
|
AgentScript
|
|
28
|
-
} from "./index-
|
|
29
|
-
import"./index-
|
|
30
|
-
import"./index-
|
|
31
|
-
import"./index-
|
|
28
|
+
} from "./index-te6r1b79.js";
|
|
29
|
+
import"./index-bmz9crym.js";
|
|
30
|
+
import"./index-q0s2dp3y.js";
|
|
31
|
+
import"./index-k7731a4v.js";
|
|
32
32
|
import {
|
|
33
33
|
ApplicationScript
|
|
34
|
-
} from "./index-
|
|
34
|
+
} from "./index-5r4e65hb.js";
|
|
35
35
|
import {
|
|
36
36
|
LibraryScript
|
|
37
|
-
} from "./index-
|
|
37
|
+
} from "./index-hvbdre8z.js";
|
|
38
38
|
import"./index-76rn3g2c.js";
|
|
39
39
|
import {
|
|
40
40
|
Exec,
|
|
@@ -42,13 +42,13 @@ import {
|
|
|
42
42
|
command,
|
|
43
43
|
runner,
|
|
44
44
|
script
|
|
45
|
-
} from "./index-
|
|
46
|
-
import"./index-
|
|
45
|
+
} from "./index-akz5xvyw.js";
|
|
46
|
+
import"./index-ynf37b66.js";
|
|
47
47
|
import {
|
|
48
48
|
ThemeValidator,
|
|
49
49
|
countBlocking,
|
|
50
50
|
formatStyleContract
|
|
51
|
-
} from "./index-
|
|
51
|
+
} from "./index-scemmfpj.js";
|
|
52
52
|
import"./index-5vy2jzar.js";
|
|
53
53
|
import {
|
|
54
54
|
AppExecutor,
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
collectScopeRecipeSources,
|
|
60
60
|
extractAgentBlock,
|
|
61
61
|
renderScopeAgentBlock
|
|
62
|
-
} from "./index-
|
|
62
|
+
} from "./index-h9cybjep.js";
|
|
63
63
|
import"./index-f39512t6.js";
|
|
64
64
|
import"./index-mxvakhsm.js";
|
|
65
65
|
import {
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
scanRecipes
|
|
68
68
|
} from "./index-xys926f2.js";
|
|
69
69
|
import"./index-1577bej2.js";
|
|
70
|
-
import"./index-
|
|
70
|
+
import"./index-h5sr2nnj.js";
|
|
71
71
|
import {
|
|
72
72
|
FileSys
|
|
73
73
|
} from "./index-67546d0j.js";
|
|
@@ -290,15 +290,18 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
290
290
|
if (!cwdPath)
|
|
291
291
|
return;
|
|
292
292
|
const stylesCssPath = path.join(cwdPath, "page", "styles.css");
|
|
293
|
-
|
|
294
|
-
|
|
293
|
+
if (!await Bun.file(stylesCssPath).exists())
|
|
294
|
+
return;
|
|
295
|
+
const violations = {
|
|
296
|
+
theme: new ThemeValidator().validate(await Bun.file(stylesCssPath).text())
|
|
297
|
+
};
|
|
295
298
|
const blocking = countBlocking(violations);
|
|
296
299
|
if (blocking === 0)
|
|
297
300
|
return;
|
|
298
301
|
throw new Error(`[themeValidator] ${blocking} blocking contrast violation(s):
|
|
299
302
|
${formatStyleContract(violations)}
|
|
300
303
|
|
|
301
|
-
` + "
|
|
304
|
+
` + "Raise the foreground/background contrast of these theme token values to the WCAG threshold.");
|
|
302
305
|
}
|
|
303
306
|
async writeTopLevelEnv(workspace, devProjectId) {
|
|
304
307
|
await workspace.writeFile(".env", `AKAN_WORKSPACE_ID=${devProjectId}
|