@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.
Files changed (65) hide show
  1. package/.build-stamp +1 -1
  2. package/{abstractCompactor-20e0cwbs.js → abstractCompactor-8yjc9sj4.js} +1 -1
  3. package/{agent.command-xdvw642m.js → agent.command-z0cam80t.js} +6 -6
  4. package/{application.command-g3f7xj25.js → application.command-2dct57za.js} +11 -12
  5. package/{applicationBuildRunner-af0wtspv.js → applicationBuildRunner-ds8acdfz.js} +3 -3
  6. package/{applicationReleasePackager-93nzdfsy.js → applicationReleasePackager-0jf6ejr4.js} +2 -2
  7. package/buildBatch.proc.js +4 -4
  8. package/{capacitorApp-b0ppke3m.js → capacitorApp-md7dnt25.js} +2 -2
  9. package/{cloud.command-0hmsv44q.js → cloud.command-8j7xrxsm.js} +10 -10
  10. package/{context.command-x92afrnf.js → context.command-xjf4y7em.js} +14 -14
  11. package/{dependencyScanner-rbs2407b.js → dependencyScanner-aqg3dkks.js} +1 -1
  12. package/{guideline.command-hpq08q66.js → guideline.command-yzm0qevv.js} +4 -4
  13. package/guidelines/conventions/conventions.instruction.md +17 -9
  14. package/guidelines/ssrRule/ssrRule.instruction.md +49 -5
  15. package/incrementalBuilder.proc.js +5 -5
  16. package/{index-737aj4fm.js → index-116w1dap.js} +4 -4
  17. package/{index-cp00yns2.js → index-5r4e65hb.js} +65 -62
  18. package/{index-abyjt72y.js → index-61x7qthy.js} +17 -21
  19. package/{index-m5gfc86a.js → index-763h7h9g.js} +1 -1
  20. package/{index-wnp7hwq7.js → index-94hdqqka.js} +1 -1
  21. package/{index-r691v756.js → index-9gqzgfsd.js} +4 -4
  22. package/{index-pehn44hr.js → index-a341yqdh.js} +3 -3
  23. package/{index-gvq17wqn.js → index-akz5xvyw.js} +17 -5
  24. package/{index-6d5r8q6k.js → index-bmz9crym.js} +13 -6
  25. package/{index-nq3avsf6.js → index-eed7vc38.js} +66 -33
  26. package/{index-46tjzh6s.js → index-h5sr2nnj.js} +24 -24
  27. package/{index-5f4gnt4c.js → index-h9cybjep.js} +91 -19
  28. package/{index-sqsfv8wg.js → index-hvbdre8z.js} +4 -10
  29. package/{index-qnv0aqmm.js → index-jcm6zr20.js} +3 -1
  30. package/{index-j37qq1f2.js → index-k7731a4v.js} +4 -4
  31. package/{index-8besc14m.js → index-q0s2dp3y.js} +1 -1
  32. package/{index-ety6takb.js → index-q13s3e01.js} +3 -3
  33. package/{index-jybbmwed.js → index-qge1hc70.js} +5 -5
  34. package/{index-sh01r3pm.js → index-safgeq9a.js} +3 -2
  35. package/{index-xjd3rqzj.js → index-scemmfpj.js} +6 -15
  36. package/{index-wbbswwqt.js → index-te6r1b79.js} +5 -5
  37. package/{index-p27h7535.js → index-vrra4ttx.js} +6 -6
  38. package/{index-hs70d8ed.js → index-y3wyqcsp.js} +6 -6
  39. package/{index-cbfp5wyp.js → index-ym9g9ggs.js} +21 -21
  40. package/{index-fgc8r6dj.js → index-ynf37b66.js} +3 -1
  41. package/{index-wybbcgxn.js → index-z52nhkjs.js} +4 -4
  42. package/index.js +18 -18
  43. package/{library.command-8vgrdtwy.js → library.command-w8b53vtt.js} +4 -4
  44. package/{localRegistry.command-0gtqj0r0.js → localRegistry.command-ymrgda7e.js} +9 -9
  45. package/{module.command-rama4zya.js → module.command-7pje37dv.js} +7 -7
  46. package/{package.command-6jxapdsg.js → package.command-jg4qk8ts.js} +4 -4
  47. package/package.json +3 -4
  48. package/{page.command-hxy7x525.js → page.command-abbpj96j.js} +3 -3
  49. package/{primitive.command-4bf6xcc3.js → primitive.command-jw4yv918.js} +8 -8
  50. package/{quality.command-h5edwegz.js → quality.command-06j6qy6n.js} +34 -4
  51. package/{repair.command-rgqf6px6.js → repair.command-x6resn10.js} +5 -5
  52. package/{scalar.command-6krkz6tw.js → scalar.command-mj2vx6rj.js} +6 -6
  53. package/templates/appSample/lib/task/task.signal.ts +11 -6
  54. package/templates/crudPages/[__model__Id]/edit/page.tsx +5 -5
  55. package/templates/crudPages/[__model__Id]/page.tsx +10 -13
  56. package/templates/crudPages/new/page.tsx +5 -5
  57. package/templates/crudPages/page.tsx +9 -9
  58. package/templates/crudSinglePage/page.tsx +11 -7
  59. package/templates/module/__model__.dictionary.ts +4 -1
  60. package/templates/module/__model__.signal.ts +2 -3
  61. package/templates/module/__model__.store.ts +1 -2
  62. package/{typeChecker-g6bh0xfv.js → typeChecker-yhs4eht8.js} +1 -1
  63. package/typecheck.proc.js +1 -1
  64. package/{workflow.command-dwhwrqhd.js → workflow.command-pmw2tere.js} +11 -11
  65. package/{workspace.command-f5h11gjn.js → workspace.command-x32k2vma.js} +29 -26
@@ -7,12 +7,12 @@ import {
7
7
  command,
8
8
  runner,
9
9
  script
10
- } from "./index-gvq17wqn.js";
10
+ } from "./index-akz5xvyw.js";
11
11
  import {
12
12
  isAllowedLibFacetRootFile,
13
13
  rootAllowedDirs,
14
14
  rootAllowedFiles
15
- } from "./index-5f4gnt4c.js";
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) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
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
- return !!(ts3.getCombinedModifierFlags(statement) & ts3.ModifierFlags.Default);
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-ety6takb.js";
5
- import"./index-6d5r8q6k.js";
6
- import"./index-8besc14m.js";
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-gvq17wqn.js";
12
- import"./index-5f4gnt4c.js";
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-r691v756.js";
4
+ } from "./index-9gqzgfsd.js";
5
5
  import"./index-ss469dec.js";
6
- import"./index-sh01r3pm.js";
6
+ import"./index-safgeq9a.js";
7
7
  import {
8
8
  renderPrimitiveReport
9
- } from "./index-8besc14m.js";
10
- import"./index-j37qq1f2.js";
9
+ } from "./index-q0s2dp3y.js";
10
+ import"./index-k7731a4v.js";
11
11
  import {
12
12
  Sys,
13
13
  command
14
- } from "./index-gvq17wqn.js";
15
- import"./index-5f4gnt4c.js";
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 { endpoint, internal, Public, slice } from "akanjs/signal";
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
- export class TaskSlice extends slice(srv.task, { guards: { root: Public, get: Public, cru: Public } }, (init) => ({
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
- // // guards: authentication/authorization guards
52
- // // export class TaskEndpoint extends endpoint(srv.task, { guards: { root: SignedIn } }, ({ query, mutation }) => ({})) {}
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 { Load } from "akanjs/ui";
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}, ${dict.model}Edit } = await fetch.edit${dict.Model}(${dict.model}Id);
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="flex justify-between m-4 mt-8">
27
- <div className="text-xl text-primary flex gap-2 items-center">
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 async function generateHead({ params }: PageProps) {
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}.id}</title>
26
- <meta name="description" content={${dict.model}.id} />
27
- <meta property="og:title" content={${dict.model}.id} />
28
- <meta property="og:description" content={${dict.model}.id} />
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 items-center">
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
- <button className="inline-flex items-center justify-center gap-2 rounded-field bg-primary px-4 py-2 font-medium text-primary-foreground text-sm transition-colors hover:bg-primary/90">
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 { Load } from "akanjs/ui";
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="flex justify-between m-4 mt-8">
22
- <div className="text-xl text-primary flex gap-2 items-center">
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="w-full mt-5 px-5 h-full ">
21
+ <div className="mt-5 h-full w-full px-5">
22
22
  <div>{l("${dict.model}.modelName")}</div>
23
- <div className="animate-fadeIn px-4 pt-4 flex gap-4 items-center">
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={\`/${dict.model}/new\`}>
26
- <button className="inline-flex items-center justify-center gap-2 rounded-field bg-primary px-4 py-2 font-medium text-primary-foreground text-sm transition-colors hover:bg-primary/90">+ {l("base.createModel", { model: l("${dict.model}.modelName") })}</button>
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="flex px-6 mt-3 gap-4">
30
+ <div className="mt-3 flex gap-4 px-6">
31
31
  <${dict.Model}.Zone.Card
32
- className="animate-fadeIn grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 justify-center gap-4 w-full"
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 flex items-center gap-4 px-4 pt-4">
22
- <div className="text-lg font-bold md:text-4xl">{l("${dict.model}.modelName")}</div>
23
- <Model.New className="inline-flex items-center gap-2 rounded-field px-3 py-1.5 text-sm transition-colors hover:bg-muted" slice={fetch.slice.${dict.model}InPublic} renderTitle="id">
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="animate-fadeIn mt-2 grid w-full grid-cols-1 justify-center gap-4 md:grid-cols-2 xl:grid-cols-3"
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: Public, get: Public, cru: Public } }, (init) => ({
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 * as cnst from "../cnst";
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
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  TypeChecker
4
- } from "./index-wnp7hwq7.js";
4
+ } from "./index-94hdqqka.js";
5
5
  import"./index-yb2wsc7f.js";
6
6
  export {
7
7
  TypeChecker
package/typecheck.proc.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  TypeChecker
4
- } from "./index-wnp7hwq7.js";
4
+ } from "./index-94hdqqka.js";
5
5
  import"./index-yb2wsc7f.js";
6
6
 
7
7
  // pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts
@@ -1,30 +1,30 @@
1
1
  // @bun
2
2
  import {
3
3
  WorkflowRunner
4
- } from "./index-pehn44hr.js";
4
+ } from "./index-a341yqdh.js";
5
5
  import {
6
6
  ScalarScript
7
- } from "./index-r691v756.js";
7
+ } from "./index-9gqzgfsd.js";
8
8
  import {
9
9
  PrimitiveScript
10
- } from "./index-wybbcgxn.js";
10
+ } from "./index-z52nhkjs.js";
11
11
  import {
12
12
  ModuleScript
13
- } from "./index-p27h7535.js";
13
+ } from "./index-vrra4ttx.js";
14
14
  import"./index-ss469dec.js";
15
- import"./index-m5gfc86a.js";
16
- import"./index-sh01r3pm.js";
17
- import"./index-6d5r8q6k.js";
15
+ import"./index-763h7h9g.js";
16
+ import"./index-safgeq9a.js";
17
+ import"./index-bmz9crym.js";
18
18
  import {
19
19
  createWorkflowStepRegistry
20
- } from "./index-8besc14m.js";
21
- import"./index-j37qq1f2.js";
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-gvq17wqn.js";
27
- import"./index-5f4gnt4c.js";
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-nq3avsf6.js";
5
- import"./index-ety6takb.js";
6
- import"./index-pehn44hr.js";
7
- import"./index-r691v756.js";
8
- import"./index-wybbcgxn.js";
9
- import"./index-p27h7535.js";
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-m5gfc86a.js";
11
+ import"./index-763h7h9g.js";
12
12
  import {
13
13
  CloudScript
14
- } from "./index-hs70d8ed.js";
14
+ } from "./index-y3wyqcsp.js";
15
15
  import {
16
16
  getLatestPackageVersion,
17
17
  getNpmRegistryUrl
18
- } from "./index-737aj4fm.js";
18
+ } from "./index-116w1dap.js";
19
19
  import {
20
20
  PackageScript
21
- } from "./index-jybbmwed.js";
22
- import"./index-cbfp5wyp.js";
21
+ } from "./index-qge1hc70.js";
22
+ import"./index-ym9g9ggs.js";
23
23
  import {
24
24
  GlobalConfig
25
- } from "./index-sh01r3pm.js";
25
+ } from "./index-safgeq9a.js";
26
26
  import {
27
27
  AgentScript
28
- } from "./index-wbbswwqt.js";
29
- import"./index-6d5r8q6k.js";
30
- import"./index-8besc14m.js";
31
- import"./index-j37qq1f2.js";
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-cp00yns2.js";
34
+ } from "./index-5r4e65hb.js";
35
35
  import {
36
36
  LibraryScript
37
- } from "./index-sqsfv8wg.js";
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-gvq17wqn.js";
46
- import"./index-fgc8r6dj.js";
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-xjd3rqzj.js";
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-5f4gnt4c.js";
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-46tjzh6s.js";
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
- const theme = await Bun.file(stylesCssPath).exists() ? new ThemeValidator().validate(await Bun.file(stylesCssPath).text()) : [];
294
- const violations = { style: [], theme };
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
- ` + "\uD14C\uB9C8 \uD1A0\uD070 \uAC12\uC758 \uC804\uACBD/\uBC30\uACBD \uCF58\uD2B8\uB77C\uC2A4\uD2B8\uB97C WCAG \uAE30\uC900 \uC774\uC0C1\uC73C\uB85C \uC870\uC815\uD558\uC138\uC694.");
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}