@akanjs/cli 3.0.0-alpha.99 → 3.0.0-beta.1

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 (71) 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-j05fr5jc.js → application.command-pj2m7584.js} +5 -5
  5. package/{applicationBuildRunner-s4gsk728.js → applicationBuildRunner-kxwbssgn.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-r6wvq2rp.js → cloud.command-jshwdq22.js} +9 -9
  10. package/{context.command-4vdt1aqq.js → context.command-ez8a0zyz.js} +13 -13
  11. package/{devTui-tnj2hh4f.js → devTui-40ggmd99.js} +85 -84
  12. package/{devTuiView-xzed2pd6.js → devTuiView-c08ccbat.js} +1 -1
  13. package/{guideline.command-p92dq6ts.js → guideline.command-xmqwx8zm.js} +11 -7
  14. package/guidelines/agentRule/agentRule.instruction.md +112 -32
  15. package/guidelines/conventions/conventions.instruction.md +100 -40
  16. package/guidelines/mcpRule/mcpRule.generate.json +11 -1
  17. package/guidelines/mcpRule/mcpRule.instruction.md +296 -53
  18. package/guidelines/queryRule/queryRule.instruction.md +17 -9
  19. package/guidelines/ssrRule/ssrRule.instruction.md +15 -13
  20. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +10 -5
  21. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +68 -3
  22. package/incrementalBuilder.proc.js +1 -1
  23. package/{index-gq44bqjt.js → index-259dsnz3.js} +2 -2
  24. package/{index-b9rkcrx8.js → index-2hq52jq3.js} +9 -7
  25. package/{index-qsq3q8fy.js → index-2tv3fdx4.js} +21 -10
  26. package/{index-qkk27bk6.js → index-4edzf1gr.js} +4 -4
  27. package/{index-yza7zkpt.js → index-600zhnve.js} +10 -10
  28. package/{index-srdssqj7.js → index-7737gxcp.js} +3 -3
  29. package/{index-zmjppp25.js → index-8pm30m73.js} +5 -5
  30. package/{index-p5neav9b.js → index-a64esmtb.js} +54 -9
  31. package/{index-0amdxycf.js → index-fz5q3gd7.js} +3 -3
  32. package/{index-fc1bh0a7.js → index-gyd220p2.js} +1 -1
  33. package/{index-5svjba73.js → index-j9yhg404.js} +1 -1
  34. package/{index-c69j78kk.js → index-kn1h7p1x.js} +1 -1
  35. package/{index-gtmz74tj.js → index-ktb5njgy.js} +2 -2
  36. package/{index-znynzt5w.js → index-mak3cd28.js} +1 -1
  37. package/{index-29sxqfaw.js → index-ne2qy0nk.js} +3 -3
  38. package/{index-hyywke0f.js → index-pnqbkf5p.js} +1 -1
  39. package/{index-8p8p0cf8.js → index-rwg2aa4f.js} +3 -3
  40. package/{index-5wd728df.js → index-v0qh106m.js} +215 -12
  41. package/{index-7d6vny25.js → index-ws5e0j51.js} +2 -2
  42. package/{index-1yxtbmbj.js → index-wt7qrtd4.js} +1 -1
  43. package/{index-gkkdx9kp.js → index-zry5nz81.js} +6 -6
  44. package/index.js +19 -19
  45. package/{library.command-s4fszngs.js → library.command-nbsky672.js} +3 -3
  46. package/{localRegistry.command-fq2w7cgz.js → localRegistry.command-yeq57wjr.js} +8 -8
  47. package/{module.command-6n7dwvav.js → module.command-29vqzrh8.js} +6 -6
  48. package/{package.command-gr82ypnr.js → package.command-axv0abmn.js} +3 -3
  49. package/package.json +2 -2
  50. package/{page.command-7gvgb3jb.js → page.command-vs9s3zrh.js} +3 -3
  51. package/{primitive.command-tk5ckw38.js → primitive.command-cbxmqbtc.js} +7 -7
  52. package/{quality.command-38v81baf.js → quality.command-gmbs7nws.js} +2 -2
  53. package/{repair.command-5xbwvsxp.js → repair.command-bqsjptsj.js} +5 -5
  54. package/{routeSourceValidator-ze6x894c.js → routeSourceValidator-apyqw7wk.js} +90 -17
  55. package/{scalar.command-0epwcr5k.js → scalar.command-6k1vhe9s.js} +5 -5
  56. package/{subspace.command-e2t36xb2.js → subspace.command-fwjfcts7.js} +7 -5
  57. package/templates/app/page/_index.tsx +3 -3
  58. package/templates/app/page/_layout.tsx +31 -32
  59. package/templates/appSample/page/task/[taskId]/_index.tsx +22 -27
  60. package/templates/appSample/page/task/[taskId]/edit.tsx +25 -30
  61. package/templates/appSample/page/task/_index.tsx +3 -7
  62. package/templates/appSample/page/task/_layout.tsx +4 -15
  63. package/templates/appSample/page/task/new.tsx +4 -10
  64. package/templates/crudPages/[__model__Id]/edit/page.tsx +26 -28
  65. package/templates/crudPages/[__model__Id]/page.tsx +20 -25
  66. package/templates/crudPages/new/page.tsx +24 -23
  67. package/templates/crudPages/page.tsx +25 -24
  68. package/templates/crudSinglePage/page.tsx +25 -24
  69. package/templates/lib/sig.ts +4 -0
  70. package/{workflow.command-kphbr7eh.js → workflow.command-nwpcdc8p.js} +10 -10
  71. package/{workspace.command-ag5hy887.js → workspace.command-8s050m0h.js} +20 -20
@@ -186,11 +186,11 @@ export class TaskFilter extends from(cnst.Task, (filter) => ({
186
186
  })),
187
187
  }))
188
188
 
189
- // 4. In page — Init the slice in an async Page and hand the init to a Zone.
190
- export default async function Page() {
189
+ // 4. In page — init the slice inside the page chain's render and hand the init to a Zone.
190
+ export default page().render(async () => {
191
191
  const [{ taskInitInTodo }] = await Promise.all([fetch.initTaskInTodo()]);
192
192
  return <Task.Zone.Card init={taskInitInTodo} sliceName="taskInTodo" />;
193
- }
193
+ });
194
194
  ```
195
195
 
196
196
  The slice name in code uses camelCase (`inTodo`). In dictionary and components it becomes `"taskInTodo"`.
@@ -328,6 +328,71 @@ export const Insight = ({ sliceName }: { sliceName: string }) => {
328
328
 
329
329
  ---
330
330
 
331
+ ### Recipe 7: Migrating `page/` to the Route Chain
332
+
333
+ A route file used to be a default function beside named exports (`pageConfig`, `head`, `generateHead`, `Loading`,
334
+ `fonts`, …). It is now one chain, and the chain is also what publishes a screen to agents. The legacy shape still
335
+ loads and logs one warning per file at boot (`… uses the legacy route shape …`); migrate file by file, then run
336
+ `bun run akan typecheck <app>` and `bun run akan lint <app>`.
337
+
338
+ ```tsx
339
+ // before — page/(user)/project/[projectId]/_index.tsx
340
+ import { fetch, usePage } from "@apps/<app>/client";
341
+ import type { PageConfig } from "akanjs/client";
342
+
343
+ interface PageProps {
344
+ params: { projectId: string };
345
+ searchParams: { tab?: string };
346
+ }
347
+ export function generateHead({ params }: PageProps) {
348
+ return <title>{params.projectId}</title>;
349
+ }
350
+ export default async function Page({ params: { projectId }, searchParams }: PageProps) {
351
+ const { l } = usePage();
352
+ const { project } = await fetch.viewProject(projectId);
353
+ return <Project.Zone.View view={project} tab={searchParams.tab} />;
354
+ }
355
+ export const pageConfig = { transition: "stack" } satisfies PageConfig;
356
+
357
+ // after
358
+ import { fetch, usePage } from "@apps/<app>/client";
359
+ import { ID } from "akanjs/base";
360
+ import { page } from "akanjs/client";
361
+
362
+ export default page()
363
+ .param("projectId", ID, { desc: "The project to show." })
364
+ .search("tab", String)
365
+ .config({ transition: "stack" })
366
+ .head(({ projectId }) => <title>{projectId}</title>)
367
+ .prompt("briefProject", "Brief one project: its status and what is due.")
368
+ .render(async ({ projectId, tab }) => {
369
+ const { l } = usePage();
370
+ const { project } = await fetch.viewProject(projectId);
371
+ return <Project.Zone.View view={project} tab={tab} />;
372
+ });
373
+ ```
374
+
375
+ | Legacy export | Chain stage |
376
+ |---|---|
377
+ | `interface PageProps { params }` + `[x]` folder | `.param("x", ID \| String \| Int \| …)` — one per `[x]` segment, every one of them, in path order |
378
+ | `searchParams.k` | `.search("k", Type)`; `[Type]` for a repeated key; the value arrives typed and optional |
379
+ | `params.lang` | `lang` — on every route's `.render()`, `.head()`, `.metadata()` and `.loading()` with no stage; `.param("lang")` is refused |
380
+ | `export const pageConfig = {…}` | `.config({…})` — `devOnly` stays a literal |
381
+ | `export const head = <…/>` / `generateHead({ params })` | `.head(<…/>)` / `.head(({ x }) => <…/>)` |
382
+ | `export const metadata` / `generateMetadata` | `.metadata({…})` / `.metadata((args) => …)` |
383
+ | `export function Loading()` | `.loading((args) => …)` |
384
+ | `export default async function Page({ params, searchParams })` | `.render(async ({ x, k }) => { …same body… })` — `async` only if it awaits |
385
+ | `_layout.tsx`: `export default function Layout({ children })` | `layout().render(({ children }) => …)` |
386
+ | `export function NotFound` / `export function Error` | `.notFound(fn)` / `.error(fn)` on `layout()` |
387
+ | root `_layout.tsx`: `fonts`, `theme`, `manifest`, `reconnect`, `wsConnect`, `layoutStyle`, `gaTrackingId` | `rootLayout().fonts([…]).theme("dark").manifest({…}).reconnect(false).wsConnect(false).layoutStyle("web").gaTrackingId("G-…")` |
388
+ | `prompt()` on `endpoint()` (removed) | `.prompt(name, description)` on the page that shows the same screen |
389
+
390
+ Rules the loader and `akan sync` enforce: a chain module has no other export; `page()` belongs in a page file and
391
+ `layout()` / `rootLayout()` in a `_layout.tsx`; a page names every `[x]` of its path, a layout may name a subset;
392
+ `.param()` and `.prompt()` names are string literals; `import "./styles.css"` stays the first line of a root layout;
393
+ `_overrides.tsx` is untouched. MCP: `prompts/get` now runs the page's body under the caller's token and hands the
394
+ model the description, what the page fetched, and the tools of those modules — see `mcpRule`.
395
+
331
396
  ### Data Flow Summary
332
397
 
333
398
  For each business question, follow this chain:
@@ -3,7 +3,7 @@ import {
3
3
  CodegenLock,
4
4
  WorkspaceExecutor,
5
5
  AppExecutor
6
- } from "./index-qsq3q8fy.js";
6
+ } from "./index-2tv3fdx4.js";
7
7
  import"./index-q0y2jq9j.js";
8
8
  import"./index-6wwzs1bc.js";
9
9
  import {
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-znynzt5w.js";
5
+ } from "./index-mak3cd28.js";
6
6
  import {
7
7
  LibExecutor
8
- } from "./index-qsq3q8fy.js";
8
+ } from "./index-2tv3fdx4.js";
9
9
  import {
10
10
  LibSource,
11
11
  formatLibStatuses
@@ -4,17 +4,17 @@ import {
4
4
  GlobalConfig,
5
5
  CloudApi,
6
6
  AiSession
7
- } from "./index-c69j78kk.js";
7
+ } from "./index-kn1h7p1x.js";
8
8
  import {
9
9
  WorkspaceExecutor,
10
10
  AppExecutor
11
- } from "./index-qsq3q8fy.js";
11
+ } from "./index-2tv3fdx4.js";
12
12
  import {
13
13
  runner
14
- } from "./index-znynzt5w.js";
14
+ } from "./index-mak3cd28.js";
15
15
  import {
16
16
  openBrowser
17
- } from "./index-5wd728df.js";
17
+ } from "./index-v0qh106m.js";
18
18
 
19
19
  // pkgs/@akanjs/cli/npmRegistry.ts
20
20
  var defaultNpmRegistry = "https://registry.npmjs.org";
@@ -283,9 +283,11 @@ ${chalk.green("\u27A4")} Authentication Required`));
283
283
  return;
284
284
  }
285
285
  }
286
- Logger.info("Logging in to npm...");
287
- await workspace.spawn("npm", ["login"], { stdio: "inherit" });
288
- Logger.info("Logged in to npm");
286
+ if (!registry) {
287
+ Logger.info("Logging in to npm...");
288
+ await workspace.spawn("npm", ["login"], { stdio: "inherit" });
289
+ Logger.info("Logged in to npm");
290
+ }
289
291
  for (const library of akanPkgs) {
290
292
  Logger.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
291
293
  await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
@@ -947,6 +947,8 @@ class AsyncDefaultExportDetector {
947
947
  if (ts.isExportAssignment(statement)) {
948
948
  if (this.#isAsyncFunctionExpression(statement.expression))
949
949
  return true;
950
+ if (ts.isCallExpression(statement.expression))
951
+ return true;
950
952
  if (ts.isIdentifier(statement.expression))
951
953
  defaultIdentifier = statement.expression.text;
952
954
  continue;
@@ -1096,13 +1098,18 @@ async function writeGeneratedRootLayoutFile(opts) {
1096
1098
  void st;
1097
1099
  ` : `import "@apps/${opts.appName}/client";
1098
1100
  `;
1099
- const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedLayout from ${JSON.stringify(inheritedSourceSpecifier)};
1100
- ` : `const inheritedLayout = {};
1101
+ const inheritedLabel = inheritedSourceAbsPath ? path4.relative(opts.appCwdPath, inheritedSourceAbsPath) : "";
1102
+ const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedModule from ${JSON.stringify(inheritedSourceSpecifier)};
1103
+ const inheritedLayout = resolveRouteModule(inheritedModule as never, ${JSON.stringify(inheritedLabel)}).module as LayoutModule;
1104
+ ` : `const inheritedLayout: LayoutModule = {};
1101
1105
  `;
1102
1106
  const prefix = routePrefixForSegments(opts.boundary.segments);
1103
- const userImport = sourceSpecifier ? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};
1104
- ` : `const UserLayout = ({ children }) => children;
1105
- const userLayout = {};
1107
+ const userLabel = opts.boundary.sourceAbsPath ? path4.relative(opts.appCwdPath, opts.boundary.sourceAbsPath) : "";
1108
+ const userImport = sourceSpecifier ? `import * as userModule from ${JSON.stringify(sourceSpecifier)};
1109
+ const userLayout = resolveRouteModule(userModule as never, ${JSON.stringify(userLabel)}).module as LayoutModule;
1110
+ const UserLayout = userLayout.default as (props: LayoutProps) => ReactNode | Promise<ReactNode>;
1111
+ ` : `const UserLayout = ({ children }: LayoutProps) => children;
1112
+ const userLayout: LayoutModule = {};
1106
1113
  `;
1107
1114
  const isAsyncUserLayout = opts.boundary.sourceAbsPath ? await AsyncDefaultExportDetector.detect(opts.boundary.sourceAbsPath) : false;
1108
1115
  const userLayoutElement = "<UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>";
@@ -1114,8 +1121,9 @@ const userLayout = {};
1114
1121
  ` : "";
1115
1122
  const layoutChild = isAsyncUserLayout ? "{layout}" : userLayoutElement;
1116
1123
  const layoutReturn = isAsyncUserLayout ? "layout" : userLayoutElement;
1117
- const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
1118
- import { loadFonts } from "akanjs/client";
1124
+ const source = opts.includeSystemProvider ? `import type { LayoutModule, LayoutProps, PageProps } from "akanjs/client";
1125
+ import { loadFonts, resolveRouteModule } from "akanjs/client";
1126
+ import type { ReactNode } from "react";
1119
1127
  import { System } from "akanjs/ui";
1120
1128
  import { env } from "@apps/${opts.appName}/env/env.client";
1121
1129
  import { allDictionary } from ${JSON.stringify(dictMacroSpecifier)};
@@ -1166,7 +1174,9 @@ ${layoutBinding} return (
1166
1174
  </System.Provider>
1167
1175
  );
1168
1176
  }
1169
- ` : `import type { LayoutProps, PageProps } from "akanjs/client";
1177
+ ` : `import type { LayoutModule, LayoutProps, PageProps } from "akanjs/client";
1178
+ import { resolveRouteModule } from "akanjs/client";
1179
+ import type { ReactNode } from "react";
1170
1180
  ${inheritedImport}${userImport}
1171
1181
  export async function generateHead(props: PageProps) {
1172
1182
  if (userLayout.generateHead) return userLayout.generateHead(props);
@@ -3245,7 +3255,7 @@ class SysExecutor extends Executor {
3245
3255
  class AppExecutor extends SysExecutor {
3246
3256
  static #routeSourceValidator = null;
3247
3257
  static async#getRouteSourceValidator() {
3248
- AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-ze6x894c.js")).RouteSourceValidator;
3258
+ AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-apyqw7wk.js")).RouteSourceValidator;
3249
3259
  return AppExecutor.#routeSourceValidator;
3250
3260
  }
3251
3261
  dist;
@@ -3419,7 +3429,8 @@ class AppExecutor extends SysExecutor {
3419
3429
  validator.validateOverridesSourceExports(routeSource, absPath);
3420
3430
  else {
3421
3431
  const info = validator.validateRouteSourceExports(routeSource, absPath, parsed.kind, {
3422
- rootLayout: isRootLayout
3432
+ rootLayout: isRootLayout,
3433
+ pattern: parsed.pattern
3423
3434
  });
3424
3435
  if (info.devOnly) {
3425
3436
  devOnlyKeys.add(key);
@@ -1,12 +1,12 @@
1
1
  // @bun
2
2
  import {
3
3
  script
4
- } from "./index-znynzt5w.js";
4
+ } from "./index-mak3cd28.js";
5
5
  import {
6
6
  AppExecutor,
7
7
  LibExecutor,
8
8
  ModuleExecutor
9
- } from "./index-qsq3q8fy.js";
9
+ } from "./index-2tv3fdx4.js";
10
10
  import {
11
11
  compactDiagnostics,
12
12
  createPrimitiveWriteReport,
@@ -39,10 +39,10 @@ import {
39
39
  hasSignalFactoryEntry,
40
40
  insertSignalFactoryEntry,
41
41
  addFieldUiPolicyForType
42
- } from "./index-fc1bh0a7.js";
42
+ } from "./index-gyd220p2.js";
43
43
  import {
44
44
  ModuleScript
45
- } from "./index-zmjppp25.js";
45
+ } from "./index-8pm30m73.js";
46
46
 
47
47
  // pkgs/@akanjs/cli/primitive/primitive.script.ts
48
48
  import { capitalize } from "akanjs/common";
@@ -1,14 +1,14 @@
1
1
  // @bun
2
2
  import {
3
3
  AppExecutor
4
- } from "./index-qsq3q8fy.js";
4
+ } from "./index-2tv3fdx4.js";
5
5
  import {
6
6
  jsonText,
7
7
  createWorkflowBaselineSummary,
8
8
  buildAkanModuleContextIndex,
9
9
  createWorkflowStepRegistry,
10
10
  toolingRolloutGate
11
- } from "./index-fc1bh0a7.js";
11
+ } from "./index-gyd220p2.js";
12
12
  import {
13
13
  buildResourceList,
14
14
  codexMcpConfigPath,
@@ -19,33 +19,33 @@ import {
19
19
  upsertCodexMcpServerBlock,
20
20
  renderDoctorText,
21
21
  AkanContextAnalyzer
22
- } from "./index-gtmz74tj.js";
22
+ } from "./index-ktb5njgy.js";
23
23
  import {
24
24
  CommandContainer,
25
25
  runner,
26
26
  script
27
- } from "./index-znynzt5w.js";
27
+ } from "./index-mak3cd28.js";
28
28
  import {
29
29
  isPlaceholderAppId2
30
- } from "./index-1yxtbmbj.js";
30
+ } from "./index-wt7qrtd4.js";
31
31
  import {
32
32
  Prompter
33
33
  } from "./index-h7yw2z9n.js";
34
34
  import {
35
35
  RepairRunner
36
- } from "./index-0amdxycf.js";
36
+ } from "./index-fz5q3gd7.js";
37
37
  import {
38
38
  WorkflowRunner
39
- } from "./index-srdssqj7.js";
39
+ } from "./index-7737gxcp.js";
40
40
  import {
41
41
  ModuleScript
42
- } from "./index-zmjppp25.js";
42
+ } from "./index-8pm30m73.js";
43
43
  import {
44
44
  PrimitiveScript
45
- } from "./index-qkk27bk6.js";
45
+ } from "./index-4edzf1gr.js";
46
46
  import {
47
47
  ScalarScript
48
- } from "./index-8p8p0cf8.js";
48
+ } from "./index-rwg2aa4f.js";
49
49
  import {
50
50
  getMobileTargets
51
51
  } from "./index-47pj3aee.js";
@@ -20,13 +20,13 @@ import {
20
20
  renderWorkflowApply,
21
21
  renderWorkflowValidation,
22
22
  renderWorkflowRunArtifact
23
- } from "./index-fc1bh0a7.js";
23
+ } from "./index-gyd220p2.js";
24
24
  import {
25
25
  AkanContextAnalyzer
26
- } from "./index-gtmz74tj.js";
26
+ } from "./index-ktb5njgy.js";
27
27
  import {
28
28
  runner
29
- } from "./index-znynzt5w.js";
29
+ } from "./index-mak3cd28.js";
30
30
 
31
31
  // pkgs/@akanjs/cli/workflow/workflow.runner.ts
32
32
  import { mkdir, readFile, writeFile } from "fs/promises";
@@ -4,14 +4,14 @@ import {
4
4
  } from "./index-q0y2jq9j.js";
5
5
  import {
6
6
  AiSession
7
- } from "./index-c69j78kk.js";
7
+ } from "./index-kn1h7p1x.js";
8
8
  import {
9
9
  ModuleExecutor
10
- } from "./index-qsq3q8fy.js";
10
+ } from "./index-2tv3fdx4.js";
11
11
  import {
12
12
  runner,
13
13
  script
14
- } from "./index-znynzt5w.js";
14
+ } from "./index-mak3cd28.js";
15
15
  import {
16
16
  sourceFile,
17
17
  moduleSourcePaths,
@@ -19,10 +19,10 @@ import {
19
19
  createPassedPrimitiveReport,
20
20
  bilingualLabelForField,
21
21
  bilingualDescriptionForField
22
- } from "./index-fc1bh0a7.js";
22
+ } from "./index-gyd220p2.js";
23
23
  import {
24
24
  PageScript
25
- } from "./index-hyywke0f.js";
25
+ } from "./index-pnqbkf5p.js";
26
26
  import {
27
27
  Prompter
28
28
  } from "./index-h7yw2z9n.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AsyncDefaultExportDetector,
4
4
  resolveSsrPageEntriesForApp
5
- } from "./index-qsq3q8fy.js";
5
+ } from "./index-2tv3fdx4.js";
6
6
  import {
7
7
  BarrelAnalyzer,
8
8
  createBarrelImportsPlugin,
@@ -1490,24 +1490,69 @@ class FontOptimizer {
1490
1490
  }
1491
1491
  #extractFontsExport(source, filePath) {
1492
1492
  const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
1493
- const fonts = [];
1493
+ const declaration = this.#findFontsDeclaration(sourceFile);
1494
+ if (!declaration)
1495
+ return [];
1496
+ const value = this.#literalToValue(declaration);
1497
+ const entries = Array.isArray(value) ? value : [];
1498
+ const fonts = entries.filter((entry) => this.#isReadableFont(entry));
1499
+ if (fonts.length !== entries.length || !Array.isArray(value))
1500
+ this.#app.logger.warn(`[font] ${path10.relative(this.#app.cwdPath, filePath)} declares fonts the build cannot read without evaluating the module \u2014 write the list inline, or nothing is subset for it and every /_akan/fonts request 404s`);
1501
+ return fonts.map((font) => this.#withFontDefaults(font));
1502
+ }
1503
+ #isReadableFont(value) {
1504
+ if (!value || typeof value !== "object")
1505
+ return false;
1506
+ const font = value;
1507
+ return typeof font.name === "string" && Array.isArray(font.paths);
1508
+ }
1509
+ #findFontsDeclaration(sourceFile) {
1494
1510
  for (const statement of sourceFile.statements) {
1511
+ if (ts.isExportAssignment(statement)) {
1512
+ if (statement.isExportEquals)
1513
+ continue;
1514
+ const stage = this.#findChainStageArgument(statement.expression, "fonts");
1515
+ if (stage)
1516
+ return stage;
1517
+ continue;
1518
+ }
1495
1519
  if (!ts.isVariableStatement(statement))
1496
1520
  continue;
1497
1521
  const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined;
1498
- const isExported = modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) ?? false;
1499
- if (!isExported)
1522
+ if (!modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
1500
1523
  continue;
1501
1524
  for (const declaration of statement.declarationList.declarations) {
1502
1525
  if (!ts.isIdentifier(declaration.name) || declaration.name.text !== "fonts")
1503
1526
  continue;
1504
- const value = declaration.initializer ? this.#literalToValue(declaration.initializer) : null;
1505
- if (Array.isArray(value)) {
1506
- fonts.push(...value.map((font) => this.#withFontDefaults(font)));
1507
- }
1527
+ if (declaration.initializer)
1528
+ return declaration.initializer;
1508
1529
  }
1509
1530
  }
1510
- return fonts;
1531
+ return null;
1532
+ }
1533
+ #findChainStageArgument(expression, stageName) {
1534
+ let node = this.#unwrapExpression(expression);
1535
+ let argument = null;
1536
+ while (node && ts.isCallExpression(node)) {
1537
+ const callee = this.#unwrapExpression(node.expression);
1538
+ if (!callee)
1539
+ return null;
1540
+ if (ts.isIdentifier(callee))
1541
+ return callee.text === "rootLayout" ? argument : null;
1542
+ if (!ts.isPropertyAccessExpression(callee))
1543
+ return null;
1544
+ if (callee.name.text === stageName)
1545
+ argument ??= node.arguments[0] ?? null;
1546
+ node = this.#unwrapExpression(callee.expression);
1547
+ }
1548
+ return null;
1549
+ }
1550
+ #unwrapExpression(expression) {
1551
+ let current = expression;
1552
+ while (current && (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current))) {
1553
+ current = current.expression;
1554
+ }
1555
+ return current;
1511
1556
  }
1512
1557
  #literalToValue(node) {
1513
1558
  if (ts.isStringLiteralLike(node))
@@ -5,13 +5,13 @@ import {
5
5
  writeGeneratedSyncState,
6
6
  createRepairReport,
7
7
  renderRepairReport
8
- } from "./index-fc1bh0a7.js";
8
+ } from "./index-gyd220p2.js";
9
9
  import {
10
10
  AkanContextAnalyzer
11
- } from "./index-gtmz74tj.js";
11
+ } from "./index-ktb5njgy.js";
12
12
  import {
13
13
  runner
14
- } from "./index-znynzt5w.js";
14
+ } from "./index-mak3cd28.js";
15
15
 
16
16
  // pkgs/@akanjs/cli/repair/repair.runner.ts
17
17
  var commandForShell = (command) => command.startsWith("akan ") ? `bun run ${command}` : command;
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AppExecutor,
4
4
  LibExecutor
5
- } from "./index-qsq3q8fy.js";
5
+ } from "./index-2tv3fdx4.js";
6
6
 
7
7
  // pkgs/@akanjs/devkit/workflow/utils.ts
8
8
  var jsonText = (value, { trailingNewline = true } = {}) => `${JSON.stringify(value, null, 2)}${trailingNewline ? `
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  AppInfo
4
- } from "./index-qsq3q8fy.js";
4
+ } from "./index-2tv3fdx4.js";
5
5
 
6
6
  // pkgs/@akanjs/devkit/slicePlanner.ts
7
7
  class SlicePlanner {
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-q0y2jq9j.js";
5
5
  import {
6
6
  Spinner
7
- } from "./index-qsq3q8fy.js";
7
+ } from "./index-2tv3fdx4.js";
8
8
 
9
9
  // pkgs/@akanjs/devkit/cloud/globalConfig.ts
10
10
  import { chmod, mkdir } from "fs/promises";
@@ -7,7 +7,7 @@ import {
7
7
  isScannedRootEntry,
8
8
  AppExecutor,
9
9
  LibExecutor
10
- } from "./index-qsq3q8fy.js";
10
+ } from "./index-2tv3fdx4.js";
11
11
  import {
12
12
  FileSys
13
13
  } from "./index-q0y2jq9j.js";
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  workflowRunArtifactPath,
21
21
  workflowSyncDir
22
- } from "./index-fc1bh0a7.js";
22
+ } from "./index-gyd220p2.js";
23
23
 
24
24
  // pkgs/@akanjs/devkit/akanContext.ts
25
25
  import { readdir } from "fs/promises";
@@ -9,7 +9,7 @@ import {
9
9
  LibExecutor,
10
10
  PkgExecutor,
11
11
  ModuleExecutor
12
- } from "./index-qsq3q8fy.js";
12
+ } from "./index-2tv3fdx4.js";
13
13
  import {
14
14
  getDirname2
15
15
  } from "./index-6wwzs1bc.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-znynzt5w.js";
5
+ } from "./index-mak3cd28.js";
6
6
  import {
7
7
  AGENT_BLOCK_START,
8
8
  AGENT_BLOCK_END,
@@ -13,14 +13,14 @@ import {
13
13
  CLAUDE_COMMENT_RULE,
14
14
  AppExecutor,
15
15
  LibExecutor
16
- } from "./index-qsq3q8fy.js";
16
+ } from "./index-2tv3fdx4.js";
17
17
  import {
18
18
  collectRecipeSources2,
19
19
  scanRecipes2
20
20
  } from "./index-by5gpp8x.js";
21
21
  import {
22
22
  AkanContextAnalyzer
23
- } from "./index-gtmz74tj.js";
23
+ } from "./index-ktb5njgy.js";
24
24
  import {
25
25
  Prompter
26
26
  } from "./index-h7yw2z9n.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-znynzt5w.js";
5
+ } from "./index-mak3cd28.js";
6
6
 
7
7
  // pkgs/@akanjs/cli/page/page.runner.ts
8
8
  class PageRunner extends runner("page") {
@@ -2,15 +2,15 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-znynzt5w.js";
5
+ } from "./index-mak3cd28.js";
6
6
  import {
7
7
  generatedFilesForSync,
8
8
  createPassedPrimitiveReport,
9
9
  scalarChangedFiles
10
- } from "./index-fc1bh0a7.js";
10
+ } from "./index-gyd220p2.js";
11
11
  import {
12
12
  AiSession
13
- } from "./index-c69j78kk.js";
13
+ } from "./index-kn1h7p1x.js";
14
14
  import {
15
15
  Prompter
16
16
  } from "./index-h7yw2z9n.js";