@akanjs/cli 2.2.10 → 2.2.11

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/index.js CHANGED
@@ -1721,6 +1721,10 @@ var rootSignalTestFilePattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(
1721
1721
  var isAllowedTestFile = (filename) => testFilePattern.test(filename);
1722
1722
  var isAllowedLibRootFile = (filename) => libRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
1723
1723
  var getScanPath = (exec, relativePath) => path5.posix.join(`${exec.type}s`, exec.name, relativePath.split(path5.sep).join("/"));
1724
+ var getModuleNameFromPath = (kind, modulePath) => {
1725
+ const dirname = path5.basename(modulePath);
1726
+ return kind === "service" ? dirname.replace(/^_+/, "") : dirname;
1727
+ };
1724
1728
  async function assertScanConvention(exec, libRoot) {
1725
1729
  const violations = [];
1726
1730
  const addViolation = (relativePath, reason) => {
@@ -1757,6 +1761,7 @@ ${violations.sort().map((violation) => `- ${violation}`).join(`
1757
1761
  }
1758
1762
  async function validateModuleFiles(exec, violations, kind, modulePath) {
1759
1763
  const { files, dirs } = await exec.getFilesAndDirs(modulePath);
1764
+ const moduleName = getModuleNameFromPath(kind, modulePath);
1760
1765
  dirs.forEach((dirname) => {
1761
1766
  violations.push(`${getScanPath(exec, path5.join(modulePath, dirname))}: unsupported module folder`);
1762
1767
  });
@@ -1764,6 +1769,8 @@ async function validateModuleFiles(exec, violations, kind, modulePath) {
1764
1769
  const filePath = path5.join(modulePath, filename);
1765
1770
  if (filename === "index.ts" || filename === "index.tsx" || isAllowedTestFile(filename))
1766
1771
  return;
1772
+ if (filename === `${moduleName}.abstract.md`)
1773
+ return;
1767
1774
  const uiMatch = filename.match(/\.([A-Z][A-Za-z0-9]*)\.tsx$/);
1768
1775
  if (uiMatch) {
1769
1776
  const fileType = uiMatch[1];
@@ -2108,7 +2115,7 @@ class PkgInfo {
2108
2115
  exec;
2109
2116
  name;
2110
2117
  scanResult;
2111
- static async getScanResult(exec) {
2118
+ static async scanExecutor(exec) {
2112
2119
  const [tsconfig, rootPackageJson] = await Promise.all([exec.getTsConfig(), exec.workspace.getPackageJson()]);
2113
2120
  const scanner = await TypeScriptDependencyScanner.from(exec);
2114
2121
  const npmSet = new Set(Object.keys({ ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies }));
@@ -2130,7 +2137,7 @@ class PkgInfo {
2130
2137
  const existingPkgInfo = PkgInfo.#pkgInfos.get(exec.name);
2131
2138
  if (existingPkgInfo && !options.refresh)
2132
2139
  return existingPkgInfo;
2133
- const scanResult = await PkgInfo.getScanResult(exec);
2140
+ const scanResult = await PkgInfo.scanExecutor(exec);
2134
2141
  const pkgInfo = new PkgInfo(exec, scanResult);
2135
2142
  PkgInfo.#pkgInfos.set(exec.name, pkgInfo);
2136
2143
  return pkgInfo;
@@ -4458,6 +4465,240 @@ class AkanAppHost {
4458
4465
  this.#builder = null;
4459
4466
  }
4460
4467
  }
4468
+ // pkgs/@akanjs/devkit/akanContext.ts
4469
+ import { readdir } from "fs/promises";
4470
+ import path10 from "path";
4471
+ import { capitalize as capitalize2 } from "akanjs/common";
4472
+ var generatedFiles = [
4473
+ "cnst.ts",
4474
+ "db.ts",
4475
+ "dict.ts",
4476
+ "option.ts",
4477
+ "sig.ts",
4478
+ "srv.ts",
4479
+ "st.ts",
4480
+ "useClient.ts",
4481
+ "useServer.ts"
4482
+ ];
4483
+ var appRootAllowFiles = new Set([
4484
+ "akan.app.json",
4485
+ "akan.config.ts",
4486
+ "capacitor.config.ts",
4487
+ "client.ts",
4488
+ "main.ts",
4489
+ "package.json",
4490
+ "server.ts",
4491
+ "tsconfig.json"
4492
+ ]);
4493
+ var appRootAllowDirs = new Set([
4494
+ ".akan",
4495
+ "android",
4496
+ "common",
4497
+ "env",
4498
+ "ios",
4499
+ "lib",
4500
+ "page",
4501
+ "private",
4502
+ "public",
4503
+ "script",
4504
+ "srvkit",
4505
+ "ui",
4506
+ "webkit"
4507
+ ]);
4508
+ var safeReadDir = async (dirPath) => {
4509
+ try {
4510
+ return (await readdir(dirPath, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
4511
+ } catch {
4512
+ return [];
4513
+ }
4514
+ };
4515
+ var safeReadText = async (filePath) => {
4516
+ try {
4517
+ return await FileSys.readText(filePath);
4518
+ } catch {
4519
+ return null;
4520
+ }
4521
+ };
4522
+ var safeReadJson = async (filePath) => {
4523
+ try {
4524
+ return await FileSys.readJson(filePath);
4525
+ } catch {
4526
+ return null;
4527
+ }
4528
+ };
4529
+ var parseAbstractSummary = (relativePath, content, includeContent) => {
4530
+ if (content === null)
4531
+ return { path: relativePath, exists: false, headings: [] };
4532
+ const headings = content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.startsWith("#")).map((line) => line.replace(/^#+\s*/, "").trim()).filter(Boolean);
4533
+ return {
4534
+ path: relativePath,
4535
+ exists: true,
4536
+ title: headings[0],
4537
+ headings: headings.slice(0, 8),
4538
+ ...includeContent ? { content } : {}
4539
+ };
4540
+ };
4541
+ var readFiles = async (dirPath) => (await safeReadDir(dirPath)).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
4542
+ var getRelative = (workspace, absolutePath) => path10.relative(workspace.workspaceRoot, absolutePath).replaceAll(path10.sep, "/");
4543
+ var createModuleContext = async (workspace, sys2, kind, folderName, moduleName, includeAbstractContent) => {
4544
+ const modulePath = kind === "scalar" ? path10.join(sys2.cwdPath, "lib", "__scalar", moduleName) : path10.join(sys2.cwdPath, "lib", folderName);
4545
+ const relativePath = getRelative(workspace, modulePath);
4546
+ const abstractPath = `${relativePath}/${moduleName}.abstract.md`;
4547
+ const abstractContent = await safeReadText(path10.join(workspace.workspaceRoot, abstractPath));
4548
+ return {
4549
+ kind,
4550
+ name: moduleName,
4551
+ folderName,
4552
+ sysName: sys2.name,
4553
+ sysType: sys2.type,
4554
+ path: relativePath,
4555
+ abstract: parseAbstractSummary(abstractPath, abstractContent, includeAbstractContent),
4556
+ files: await readFiles(modulePath)
4557
+ };
4558
+ };
4559
+ var getSysModules = async (workspace, sys2, {
4560
+ includeAbstractContent = false,
4561
+ module: moduleFilter
4562
+ } = {}) => {
4563
+ const libPath = path10.join(sys2.cwdPath, "lib");
4564
+ const entries = await safeReadDir(libPath);
4565
+ const modules = [];
4566
+ for (const entry of entries) {
4567
+ if (!entry.isDirectory())
4568
+ continue;
4569
+ if (entry.name === "__scalar")
4570
+ continue;
4571
+ if (entry.name.startsWith("__"))
4572
+ continue;
4573
+ if (entry.name.startsWith("_")) {
4574
+ const serviceName = entry.name.replace(/^_+/, "");
4575
+ if (moduleFilter && moduleFilter !== serviceName && moduleFilter !== entry.name)
4576
+ continue;
4577
+ if (!await FileSys.fileExists(path10.join(libPath, entry.name, `${serviceName}.service.ts`)))
4578
+ continue;
4579
+ modules.push(await createModuleContext(workspace, sys2, "service", entry.name, serviceName, includeAbstractContent));
4580
+ } else {
4581
+ if (moduleFilter && moduleFilter !== entry.name)
4582
+ continue;
4583
+ if (!await FileSys.fileExists(path10.join(libPath, entry.name, `${entry.name}.constant.ts`)))
4584
+ continue;
4585
+ modules.push(await createModuleContext(workspace, sys2, "domain", entry.name, entry.name, includeAbstractContent));
4586
+ }
4587
+ }
4588
+ const scalarRoot = path10.join(libPath, "__scalar");
4589
+ for (const entry of await safeReadDir(scalarRoot)) {
4590
+ if (!entry.isDirectory() || entry.name.startsWith("_"))
4591
+ continue;
4592
+ if (moduleFilter && moduleFilter !== entry.name)
4593
+ continue;
4594
+ if (!await FileSys.fileExists(path10.join(scalarRoot, entry.name, `${entry.name}.constant.ts`)))
4595
+ continue;
4596
+ modules.push(await createModuleContext(workspace, sys2, "scalar", entry.name, entry.name, includeAbstractContent));
4597
+ }
4598
+ return modules.sort((a, b) => `${a.sysName}:${a.path}`.localeCompare(`${b.sysName}:${b.path}`));
4599
+ };
4600
+ var getSysContext = async (workspace, type, name, options) => {
4601
+ const sys2 = type === "app" ? AppExecutor.from(workspace, name) : LibExecutor.from(workspace, name);
4602
+ return {
4603
+ type,
4604
+ name,
4605
+ path: `${type}s/${name}`,
4606
+ hasConfig: await FileSys.fileExists(path10.join(sys2.cwdPath, "akan.config.ts")),
4607
+ modules: await getSysModules(workspace, sys2, {
4608
+ includeAbstractContent: options.includeAbstractContent,
4609
+ module: options.module
4610
+ })
4611
+ };
4612
+ };
4613
+
4614
+ class AkanContextAnalyzer {
4615
+ static async analyze(workspace, options = {}) {
4616
+ const [appNames, libNames, pkgNames] = await workspace.getExecs();
4617
+ const rootPackageJson = await safeReadJson(path10.join(workspace.workspaceRoot, "package.json"));
4618
+ const filteredApps = options.app ? appNames.filter((name) => name === options.app) : appNames;
4619
+ const [apps, libs, pkgs] = await Promise.all([
4620
+ Promise.all(filteredApps.map((name) => getSysContext(workspace, "app", name, options))),
4621
+ Promise.all(libNames.map((name) => getSysContext(workspace, "lib", name, options))),
4622
+ Promise.all(pkgNames.map(async (name) => {
4623
+ const packageJson = await safeReadJson(path10.join(workspace.workspaceRoot, "pkgs", name, "package.json"));
4624
+ return {
4625
+ name,
4626
+ path: `pkgs/${name}`,
4627
+ ...packageJson?.version ? { version: packageJson.version } : {}
4628
+ };
4629
+ }))
4630
+ ]);
4631
+ return {
4632
+ schemaVersion: 1,
4633
+ repoName: workspace.repoName,
4634
+ root: workspace.workspaceRoot,
4635
+ packageVersion: rootPackageJson?.dependencies?.akanjs ?? rootPackageJson?.devDependencies?.["@akanjs/devkit"],
4636
+ apps,
4637
+ libs,
4638
+ pkgs,
4639
+ generatedFiles,
4640
+ validationCommands: ["akan lint <app-or-lib-or-pkg>", "akan build <app-name>", "akan start <app-name>"]
4641
+ };
4642
+ }
4643
+ static async doctor(workspace, { strict = false } = {}) {
4644
+ const context = await AkanContextAnalyzer.analyze(workspace);
4645
+ const diagnostics = [];
4646
+ for (const app of context.apps) {
4647
+ const appPath = path10.join(workspace.workspaceRoot, app.path);
4648
+ for (const entry of await safeReadDir(appPath)) {
4649
+ const allowed = entry.isDirectory() ? appRootAllowDirs.has(entry.name) : appRootAllowFiles.has(entry.name);
4650
+ if (!allowed) {
4651
+ diagnostics.push({
4652
+ severity: "warning",
4653
+ code: "app-root-unknown-entry",
4654
+ path: `${app.path}/${entry.name}`,
4655
+ message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in app root: ${app.path}/${entry.name}`
4656
+ });
4657
+ }
4658
+ }
4659
+ }
4660
+ for (const sys2 of [...context.apps, ...context.libs]) {
4661
+ for (const module of sys2.modules) {
4662
+ if (!module.abstract.exists) {
4663
+ diagnostics.push({
4664
+ severity: strict ? "error" : "warning",
4665
+ code: "module-abstract-missing",
4666
+ path: module.abstract.path,
4667
+ message: `${capitalize2(module.kind)} module ${sys2.name}:${module.name} should include ${module.abstract.path}`
4668
+ });
4669
+ }
4670
+ }
4671
+ }
4672
+ return { schemaVersion: 1, strict, diagnostics };
4673
+ }
4674
+ static findModules(context, moduleName) {
4675
+ const modules = [...context.apps, ...context.libs].flatMap((sys2) => sys2.modules);
4676
+ return moduleName ? modules.filter((module) => module.name === moduleName || module.folderName === moduleName) : modules;
4677
+ }
4678
+ static renderMarkdown(context, { module: moduleName } = {}) {
4679
+ const lines = [`# Akan Workspace Context`, "", `- Repo: ${context.repoName}`, `- Root: ${context.root}`];
4680
+ if (context.packageVersion)
4681
+ lines.push(`- Akan version: ${context.packageVersion}`);
4682
+ lines.push("", "## Apps", ...context.apps.map((app) => `- ${app.name}: ${app.modules.length} module(s)`));
4683
+ lines.push("", "## Libraries", ...context.libs.map((lib) => `- ${lib.name}: ${lib.modules.length} module(s)`));
4684
+ lines.push("", "## Packages", ...context.pkgs.map((pkg) => `- ${pkg.name}${pkg.version ? ` (${pkg.version})` : ""}`));
4685
+ const modules = AkanContextAnalyzer.findModules(context, moduleName);
4686
+ lines.push("", "## Modules");
4687
+ for (const module of modules) {
4688
+ lines.push("", `### ${module.sysName}:${module.name} (${module.kind})`, `- Path: ${module.path}`);
4689
+ lines.push(`- Abstract: ${module.abstract.exists ? module.abstract.path : "missing"}`);
4690
+ if (module.abstract.exists && module.abstract.content)
4691
+ lines.push("", module.abstract.content.trim(), "");
4692
+ else if (module.abstract.headings.length)
4693
+ lines.push(`- Abstract headings: ${module.abstract.headings.join(", ")}`);
4694
+ lines.push(`- Files: ${module.files.join(", ") || "none"}`);
4695
+ }
4696
+ lines.push("", "## Validation", ...context.validationCommands.map((command) => `- \`${command}\``));
4697
+ return `${lines.join(`
4698
+ `)}
4699
+ `;
4700
+ }
4701
+ }
4461
4702
  // pkgs/@akanjs/devkit/applicationBuildReporter.ts
4462
4703
  import { Logger as Logger6 } from "akanjs/common";
4463
4704
 
@@ -4504,20 +4745,20 @@ Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
4504
4745
  }
4505
4746
  // pkgs/@akanjs/devkit/applicationBuildRunner.ts
4506
4747
  import { mkdir as mkdir7, rm as rm2 } from "fs/promises";
4507
- import path32 from "path";
4748
+ import path33 from "path";
4508
4749
 
4509
4750
  // pkgs/@akanjs/devkit/frontendBuild/allRoutesBuilder.ts
4510
- import path19 from "path";
4751
+ import path20 from "path";
4511
4752
 
4512
4753
  // pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
4513
4754
  import { mkdir as mkdir3 } from "fs/promises";
4514
- import path10 from "path";
4755
+ import path11 from "path";
4515
4756
  var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
4516
4757
  async function appHasStModule(appCwdPath) {
4517
- return Bun.file(path10.join(appCwdPath, "lib", "st.ts")).exists();
4758
+ return Bun.file(path11.join(appCwdPath, "lib", "st.ts")).exists();
4518
4759
  }
4519
- var IMPLICIT_LAYOUT_DIR = path10.join(".akan", "generated", "root-layouts");
4520
- var IMPLICIT_DICT_DIR = path10.join(".akan", "generated", "dict");
4760
+ var IMPLICIT_LAYOUT_DIR = path11.join(".akan", "generated", "root-layouts");
4761
+ var IMPLICIT_DICT_DIR = path11.join(".akan", "generated", "dict");
4521
4762
  function getRootBoundarySegments(key) {
4522
4763
  const match = LAYOUT_KEY_RE.exec(key);
4523
4764
  if (!match)
@@ -4532,10 +4773,10 @@ function implicitRootLayoutKey(segments) {
4532
4773
  }
4533
4774
  function implicitRootLayoutAbsPath(appCwdPath, segments) {
4534
4775
  const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
4535
- return path10.join(path10.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
4776
+ return path11.join(path11.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
4536
4777
  }
4537
4778
  function implicitDictionaryMacroAbsPath(appCwdPath) {
4538
- return path10.join(path10.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
4779
+ return path11.join(path11.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
4539
4780
  }
4540
4781
  function isRootBoundarySegments(segments, basePaths) {
4541
4782
  const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
@@ -4558,7 +4799,7 @@ function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
4558
4799
  const id = segments.join("/");
4559
4800
  boundaries.set(id, {
4560
4801
  sourceKey: key,
4561
- sourceAbsPath: path10.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
4802
+ sourceAbsPath: path11.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
4562
4803
  segments
4563
4804
  });
4564
4805
  }
@@ -4576,21 +4817,21 @@ function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
4576
4817
  const segments = getRootBoundarySegments(key);
4577
4818
  return segments !== null && segments.length === 0;
4578
4819
  });
4579
- return rootLayoutKey ? path10.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
4820
+ return rootLayoutKey ? path11.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
4580
4821
  }
4581
4822
  function routePrefixForSegments(segments) {
4582
4823
  const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
4583
4824
  return visible[0] ?? null;
4584
4825
  }
4585
4826
  async function assertEnvClientConvention(appCwdPath, appName) {
4586
- const envPath = path10.join(appCwdPath, "env", "env.client.ts");
4827
+ const envPath = path11.join(appCwdPath, "env", "env.client.ts");
4587
4828
  if (!await Bun.file(envPath).exists()) {
4588
4829
  throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
4589
4830
  }
4590
4831
  }
4591
4832
  async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
4592
4833
  const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
4593
- await mkdir3(path10.dirname(absPath), { recursive: true });
4834
+ await mkdir3(path11.dirname(absPath), { recursive: true });
4594
4835
  await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
4595
4836
 
4596
4837
  export const allDictionary = getAllDictionary();
@@ -4601,13 +4842,13 @@ async function writeGeneratedRootLayoutFile(opts) {
4601
4842
  await assertEnvClientConvention(opts.appCwdPath, opts.appName);
4602
4843
  const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
4603
4844
  const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
4604
- await mkdir3(path10.dirname(absPath), { recursive: true });
4605
- const dictMacroRel = dictMacroAbsPath ? path10.relative(path10.dirname(absPath), dictMacroAbsPath).split(path10.sep).join("/") : null;
4845
+ await mkdir3(path11.dirname(absPath), { recursive: true });
4846
+ const dictMacroRel = dictMacroAbsPath ? path11.relative(path11.dirname(absPath), dictMacroAbsPath).split(path11.sep).join("/") : null;
4606
4847
  const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
4607
- const sourceRel = opts.boundary.sourceAbsPath ? path10.relative(path10.dirname(absPath), opts.boundary.sourceAbsPath).split(path10.sep).join("/") : null;
4848
+ const sourceRel = opts.boundary.sourceAbsPath ? path11.relative(path11.dirname(absPath), opts.boundary.sourceAbsPath).split(path11.sep).join("/") : null;
4608
4849
  const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
4609
4850
  const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
4610
- const inheritedSourceRel = inheritedSourceAbsPath ? path10.relative(path10.dirname(absPath), inheritedSourceAbsPath).split(path10.sep).join("/") : null;
4851
+ const inheritedSourceRel = inheritedSourceAbsPath ? path11.relative(path11.dirname(absPath), inheritedSourceAbsPath).split(path11.sep).join("/") : null;
4611
4852
  const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
4612
4853
  const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
4613
4854
  void st;
@@ -4685,7 +4926,7 @@ export default function GeneratedLayout({ children, params, searchParams }: Layo
4685
4926
  return absPath;
4686
4927
  }
4687
4928
  async function resolveSsrPageEntries(opts) {
4688
- const absPageDir = path10.resolve(opts.appCwdPath, "page");
4929
+ const absPageDir = path11.resolve(opts.appCwdPath, "page");
4689
4930
  const hasSt = await appHasStModule(opts.appCwdPath);
4690
4931
  const basePaths = opts.basePaths ?? [];
4691
4932
  const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
@@ -4696,7 +4937,7 @@ async function resolveSsrPageEntries(opts) {
4696
4937
  }));
4697
4938
  const base = opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map((key) => ({
4698
4939
  key,
4699
- moduleAbsPath: path10.resolve(absPageDir, key)
4940
+ moduleAbsPath: path11.resolve(absPageDir, key)
4700
4941
  }));
4701
4942
  const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
4702
4943
  key: implicitRootLayoutKey(boundary.segments),
@@ -4720,14 +4961,14 @@ async function resolveSsrPageEntriesForApp(app, pageKeys) {
4720
4961
  }
4721
4962
 
4722
4963
  // pkgs/@akanjs/devkit/artifact/routeSeedIndex.ts
4723
- import path11 from "path";
4964
+ import path12 from "path";
4724
4965
  import { assertUniqueRoutePatterns, compareRouteSpecificity, parseRouteModuleKey as parseRouteModuleKey2 } from "akanjs/common";
4725
4966
  function computeRouteSeedIndex(pageEntries) {
4726
4967
  const layoutsByPrefix = new Map;
4727
4968
  const pagesBySegments = [];
4728
4969
  for (const { key, moduleAbsPath, seedAbsPaths } of pageEntries) {
4729
4970
  const parsed = parseRouteModuleKey2(key);
4730
- const files = [path11.resolve(moduleAbsPath), ...(seedAbsPaths ?? []).map((seed) => path11.resolve(seed))];
4971
+ const files = [path12.resolve(moduleAbsPath), ...(seedAbsPaths ?? []).map((seed) => path12.resolve(seed))];
4731
4972
  if (parsed.kind === "layout") {
4732
4973
  const prefix = parsed.routeSegments.join("/");
4733
4974
  const prev = layoutsByPrefix.get(prefix) ?? [];
@@ -4764,7 +5005,7 @@ function computeRouteSeedIndex(pageEntries) {
4764
5005
  }
4765
5006
  var ROUTE_SEED_INDEX_JSON = "route-seed-index.json";
4766
5007
  function serializeRouteSeedIndexForArtifact(index, artifactDir, options = {}) {
4767
- const normalizedArtifactDir = path11.resolve(artifactDir);
5008
+ const normalizedArtifactDir = path12.resolve(artifactDir);
4768
5009
  if (options.production) {
4769
5010
  return {
4770
5011
  entries: index.entries.map((entry) => ({ routeId: entry.routeId }))
@@ -4779,22 +5020,22 @@ function serializeRouteSeedIndexForArtifact(index, artifactDir, options = {}) {
4779
5020
  };
4780
5021
  }
4781
5022
  async function saveRouteSeedIndex(artifactDir, index, options = {}) {
4782
- const absPath = path11.join(path11.resolve(artifactDir), ROUTE_SEED_INDEX_JSON);
5023
+ const absPath = path12.join(path12.resolve(artifactDir), ROUTE_SEED_INDEX_JSON);
4783
5024
  await Bun.write(absPath, `${JSON.stringify(serializeRouteSeedIndexForArtifact(index, artifactDir, options), null, 2)}
4784
5025
  `);
4785
5026
  return absPath;
4786
5027
  }
4787
5028
  function serializeArtifactPath(artifactPath, artifactDir) {
4788
- if (!path11.isAbsolute(artifactPath))
5029
+ if (!path12.isAbsolute(artifactPath))
4789
5030
  return artifactPath;
4790
- return path11.relative(artifactDir, artifactPath).split(path11.sep).join("/");
5031
+ return path12.relative(artifactDir, artifactPath).split(path12.sep).join("/");
4791
5032
  }
4792
5033
 
4793
5034
  // pkgs/@akanjs/devkit/frontendBuild/clientEntryDiscovery.ts
4794
- import path14 from "path";
5035
+ import path15 from "path";
4795
5036
 
4796
5037
  // pkgs/@akanjs/devkit/transforms/barrelAnalyzer.ts
4797
- import path12 from "path";
5038
+ import path13 from "path";
4798
5039
  import { Logger as Logger7 } from "akanjs/common";
4799
5040
  var REEXPORT_RE = /(?:^|\n)\s*export\s+(?:type\s+)?(?:(\*)(?:\s+as\s+(\w+))?|\{\s*([^}]*?)\s*\})\s+from\s+(["'])([^"']+)\4;?/g;
4800
5041
  var LOCAL_NAMED_RE = /(?:^|\n)\s*export\s+\{\s*([^}]*?)\s*\}(?!\s*from)/g;
@@ -4917,7 +5158,7 @@ class BarrelAnalyzer {
4917
5158
  }
4918
5159
  #scanExports(source, absFile) {
4919
5160
  try {
4920
- const transpiler = [".tsx", ".jsx"].includes(path12.extname(absFile)) ? this.#tsxTranspiler : this.#tsTranspiler;
5161
+ const transpiler = [".tsx", ".jsx"].includes(path13.extname(absFile)) ? this.#tsxTranspiler : this.#tsTranspiler;
4921
5162
  const { exports } = transpiler.scan(source);
4922
5163
  return new Set(exports);
4923
5164
  } catch (err) {
@@ -4926,16 +5167,16 @@ class BarrelAnalyzer {
4926
5167
  }
4927
5168
  }
4928
5169
  #subpathFor(pkg, absFile) {
4929
- const rel = path12.relative(pkg.pkgDir, absFile);
4930
- if (!rel || rel.startsWith("..") || path12.isAbsolute(rel))
5170
+ const rel = path13.relative(pkg.pkgDir, absFile);
5171
+ if (!rel || rel.startsWith("..") || path13.isAbsolute(rel))
4931
5172
  return null;
4932
5173
  if (pkg.preserveFilePath)
4933
- return `${pkg.pkgName}/${rel.split(path12.sep).join("/")}`;
5174
+ return `${pkg.pkgName}/${rel.split(path13.sep).join("/")}`;
4934
5175
  const noExt = stripKnownExt(rel);
4935
5176
  const tail = collapseIndex(noExt);
4936
5177
  if (tail === "")
4937
5178
  return pkg.pkgName;
4938
- return `${pkg.pkgName}/${tail.split(path12.sep).join("/")}`;
5179
+ return `${pkg.pkgName}/${tail.split(path13.sep).join("/")}`;
4939
5180
  }
4940
5181
  async#resolveRel(fromFile, relSpec) {
4941
5182
  if (this.#opts.resolveRelative)
@@ -4976,9 +5217,9 @@ var readIfExists = async (absFile) => {
4976
5217
  return file.text();
4977
5218
  };
4978
5219
  var defaultResolveRelative = async (fromFile, relSpec) => {
4979
- const baseDir = path12.dirname(fromFile);
4980
- const joined = path12.resolve(baseDir, relSpec);
4981
- if (path12.extname(joined)) {
5220
+ const baseDir = path13.dirname(fromFile);
5221
+ const joined = path13.resolve(baseDir, relSpec);
5222
+ if (path13.extname(joined)) {
4982
5223
  if (await Bun.file(joined).exists())
4983
5224
  return joined;
4984
5225
  return null;
@@ -4989,7 +5230,7 @@ var defaultResolveRelative = async (fromFile, relSpec) => {
4989
5230
  return cand;
4990
5231
  }
4991
5232
  for (const ext of CANDIDATE_EXTS) {
4992
- const cand = path12.join(joined, `index${ext}`);
5233
+ const cand = path13.join(joined, `index${ext}`);
4993
5234
  if (await Bun.file(cand).exists())
4994
5235
  return cand;
4995
5236
  }
@@ -5003,14 +5244,14 @@ var stripKnownExt = (relPath) => {
5003
5244
  return relPath;
5004
5245
  };
5005
5246
  var collapseIndex = (relPathNoExt) => {
5006
- const parts = relPathNoExt.split(path12.sep);
5247
+ const parts = relPathNoExt.split(path13.sep);
5007
5248
  if (parts[parts.length - 1] === "index")
5008
5249
  parts.pop();
5009
- return parts.join(path12.sep);
5250
+ return parts.join(path13.sep);
5010
5251
  };
5011
5252
 
5012
5253
  // pkgs/@akanjs/devkit/transforms/barrelImportsPlugin.ts
5013
- import path13 from "path";
5254
+ import path14 from "path";
5014
5255
  import ts4 from "typescript";
5015
5256
  var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAfter } = {}) => {
5016
5257
  const akanConfig2 = await app.getConfig();
@@ -5069,10 +5310,10 @@ var createTsconfigPackageResolver = async (app) => {
5069
5310
  const raw = exact[0];
5070
5311
  if (!raw)
5071
5312
  return null;
5072
- const entryFile = path13.resolve(app.workspace.workspaceRoot, raw);
5313
+ const entryFile = path14.resolve(app.workspace.workspaceRoot, raw);
5073
5314
  if (!await Bun.file(entryFile).exists())
5074
5315
  return null;
5075
- const parsed = path13.parse(entryFile);
5316
+ const parsed = path14.parse(entryFile);
5076
5317
  const lastSlash = pkgName.lastIndexOf("/");
5077
5318
  if (parsed.name !== "index" && lastSlash !== -1) {
5078
5319
  const facet = pkgName.slice(lastSlash + 1);
@@ -5081,7 +5322,7 @@ var createTsconfigPackageResolver = async (app) => {
5081
5322
  return { pkgName: parentSpec, entryFile, pkgDir: parsed.dir };
5082
5323
  }
5083
5324
  }
5084
- return { pkgName, entryFile, pkgDir: path13.dirname(entryFile) };
5325
+ return { pkgName, entryFile, pkgDir: path14.dirname(entryFile) };
5085
5326
  }
5086
5327
  for (const { prefix, replacements } of wildcardEntries) {
5087
5328
  if (!pkgName.startsWith(prefix))
@@ -5091,7 +5332,7 @@ var createTsconfigPackageResolver = async (app) => {
5091
5332
  if (!repl)
5092
5333
  continue;
5093
5334
  const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
5094
- const candidate = path13.resolve(app.workspace.workspaceRoot, replPath + suffix);
5335
+ const candidate = path14.resolve(app.workspace.workspaceRoot, replPath + suffix);
5095
5336
  for (const ext of CANDIDATE_EXTS2) {
5096
5337
  const file = `${candidate}${ext}`;
5097
5338
  if (await Bun.file(file).exists()) {
@@ -5099,14 +5340,14 @@ var createTsconfigPackageResolver = async (app) => {
5099
5340
  if (lastSlash !== -1) {
5100
5341
  const parentSpec = pkgName.slice(0, lastSlash);
5101
5342
  if (parentSpec.length > 0) {
5102
- return { pkgName: parentSpec, entryFile: file, pkgDir: path13.dirname(file) };
5343
+ return { pkgName: parentSpec, entryFile: file, pkgDir: path14.dirname(file) };
5103
5344
  }
5104
5345
  }
5105
- return { pkgName, entryFile: file, pkgDir: path13.dirname(file) };
5346
+ return { pkgName, entryFile: file, pkgDir: path14.dirname(file) };
5106
5347
  }
5107
5348
  }
5108
5349
  for (const ext of CANDIDATE_EXTS2) {
5109
- const file = path13.join(candidate, `index${ext}`);
5350
+ const file = path14.join(candidate, `index${ext}`);
5110
5351
  if (await Bun.file(file).exists()) {
5111
5352
  return { pkgName, entryFile: file, pkgDir: candidate };
5112
5353
  }
@@ -5117,16 +5358,16 @@ var createTsconfigPackageResolver = async (app) => {
5117
5358
  const exported = await resolveNodePackageExport(app.workspace.workspaceRoot, pkgName);
5118
5359
  if (exported)
5119
5360
  return exported;
5120
- const pkgJsonPath = path13.join(app.workspace.workspaceRoot, "node_modules", pkgName, "package.json");
5361
+ const pkgJsonPath = path14.join(app.workspace.workspaceRoot, "node_modules", pkgName, "package.json");
5121
5362
  if (!await Bun.file(pkgJsonPath).exists())
5122
5363
  return null;
5123
5364
  try {
5124
5365
  const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text());
5125
5366
  const rel = pkgJson.module ?? pkgJson.main ?? "index.js";
5126
- const entryFile = path13.resolve(path13.dirname(pkgJsonPath), rel);
5367
+ const entryFile = path14.resolve(path14.dirname(pkgJsonPath), rel);
5127
5368
  if (!await Bun.file(entryFile).exists())
5128
5369
  return null;
5129
- return { pkgName, entryFile, pkgDir: path13.dirname(pkgJsonPath) };
5370
+ return { pkgName, entryFile, pkgDir: path14.dirname(pkgJsonPath) };
5130
5371
  } catch {
5131
5372
  return null;
5132
5373
  }
@@ -5140,22 +5381,22 @@ var resolveNodePackageExport = async (workspaceRoot, specifier) => {
5140
5381
  const packageName = getPackageName(specifier);
5141
5382
  if (!packageName)
5142
5383
  return null;
5143
- const pkgJsonPath = path13.join(workspaceRoot, "node_modules", packageName, "package.json");
5384
+ const pkgJsonPath = path14.join(workspaceRoot, "node_modules", packageName, "package.json");
5144
5385
  if (!await Bun.file(pkgJsonPath).exists())
5145
5386
  return null;
5146
5387
  try {
5147
- const pkgDir = path13.dirname(pkgJsonPath);
5388
+ const pkgDir = path14.dirname(pkgJsonPath);
5148
5389
  const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text());
5149
5390
  const subpath = specifier === packageName ? "." : `.${specifier.slice(packageName.length)}`;
5150
5391
  const exported = resolvePackageExport(pkgJson.exports, subpath);
5151
5392
  const rel = exported ?? (subpath === "." ? pkgJson.module ?? pkgJson.main ?? "index.js" : null);
5152
5393
  if (!rel || !rel.startsWith("."))
5153
5394
  return null;
5154
- const entryFile = await resolveFileCandidate(path13.resolve(pkgDir, rel));
5395
+ const entryFile = await resolveFileCandidate(path14.resolve(pkgDir, rel));
5155
5396
  if (!entryFile)
5156
5397
  return null;
5157
5398
  const pkgEntryName = specifier;
5158
- return { pkgName: pkgEntryName, entryFile, pkgDir: path13.dirname(entryFile), preserveFilePath: true };
5399
+ return { pkgName: pkgEntryName, entryFile, pkgDir: path14.dirname(entryFile), preserveFilePath: true };
5159
5400
  } catch {
5160
5401
  return null;
5161
5402
  }
@@ -5212,7 +5453,7 @@ var getPackageName = (specifier) => {
5212
5453
  var resolveFileCandidate = async (candidate) => {
5213
5454
  if (await Bun.file(candidate).exists())
5214
5455
  return candidate;
5215
- if (path13.extname(candidate))
5456
+ if (path14.extname(candidate))
5216
5457
  return null;
5217
5458
  for (const ext of CANDIDATE_EXTS2) {
5218
5459
  const file = `${candidate}${ext}`;
@@ -5220,7 +5461,7 @@ var resolveFileCandidate = async (candidate) => {
5220
5461
  return file;
5221
5462
  }
5222
5463
  for (const ext of CANDIDATE_EXTS2) {
5223
- const file = path13.join(candidate, `index${ext}`);
5464
+ const file = path14.join(candidate, `index${ext}`);
5224
5465
  if (await Bun.file(file).exists())
5225
5466
  return file;
5226
5467
  }
@@ -5434,7 +5675,7 @@ class GraphClientEntryDiscovery {
5434
5675
  }
5435
5676
  invalidate(files) {
5436
5677
  for (const file of files) {
5437
- const absPath = path14.resolve(file);
5678
+ const absPath = path15.resolve(file);
5438
5679
  this.#readCache.delete(absPath);
5439
5680
  this.#rewriteCache.delete(absPath);
5440
5681
  this.#importCache.delete(absPath);
@@ -5444,7 +5685,7 @@ class GraphClientEntryDiscovery {
5444
5685
  this.#reachableEntriesCache.clear();
5445
5686
  }
5446
5687
  async#fileExists(p) {
5447
- const absPath = path14.resolve(p);
5688
+ const absPath = path15.resolve(p);
5448
5689
  let cached = this.#fileExistsCache.get(absPath);
5449
5690
  if (!cached) {
5450
5691
  cached = Bun.file(absPath).exists();
@@ -5453,7 +5694,7 @@ class GraphClientEntryDiscovery {
5453
5694
  return cached;
5454
5695
  }
5455
5696
  #readFile(file) {
5456
- const absPath = path14.resolve(file);
5697
+ const absPath = path15.resolve(file);
5457
5698
  let cached = this.#readCache.get(absPath);
5458
5699
  if (!cached) {
5459
5700
  cached = Bun.file(absPath).text().catch(() => null);
@@ -5462,7 +5703,7 @@ class GraphClientEntryDiscovery {
5462
5703
  return cached;
5463
5704
  }
5464
5705
  async#resolveFileCandidate(absPathNoExt) {
5465
- const cacheKey = path14.resolve(absPathNoExt);
5706
+ const cacheKey = path15.resolve(absPathNoExt);
5466
5707
  let cached = this.#resolvedFileCache.get(cacheKey);
5467
5708
  if (cached)
5468
5709
  return cached;
@@ -5475,7 +5716,7 @@ class GraphClientEntryDiscovery {
5475
5716
  return f;
5476
5717
  }
5477
5718
  for (const ext of SOURCE_EXTS2) {
5478
- const f = path14.join(cacheKey, `index${ext}`);
5719
+ const f = path15.join(cacheKey, `index${ext}`);
5479
5720
  if (await this.#fileExists(f))
5480
5721
  return f;
5481
5722
  }
@@ -5491,7 +5732,7 @@ class GraphClientEntryDiscovery {
5491
5732
  return cached;
5492
5733
  cached = (async () => {
5493
5734
  if (spec.startsWith(".") || spec.startsWith("/")) {
5494
- const abs = spec.startsWith("/") ? spec : path14.resolve(importerDir, spec);
5735
+ const abs = spec.startsWith("/") ? spec : path15.resolve(importerDir, spec);
5495
5736
  return this.#resolveFileCandidate(abs);
5496
5737
  }
5497
5738
  const pkg = await this.#resolvePackage(spec);
@@ -5503,7 +5744,7 @@ class GraphClientEntryDiscovery {
5503
5744
  return cached;
5504
5745
  }
5505
5746
  async#getRewrittenSource(file, content) {
5506
- const absPath = path14.resolve(file);
5747
+ const absPath = path15.resolve(file);
5507
5748
  let cached = this.#rewriteCache.get(absPath);
5508
5749
  if (!cached) {
5509
5750
  cached = (async () => {
@@ -5520,7 +5761,7 @@ class GraphClientEntryDiscovery {
5520
5761
  return cached;
5521
5762
  }
5522
5763
  async#getImports(file, source) {
5523
- const absPath = path14.resolve(file);
5764
+ const absPath = path15.resolve(file);
5524
5765
  let cached = this.#importCache.get(absPath);
5525
5766
  if (!cached) {
5526
5767
  cached = Promise.resolve().then(() => {
@@ -5535,7 +5776,7 @@ class GraphClientEntryDiscovery {
5535
5776
  return cached;
5536
5777
  }
5537
5778
  async#discoverFromFile(file, visiting) {
5538
- const absPath = path14.resolve(file);
5779
+ const absPath = path15.resolve(file);
5539
5780
  const cached = this.#reachableEntriesCache.get(absPath);
5540
5781
  if (cached)
5541
5782
  return new Set(cached);
@@ -5552,7 +5793,7 @@ class GraphClientEntryDiscovery {
5552
5793
  }
5553
5794
  const source = await this.#getRewrittenSource(absPath, content);
5554
5795
  const imports = await this.#getImports(absPath, source);
5555
- const importerDir = path14.dirname(absPath);
5796
+ const importerDir = path15.dirname(absPath);
5556
5797
  for (const imp of imports) {
5557
5798
  const spec = imp.path;
5558
5799
  if (!spec)
@@ -5578,14 +5819,14 @@ class GraphClientEntryDiscovery {
5578
5819
 
5579
5820
  // pkgs/@akanjs/devkit/frontendBuild/routeClientBuilder.ts
5580
5821
  import { mkdir as mkdir4 } from "fs/promises";
5581
- import path17 from "path";
5822
+ import path18 from "path";
5582
5823
 
5583
5824
  // pkgs/@akanjs/devkit/transforms/rscUseClientTransform.ts
5584
- import path15 from "path";
5825
+ import path16 from "path";
5585
5826
  var USE_CLIENT_RE2 = /^\s*(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*["']use client["']/;
5586
5827
  var IMPLICIT_ROOT_LAYOUT_RE = /[/\\]\.akan[/\\]generated[/\\](?:implicit-root-layout|root-layouts[/\\].*__root_layout)\.(tsx|ts|jsx|js)$/;
5587
5828
  function toClientReferencePath(absPath, workspaceRoot) {
5588
- return path15.relative(path15.resolve(workspaceRoot), path15.resolve(absPath)).split(path15.sep).join("/");
5829
+ return path16.relative(path16.resolve(workspaceRoot), path16.resolve(absPath)).split(path16.sep).join("/");
5589
5830
  }
5590
5831
  function transformUseClient(source, args) {
5591
5832
  if (!USE_CLIENT_RE2.test(source))
@@ -5621,7 +5862,7 @@ function loaderFor2(absPath) {
5621
5862
 
5622
5863
  // pkgs/@akanjs/devkit/frontendBuild/clientEntriesBundler.ts
5623
5864
  import fs2 from "fs";
5624
- import path16 from "path";
5865
+ import path17 from "path";
5625
5866
 
5626
5867
  // pkgs/@akanjs/devkit/frontendBuild/clientBuildTypes.ts
5627
5868
  var CLIENT_BUNDLE_NAMING = {
@@ -5710,23 +5951,23 @@ class ClientEntriesBundler {
5710
5951
  };
5711
5952
  }
5712
5953
  async#createOpaqueEntryAliases() {
5713
- const aliasDir = path16.join(this.#app.cwdPath, ".akan", "generated", "client-entry-alias", this.#outputSubdir);
5954
+ const aliasDir = path17.join(this.#app.cwdPath, ".akan", "generated", "client-entry-alias", this.#outputSubdir);
5714
5955
  fs2.mkdirSync(aliasDir, { recursive: true });
5715
5956
  const originalByAlias = new Map;
5716
5957
  const aliasedEntries = await Promise.all(this.#entries.map(async (entry) => {
5717
- const absEntry = path16.resolve(entry);
5958
+ const absEntry = path17.resolve(entry);
5718
5959
  const hash = Bun.hash(`${this.#app.name}
5719
5960
  ${this.#outputSubdir}
5720
5961
  ${absEntry}`).toString(36);
5721
- const aliasPath = path16.join(aliasDir, `${hash}.tsx`);
5962
+ const aliasPath = path17.join(aliasDir, `${hash}.tsx`);
5722
5963
  await Bun.write(aliasPath, this.#createOpaqueEntryAliasSource(absEntry, await this.#scanEntryExportNames(absEntry)));
5723
- originalByAlias.set(path16.resolve(aliasPath), absEntry);
5964
+ originalByAlias.set(path17.resolve(aliasPath), absEntry);
5724
5965
  return aliasPath;
5725
5966
  }));
5726
5967
  return { entries: aliasedEntries, originalByAlias, aliasDir };
5727
5968
  }
5728
5969
  #createOpaqueEntryAliasSource(absEntry, exportNames) {
5729
- const entryLit = JSON.stringify(path16.resolve(absEntry));
5970
+ const entryLit = JSON.stringify(path17.resolve(absEntry));
5730
5971
  if (exportNames.length === 0)
5731
5972
  return `export * from ${entryLit};
5732
5973
  `;
@@ -5809,16 +6050,16 @@ ${absEntry}`).toString(36);
5809
6050
  return rewritten;
5810
6051
  }
5811
6052
  #toServeUrl(absOutPath) {
5812
- const rel = path16.relative(this.#outdir, absOutPath).split(path16.sep).join("/");
6053
+ const rel = path17.relative(this.#outdir, absOutPath).split(path17.sep).join("/");
5813
6054
  return `${this.#servePrefix}/${rel}`;
5814
6055
  }
5815
6056
  #absFromOutdir(p) {
5816
- return path16.isAbsolute(p) ? p : path16.resolve(this.#outdir, p);
6057
+ return path17.isAbsolute(p) ? p : path17.resolve(this.#outdir, p);
5817
6058
  }
5818
6059
  #absFromEntryPoint(p) {
5819
- if (path16.isAbsolute(p))
5820
- return path16.resolve(p);
5821
- const candidates = [path16.resolve(process.cwd(), p), path16.resolve(this.#app.cwdPath, p)];
6060
+ if (path17.isAbsolute(p))
6061
+ return path17.resolve(p);
6062
+ const candidates = [path17.resolve(process.cwd(), p), path17.resolve(this.#app.cwdPath, p)];
5822
6063
  return candidates.find((candidate) => fs2.existsSync(candidate)) ?? candidates[0];
5823
6064
  }
5824
6065
  #collectChunkUrls(absOutPath, visited = new Set) {
@@ -5968,13 +6209,13 @@ class RouteClientBuilder {
5968
6209
  ssrModuleMap[row.id][row.name] = { id: ssrOutput, chunks: [ssrOutput, ssrOutput], name: row.name, async: true };
5969
6210
  }
5970
6211
  for (const entry of bootstrapEntries.buildEntries) {
5971
- const buildEntry = path17.resolve(entry);
5972
- const originalEntry = path17.resolve(bootstrapEntries.originalByBuildEntry.get(buildEntry) ?? buildEntry);
6212
+ const buildEntry = path18.resolve(entry);
6213
+ const originalEntry = path18.resolve(bootstrapEntries.originalByBuildEntry.get(buildEntry) ?? buildEntry);
5973
6214
  if (!acceptedEntries.has(originalEntry))
5974
6215
  continue;
5975
6216
  const deps = new Set([originalEntry]);
5976
6217
  for (const dep of browserBundle.entryDepsByAbsPath.get(buildEntry) ?? [])
5977
- deps.add(path17.resolve(dep));
6218
+ deps.add(path18.resolve(dep));
5978
6219
  const sortedDeps = [...deps].sort();
5979
6220
  clientDepsByEntry[originalEntry] = sortedDeps;
5980
6221
  for (const dep of sortedDeps)
@@ -6026,25 +6267,25 @@ class RouteClientBuilder {
6026
6267
  }).bundle();
6027
6268
  }
6028
6269
  async#createBootstrapEntries(entries) {
6029
- if (!await Bun.file(path17.join(this.#app.cwdPath, "lib", "st.ts")).exists()) {
6270
+ if (!await Bun.file(path18.join(this.#app.cwdPath, "lib", "st.ts")).exists()) {
6030
6271
  return { buildEntries: entries, originalByBuildEntry: new Map };
6031
6272
  }
6032
- const outdir = path17.join(this.#app.cwdPath, ".akan", "generated", "client-entry-bootstrap");
6273
+ const outdir = path18.join(this.#app.cwdPath, ".akan", "generated", "client-entry-bootstrap");
6033
6274
  await mkdir4(outdir, { recursive: true });
6034
6275
  const originalByBuildEntry = new Map;
6035
6276
  const buildEntries = await Promise.all(entries.map(async (entry) => {
6036
- const absEntry = path17.resolve(entry);
6277
+ const absEntry = path18.resolve(entry);
6037
6278
  const hash = Bun.hash(`${this.#app.name}
6038
6279
  ${absEntry}`).toString(36);
6039
- const base = path17.basename(absEntry).replace(/[^A-Za-z0-9._-]/g, "_");
6040
- const wrapperEntry = path17.join(outdir, `${base}-${hash}.tsx`);
6280
+ const base = path18.basename(absEntry).replace(/[^A-Za-z0-9._-]/g, "_");
6281
+ const wrapperEntry = path18.join(outdir, `${base}-${hash}.tsx`);
6041
6282
  const exportNames = await this.#scanExportNames(absEntry);
6042
6283
  await Bun.write(wrapperEntry, RouteClientBuilder.createStoreBootstrapEntrySource({
6043
6284
  appName: this.#app.name,
6044
6285
  originalEntry: absEntry,
6045
6286
  exportNames
6046
6287
  }));
6047
- originalByBuildEntry.set(path17.resolve(wrapperEntry), absEntry);
6288
+ originalByBuildEntry.set(path18.resolve(wrapperEntry), absEntry);
6048
6289
  return wrapperEntry;
6049
6290
  }));
6050
6291
  return { buildEntries, originalByBuildEntry };
@@ -6096,11 +6337,11 @@ ${defaultNames.map((name) => `export default ${name};`).join(`
6096
6337
  try {
6097
6338
  return Bun.resolveSync("akanjs/server", import.meta.dir);
6098
6339
  } catch {
6099
- return path17.resolve(import.meta.dir, "../../../server/index.ts");
6340
+ return path18.resolve(import.meta.dir, "../../../server/index.ts");
6100
6341
  }
6101
6342
  }
6102
6343
  static createStoreBootstrapEntrySource(args) {
6103
- const originalEntry = JSON.stringify(path17.resolve(args.originalEntry));
6344
+ const originalEntry = JSON.stringify(path18.resolve(args.originalEntry));
6104
6345
  const namedExports = args.exportNames.filter((name) => name !== "default");
6105
6346
  const lines = [
6106
6347
  `import ${JSON.stringify(`@apps/${args.appName}/client`)};`,
@@ -6126,7 +6367,7 @@ ${defaultNames.map((name) => `export default ${name};`).join(`
6126
6367
  }
6127
6368
 
6128
6369
  // pkgs/@akanjs/devkit/frontendBuild/routesManifestArtifactSerializer.ts
6129
- import path18 from "path";
6370
+ import path19 from "path";
6130
6371
 
6131
6372
  class RoutesManifestArtifactSerializer {
6132
6373
  #manifest;
@@ -6134,7 +6375,7 @@ class RoutesManifestArtifactSerializer {
6134
6375
  #production;
6135
6376
  constructor(manifest, artifactDir, options = {}) {
6136
6377
  this.#manifest = manifest;
6137
- this.#artifactDir = path18.resolve(artifactDir);
6378
+ this.#artifactDir = path19.resolve(artifactDir);
6138
6379
  this.#production = options.production ?? false;
6139
6380
  }
6140
6381
  static serialize(manifest, artifactDir, options = {}) {
@@ -6167,9 +6408,9 @@ class RoutesManifestArtifactSerializer {
6167
6408
  };
6168
6409
  }
6169
6410
  #serializeArtifactPath(artifactPath) {
6170
- if (!path18.isAbsolute(artifactPath))
6411
+ if (!path19.isAbsolute(artifactPath))
6171
6412
  return artifactPath;
6172
- return path18.relative(this.#artifactDir, artifactPath).split(path18.sep).join("/");
6413
+ return path19.relative(this.#artifactDir, artifactPath).split(path19.sep).join("/");
6173
6414
  }
6174
6415
  }
6175
6416
 
@@ -6209,7 +6450,7 @@ class AllRoutesBuilder {
6209
6450
  routeIds: this.#routeIds,
6210
6451
  ...this.#merged
6211
6452
  };
6212
- const manifestPath = path19.join(path19.resolve(this.#artifactDir), "routes-manifest.json");
6453
+ const manifestPath = path20.join(path20.resolve(this.#artifactDir), "routes-manifest.json");
6213
6454
  await Bun.write(manifestPath, `${JSON.stringify(RoutesManifestArtifactSerializer.serialize(manifest, this.#artifactDir, {
6214
6455
  production: this.#command === "build"
6215
6456
  }), null, 2)}
@@ -6246,11 +6487,11 @@ class AllRoutesBuilder {
6246
6487
  }
6247
6488
  // pkgs/@akanjs/devkit/frontendBuild/csrArtifactBuilder.ts
6248
6489
  import { mkdir as mkdir5, rm, unlink } from "fs/promises";
6249
- import path21 from "path";
6490
+ import path22 from "path";
6250
6491
 
6251
6492
  // pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
6252
6493
  import fs3 from "fs";
6253
- import path20 from "path";
6494
+ import path21 from "path";
6254
6495
  import ts5 from "typescript";
6255
6496
 
6256
6497
  class PagesEntrySourceGenerator {
@@ -6263,7 +6504,7 @@ class PagesEntrySourceGenerator {
6263
6504
  }
6264
6505
  generate() {
6265
6506
  const lines = this.#pageEntries.map(({ key, moduleAbsPath }) => {
6266
- const absPath = path20.resolve(moduleAbsPath);
6507
+ const absPath = path21.resolve(moduleAbsPath);
6267
6508
  return ` ${JSON.stringify(key)}: () => import(${JSON.stringify(absPath)}),`;
6268
6509
  });
6269
6510
  return `export const pages = {
@@ -6277,7 +6518,7 @@ ${lines.join(`
6277
6518
  }
6278
6519
  generateStatic() {
6279
6520
  const imports = this.#pageEntries.map(({ moduleAbsPath }, index) => {
6280
- const absPath = path20.resolve(moduleAbsPath);
6521
+ const absPath = path21.resolve(moduleAbsPath);
6281
6522
  return `import * as page${index} from ${JSON.stringify(absPath)};`;
6282
6523
  });
6283
6524
  const entries = this.#pageEntries.map(({ key, moduleAbsPath }, index) => {
@@ -6294,7 +6535,7 @@ ${entries.join(`
6294
6535
  }
6295
6536
  static #hasAsyncDefaultExport(moduleAbsPath) {
6296
6537
  try {
6297
- const source = fs3.readFileSync(path20.resolve(moduleAbsPath), "utf8");
6538
+ const source = fs3.readFileSync(path21.resolve(moduleAbsPath), "utf8");
6298
6539
  const sourceFile = ts5.createSourceFile(moduleAbsPath, source, ts5.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
6299
6540
  return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile);
6300
6541
  } catch {
@@ -6373,7 +6614,7 @@ class CsrArtifactBuilder {
6373
6614
  const csrBasePaths = [...akanConfig2.basePaths];
6374
6615
  const htmlEntries = csrBasePaths.length > 0 ? csrBasePaths : ["index"];
6375
6616
  await rm(this.#outputDir, { recursive: true, force: true });
6376
- await mkdir5(path21.join(this.#app.cwdPath, ".akan/generated/csr"), { recursive: true });
6617
+ await mkdir5(path22.join(this.#app.cwdPath, ".akan/generated/csr"), { recursive: true });
6377
6618
  const generatedHtmlFiles = Object.fromEntries(htmlEntries.map((basePath2) => this.#createHtmlFile(basePath2)));
6378
6619
  const result = await Bun.build({
6379
6620
  target: "browser",
@@ -6405,7 +6646,7 @@ ${logs}` : ""}`);
6405
6646
  return { outputDir: this.#outputDir };
6406
6647
  }
6407
6648
  get #outputDir() {
6408
- return path21.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
6649
+ return path22.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
6409
6650
  }
6410
6651
  #define() {
6411
6652
  const nodeEnv = this.#command === "build" ? "production" : "development";
@@ -6436,8 +6677,8 @@ ${logs}` : ""}`);
6436
6677
  ];
6437
6678
  }
6438
6679
  async#loadCsrArtifact() {
6439
- const artifactDir = path21.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
6440
- const artifactFile = Bun.file(path21.join(artifactDir, "base-artifact.json"));
6680
+ const artifactDir = path22.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
6681
+ const artifactFile = Bun.file(path22.join(artifactDir, "base-artifact.json"));
6441
6682
  if (!await artifactFile.exists())
6442
6683
  return { cssAssets: {} };
6443
6684
  const artifact = await artifactFile.json();
@@ -6450,7 +6691,7 @@ ${logs}` : ""}`);
6450
6691
  const htmlFile = Bun.file(htmlPath);
6451
6692
  if (!await htmlFile.exists())
6452
6693
  continue;
6453
- const basePath2 = path21.basename(htmlPath, ".html") === "index" ? "" : path21.basename(htmlPath, ".html");
6694
+ const basePath2 = path22.basename(htmlPath, ".html") === "index" ? "" : path22.basename(htmlPath, ".html");
6454
6695
  const inlined = await this.#inlineHtmlAssets(await htmlFile.text(), htmlPath, cssAssets[basePath2]);
6455
6696
  for (const filePath of inlined.jsFiles)
6456
6697
  jsFiles.add(filePath);
@@ -6492,7 +6733,7 @@ ${remainingAssets.join(`
6492
6733
  next = CsrArtifactBuilder.injectBeforeHeadEnd(next, style);
6493
6734
  }
6494
6735
  if (cssAsset) {
6495
- const cssPath = path21.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact", cssAsset.cssRelPath);
6736
+ const cssPath = path22.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact", cssAsset.cssRelPath);
6496
6737
  const css = await Bun.file(cssPath).text();
6497
6738
  const style = CsrArtifactBuilder.createInlineStyle(css);
6498
6739
  if (!next.includes(style))
@@ -6563,16 +6804,16 @@ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
6563
6804
  throw new Error(`[csr-build] cannot inline external script: ${src}`);
6564
6805
  }
6565
6806
  const normalized = src.startsWith("/") ? src.slice(1) : src;
6566
- return path21.resolve(path21.dirname(htmlPath), normalized);
6807
+ return path22.resolve(path22.dirname(htmlPath), normalized);
6567
6808
  }
6568
6809
  }
6569
6810
  // pkgs/@akanjs/devkit/frontendBuild/cssCompiler.ts
6570
- import path23 from "path";
6811
+ import path24 from "path";
6571
6812
  import { Logger as Logger8 } from "akanjs/common";
6572
6813
  import { compile } from "tailwindcss";
6573
6814
 
6574
6815
  // pkgs/@akanjs/devkit/frontendBuild/cssImportResolver.ts
6575
- import path22 from "path";
6816
+ import path23 from "path";
6576
6817
  var CSS_IMPORT_EXTS = ["", ".css", "/styles.css", "/index.css"];
6577
6818
 
6578
6819
  class CssImportResolver {
@@ -6625,7 +6866,7 @@ class CssImportResolver {
6625
6866
  const exact = this.#paths[id];
6626
6867
  if (exact) {
6627
6868
  for (const repl of exact) {
6628
- const resolved = await this.#firstExisting(path22.resolve(this.#workspaceRoot, repl));
6869
+ const resolved = await this.#firstExisting(path23.resolve(this.#workspaceRoot, repl));
6629
6870
  if (resolved)
6630
6871
  return resolved;
6631
6872
  }
@@ -6636,7 +6877,7 @@ class CssImportResolver {
6636
6877
  const suffix = id.slice(prefix.length);
6637
6878
  for (const repl of replacements) {
6638
6879
  const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
6639
- const resolved = await this.#firstExisting(path22.resolve(this.#workspaceRoot, replPath + suffix));
6880
+ const resolved = await this.#firstExisting(path23.resolve(this.#workspaceRoot, replPath + suffix));
6640
6881
  if (resolved)
6641
6882
  return resolved;
6642
6883
  }
@@ -6666,25 +6907,25 @@ class CssImportResolver {
6666
6907
  try {
6667
6908
  if (!await Bun.file(pkgPath).exists())
6668
6909
  return null;
6669
- const pkgDir = path22.dirname(pkgPath);
6910
+ const pkgDir = path23.dirname(pkgPath);
6670
6911
  const pkg = await Bun.file(pkgPath).json();
6671
6912
  const subpath = id === pkgName ? "." : `.${id.slice(pkgName.length)}`;
6672
6913
  const exportValue = pkg.exports?.[subpath];
6673
6914
  const styleEntry = (typeof exportValue === "string" ? exportValue : exportValue?.style || exportValue?.import || exportValue?.default) || pkg.exports?.["."]?.style || pkg.style || "index.css";
6674
- return await this.#firstExisting(path22.resolve(pkgDir, styleEntry));
6915
+ return await this.#firstExisting(path23.resolve(pkgDir, styleEntry));
6675
6916
  } catch {
6676
6917
  return null;
6677
6918
  }
6678
6919
  }
6679
6920
  #resolutionBases(fromBase) {
6680
- return [fromBase, this.#workspaceRoot, path22.dirname(Bun.main), path22.resolve(path22.dirname(Bun.main), "../..")];
6921
+ return [fromBase, this.#workspaceRoot, path23.dirname(Bun.main), path23.resolve(path23.dirname(Bun.main), "../..")];
6681
6922
  }
6682
6923
  #packageJsonCandidates(pkgName) {
6683
6924
  return [
6684
- path22.join(this.#workspaceRoot, "pkgs", pkgName, "package.json"),
6685
- path22.join(this.#workspaceRoot, "node_modules", pkgName, "package.json"),
6686
- path22.join(path22.dirname(Bun.main), "node_modules", pkgName, "package.json"),
6687
- path22.join(path22.dirname(Bun.main), "../../", pkgName, "package.json")
6925
+ path23.join(this.#workspaceRoot, "pkgs", pkgName, "package.json"),
6926
+ path23.join(this.#workspaceRoot, "node_modules", pkgName, "package.json"),
6927
+ path23.join(path23.dirname(Bun.main), "node_modules", pkgName, "package.json"),
6928
+ path23.join(path23.dirname(Bun.main), "../../", pkgName, "package.json")
6688
6929
  ];
6689
6930
  }
6690
6931
  async#firstExisting(basePath2) {
@@ -6702,7 +6943,7 @@ class CssImportResolver {
6702
6943
  return parts[0] ?? null;
6703
6944
  }
6704
6945
  static isCssFile(filePath) {
6705
- return path22.extname(filePath) === ".css";
6946
+ return path23.extname(filePath) === ".css";
6706
6947
  }
6707
6948
  }
6708
6949
 
@@ -6769,7 +7010,7 @@ class CssCompiler {
6769
7010
  pageKeys
6770
7011
  } = {}) {
6771
7012
  pageKeys ??= await this.#app.getPageKeys({ refresh });
6772
- const seeds = pageKeys.map((key) => path23.resolve(this.#app.cwdPath, "page", key));
7013
+ const seeds = pageKeys.map((key) => path24.resolve(this.#app.cwdPath, "page", key));
6773
7014
  const cssFiles = new Set;
6774
7015
  const sourceFiles = new Set;
6775
7016
  const queue = [...seeds];
@@ -6801,7 +7042,7 @@ class CssCompiler {
6801
7042
  } catch {
6802
7043
  continue;
6803
7044
  }
6804
- const importerDir = path23.dirname(filePath);
7045
+ const importerDir = path24.dirname(filePath);
6805
7046
  for (const imp of imports) {
6806
7047
  const spec = imp.path;
6807
7048
  if (!spec)
@@ -6827,7 +7068,7 @@ class CssCompiler {
6827
7068
  const compileStarted = Date.now();
6828
7069
  const compilers = await Promise.all(cssPaths.map(async (cssPath) => {
6829
7070
  const css = await Bun.file(cssPath).text();
6830
- const base = path23.dirname(cssPath);
7071
+ const base = path24.dirname(cssPath);
6831
7072
  const compiler = await compile(css, {
6832
7073
  base,
6833
7074
  loadStylesheet: (id, fromBase) => this.#loadStylesheet(id, fromBase),
@@ -6858,11 +7099,11 @@ class CssCompiler {
6858
7099
  async#loadStylesheet(id, fromBase) {
6859
7100
  const p = await this.#resolveCssImport(id, fromBase);
6860
7101
  const content = await Bun.file(p).text();
6861
- return { path: p, base: path23.dirname(p), content };
7102
+ return { path: p, base: path24.dirname(p), content };
6862
7103
  }
6863
7104
  async#resolveCssImport(id, fromBase) {
6864
7105
  if (id.startsWith(".") || id.startsWith("/"))
6865
- return path23.resolve(fromBase, id);
7106
+ return path24.resolve(fromBase, id);
6866
7107
  const resolver = await this.#getCssImportResolver();
6867
7108
  const resolved = await resolver.resolve(id, fromBase);
6868
7109
  if (resolved)
@@ -6878,11 +7119,11 @@ class CssCompiler {
6878
7119
  async#loadModule(id, fromBase) {
6879
7120
  const p = __require.resolve(id, { paths: [fromBase] });
6880
7121
  const mod = await import(p);
6881
- return { path: p, base: path23.dirname(p), module: mod.default ?? mod };
7122
+ return { path: p, base: path24.dirname(p), module: mod.default ?? mod };
6882
7123
  }
6883
7124
  async#resolveSourceImport(id, fromBase, resolvePackage) {
6884
7125
  if (id.startsWith(".") || id.startsWith("/")) {
6885
- const abs = id.startsWith("/") ? id : path23.resolve(fromBase, id);
7126
+ const abs = id.startsWith("/") ? id : path24.resolve(fromBase, id);
6886
7127
  return resolveSourceFileCandidate(abs);
6887
7128
  }
6888
7129
  const pkg = await resolvePackage(id);
@@ -6924,7 +7165,7 @@ async function resolveSourceFileCandidate(absPathNoExt) {
6924
7165
  return filePath;
6925
7166
  }
6926
7167
  for (const ext of SOURCE_EXTS3) {
6927
- const filePath = path23.join(absPathNoExt, `index${ext}`);
7168
+ const filePath = path24.join(absPathNoExt, `index${ext}`);
6928
7169
  if (await Bun.file(filePath).exists())
6929
7170
  return filePath;
6930
7171
  }
@@ -6947,20 +7188,20 @@ function resolveSourceWithRequire(id, fromBase) {
6947
7188
  }
6948
7189
  }
6949
7190
  function isSourceFile(filePath) {
6950
- return SOURCE_EXTS3.includes(path23.extname(filePath));
7191
+ return SOURCE_EXTS3.includes(path24.extname(filePath));
6951
7192
  }
6952
7193
  function isIgnoredNodeModuleSource(filePath) {
6953
7194
  return NODE_MODULES_RE3.test(filePath) && !AKANJS_NODE_MODULE_RE3.test(filePath);
6954
7195
  }
6955
7196
  function getPageKeyBasePath(pageKey, basePaths) {
6956
- const normalized = pageKey.split(path23.sep).join("/").replace(/^\.\//, "");
7197
+ const normalized = pageKey.split(path24.sep).join("/").replace(/^\.\//, "");
6957
7198
  const segments = normalized.split("/");
6958
7199
  const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
6959
7200
  return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
6960
7201
  }
6961
7202
  // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
6962
7203
  import { mkdir as mkdir6 } from "fs/promises";
6963
- import path24 from "path";
7204
+ import path25 from "path";
6964
7205
  import {
6965
7206
  generateFontFace,
6966
7207
  getMetricsForFamily,
@@ -6984,7 +7225,7 @@ class FontOptimizer {
6984
7225
  constructor(app, command = "start") {
6985
7226
  this.#app = app;
6986
7227
  this.#command = command;
6987
- this.#artifactRoot = path24.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
7228
+ this.#artifactRoot = path25.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
6988
7229
  }
6989
7230
  async optimize() {
6990
7231
  const fonts = await this.discoverFonts();
@@ -7003,7 +7244,7 @@ class FontOptimizer {
7003
7244
  const pageKeys = await this.#app.getPageKeys();
7004
7245
  const fonts = [];
7005
7246
  await Promise.all(pageKeys.map(async (key) => {
7006
- const filePath = path24.resolve(this.#app.cwdPath, "page", key);
7247
+ const filePath = path25.resolve(this.#app.cwdPath, "page", key);
7007
7248
  const file = Bun.file(filePath);
7008
7249
  if (!await file.exists())
7009
7250
  return;
@@ -7019,8 +7260,8 @@ class FontOptimizer {
7019
7260
  this.#app.logger.warn(`[font] source not found: ${face.src}`);
7020
7261
  continue;
7021
7262
  }
7022
- const outputPath = path24.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
7023
- await mkdir6(path24.dirname(outputPath), { recursive: true });
7263
+ const outputPath = path25.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
7264
+ await mkdir6(path25.dirname(outputPath), { recursive: true });
7024
7265
  const sourceBuffer = Buffer.from(await Bun.file(sourcePath).arrayBuffer());
7025
7266
  const outputBuffer = font.subset === false ? await this.#convertToWoff2(sourceBuffer, sourcePath) : await subsetFont(sourceBuffer, await this.#getSubsetText(font), { targetFormat: "woff2" });
7026
7267
  await Bun.write(outputPath, outputBuffer);
@@ -7167,8 +7408,8 @@ class FontOptimizer {
7167
7408
  return null;
7168
7409
  const rel = src.replace(/^\//, "");
7169
7410
  const candidates = [
7170
- this.#command === "build" ? path24.join(this.#app.dist.cwdPath, "public", rel) : null,
7171
- path24.join(this.#app.cwdPath, "public", rel),
7411
+ this.#command === "build" ? path25.join(this.#app.dist.cwdPath, "public", rel) : null,
7412
+ path25.join(this.#app.cwdPath, "public", rel),
7172
7413
  this.#resolveWorkspacePublicPath(rel)
7173
7414
  ].filter(Boolean);
7174
7415
  for (const candidate of candidates) {
@@ -7196,7 +7437,7 @@ class FontOptimizer {
7196
7437
  return "woff2";
7197
7438
  if (signature === "OTTO")
7198
7439
  return "otf";
7199
- const ext = path24.extname(sourcePath).slice(1).toLowerCase();
7440
+ const ext = path25.extname(sourcePath).slice(1).toLowerCase();
7200
7441
  if (ext === "otf" || ext === "woff" || ext === "woff2")
7201
7442
  return ext;
7202
7443
  return "ttf";
@@ -7205,7 +7446,7 @@ class FontOptimizer {
7205
7446
  const [root, dep, ...rest] = rel.split("/");
7206
7447
  if (root !== "libs" || !dep || rest.length === 0)
7207
7448
  return null;
7208
- return path24.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
7449
+ return path25.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
7209
7450
  }
7210
7451
  async#getSubsetText(font) {
7211
7452
  const parts = new Set;
@@ -7215,7 +7456,7 @@ class FontOptimizer {
7215
7456
  if (font.subsetText)
7216
7457
  parts.add(font.subsetText);
7217
7458
  for (const filePath of font.subsetFiles ?? []) {
7218
- const abs = path24.isAbsolute(filePath) ? filePath : path24.join(this.#app.cwdPath, filePath);
7459
+ const abs = path25.isAbsolute(filePath) ? filePath : path25.join(this.#app.cwdPath, filePath);
7219
7460
  const file = Bun.file(abs);
7220
7461
  if (await file.exists())
7221
7462
  parts.add(await file.text());
@@ -7234,7 +7475,7 @@ class FontOptimizer {
7234
7475
  return "";
7235
7476
  }
7236
7477
  async#collectAutoSubsetText() {
7237
- const roots = ["page", "ui"].map((dir) => path24.join(this.#app.cwdPath, dir));
7478
+ const roots = ["page", "ui"].map((dir) => path25.join(this.#app.cwdPath, dir));
7238
7479
  const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx,html,md}");
7239
7480
  const parts = [];
7240
7481
  await Promise.all(roots.map(async (root) => {
@@ -7348,7 +7589,7 @@ ${declarations.map(([prop, value]) => ` ${prop}: ${value};`).join(`
7348
7589
  }
7349
7590
  }
7350
7591
  // pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
7351
- import path25 from "path";
7592
+ import path26 from "path";
7352
7593
  var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
7353
7594
  var CSS_EXTS = new Set([".css"]);
7354
7595
  var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
@@ -7357,10 +7598,10 @@ class HmrChangeClassifier {
7357
7598
  classify(abs) {
7358
7599
  if (this.#isUninteresting(abs))
7359
7600
  return "ignore";
7360
- const base = path25.basename(abs);
7601
+ const base = path26.basename(abs);
7361
7602
  if (CONFIG_BASENAMES.has(base))
7362
7603
  return "config";
7363
- const ext = path25.extname(abs).toLowerCase();
7604
+ const ext = path26.extname(abs).toLowerCase();
7364
7605
  if (CSS_EXTS.has(ext))
7365
7606
  return "css";
7366
7607
  if (SOURCE_EXTS4.has(ext))
@@ -7368,23 +7609,23 @@ class HmrChangeClassifier {
7368
7609
  return "ignore";
7369
7610
  }
7370
7611
  #isUninteresting(abs) {
7371
- const base = path25.basename(abs);
7612
+ const base = path26.basename(abs);
7372
7613
  if (!base)
7373
7614
  return true;
7374
7615
  if (base.startsWith("."))
7375
7616
  return true;
7376
7617
  if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
7377
7618
  return true;
7378
- if (abs.includes(`${path25.sep}node_modules${path25.sep}`))
7619
+ if (abs.includes(`${path26.sep}node_modules${path26.sep}`))
7379
7620
  return true;
7380
- if (abs.includes(`${path25.sep}.akan${path25.sep}`))
7621
+ if (abs.includes(`${path26.sep}.akan${path26.sep}`))
7381
7622
  return true;
7382
7623
  return false;
7383
7624
  }
7384
7625
  }
7385
7626
  // pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
7386
7627
  import fs4 from "fs";
7387
- import path26 from "path";
7628
+ import path27 from "path";
7388
7629
  class HmrWatcher {
7389
7630
  #roots;
7390
7631
  #debounceMs;
@@ -7397,7 +7638,7 @@ class HmrWatcher {
7397
7638
  #stopped = false;
7398
7639
  #flushing = false;
7399
7640
  constructor(opts) {
7400
- this.#roots = [...new Set(opts.roots.map((r) => path26.resolve(r)))];
7641
+ this.#roots = [...new Set(opts.roots.map((r) => path27.resolve(r)))];
7401
7642
  this.#debounceMs = opts.debounceMs ?? 80;
7402
7643
  this.#onBatch = opts.onBatch;
7403
7644
  this.#logger = opts.logger;
@@ -7408,7 +7649,7 @@ class HmrWatcher {
7408
7649
  const w = fs4.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
7409
7650
  if (!filename)
7410
7651
  return;
7411
- const abs = path26.resolve(root, filename.toString());
7652
+ const abs = path27.resolve(root, filename.toString());
7412
7653
  this.#queue(abs);
7413
7654
  });
7414
7655
  this.#watchers.push(w);
@@ -7466,10 +7707,10 @@ class HmrWatcher {
7466
7707
  }
7467
7708
  }
7468
7709
  // pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
7469
- import path28 from "path";
7710
+ import path29 from "path";
7470
7711
 
7471
7712
  // pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
7472
- import path27 from "path";
7713
+ import path28 from "path";
7473
7714
  var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
7474
7715
  var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "akanjs/server", "@akanjs/cli", "@akanjs/devkit"]);
7475
7716
  var DEFAULT_EXCLUDE_PREFIX = ["akanjs/server/", "@akanjs/cli/", "@akanjs/devkit/"];
@@ -7504,7 +7745,7 @@ async function createExternalizeFrameworkPlugin(options) {
7504
7745
  const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
7505
7746
  if (!replPath)
7506
7747
  continue;
7507
- const candidate = path27.resolve(workspaceRoot, replPath + suffix);
7748
+ const candidate = path28.resolve(workspaceRoot, replPath + suffix);
7508
7749
  const hit = await firstExisting(candidate);
7509
7750
  if (hit)
7510
7751
  return hit;
@@ -7516,8 +7757,8 @@ async function createExternalizeFrameworkPlugin(options) {
7516
7757
  if (spec === pkg)
7517
7758
  continue;
7518
7759
  const suffix = spec.slice(pkg.length + 1);
7519
- const pkgDir = path27.dirname(path27.resolve(workspaceRoot, entryFile));
7520
- const candidate = path27.join(pkgDir, suffix);
7760
+ const pkgDir = path28.dirname(path28.resolve(workspaceRoot, entryFile));
7761
+ const candidate = path28.join(pkgDir, suffix);
7521
7762
  const hit = await firstExisting(candidate);
7522
7763
  if (hit)
7523
7764
  return hit;
@@ -7565,7 +7806,7 @@ async function firstExisting(basePath2) {
7565
7806
  return candidate;
7566
7807
  }
7567
7808
  for (const ext of CANDIDATE_EXTS3) {
7568
- const candidate = path27.join(basePath2, `index${ext}`);
7809
+ const candidate = path28.join(basePath2, `index${ext}`);
7569
7810
  if (await Bun.file(candidate).exists())
7570
7811
  return candidate;
7571
7812
  }
@@ -7654,11 +7895,11 @@ class PagesBundleBuilder {
7654
7895
  const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
7655
7896
  if (!entryArtifact)
7656
7897
  throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
7657
- const bundlePath = path28.resolve(entryArtifact.path);
7898
+ const bundlePath = path29.resolve(entryArtifact.path);
7658
7899
  const buildId = Date.now();
7659
7900
  const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
7660
7901
  const chunkCount = result.outputs.filter((output) => output.kind === "chunk").length;
7661
- this.#app.verbose(`[PagesBundleBuilder] ${path28.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
7902
+ this.#app.verbose(`[PagesBundleBuilder] ${path29.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
7662
7903
  return {
7663
7904
  bundlePath,
7664
7905
  buildId,
@@ -7701,11 +7942,11 @@ class PagesBundleBuilder {
7701
7942
  }
7702
7943
  // pkgs/@akanjs/devkit/frontendBuild/precompressArtifacts.ts
7703
7944
  import fs5 from "fs";
7704
- import path29 from "path";
7945
+ import path30 from "path";
7705
7946
  var COMPRESSIBLE_EXTS = new Set([".css", ".html", ".js", ".json", ".svg"]);
7706
7947
  var MIN_COMPRESS_BYTES = 1024;
7707
7948
  async function precompressArtifacts(app) {
7708
- const roots = [path29.join(app.dist.cwdPath, ".akan/artifact/client")];
7949
+ const roots = [path30.join(app.dist.cwdPath, ".akan/artifact/client")];
7709
7950
  const result = { files: 0, inputBytes: 0, outputBytes: 0 };
7710
7951
  await Promise.all(roots.map((root) => precompressRoot(root, result)));
7711
7952
  if (result.files > 0) {
@@ -7731,7 +7972,7 @@ async function precompressRoot(root, result) {
7731
7972
  async function shouldPrecompress(filePath) {
7732
7973
  if (filePath.endsWith(".gz"))
7733
7974
  return false;
7734
- if (!COMPRESSIBLE_EXTS.has(path29.extname(filePath).toLowerCase()))
7975
+ if (!COMPRESSIBLE_EXTS.has(path30.extname(filePath).toLowerCase()))
7735
7976
  return false;
7736
7977
  const file = Bun.file(filePath);
7737
7978
  if (!await file.exists())
@@ -7749,7 +7990,7 @@ function formatBytes(bytes) {
7749
7990
  return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
7750
7991
  }
7751
7992
  // pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
7752
- import path30 from "path";
7993
+ import path31 from "path";
7753
7994
  import { optimize } from "@tailwindcss/node";
7754
7995
  function prepareCssAsset(command, basePath2, cssText) {
7755
7996
  return optimize(cssText, { file: `${basePath2 || "root"}.css`, minify: command === "build" }).code;
@@ -7765,7 +8006,7 @@ class SsrBaseArtifactBuilder {
7765
8006
  this.#app = app;
7766
8007
  this.#command = command;
7767
8008
  this.#artifactDir = `${command === "build" ? app.dist.cwdPath : app.cwdPath}/.akan/artifact`;
7768
- this.#absArtifactDir = path30.resolve(this.#artifactDir);
8009
+ this.#absArtifactDir = path31.resolve(this.#artifactDir);
7769
8010
  }
7770
8011
  async build() {
7771
8012
  const akanConfig2 = await this.#app.getConfig();
@@ -7785,7 +8026,7 @@ class SsrBaseArtifactBuilder {
7785
8026
  rscClientUrl,
7786
8027
  vendorMap,
7787
8028
  cssAssets,
7788
- pagesBundlePath: this.#command === "build" ? path30.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
8029
+ pagesBundlePath: this.#command === "build" ? path31.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
7789
8030
  pagesBundleBuildId: pagesBundle.buildId,
7790
8031
  domains: [...akanConfig2.domains],
7791
8032
  subRoutes: Object.fromEntries(Array.from(akanConfig2.subRoutes.entries()).map(([basePath2, domains]) => [basePath2, [...domains]])),
@@ -7794,7 +8035,7 @@ class SsrBaseArtifactBuilder {
7794
8035
  i18n: akanConfig2.i18n,
7795
8036
  imageConfig: akanConfig2.images
7796
8037
  };
7797
- await Bun.write(path30.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
8038
+ await Bun.write(path31.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
7798
8039
  `);
7799
8040
  this.#app.verbose(`[base-artifact] complete in ${Date.now() - this.#started}ms`);
7800
8041
  return { artifact, seedIndex, cssCompiler, optimizedFonts };
@@ -7816,15 +8057,15 @@ class SsrBaseArtifactBuilder {
7816
8057
  async#resolveAkanServerPath() {
7817
8058
  const candidates = [];
7818
8059
  try {
7819
- candidates.push(path30.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
8060
+ candidates.push(path31.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
7820
8061
  } catch {}
7821
- candidates.push(path30.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path30.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
8062
+ candidates.push(path31.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path31.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
7822
8063
  try {
7823
- candidates.push(path30.dirname(Bun.resolveSync("akanjs/server", path30.dirname(Bun.main))));
8064
+ candidates.push(path31.dirname(Bun.resolveSync("akanjs/server", path31.dirname(Bun.main))));
7824
8065
  } catch {}
7825
- candidates.push(path30.join(path30.dirname(Bun.main), "node_modules/akanjs/server"), path30.join(path30.dirname(Bun.main), "../../akanjs/server"), path30.resolve(import.meta.dir, "../../server"), path30.resolve(import.meta.dir, "../server"));
8066
+ candidates.push(path31.join(path31.dirname(Bun.main), "node_modules/akanjs/server"), path31.join(path31.dirname(Bun.main), "../../akanjs/server"), path31.resolve(import.meta.dir, "../../server"), path31.resolve(import.meta.dir, "../server"));
7826
8067
  for (const candidate of candidates) {
7827
- if (await Bun.file(path30.join(candidate, "rscClient.tsx")).exists())
8068
+ if (await Bun.file(path31.join(candidate, "rscClient.tsx")).exists())
7828
8069
  return candidate;
7829
8070
  }
7830
8071
  throw new Error(`[base-artifact] failed to locate akanjs/server; looked in: ${candidates.join(", ")}`);
@@ -7853,14 +8094,14 @@ ${preparedCssText}`).toString(36);
7853
8094
  `styles/${cssAssetName}-${cssHash}.css`,
7854
8095
  `/_akan/styles/${cssAssetName}-${cssHash}.css`
7855
8096
  ];
7856
- await Bun.write(path30.join(this.#absArtifactDir, cssRelPath), preparedCssText);
8097
+ await Bun.write(path31.join(this.#absArtifactDir, cssRelPath), preparedCssText);
7857
8098
  this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath2} -> ${cssRelPath}`);
7858
8099
  return [basePath2, { cssUrl, cssRelPath }];
7859
8100
  }
7860
8101
  }
7861
8102
  // pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
7862
8103
  import fs6 from "fs";
7863
- import path31 from "path";
8104
+ import path32 from "path";
7864
8105
 
7865
8106
  class WatchRootResolver {
7866
8107
  #app;
@@ -7870,15 +8111,15 @@ class WatchRootResolver {
7870
8111
  async resolve() {
7871
8112
  const tsconfig = await this.#app.getTsConfig();
7872
8113
  const set = new Set;
7873
- set.add(path31.resolve(`${this.#app.cwdPath}/page`));
8114
+ set.add(path32.resolve(`${this.#app.cwdPath}/page`));
7874
8115
  for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
7875
8116
  for (const target of targets) {
7876
8117
  if (!target)
7877
8118
  continue;
7878
- if (path31.isAbsolute(target))
8119
+ if (path32.isAbsolute(target))
7879
8120
  continue;
7880
8121
  const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
7881
- const resolved = path31.resolve(this.#app.workspace.workspaceRoot, cleaned);
8122
+ const resolved = path32.resolve(this.#app.workspace.workspaceRoot, cleaned);
7882
8123
  if (fs6.existsSync(resolved))
7883
8124
  set.add(resolved);
7884
8125
  }
@@ -7945,7 +8186,7 @@ class ApplicationBuildRunner {
7945
8186
  phases: this.#phases,
7946
8187
  durationMs: Date.now() - this.#startedAt,
7947
8188
  outputDir: this.#app.dist.cwdPath,
7948
- artifactDir: path32.join(this.#app.dist.cwdPath, ".akan/artifact")
8189
+ artifactDir: path33.join(this.#app.dist.cwdPath, ".akan/artifact")
7949
8190
  };
7950
8191
  }
7951
8192
  async typecheck(options = {}) {
@@ -7953,7 +8194,7 @@ class ApplicationBuildRunner {
7953
8194
  await this.#app.getPageKeys({ refresh: true });
7954
8195
  const { typecheckDir, tsconfigPath } = await this.#writeTypecheckTsconfig({ incremental });
7955
8196
  if (clean)
7956
- await rm2(path32.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
8197
+ await rm2(path33.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
7957
8198
  await this.#checkProjectInChildProcess(tsconfigPath);
7958
8199
  }
7959
8200
  async#runPhase(id, label, task, summarize, options = {}) {
@@ -7996,6 +8237,7 @@ class ApplicationBuildRunner {
7996
8237
  outdir: this.#app.dist.cwdPath,
7997
8238
  target: "bun",
7998
8239
  minify: true,
8240
+ naming: { entry: "[name].[ext]", chunk: "chunk-[hash].[ext]" },
7999
8241
  define: { "process.env.NODE_ENV": JSON.stringify("production") },
8000
8242
  plugins: backendExternals.length > 0 ? [this.#createExternalSpecifiersPlugin(backendExternals)] : []
8001
8243
  });
@@ -8009,16 +8251,52 @@ class ApplicationBuildRunner {
8009
8251
  define: { "process.env.NODE_ENV": JSON.stringify("production") },
8010
8252
  plugins: backendExternals.length > 0 ? [this.#createExternalSpecifiersPlugin(backendExternals)] : []
8011
8253
  });
8254
+ const consoleRuntimeResult = await this.#buildOrThrow("console-runtime", {
8255
+ entrypoints: [this.#resolveConsoleRuntimeBuildEntry()],
8256
+ outdir: this.#app.dist.cwdPath,
8257
+ target: "bun",
8258
+ minify: true,
8259
+ naming: { entry: "console-runtime.[ext]", chunk: "chunk-[hash].[ext]" },
8260
+ define: { "process.env.NODE_ENV": JSON.stringify("production") }
8261
+ });
8262
+ await this.#writeConsoleShim();
8012
8263
  return {
8013
- entrypoints: backendEntryPoints.length + 1,
8014
- outputs: backendResult.outputs.length + rscWorkerResult.outputs.length
8264
+ entrypoints: backendEntryPoints.length + 2,
8265
+ outputs: backendResult.outputs.length + rscWorkerResult.outputs.length + consoleRuntimeResult.outputs.length + 1
8015
8266
  };
8016
8267
  }
8268
+ async#writeConsoleShim() {
8269
+ await Bun.write(path33.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
8270
+ import { assertAkanConsoleAllowed, startAkanConsole } from "./console-runtime.js";
8271
+
8272
+ const run = async () => {
8273
+ assertAkanConsoleAllowed(server.env);
8274
+ await server.start({ listen: false, web: false });
8275
+ try {
8276
+ await startAkanConsole(server, { globals: { cnst, db, dict, option, sig, srv } });
8277
+ } finally {
8278
+ await server.stop();
8279
+ }
8280
+ };
8281
+
8282
+ void run().catch((error) => {
8283
+ console.error(error);
8284
+ process.exit(1);
8285
+ });
8286
+ `);
8287
+ }
8017
8288
  #resolveRscWorkerBuildEntry() {
8018
8289
  try {
8019
8290
  return Bun.resolveSync("akanjs/server/rsc-worker", import.meta.dir);
8020
8291
  } catch {
8021
- return path32.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
8292
+ return path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
8293
+ }
8294
+ }
8295
+ #resolveConsoleRuntimeBuildEntry() {
8296
+ try {
8297
+ return path33.join(path33.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
8298
+ } catch {
8299
+ return path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
8022
8300
  }
8023
8301
  }
8024
8302
  async#buildCsr() {
@@ -8035,7 +8313,7 @@ class ApplicationBuildRunner {
8035
8313
  return { base, allRoutes };
8036
8314
  }
8037
8315
  async#writeTypecheckTsconfig({ incremental = true } = {}) {
8038
- const typecheckDir = path32.join(this.#app.cwdPath, ".akan", "typecheck");
8316
+ const typecheckDir = path33.join(this.#app.cwdPath, ".akan", "typecheck");
8039
8317
  await mkdir7(typecheckDir, { recursive: true });
8040
8318
  const tsconfig = {
8041
8319
  extends: "../../tsconfig.json",
@@ -8054,7 +8332,7 @@ class ApplicationBuildRunner {
8054
8332
  ],
8055
8333
  references: []
8056
8334
  };
8057
- const tsconfigPath = path32.join(typecheckDir, "tsconfig.json");
8335
+ const tsconfigPath = path33.join(typecheckDir, "tsconfig.json");
8058
8336
  await Bun.write(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
8059
8337
  `);
8060
8338
  return { typecheckDir, tsconfigPath };
@@ -8080,10 +8358,10 @@ class ApplicationBuildRunner {
8080
8358
  }
8081
8359
  async#resolveTypecheckWorkerEntry() {
8082
8360
  const candidates = [
8083
- path32.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8084
- path32.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8085
- path32.join(import.meta.dir, "typecheck.proc.js"),
8086
- path32.join(import.meta.dir, "typecheck.proc.ts")
8361
+ path33.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8362
+ path33.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8363
+ path33.join(import.meta.dir, "typecheck.proc.js"),
8364
+ path33.join(import.meta.dir, "typecheck.proc.ts")
8087
8365
  ];
8088
8366
  for (const candidate of candidates)
8089
8367
  if (await Bun.file(candidate).exists())
@@ -8259,13 +8537,13 @@ class ApplicationReleasePackager {
8259
8537
  await cp(this.#app.dist.cwdPath, `${sourceRoot}/apps/${this.#app.name}`, { recursive: true });
8260
8538
  const libDeps = ["social", "shared", "platform", "util"];
8261
8539
  await Promise.all(libDeps.map((lib) => cp(`${this.#app.workspace.cwdPath}/libs/${lib}`, `${sourceRoot}/libs/${lib}`, { recursive: true })));
8262
- await Promise.all([".next", "ios", "android", "public/libs"].map(async (path33) => {
8263
- const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path33}`;
8540
+ await Promise.all([".next", "ios", "android", "public/libs"].map(async (path34) => {
8541
+ const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path34}`;
8264
8542
  if (await FileSys.dirExists(targetPath))
8265
8543
  await rm3(targetPath, { recursive: true, force: true });
8266
8544
  }));
8267
8545
  const syncPaths = [".husky", ".gitignore", "package.json"];
8268
- await Promise.all(syncPaths.map((path33) => cp(`${this.#app.workspace.cwdPath}/${path33}`, `${sourceRoot}/${path33}`, { recursive: true })));
8546
+ await Promise.all(syncPaths.map((path34) => cp(`${this.#app.workspace.cwdPath}/${path34}`, `${sourceRoot}/${path34}`, { recursive: true })));
8269
8547
  await this.#writeSourceTsconfig(sourceRoot, libDeps);
8270
8548
  await Bun.write(`${sourceRoot}/README.md`, readme);
8271
8549
  await this.#app.workspace.spawn("tar", [
@@ -8356,20 +8634,20 @@ class ApplicationReleasePackager {
8356
8634
  }
8357
8635
  }
8358
8636
  // pkgs/@akanjs/devkit/applicationTestPreload.ts
8359
- import path33 from "path";
8637
+ import path34 from "path";
8360
8638
  var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
8361
8639
  async function resolveSignalTestPreloadPath(target) {
8362
8640
  const candidates = [];
8363
8641
  const addResolvedPackageCandidate = (basePath2) => {
8364
8642
  try {
8365
- candidates.push(path33.join(path33.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
8643
+ candidates.push(path34.join(path34.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
8366
8644
  } catch {}
8367
8645
  };
8368
8646
  addResolvedPackageCandidate(target.cwdPath);
8369
8647
  addResolvedPackageCandidate(process.cwd());
8370
- addResolvedPackageCandidate(path33.dirname(Bun.main));
8648
+ addResolvedPackageCandidate(path34.dirname(Bun.main));
8371
8649
  addResolvedPackageCandidate(import.meta.dir);
8372
- candidates.push(path33.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(path33.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
8650
+ candidates.push(path34.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(path34.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
8373
8651
  for (const candidate of [...new Set(candidates)]) {
8374
8652
  if (await Bun.file(candidate).exists())
8375
8653
  return candidate;
@@ -8379,7 +8657,7 @@ async function resolveSignalTestPreloadPath(target) {
8379
8657
  // pkgs/@akanjs/devkit/builder.ts
8380
8658
  import { existsSync as existsSync2 } from "fs";
8381
8659
  import { mkdir as mkdir9 } from "fs/promises";
8382
- import path34 from "path";
8660
+ import path35 from "path";
8383
8661
  var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
8384
8662
  var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
8385
8663
  var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
@@ -8396,14 +8674,14 @@ class Builder {
8396
8674
  #globEntrypoints(cwd, pattern) {
8397
8675
  const glob = new Bun.Glob(pattern);
8398
8676
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
8399
- const segments = relativePath.split(path34.sep);
8677
+ const segments = relativePath.split(path35.sep);
8400
8678
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
8401
- }).map((rel) => path34.join(cwd, rel));
8679
+ }).map((rel) => path35.join(cwd, rel));
8402
8680
  }
8403
8681
  #globFiles(cwd, pattern = "**/*.*") {
8404
8682
  const glob = new Bun.Glob(pattern);
8405
8683
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
8406
- const segments = relativePath.split(path34.sep);
8684
+ const segments = relativePath.split(path35.sep);
8407
8685
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
8408
8686
  });
8409
8687
  }
@@ -8411,17 +8689,17 @@ class Builder {
8411
8689
  const out = [];
8412
8690
  for (const p of additionalEntryPoints) {
8413
8691
  if (p.includes("*")) {
8414
- const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path34.sep}`) ? p.slice(cwd.length + 1) : p;
8692
+ const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path35.sep}`) ? p.slice(cwd.length + 1) : p;
8415
8693
  out.push(...this.#globEntrypoints(cwd, rel));
8416
8694
  } else
8417
- out.push(path34.isAbsolute(p) ? p : path34.join(cwd, p));
8695
+ out.push(path35.isAbsolute(p) ? p : path35.join(cwd, p));
8418
8696
  }
8419
8697
  return out;
8420
8698
  }
8421
8699
  #getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
8422
8700
  const cwd = this.#executor.cwdPath;
8423
8701
  const entrypoints = [
8424
- ...bundle ? [path34.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
8702
+ ...bundle ? [path35.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
8425
8703
  ...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
8426
8704
  ];
8427
8705
  return {
@@ -8442,9 +8720,9 @@ class Builder {
8442
8720
  for (const relativePath of this.#globFiles(cwd)) {
8443
8721
  if (relativePath === "package.json")
8444
8722
  continue;
8445
- const sourcePath = path34.join(cwd, relativePath);
8446
- const targetPath = path34.join(this.#distExecutor.cwdPath, relativePath);
8447
- await mkdir9(path34.dirname(targetPath), { recursive: true });
8723
+ const sourcePath = path35.join(cwd, relativePath);
8724
+ const targetPath = path35.join(this.#distExecutor.cwdPath, relativePath);
8725
+ await mkdir9(path35.dirname(targetPath), { recursive: true });
8448
8726
  await Bun.write(targetPath, Bun.file(sourcePath));
8449
8727
  }
8450
8728
  }
@@ -8455,13 +8733,13 @@ class Builder {
8455
8733
  return withoutFormatDir;
8456
8734
  if (!hasDotSlash && withoutFormatDir === publishedPath)
8457
8735
  return publishedPath;
8458
- const parsed = path34.posix.parse(withoutFormatDir);
8736
+ const parsed = path35.posix.parse(withoutFormatDir);
8459
8737
  if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
8460
8738
  return withoutFormatDir;
8461
- const withoutExt = path34.posix.join(parsed.dir, parsed.name);
8739
+ const withoutExt = path35.posix.join(parsed.dir, parsed.name);
8462
8740
  const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
8463
8741
  const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
8464
- const matchedSource = sourceCandidates.find((candidate) => existsSync2(path34.join(this.#executor.cwdPath, candidate)));
8742
+ const matchedSource = sourceCandidates.find((candidate) => existsSync2(path35.join(this.#executor.cwdPath, candidate)));
8465
8743
  if (!matchedSource)
8466
8744
  return withoutFormatDir;
8467
8745
  return hasDotSlash ? `./${matchedSource}` : matchedSource;
@@ -8511,9 +8789,9 @@ class Builder {
8511
8789
  }
8512
8790
  // pkgs/@akanjs/devkit/capacitorApp.ts
8513
8791
  import { cp as cp2, mkdir as mkdir10, rm as rm4 } from "fs/promises";
8514
- import path35 from "path";
8792
+ import path36 from "path";
8515
8793
  import { MobileProject } from "@trapezedev/project";
8516
- import { capitalize as capitalize2 } from "akanjs/common";
8794
+ import { capitalize as capitalize3 } from "akanjs/common";
8517
8795
 
8518
8796
  // pkgs/@akanjs/devkit/fileEditor.ts
8519
8797
  class FileEditor {
@@ -8706,10 +8984,10 @@ class CapacitorApp {
8706
8984
  constructor(app, target) {
8707
8985
  this.app = app;
8708
8986
  this.target = target;
8709
- this.targetRootPath = path35.posix.join(".akan", "mobile", this.target.name);
8710
- this.targetRoot = path35.join(this.app.cwdPath, this.targetRootPath);
8711
- this.targetWebRoot = path35.join(this.targetRoot, "www");
8712
- this.targetAssetRoot = path35.join(this.targetRoot, "assets");
8987
+ this.targetRootPath = path36.posix.join(".akan", "mobile", this.target.name);
8988
+ this.targetRoot = path36.join(this.app.cwdPath, this.targetRootPath);
8989
+ this.targetWebRoot = path36.join(this.targetRoot, "www");
8990
+ this.targetAssetRoot = path36.join(this.targetRoot, "assets");
8713
8991
  this.project = new MobileProject(this.app.cwdPath, {
8714
8992
  android: { path: this.androidRootPath },
8715
8993
  ios: { path: this.iosProjectPath }
@@ -8725,9 +9003,9 @@ class CapacitorApp {
8725
9003
  await this.#writeCapacitorConfig();
8726
9004
  if (regenerate) {
8727
9005
  if (!platform || platform === "ios")
8728
- await rm4(path35.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
9006
+ await rm4(path36.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
8729
9007
  if (!platform || platform === "android")
8730
- await rm4(path35.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
9008
+ await rm4(path36.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
8731
9009
  }
8732
9010
  const project = this.project;
8733
9011
  await this.project.load();
@@ -8791,7 +9069,7 @@ class CapacitorApp {
8791
9069
  await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
8792
9070
  }
8793
9071
  async#updateAndroidBuildTypes() {
8794
- const appGradle = await FileEditor.create(path35.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
9072
+ const appGradle = await FileEditor.create(path36.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
8795
9073
  const buildTypesBlock = `
8796
9074
  debug {
8797
9075
  applicationIdSuffix ".debug"
@@ -8834,7 +9112,7 @@ class CapacitorApp {
8834
9112
  const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
8835
9113
  await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
8836
9114
  stdio: "inherit",
8837
- cwd: path35.join(this.app.cwdPath, this.androidRootPath),
9115
+ cwd: path36.join(this.app.cwdPath, this.androidRootPath),
8838
9116
  env: await this.#commandEnv("release", env)
8839
9117
  });
8840
9118
  }
@@ -8842,10 +9120,10 @@ class CapacitorApp {
8842
9120
  await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
8843
9121
  }
8844
9122
  async#ensureAndroidAssetsDir() {
8845
- await mkdir10(path35.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
9123
+ await mkdir10(path36.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
8846
9124
  }
8847
9125
  async#ensureAndroidDebugKeystore() {
8848
- const keystorePath = path35.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
9126
+ const keystorePath = path36.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
8849
9127
  if (await Bun.file(keystorePath).exists())
8850
9128
  return;
8851
9129
  await this.#spawn("keytool", [
@@ -8891,12 +9169,12 @@ class CapacitorApp {
8891
9169
  await this.#prepareAndroid({ operation: "release", env: "main" });
8892
9170
  }
8893
9171
  async prepareWww() {
8894
- const htmlSource = path35.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
9172
+ const htmlSource = path36.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
8895
9173
  if (!await Bun.file(htmlSource).exists())
8896
9174
  throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
8897
9175
  await rm4(this.targetWebRoot, { recursive: true, force: true });
8898
9176
  await mkdir10(this.targetWebRoot, { recursive: true });
8899
- await Bun.write(path35.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
9177
+ await Bun.write(path36.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
8900
9178
  }
8901
9179
  #injectMobileTargetMeta(html) {
8902
9180
  const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
@@ -8908,7 +9186,7 @@ class CapacitorApp {
8908
9186
  }
8909
9187
  async#writeCapacitorConfig() {
8910
9188
  await mkdir10(this.targetRoot, { recursive: true });
8911
- const appInfoPath = path35.relative(this.app.cwdPath, path35.join(this.app.cwdPath, "akan.app.json")).split(path35.sep).join("/");
9189
+ const appInfoPath = path36.relative(this.app.cwdPath, path36.join(this.app.cwdPath, "akan.app.json")).split(path36.sep).join("/");
8912
9190
  const content = `import type { AppScanResult } from "akanjs";
8913
9191
  import { withBase } from "${process.env.USE_AKANJS_PKGS === "true" ? "../../pkgs/" : ""}akanjs/capacitor.base.config";
8914
9192
  import appInfo from "${appInfoPath.startsWith(".") ? appInfoPath : `./${appInfoPath}`}";
@@ -8929,18 +9207,18 @@ export default withBase(
8929
9207
  appInfo as AppScanResult,
8930
9208
  );
8931
9209
  `;
8932
- await Bun.write(path35.join(this.app.cwdPath, "capacitor.config.ts"), content);
9210
+ await Bun.write(path36.join(this.app.cwdPath, "capacitor.config.ts"), content);
8933
9211
  }
8934
9212
  async#prepareTargetAssets() {
8935
9213
  if (!this.target.assets)
8936
9214
  return;
8937
9215
  await mkdir10(this.targetAssetRoot, { recursive: true });
8938
9216
  if (this.target.assets.icon)
8939
- await cp2(path35.join(this.app.cwdPath, this.target.assets.icon), path35.join(this.targetAssetRoot, "icon.png"), {
9217
+ await cp2(path36.join(this.app.cwdPath, this.target.assets.icon), path36.join(this.targetAssetRoot, "icon.png"), {
8940
9218
  force: true
8941
9219
  });
8942
9220
  if (this.target.assets.splash)
8943
- await cp2(path35.join(this.app.cwdPath, this.target.assets.splash), path35.join(this.targetAssetRoot, "splash.png"), {
9221
+ await cp2(path36.join(this.app.cwdPath, this.target.assets.splash), path36.join(this.targetAssetRoot, "splash.png"), {
8944
9222
  force: true
8945
9223
  });
8946
9224
  }
@@ -8948,11 +9226,11 @@ export default withBase(
8948
9226
  const files = this.target.files?.[platform];
8949
9227
  if (!files)
8950
9228
  return;
8951
- const platformRoot = path35.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
9229
+ const platformRoot = path36.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
8952
9230
  await Promise.all(Object.entries(files).map(async ([to, from]) => {
8953
- const targetPath = path35.join(platformRoot, to);
8954
- await mkdir10(path35.dirname(targetPath), { recursive: true });
8955
- await cp2(path35.join(this.app.cwdPath, from), targetPath, { force: true });
9231
+ const targetPath = path36.join(platformRoot, to);
9232
+ await mkdir10(path36.dirname(targetPath), { recursive: true });
9233
+ await cp2(path36.join(this.app.cwdPath, from), targetPath, { force: true });
8956
9234
  }));
8957
9235
  }
8958
9236
  async#generateAssets({ operation, env }) {
@@ -8962,7 +9240,7 @@ export default withBase(
8962
9240
  "@capacitor/assets",
8963
9241
  "generate",
8964
9242
  "--assetPath",
8965
- path35.posix.join(this.targetRootPath, "assets"),
9243
+ path36.posix.join(this.targetRootPath, "assets"),
8966
9244
  "--iosProject",
8967
9245
  this.iosProjectPath,
8968
9246
  "--androidProject",
@@ -9064,7 +9342,7 @@ export default withBase(
9064
9342
  this.#setPermissionsInAndroid(["POST_NOTIFICATIONS"]);
9065
9343
  }
9066
9344
  async#setPermissionInIos(permissions) {
9067
- const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize2(key)}`, value]));
9345
+ const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize3(key)}`, value]));
9068
9346
  await Promise.all([
9069
9347
  this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
9070
9348
  this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs)
@@ -9149,15 +9427,15 @@ var Pkg = createInternalArgToken("Pkg");
9149
9427
  var Module = createInternalArgToken("Module");
9150
9428
  var Workspace = createInternalArgToken("Workspace");
9151
9429
  // pkgs/@akanjs/devkit/commandDecorators/command.ts
9152
- import path36 from "path";
9430
+ import path37 from "path";
9153
9431
  import { confirm, input as input2, select as select2 } from "@inquirer/prompts";
9154
9432
  import { Logger as Logger10 } from "akanjs/common";
9155
9433
  import chalk6 from "chalk";
9156
9434
  import { program } from "commander";
9157
9435
 
9158
9436
  // pkgs/@akanjs/devkit/commandDecorators/dependencyBuilder.ts
9159
- var capitalize3 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
9160
- var createDependencyKey = (refName, kind) => `${refName}${capitalize3(kind)}`;
9437
+ var capitalize4 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
9438
+ var createDependencyKey = (refName, kind) => `${refName}${capitalize4(kind)}`;
9161
9439
 
9162
9440
  class CommandContainer {
9163
9441
  static #instances = new Map;
@@ -9649,7 +9927,7 @@ var runCommands = async (...commands) => {
9649
9927
  process.exit(1);
9650
9928
  });
9651
9929
  const __dirname2 = getDirname(import.meta.url);
9652
- const packageJsonCandidates = [`${path36.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
9930
+ const packageJsonCandidates = [`${path37.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
9653
9931
  let cliPackageJson = null;
9654
9932
  for (const packageJsonPath of packageJsonCandidates) {
9655
9933
  if (!await FileSys.fileExists(packageJsonPath))
@@ -9925,8 +10203,8 @@ var scanModuleSpecifiers = (source, filePath, includeExports) => {
9925
10203
  return importSpecifiers;
9926
10204
  };
9927
10205
  var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
9928
- const configFile = ts7.readConfigFile(tsConfigPath, (path37) => {
9929
- return ts7.sys.readFile(path37);
10206
+ const configFile = ts7.readConfigFile(tsConfigPath, (path38) => {
10207
+ return ts7.sys.readFile(path38);
9930
10208
  });
9931
10209
  return ts7.parseJsonConfigFileContent(configFile.config, ts7.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
9932
10210
  };
@@ -10075,10 +10353,7 @@ import { input as input3, select as select3 } from "@inquirer/prompts";
10075
10353
  class Prompter {
10076
10354
  static async#getGuidelineRoot() {
10077
10355
  const dirname2 = getDirname(import.meta.url);
10078
- const candidates = [
10079
- `${dirname2}/guidelines`,
10080
- `${dirname2}/../cli/guidelines`
10081
- ];
10356
+ const candidates = [`${dirname2}/guidelines`, `${dirname2}/../cli/guidelines`];
10082
10357
  for (const candidate of candidates) {
10083
10358
  try {
10084
10359
  await fsPromise.access(candidate);
@@ -10089,12 +10364,16 @@ class Prompter {
10089
10364
  }
10090
10365
  static async selectGuideline() {
10091
10366
  const guidelineRoot = await Prompter.#getGuidelineRoot();
10092
- const guideNames = (await fsPromise.readdir(guidelineRoot)).filter((name) => !name.startsWith("_"));
10367
+ const guideNames = await Prompter.listGuidelines();
10093
10368
  return await select3({
10094
10369
  message: "Select a guideline",
10095
10370
  choices: guideNames.map((name) => ({ name, value: name }))
10096
10371
  });
10097
10372
  }
10373
+ static async listGuidelines() {
10374
+ const guidelineRoot = await Prompter.#getGuidelineRoot();
10375
+ return (await fsPromise.readdir(guidelineRoot)).filter((name) => !name.startsWith("_")).sort();
10376
+ }
10098
10377
  static async getGuideJson(guideName) {
10099
10378
  const guidelineRoot = await Prompter.#getGuidelineRoot();
10100
10379
  const filePath = `${guidelineRoot}/${guideName}/${guideName}.generate.json`;
@@ -10165,12 +10444,106 @@ import { Box as Box2, Newline, Text as Text2, useInput as useInput2 } from "ink"
10165
10444
  import { useEffect as useEffect3, useState as useState3 } from "react";
10166
10445
  import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime";
10167
10446
  "use client";
10447
+ // pkgs/@akanjs/cli/agent/agent.script.ts
10448
+ import { Logger as Logger11 } from "akanjs/common";
10449
+
10450
+ // pkgs/@akanjs/cli/agent/agent.runner.ts
10451
+ var targetPaths = {
10452
+ cursor: ".cursor/rules/akan.mdc",
10453
+ "agents-md": "AGENTS.md",
10454
+ claude: "CLAUDE.md"
10455
+ };
10456
+ var targetTitle = {
10457
+ cursor: "Akan Cursor Rules",
10458
+ "agents-md": "Akan Agent Rules",
10459
+ claude: "Akan Claude Rules"
10460
+ };
10461
+ var renderAgentRules = async (workspace, target) => {
10462
+ const context = await AkanContextAnalyzer.analyze(workspace);
10463
+ const frameworkGuide = await Prompter.getInstruction("framework");
10464
+ return `# ${targetTitle[target]}
10465
+
10466
+ This file is generated by \`akan agent install ${target}\`.
10467
+
10468
+ ## Workspace
10469
+
10470
+ - Repo: ${context.repoName}
10471
+ - Apps: ${context.apps.map((app) => app.name).join(", ") || "none"}
10472
+ - Libraries: ${context.libs.map((lib) => lib.name).join(", ") || "none"}
10473
+ - Packages: ${context.pkgs.map((pkg) => pkg.name).join(", ") || "none"}
10474
+
10475
+ ## Akan Module Abstracts
10476
+
10477
+ - Before changing a domain, service, or scalar module, read its \`*.abstract.md\` file first.
10478
+ - Update the abstract when business invariants, workflows, or public behavior change.
10479
+ - Do not update the abstract for formatting-only, import-only, or style-only changes.
10480
+ - Service modules live in \`lib/_<service>\`, but their abstract file is \`<service>.abstract.md\`.
10481
+
10482
+ ## Generated Files
10483
+
10484
+ Do not hand-edit generated registry files such as ${context.generatedFiles.map((file) => `\`${file}\``).join(", ")}.
10485
+
10486
+ ## Validation
10487
+
10488
+ ${context.validationCommands.map((command3) => `- \`${command3}\``).join(`
10489
+ `)}
10490
+
10491
+ ## Framework Guide
10492
+
10493
+ ${frameworkGuide.trim()}
10494
+ `;
10495
+ };
10496
+
10497
+ class AgentRunner extends runner("agent") {
10498
+ async install(workspace, targets, { force = false } = {}) {
10499
+ const written = [];
10500
+ for (const target of targets) {
10501
+ const filePath = targetPaths[target];
10502
+ if (!force && await workspace.exists(filePath)) {
10503
+ throw new Error(`${filePath} already exists. Re-run with --force to overwrite it.`);
10504
+ }
10505
+ const content = await renderAgentRules(workspace, target);
10506
+ await workspace.writeFile(filePath, content, { overwrite: force });
10507
+ written.push(filePath);
10508
+ }
10509
+ return written;
10510
+ }
10511
+ }
10512
+
10513
+ // pkgs/@akanjs/cli/agent/agent.script.ts
10514
+ var resolveTargets = (target) => {
10515
+ if (!target || target === "all")
10516
+ return ["cursor", "agents-md", "claude"];
10517
+ if (target === "cursor" || target === "agents-md" || target === "claude")
10518
+ return [target];
10519
+ throw new Error(`Unknown agent target: ${target}. Use cursor, agents-md, claude, or all.`);
10520
+ };
10521
+
10522
+ class AgentScript extends script("agent", [AgentRunner]) {
10523
+ async agent(workspace, action, target, { force = false } = {}) {
10524
+ if (action !== "install")
10525
+ throw new Error(`Unknown agent action: ${action}. Use "install".`);
10526
+ const written = await this.agentRunner.install(workspace, resolveTargets(target), { force });
10527
+ Logger11.rawLog(`Agent rules written:
10528
+ ${written.map((file) => `- ${file}`).join(`
10529
+ `)}`);
10530
+ }
10531
+ }
10532
+
10533
+ // pkgs/@akanjs/cli/agent/agent.command.ts
10534
+ class AgentCommand extends command("agent", [AgentScript], ({ public: target }) => ({
10535
+ agent: target({ desc: "Install Akan agent rules for editors and coding agents" }).arg("action", String, { desc: "install" }).arg("target", String, { desc: "cursor, agents-md, claude, or all", nullable: true }).option("force", Boolean, { desc: "overwrite existing rule files", default: false }).with(Workspace).exec(async function(action, targetName, force, workspace) {
10536
+ await this.agentScript.agent(workspace, action, targetName, { force });
10537
+ })
10538
+ })) {
10539
+ }
10540
+
10168
10541
  // pkgs/@akanjs/cli/application/application.command.ts
10169
10542
  import { select as select6 } from "@inquirer/prompts";
10170
10543
 
10171
10544
  // pkgs/@akanjs/cli/application/application.script.ts
10172
10545
  import { confirm as confirm3 } from "@inquirer/prompts";
10173
- import { Logger as Logger12 } from "akanjs/common";
10546
+ import { Logger as Logger13 } from "akanjs/common";
10174
10547
 
10175
10548
  // pkgs/@akanjs/cli/semver.ts
10176
10549
  function parseVersion(version) {
@@ -10288,7 +10661,7 @@ import { StringOutputParser } from "@langchain/core/output_parsers";
10288
10661
  import { PromptTemplate as PromptTemplate2 } from "@langchain/core/prompts";
10289
10662
  import { RunnableSequence as RunnableSequence2 } from "@langchain/core/runnables";
10290
10663
  import { ChatOpenAI as ChatOpenAI3 } from "@langchain/openai";
10291
- import { Logger as Logger11 } from "akanjs/common";
10664
+ import { Logger as Logger12 } from "akanjs/common";
10292
10665
  import ora3 from "ora";
10293
10666
 
10294
10667
  // pkgs/@akanjs/cli/openBrowser.ts
@@ -10343,6 +10716,37 @@ class ApplicationRunner extends runner("application") {
10343
10716
  stdio: "inherit"
10344
10717
  });
10345
10718
  }
10719
+ async runConsole(app) {
10720
+ const serverPath = `${app.cwdPath}/server.ts`;
10721
+ if (!await app.exists("server.ts"))
10722
+ throw new Error(`Server file not found: apps/${app.name}/server.ts`);
10723
+ const code = `
10724
+ const serverModule = await import(${JSON.stringify(serverPath)});
10725
+ const { assertAkanConsoleAllowed, startAkanConsole } = await import("akanjs/server");
10726
+ const server = serverModule.server;
10727
+ if (!server?.start) throw new Error("server.ts must export server with start()");
10728
+ assertAkanConsoleAllowed(server.env);
10729
+ await server.start({ listen: false, web: false });
10730
+ try {
10731
+ await startAkanConsole(server, {
10732
+ globals: {
10733
+ srv: serverModule.srv,
10734
+ sig: serverModule.sig,
10735
+ db: serverModule.db,
10736
+ cnst: serverModule.cnst,
10737
+ dict: serverModule.dict,
10738
+ option: serverModule.option,
10739
+ },
10740
+ });
10741
+ } finally {
10742
+ await server.stop();
10743
+ }
10744
+ `;
10745
+ await app.spawn("bun", ["-e", code], {
10746
+ env: app.getCommandEnv({ AKAN_COMMAND_TYPE: "console" }),
10747
+ stdio: "inherit"
10748
+ });
10749
+ }
10346
10750
  async typecheck(app, options = {}) {
10347
10751
  await new ApplicationBuildRunner(app).typecheck(options);
10348
10752
  }
@@ -10477,7 +10881,7 @@ class ApplicationRunner extends runner("application") {
10477
10881
  return;
10478
10882
  for (const failure of failures) {
10479
10883
  const message = failure.error instanceof Error ? failure.error.message : String(failure.error);
10480
- Logger11.rawLog(`Mobile target ${failure.target} failed: ${message}`, undefined, "error");
10884
+ Logger12.rawLog(`Mobile target ${failure.target} failed: ${message}`, undefined, "error");
10481
10885
  }
10482
10886
  throw new Error(`${failures.length}/${results.length} mobile targets failed`);
10483
10887
  }
@@ -10650,6 +11054,10 @@ class ApplicationScript extends script("application", [
10650
11054
  await app.scanSync();
10651
11055
  await this.applicationRunner.runScript(app, scriptFilename);
10652
11056
  }
11057
+ async console(app) {
11058
+ await app.scanSync();
11059
+ await this.applicationRunner.runConsole(app);
11060
+ }
10653
11061
  async build(app, {
10654
11062
  write = true,
10655
11063
  fast = false,
@@ -10657,18 +11065,18 @@ class ApplicationScript extends script("application", [
10657
11065
  } = {}) {
10658
11066
  await app.scanSync({ write });
10659
11067
  if (!quiet)
10660
- Logger12.rawLog(`Creating an optimized production build for ${app.name}...`);
11068
+ Logger13.rawLog(`Creating an optimized production build for ${app.name}...`);
10661
11069
  try {
10662
11070
  const result = await this.applicationRunner.build(app, {
10663
11071
  fast,
10664
11072
  spinner: !quiet
10665
11073
  });
10666
- Logger12.rawLog(`${app.name} built in dist/apps/${app.name}`);
11074
+ Logger13.rawLog(`${app.name} built in dist/apps/${app.name}`);
10667
11075
  if (!quiet)
10668
11076
  ApplicationBuildReporter.printSummary(result);
10669
11077
  } catch (error) {
10670
- Logger12.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
10671
- Logger12.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
11078
+ Logger13.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
11079
+ Logger13.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
10672
11080
  throw error;
10673
11081
  }
10674
11082
  }
@@ -10684,7 +11092,7 @@ class ApplicationScript extends script("application", [
10684
11092
  spinner2.succeed(`${app.name} typechecked`);
10685
11093
  } catch (error) {
10686
11094
  spinner2.fail(`${app.name} typecheck failed`);
10687
- Logger12.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
11095
+ Logger13.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
10688
11096
  throw error;
10689
11097
  }
10690
11098
  }
@@ -10866,6 +11274,9 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
10866
11274
  script: target({ desc: "Run a custom script in the application" }).with(App).arg("filename", String, { desc: "name of script", nullable: true }).exec(async function(app, filename) {
10867
11275
  await this.applicationScript.script(app, filename);
10868
11276
  }),
11277
+ console: target({ desc: "Open an interactive server console for the application" }).with(App).exec(async function(app) {
11278
+ await this.applicationScript.console(app);
11279
+ }),
10869
11280
  build: target({ short: true, desc: "Build the application for production (frontend + backend)" }).with(App).option("write", Boolean, { desc: "write code generation", default: true }).option("fast", Boolean, { desc: "fast build", default: false }).option("quiet", Boolean, { desc: "hide build progress output", default: false }).exec(async function(app, write, fast, quiet) {
10870
11281
  await this.applicationScript.build(app, { write, fast, quiet });
10871
11282
  }),
@@ -10987,11 +11398,11 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
10987
11398
  }
10988
11399
 
10989
11400
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
10990
- import { Logger as Logger15 } from "akanjs/common";
11401
+ import { Logger as Logger16 } from "akanjs/common";
10991
11402
 
10992
11403
  // pkgs/@akanjs/cli/package/package.runner.ts
10993
- import path37 from "path";
10994
- import { Logger as Logger13 } from "akanjs/common";
11404
+ import path38 from "path";
11405
+ import { Logger as Logger14 } from "akanjs/common";
10995
11406
  var {$: $2 } = globalThis.Bun;
10996
11407
 
10997
11408
  class PackageRunner extends runner("package") {
@@ -10999,16 +11410,16 @@ class PackageRunner extends runner("package") {
10999
11410
  const pkgJson = process.env.USE_AKANJS_PKGS === "true" ? await FileSys.readJson(`${workspace?.workspaceRoot ?? process.cwd()}/pkgs/akanjs/package.json`) : await this.#getInstalledPackageJson();
11000
11411
  const version = pkgJson.name === "akanjs" ? pkgJson.version : pkgJson.dependencies?.akanjs ?? pkgJson.version;
11001
11412
  if (log)
11002
- Logger13.rawLog(`akanjs@${version}`);
11413
+ Logger14.rawLog(`akanjs@${version}`);
11003
11414
  return version;
11004
11415
  }
11005
11416
  async#getInstalledPackageJson() {
11006
11417
  const packageJsonCandidates = [
11007
- `${path37.dirname(Bun.main)}/package.json`,
11418
+ `${path38.dirname(Bun.main)}/package.json`,
11008
11419
  `${process.cwd()}/node_modules/akanjs/package.json`
11009
11420
  ];
11010
11421
  try {
11011
- packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path37.dirname(Bun.main)));
11422
+ packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path38.dirname(Bun.main)));
11012
11423
  } catch {}
11013
11424
  for (const packageJsonPath of packageJsonCandidates) {
11014
11425
  if (!await Bun.file(packageJsonPath).exists())
@@ -11017,7 +11428,7 @@ class PackageRunner extends runner("package") {
11017
11428
  if (packageJson.name === "akanjs" || packageJson.name === "@akanjs/cli")
11018
11429
  return packageJson;
11019
11430
  }
11020
- throw new Error(`[package] failed to locate akanjs package.json from ${path37.dirname(Bun.main)}`);
11431
+ throw new Error(`[package] failed to locate akanjs package.json from ${path38.dirname(Bun.main)}`);
11021
11432
  }
11022
11433
  async createPackage(workspace, pkgName) {
11023
11434
  await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
@@ -11125,9 +11536,9 @@ class PackageScript extends script("package", [PackageRunner]) {
11125
11536
  }
11126
11537
 
11127
11538
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
11128
- import path38 from "path";
11539
+ import path39 from "path";
11129
11540
  import { confirm as confirm4, input as input5, select as select7 } from "@inquirer/prompts";
11130
- import { Logger as Logger14, sleep } from "akanjs/common";
11541
+ import { Logger as Logger15, sleep } from "akanjs/common";
11131
11542
  import chalk7 from "chalk";
11132
11543
  import * as QRcode from "qrcode";
11133
11544
 
@@ -11202,7 +11613,7 @@ class CloudRunner extends runner("cloud") {
11202
11613
  const servers = await GlobalConfig.getRemoteEnvServers();
11203
11614
  const serverEntries = Object.entries(servers).sort(([nameA], [nameB]) => nameA.localeCompare(nameB));
11204
11615
  if (serverEntries.length === 0) {
11205
- Logger14.info("No remote env servers configured. Add the first remote server for SCP mode.");
11616
+ Logger15.info("No remote env servers configured. Add the first remote server for SCP mode.");
11206
11617
  return await this.#addRemoteEnvServer();
11207
11618
  }
11208
11619
  const selectedName = await select7({
@@ -11242,7 +11653,7 @@ class CloudRunner extends runner("cloud") {
11242
11653
  if (!shouldRemove)
11243
11654
  return;
11244
11655
  await GlobalConfig.removeRemoteEnvServer(selectedName);
11245
- Logger14.info(`Removed remote env server "${selectedName}"`);
11656
+ Logger15.info(`Removed remote env server "${selectedName}"`);
11246
11657
  }
11247
11658
  async#getRemoteEnvServerWithUsername() {
11248
11659
  const remoteServer = await this.#selectRemoteEnvServer();
@@ -11283,17 +11694,17 @@ class CloudRunner extends runner("cloud") {
11283
11694
  const cloudApi2 = new CloudApi(workspace, config);
11284
11695
  const self = config.auth ? await cloudApi2.getRemoteSelf() : null;
11285
11696
  if (self) {
11286
- Logger14.rawLog(chalk7.green(`
11697
+ Logger15.rawLog(chalk7.green(`
11287
11698
  \u2713 Already logged in akan cloud as ${self.nickname}
11288
11699
  `));
11289
11700
  return true;
11290
11701
  }
11291
11702
  const remoteId = crypto.randomUUID();
11292
11703
  const signinUrl = `${cloudApi2.host}/remoteAuth?remoteId=${encodeURIComponent(remoteId)}`;
11293
- Logger14.rawLog(chalk7.bold(`
11704
+ Logger15.rawLog(chalk7.bold(`
11294
11705
  ${chalk7.green("\u27A4")} Authentication Required`));
11295
- Logger14.rawLog(chalk7.dim("Please visit or click the following URL:"));
11296
- Logger14.rawLog(`${chalk7.cyan.underline(signinUrl)}
11706
+ Logger15.rawLog(chalk7.dim("Please visit or click the following URL:"));
11707
+ Logger15.rawLog(`${chalk7.cyan.underline(signinUrl)}
11297
11708
  `);
11298
11709
  try {
11299
11710
  const qrcode = await new Promise((resolve, reject) => {
@@ -11303,23 +11714,23 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11303
11714
  resolve(data);
11304
11715
  });
11305
11716
  });
11306
- Logger14.rawLog(qrcode);
11717
+ Logger15.rawLog(qrcode);
11307
11718
  await openBrowser(signinUrl);
11308
- Logger14.rawLog(chalk7.dim("Opening browser..."));
11719
+ Logger15.rawLog(chalk7.dim("Opening browser..."));
11309
11720
  } catch {
11310
- Logger14.rawLog(chalk7.yellow("Could not open browser. Please visit the URL manually."));
11721
+ Logger15.rawLog(chalk7.yellow("Could not open browser. Please visit the URL manually."));
11311
11722
  }
11312
- Logger14.rawLog(chalk7.dim("Waiting for authentication..."));
11723
+ Logger15.rawLog(chalk7.dim("Waiting for authentication..."));
11313
11724
  const MAX_RETRY = 300;
11314
11725
  for (let i = 0;i < MAX_RETRY; i++) {
11315
11726
  const accessToken = await cloudApi2.getRemoteAuthToken(remoteId);
11316
11727
  const self2 = await cloudApi2.getRemoteSelf();
11317
11728
  if (accessToken && self2) {
11318
11729
  await GlobalConfig.setHostConfig({ host: config.host, auth: { accessToken, self: self2 } });
11319
- Logger14.rawLog(chalk7.green(`\r\u2713 Authentication successful!`));
11320
- Logger14.rawLog(chalk7.green.bold(`
11730
+ Logger15.rawLog(chalk7.green(`\r\u2713 Authentication successful!`));
11731
+ Logger15.rawLog(chalk7.green.bold(`
11321
11732
  \u2728 Welcome aboard, ${self2.nickname ?? "anonymous"}!`));
11322
- Logger14.rawLog(chalk7.dim(`You're now ready to use Akan CLI!
11733
+ Logger15.rawLog(chalk7.dim(`You're now ready to use Akan CLI!
11323
11734
  `));
11324
11735
  return true;
11325
11736
  }
@@ -11331,17 +11742,17 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11331
11742
  const config = await GlobalConfig.getHostConfig(host);
11332
11743
  if (config.auth?.self) {
11333
11744
  await GlobalConfig.setHostConfig(getDefaultHostConfig(config.host));
11334
- Logger14.rawLog(chalk7.magenta.bold(`
11745
+ Logger15.rawLog(chalk7.magenta.bold(`
11335
11746
  \uD83D\uDC4B Goodbye, ${config.auth.self.nickname ?? "anonymous"}!`));
11336
- Logger14.rawLog(chalk7.dim(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
11747
+ Logger15.rawLog(chalk7.dim(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
11337
11748
  `));
11338
- Logger14.rawLog(chalk7.cyan("You have been successfully logged out."));
11339
- Logger14.rawLog(chalk7.dim(`Thank you for using Akan CLI. Come back soon! \uD83C\uDF1F
11749
+ Logger15.rawLog(chalk7.cyan("You have been successfully logged out."));
11750
+ Logger15.rawLog(chalk7.dim(`Thank you for using Akan CLI. Come back soon! \uD83C\uDF1F
11340
11751
  `));
11341
11752
  } else {
11342
- Logger14.rawLog(chalk7.yellow.bold(`
11753
+ Logger15.rawLog(chalk7.yellow.bold(`
11343
11754
  \u26A0\uFE0F No active session found`));
11344
- Logger14.rawLog(chalk7.dim(`You were not logged in to begin with
11755
+ Logger15.rawLog(chalk7.dim(`You were not logged in to begin with
11345
11756
  `));
11346
11757
  }
11347
11758
  }
@@ -11350,7 +11761,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11350
11761
  }
11351
11762
  resetLlm() {
11352
11763
  AiSession.setLlmConfig(null);
11353
- Logger14.rawLog(chalk7.green("\u2611\uFE0F LLM model config is cleared. Please run `akan set-llm` to set a new LLM model."));
11764
+ Logger15.rawLog(chalk7.green("\u2611\uFE0F LLM model config is cleared. Please run `akan set-llm` to set a new LLM model."));
11354
11765
  }
11355
11766
  async getAkanPkgs(workspace) {
11356
11767
  const pkgs = await workspace.getPkgs();
@@ -11374,8 +11785,8 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11374
11785
  }
11375
11786
  };
11376
11787
  const { nextVersion, latestPublishedVersion } = await getNextVersion(targetVersionPrefix, tag);
11377
- Logger14.info(`Latest published version of akanjs: ${latestPublishedVersion ?? "none"}`);
11378
- Logger14.info(`Next version of akanjs: ${nextVersion}`);
11788
+ Logger15.info(`Latest published version of akanjs: ${latestPublishedVersion ?? "none"}`);
11789
+ Logger15.info(`Next version of akanjs: ${nextVersion}`);
11379
11790
  for (const library of akanPkgs) {
11380
11791
  const packageJson = await workspace.readJson(`pkgs/${library}/package.json`);
11381
11792
  const newPackageJsonStr = JSON.stringify(this.#normalizeAkanPackageJson(packageJson, library, nextVersion), null, 2);
@@ -11389,20 +11800,20 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11389
11800
  message: "Are you sure you want to deploy the libraries?"
11390
11801
  });
11391
11802
  if (!isDeployConfirmed) {
11392
- Logger14.error("Deployment cancelled");
11803
+ Logger15.error("Deployment cancelled");
11393
11804
  return;
11394
11805
  }
11395
11806
  }
11396
11807
  await Promise.all(akanPkgs.map(async (library) => {
11397
- Logger14.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
11808
+ Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
11398
11809
  await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
11399
- cwd: path38.join(workspace.workspaceRoot, "dist/pkgs", library),
11810
+ cwd: path39.join(workspace.workspaceRoot, "dist/pkgs", library),
11400
11811
  env: this.#getRegistryEnv(registry),
11401
11812
  stdio: "inherit"
11402
11813
  });
11403
- Logger14.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
11814
+ Logger15.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
11404
11815
  }));
11405
- Logger14.info(`All libraries are published to ${registry ?? "npm"}`);
11816
+ Logger15.info(`All libraries are published to ${registry ?? "npm"}`);
11406
11817
  }
11407
11818
  async update(workspace, tag = "latest", { registryUrl } = {}) {
11408
11819
  const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
@@ -11454,7 +11865,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11454
11865
  await workspace.remove(localPath);
11455
11866
  }
11456
11867
  async uploadEnv(cloudApi2, workspaceId, filePath) {
11457
- const file = new File([Bun.file(filePath)], path38.basename(filePath));
11868
+ const file = new File([Bun.file(filePath)], path39.basename(filePath));
11458
11869
  await cloudApi2.uploadEnv(workspaceId, file);
11459
11870
  }
11460
11871
  async downloadEnvByScp(workspace) {
@@ -11465,7 +11876,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11465
11876
  await workspace.mkdir("local");
11466
11877
  await workspace.remove(envArchivePath);
11467
11878
  try {
11468
- Logger14.info(`Downloading env archive from remote server "${remoteServer.name}"...`);
11879
+ Logger15.info(`Downloading env archive from remote server "${remoteServer.name}"...`);
11469
11880
  await workspace.spawn("scp", this.#getScpArgs(remoteServer.config, remoteTarget, envArchivePath), {
11470
11881
  cwd: workspace.workspaceRoot,
11471
11882
  stdio: "inherit"
@@ -11488,7 +11899,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11488
11899
  cwd: workspace.workspaceRoot,
11489
11900
  stdio: "inherit"
11490
11901
  });
11491
- Logger14.info(`Uploading env archive to remote server "${remoteServer.name}"...`);
11902
+ Logger15.info(`Uploading env archive to remote server "${remoteServer.name}"...`);
11492
11903
  await workspace.spawn("scp", this.#getScpArgs(remoteServer.config, filePath, remoteTarget), {
11493
11904
  cwd: workspace.workspaceRoot,
11494
11905
  stdio: "inherit"
@@ -11512,7 +11923,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11512
11923
  await workspace.spawn("tar", ["-cf", "local/env.tar", ...envFilePaths], {
11513
11924
  cwd: workspace.workspaceRoot
11514
11925
  });
11515
- Logger14.info(`Archived ${envFilePaths.length} environment files to local/env.tar`);
11926
+ Logger15.info(`Archived ${envFilePaths.length} environment files to local/env.tar`);
11516
11927
  return { files: envFilePaths, path: "local/env.tar" };
11517
11928
  }
11518
11929
  }
@@ -11546,13 +11957,13 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
11546
11957
  }
11547
11958
  async uploadEnv(workspace) {
11548
11959
  const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
11549
- const { path: path39 } = await this.cloudRunner.gatherEnvFiles(workspace);
11960
+ const { path: path40 } = await this.cloudRunner.gatherEnvFiles(workspace);
11550
11961
  if (workspaceId) {
11551
11962
  const cloudApi2 = await CloudApi.fromHost(workspace);
11552
- await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path39);
11963
+ await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path40);
11553
11964
  return;
11554
11965
  }
11555
- await this.cloudRunner.uploadEnvByScp(workspace, path39);
11966
+ await this.cloudRunner.uploadEnvByScp(workspace, path40);
11556
11967
  }
11557
11968
  async deployAkan(workspace, { test = true, registryUrl } = {}) {
11558
11969
  const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
@@ -11569,7 +11980,7 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
11569
11980
  const spinner2 = workspace.spinning("Updating Akan.js packages and CLI...");
11570
11981
  await this.cloudRunner.update(workspace, tag, { registryUrl });
11571
11982
  spinner2.succeed("Akan.js packages and CLI updated, global version is below");
11572
- Logger15.raw("> Akan version: ");
11983
+ Logger16.raw("> Akan version: ");
11573
11984
  await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
11574
11985
  }
11575
11986
  }
@@ -11643,6 +12054,235 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
11643
12054
  })) {
11644
12055
  }
11645
12056
 
12057
+ // pkgs/@akanjs/cli/context/context.script.ts
12058
+ import { Logger as Logger17 } from "akanjs/common";
12059
+
12060
+ // pkgs/@akanjs/cli/context/context.runner.ts
12061
+ var jsonText = (value) => JSON.stringify(value, null, 2);
12062
+ var renderDoctorText = (result) => {
12063
+ if (result.diagnostics.length === 0)
12064
+ return `No Akan workspace diagnostics found.
12065
+ `;
12066
+ return `${result.diagnostics.map((diagnostic) => [
12067
+ `[${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`,
12068
+ diagnostic.path ? ` ${diagnostic.path}` : ""
12069
+ ].filter(Boolean).join(`
12070
+ `)).join(`
12071
+
12072
+ `)}
12073
+ `;
12074
+ };
12075
+ var resourceList = [
12076
+ { uri: "akan://docs/framework", name: "Akan framework guide", mimeType: "text/markdown" },
12077
+ { uri: "akan://guidelines/framework", name: "Framework guideline", mimeType: "text/markdown" },
12078
+ { uri: "akan://guidelines/modelSignal", name: "Model signal guideline", mimeType: "text/markdown" },
12079
+ { uri: "akan://workspace/summary", name: "Workspace summary", mimeType: "application/json" },
12080
+ { uri: "akan://workspace/apps", name: "Workspace apps", mimeType: "application/json" },
12081
+ { uri: "akan://workspace/modules", name: "Workspace modules", mimeType: "application/json" }
12082
+ ];
12083
+
12084
+ class ContextRunner extends runner("context") {
12085
+ async getContext(workspace, {
12086
+ format = "markdown",
12087
+ app = null,
12088
+ module = null
12089
+ } = {}) {
12090
+ const context = await AkanContextAnalyzer.analyze(workspace, {
12091
+ app,
12092
+ module,
12093
+ includeAbstractContent: !!module
12094
+ });
12095
+ return format === "json" ? `${jsonText(context)}
12096
+ ` : AkanContextAnalyzer.renderMarkdown(context, { module });
12097
+ }
12098
+ async doctor(workspace, { format = "text", strict = false } = {}) {
12099
+ const result = await AkanContextAnalyzer.doctor(workspace, { strict });
12100
+ return format === "json" ? `${jsonText(result)}
12101
+ ` : renderDoctorText(result);
12102
+ }
12103
+ async getGuidelineResource(name) {
12104
+ return await Prompter.getInstruction(name);
12105
+ }
12106
+ async runMcp(workspace) {
12107
+ const decoder = new TextDecoder;
12108
+ let buffer = "";
12109
+ const respond = (id, result) => {
12110
+ const payload = JSON.stringify({ jsonrpc: "2.0", id, result });
12111
+ process.stdout.write(`Content-Length: ${Buffer.byteLength(payload)}\r
12112
+ \r
12113
+ ${payload}`);
12114
+ };
12115
+ const respondError = (id, code, message) => {
12116
+ const payload = JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
12117
+ process.stdout.write(`Content-Length: ${Buffer.byteLength(payload)}\r
12118
+ \r
12119
+ ${payload}`);
12120
+ };
12121
+ const readResource = async (uri) => {
12122
+ const context = await AkanContextAnalyzer.analyze(workspace);
12123
+ if (uri === "akan://docs/framework" || uri === "akan://guidelines/framework")
12124
+ return { uri, mimeType: "text/markdown", text: await Prompter.getInstruction("framework") };
12125
+ if (uri === "akan://guidelines/modelSignal")
12126
+ return { uri, mimeType: "text/markdown", text: await Prompter.getInstruction("modelSignal") };
12127
+ if (uri === "akan://workspace/summary")
12128
+ return { uri, mimeType: "application/json", text: jsonText(context) };
12129
+ if (uri === "akan://workspace/apps")
12130
+ return { uri, mimeType: "application/json", text: jsonText(context.apps) };
12131
+ if (uri === "akan://workspace/modules")
12132
+ return { uri, mimeType: "application/json", text: jsonText(AkanContextAnalyzer.findModules(context)) };
12133
+ const abstractMatch = uri.match(/^akan:\/\/workspace\/modules\/(.+)\/abstract$/);
12134
+ if (abstractMatch) {
12135
+ const detailed = await AkanContextAnalyzer.analyze(workspace, {
12136
+ module: abstractMatch[1],
12137
+ includeAbstractContent: true
12138
+ });
12139
+ const abstract = AkanContextAnalyzer.findModules(detailed, abstractMatch[1])[0]?.abstract;
12140
+ return { uri, mimeType: "text/markdown", text: abstract?.content ?? "" };
12141
+ }
12142
+ throw new Error(`Unknown resource: ${uri}`);
12143
+ };
12144
+ const handle = async (request) => {
12145
+ const params = request.params ?? {};
12146
+ if (request.method === "initialize") {
12147
+ respond(request.id, {
12148
+ protocolVersion: "2024-11-05",
12149
+ capabilities: { tools: {}, resources: {} },
12150
+ serverInfo: { name: "akan", version: process.env.AKAN_VERSION ?? "0.0.0" }
12151
+ });
12152
+ } else if (request.method === "tools/list") {
12153
+ respond(request.id, {
12154
+ tools: [
12155
+ { name: "get_workspace_summary", inputSchema: { type: "object", properties: {} } },
12156
+ { name: "list_apps", inputSchema: { type: "object", properties: {} } },
12157
+ { name: "list_modules", inputSchema: { type: "object", properties: {} } },
12158
+ {
12159
+ name: "get_module_context",
12160
+ inputSchema: { type: "object", properties: { module: { type: "string" } } }
12161
+ },
12162
+ {
12163
+ name: "get_guideline",
12164
+ inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] }
12165
+ },
12166
+ {
12167
+ name: "explain_command",
12168
+ inputSchema: { type: "object", properties: { command: { type: "string" } }, required: ["command"] }
12169
+ },
12170
+ { name: "doctor_workspace", inputSchema: { type: "object", properties: { strict: { type: "boolean" } } } }
12171
+ ]
12172
+ });
12173
+ } else if (request.method === "tools/call") {
12174
+ const name = params.name;
12175
+ const args = params.arguments ?? {};
12176
+ const context = await AkanContextAnalyzer.analyze(workspace, {
12177
+ module: args.module ?? null,
12178
+ includeAbstractContent: name === "get_module_context"
12179
+ });
12180
+ const result = await (async () => {
12181
+ if (name === "get_workspace_summary")
12182
+ return context;
12183
+ if (name === "list_apps")
12184
+ return context.apps;
12185
+ if (name === "list_modules")
12186
+ return AkanContextAnalyzer.findModules(context);
12187
+ if (name === "get_module_context")
12188
+ return AkanContextAnalyzer.findModules(context, args.module);
12189
+ if (name === "get_guideline")
12190
+ return await Prompter.getInstruction(args.name);
12191
+ if (name === "doctor_workspace")
12192
+ return await AkanContextAnalyzer.doctor(workspace, { strict: !!args.strict });
12193
+ if (name === "explain_command")
12194
+ return this.explainCommand(args.command);
12195
+ throw new Error(`Unknown tool: ${name}`);
12196
+ })();
12197
+ respond(request.id, {
12198
+ content: [{ type: "text", text: typeof result === "string" ? result : jsonText(result) }]
12199
+ });
12200
+ } else if (request.method === "resources/list") {
12201
+ respond(request.id, { resources: resourceList });
12202
+ } else if (request.method === "resources/read") {
12203
+ respond(request.id, { contents: [await readResource(params.uri)] });
12204
+ } else if (!request.method.endsWith("/initialized")) {
12205
+ respondError(request.id, -32601, `Unknown method: ${request.method}`);
12206
+ }
12207
+ };
12208
+ const parse = async () => {
12209
+ while (true) {
12210
+ const headerEnd = buffer.indexOf(`\r
12211
+ \r
12212
+ `);
12213
+ if (headerEnd < 0)
12214
+ return;
12215
+ const header = buffer.slice(0, headerEnd);
12216
+ const match = /Content-Length:\s*(\d+)/i.exec(header);
12217
+ if (!match) {
12218
+ buffer = buffer.slice(headerEnd + 4);
12219
+ continue;
12220
+ }
12221
+ const length = Number(match[1]);
12222
+ const bodyStart = headerEnd + 4;
12223
+ const bodyEnd = bodyStart + length;
12224
+ if (buffer.length < bodyEnd)
12225
+ return;
12226
+ const body = buffer.slice(bodyStart, bodyEnd);
12227
+ buffer = buffer.slice(bodyEnd);
12228
+ await handle(JSON.parse(body));
12229
+ }
12230
+ };
12231
+ for await (const chunk of Bun.stdin.stream()) {
12232
+ buffer += decoder.decode(chunk);
12233
+ await parse();
12234
+ }
12235
+ }
12236
+ explainCommand(command3) {
12237
+ const explanations = {
12238
+ context: "`akan context` prints agent-readable workspace, app, module, and abstract metadata.",
12239
+ doctor: "`akan doctor` reports workspace convention diagnostics. Use `--format json` for agents.",
12240
+ "guideline show": "`akan guideline show <name>` prints an Akan codegen guideline instruction.",
12241
+ agent: "`akan agent install <target>` writes editor-specific agent rules with overwrite protection.",
12242
+ mcp: "`akan mcp` starts the read-only Akan MCP server over stdio."
12243
+ };
12244
+ return explanations[command3] ?? `No detailed explanation is available for ${command3}. Run \`akan --help\` for command help.`;
12245
+ }
12246
+ }
12247
+
12248
+ // pkgs/@akanjs/cli/context/context.script.ts
12249
+ class ContextScript extends script("context", [ContextRunner]) {
12250
+ async context(workspace, options = {}) {
12251
+ Logger17.rawLog(await this.contextRunner.getContext(workspace, options));
12252
+ }
12253
+ async doctor(workspace, options = {}) {
12254
+ Logger17.rawLog(await this.contextRunner.doctor(workspace, options));
12255
+ }
12256
+ async mcp(workspace) {
12257
+ await this.contextRunner.runMcp(workspace);
12258
+ }
12259
+ }
12260
+
12261
+ // pkgs/@akanjs/cli/context/context.command.ts
12262
+ class ContextCommand extends command("context", [ContextScript], ({ public: target }) => ({
12263
+ context: target({ desc: "Print agent-readable Akan workspace context" }).option("format", String, {
12264
+ desc: "output format",
12265
+ default: "markdown",
12266
+ enum: ["markdown", "json"]
12267
+ }).option("app", String, { desc: "app name to include", nullable: true }).option("module", String, { desc: "module name to include with abstract content", nullable: true }).with(Workspace).exec(async function(format, app, module, workspace) {
12268
+ await this.contextScript.context(workspace, { format, app, module });
12269
+ }),
12270
+ doctor: target({ desc: "Report Akan workspace convention diagnostics" }).option("format", String, {
12271
+ desc: "output format",
12272
+ default: "text",
12273
+ enum: ["text", "json"]
12274
+ }).option("strict", Boolean, { desc: "treat recommended conventions as errors", default: false }).with(Workspace).exec(async function(format, strict, workspace) {
12275
+ await this.contextScript.doctor(workspace, { format, strict });
12276
+ }),
12277
+ mcp: target({ desc: "Start the read-only Akan MCP server over stdio" }).with(Workspace).exec(async function(workspace) {
12278
+ await this.contextScript.mcp(workspace);
12279
+ })
12280
+ })) {
12281
+ }
12282
+
12283
+ // pkgs/@akanjs/cli/guideline/guideline.script.ts
12284
+ import { Logger as Logger18 } from "akanjs/common";
12285
+
11646
12286
  // pkgs/@akanjs/cli/guideline/guideline.prompt.ts
11647
12287
  import { randomPicks } from "akanjs/common";
11648
12288
 
@@ -11664,14 +12304,14 @@ class GuidelinePrompt extends Prompter {
11664
12304
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
11665
12305
  const glob = new Bun.Glob(matchPattern);
11666
12306
  const paths = [];
11667
- for await (const path39 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
11668
- if (avoidDirs.some((dir) => path39.includes(dir)))
12307
+ for await (const path40 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
12308
+ if (avoidDirs.some((dir) => path40.includes(dir)))
11669
12309
  continue;
11670
- const fileContent = await FileSys.readText(path39);
12310
+ const fileContent = await FileSys.readText(path40);
11671
12311
  const textFilter = filterText ? new RegExp(filterText) : null;
11672
12312
  if (filterText && !textFilter?.test(fileContent))
11673
12313
  continue;
11674
- paths.push(path39);
12314
+ paths.push(path40);
11675
12315
  }
11676
12316
  return paths;
11677
12317
  }
@@ -11906,6 +12546,22 @@ class GuidelineRunner extends runner("guideline") {
11906
12546
 
11907
12547
  // pkgs/@akanjs/cli/guideline/guideline.script.ts
11908
12548
  class GuidelineScript extends script("guideline", [GuidelineRunner]) {
12549
+ async guideline(action, name = null, format = "markdown") {
12550
+ if (action === "list") {
12551
+ const guidelines = await Prompter.listGuidelines();
12552
+ Logger18.rawLog(format === "json" ? JSON.stringify({ guidelines }, null, 2) : guidelines.join(`
12553
+ `));
12554
+ return;
12555
+ }
12556
+ if (action === "show") {
12557
+ if (!name)
12558
+ throw new Error("Guideline name is required. Example: akan guideline show framework");
12559
+ const [instruction, guideJson] = await Promise.all([Prompter.getInstruction(name), Prompter.getGuideJson(name)]);
12560
+ Logger18.rawLog(format === "json" ? JSON.stringify({ name, instruction, guideJson }, null, 2) : instruction);
12561
+ return;
12562
+ }
12563
+ throw new Error(`Unknown guideline action: ${action}. Use "list" or "show".`);
12564
+ }
11909
12565
  async generateInstruction(workspace, name = null) {
11910
12566
  const guideName = name ?? await Prompter.selectGuideline();
11911
12567
  await this.guidelineRunner.generateInstruction(workspace, guideName);
@@ -11934,6 +12590,13 @@ class GuidelineScript extends script("guideline", [GuidelineRunner]) {
11934
12590
 
11935
12591
  // pkgs/@akanjs/cli/guideline/guideline.command.ts
11936
12592
  class GuidelineCommand extends command("guideline", [GuidelineScript], ({ public: target }) => ({
12593
+ guideline: target({ desc: "List or show Akan AI guideline instructions" }).arg("action", String, { desc: "list or show" }).arg("name", String, { desc: "guideline name for show", nullable: true }).option("format", String, {
12594
+ desc: "output format",
12595
+ default: "markdown",
12596
+ enum: ["markdown", "json"]
12597
+ }).exec(async function(action, name, format) {
12598
+ await this.guidelineScript.guideline(action, name, format);
12599
+ }),
11937
12600
  generateInstruction: target({ devOnly: true, desc: "Generate AI development guideline/instruction for your project" }).arg("name", String, { ask: "name of the instruction", nullable: true }).with(Workspace).exec(async function(name, workspace) {
11938
12601
  await this.guidelineScript.generateInstruction(workspace, name);
11939
12602
  }),
@@ -11968,8 +12631,8 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
11968
12631
 
11969
12632
  // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
11970
12633
  import { mkdir as mkdir11, rm as rm5 } from "fs/promises";
11971
- import path39 from "path";
11972
- import { Logger as Logger16 } from "akanjs/common";
12634
+ import path40 from "path";
12635
+ import { Logger as Logger19 } from "akanjs/common";
11973
12636
  var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
11974
12637
  var containerName = "akan-verdaccio";
11975
12638
  var smokeRepoName = "akan-local-smoke";
@@ -11983,11 +12646,11 @@ class LocalRegistryRunner extends runner("localRegistry") {
11983
12646
  const registry = this.getRegistryUrl(registryUrl);
11984
12647
  try {
11985
12648
  await workspace.spawn("docker", ["inspect", containerName]);
11986
- Logger16.info(`Local registry is already running at ${registry}`);
12649
+ Logger19.info(`Local registry is already running at ${registry}`);
11987
12650
  return registry;
11988
12651
  } catch {}
11989
- const configPath2 = path39.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
11990
- const storagePath = path39.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
12652
+ const configPath2 = path40.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
12653
+ const storagePath = path40.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
11991
12654
  await mkdir11(storagePath, { recursive: true });
11992
12655
  await workspace.spawn("docker", [
11993
12656
  "run",
@@ -12003,20 +12666,20 @@ class LocalRegistryRunner extends runner("localRegistry") {
12003
12666
  `${storagePath}:/verdaccio/storage`,
12004
12667
  "verdaccio/verdaccio:6"
12005
12668
  ], { stdio: "inherit" });
12006
- Logger16.info(`Local registry is running at ${registry}`);
12669
+ Logger19.info(`Local registry is running at ${registry}`);
12007
12670
  return registry;
12008
12671
  }
12009
12672
  async reset(workspace) {
12010
12673
  try {
12011
12674
  await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
12012
12675
  } catch {}
12013
- await rm5(path39.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
12014
- Logger16.info("Local registry storage has been reset");
12676
+ await rm5(path40.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
12677
+ Logger19.info("Local registry storage has been reset");
12015
12678
  }
12016
12679
  async smoke(workspace, { registryUrl } = {}) {
12017
12680
  const registry = this.getRegistryUrl(registryUrl);
12018
- const smokeRoot = path39.join(workspace.workspaceRoot, ".akan/e2e");
12019
- await rm5(path39.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
12681
+ const smokeRoot = path40.join(workspace.workspaceRoot, ".akan/e2e");
12682
+ await rm5(path40.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
12020
12683
  await workspace.spawn(process.execPath, [
12021
12684
  "dist/pkgs/create-akan-workspace/index.js",
12022
12685
  smokeRepoName,
@@ -12033,11 +12696,11 @@ class LocalRegistryRunner extends runner("localRegistry") {
12033
12696
  stdio: "inherit"
12034
12697
  });
12035
12698
  await workspace.spawn("akan", ["build", smokeAppName], {
12036
- cwd: path39.join(smokeRoot, smokeRepoName),
12699
+ cwd: path40.join(smokeRoot, smokeRepoName),
12037
12700
  env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
12038
12701
  stdio: "inherit"
12039
12702
  });
12040
- Logger16.info(`Local registry smoke test completed for ${smokeRepoName}/${smokeAppName}`);
12703
+ Logger19.info(`Local registry smoke test completed for ${smokeRepoName}/${smokeAppName}`);
12041
12704
  }
12042
12705
  }
12043
12706
 
@@ -12112,7 +12775,7 @@ import { lowerlize } from "akanjs/common";
12112
12775
 
12113
12776
  // pkgs/@akanjs/cli/module/module.script.ts
12114
12777
  import { input as input6 } from "@inquirer/prompts";
12115
- import { capitalize as capitalize6, randomPicks as randomPicks2 } from "akanjs/common";
12778
+ import { capitalize as capitalize7, randomPicks as randomPicks2 } from "akanjs/common";
12116
12779
 
12117
12780
  // pkgs/@akanjs/cli/page/page.runner.ts
12118
12781
  class PageRunner extends runner("page") {
@@ -12142,7 +12805,7 @@ function pluralizeName(name) {
12142
12805
  }
12143
12806
 
12144
12807
  // pkgs/@akanjs/cli/module/module.request.ts
12145
- import { capitalize as capitalize4 } from "akanjs/common";
12808
+ import { capitalize as capitalize5 } from "akanjs/common";
12146
12809
 
12147
12810
  // pkgs/@akanjs/cli/module/module.prompt.ts
12148
12811
  var componentDefaultDescription = ({
@@ -12267,7 +12930,7 @@ var requestTemplate = ({
12267
12930
  ${componentDefaultDescription({
12268
12931
  sysName,
12269
12932
  modelName,
12270
- ModelName: ModelName ?? capitalize4(modelName),
12933
+ ModelName: ModelName ?? capitalize5(modelName),
12271
12934
  exampleFiles,
12272
12935
  constant,
12273
12936
  properties
@@ -12324,7 +12987,7 @@ var requestView = ({
12324
12987
  ${componentDefaultDescription({
12325
12988
  sysName,
12326
12989
  modelName,
12327
- ModelName: ModelName ?? capitalize4(modelName),
12990
+ ModelName: ModelName ?? capitalize5(modelName),
12328
12991
  exampleFiles,
12329
12992
  constant,
12330
12993
  properties
@@ -12385,7 +13048,7 @@ var requestUnit = ({
12385
13048
  ${componentDefaultDescription({
12386
13049
  sysName,
12387
13050
  modelName,
12388
- ModelName: ModelName ?? capitalize4(modelName),
13051
+ ModelName: ModelName ?? capitalize5(modelName),
12389
13052
  exampleFiles,
12390
13053
  constant,
12391
13054
  properties
@@ -12434,7 +13097,7 @@ var requestUnit = ({
12434
13097
  `;
12435
13098
 
12436
13099
  // pkgs/@akanjs/cli/module/module.runner.ts
12437
- import { capitalize as capitalize5 } from "akanjs/common";
13100
+ import { capitalize as capitalize6 } from "akanjs/common";
12438
13101
  class ModuleRunner extends runner("module") {
12439
13102
  async createService(module) {
12440
13103
  const serviceName = module.name.replace(/^_+/, "");
@@ -12443,13 +13106,15 @@ class ModuleRunner extends runner("module") {
12443
13106
  template: "service",
12444
13107
  dict: { model: serviceName, sysName: module.sys.name }
12445
13108
  });
12446
- const [dictionaryContent, serviceContent, signalContent, storeContent] = await Promise.all([
13109
+ const [abstractContent, dictionaryContent, serviceContent, signalContent, storeContent] = await Promise.all([
13110
+ module.readFile(`${serviceName}.abstract.md`),
12447
13111
  module.readFile(`${serviceName}.dictionary.ts`),
12448
13112
  module.readFile(`${serviceName}.service.ts`),
12449
13113
  module.readFile(`${serviceName}.signal.ts`),
12450
13114
  module.readFile(`${serviceName}.store.ts`)
12451
13115
  ]);
12452
13116
  return {
13117
+ abstract: { filename: `${serviceName}.abstract.md`, content: abstractContent },
12453
13118
  dictionary: { filename: `${serviceName}.dictionary.ts`, content: dictionaryContent },
12454
13119
  service: { filename: `${serviceName}.service.ts`, content: serviceContent },
12455
13120
  signal: { filename: `${serviceName}.signal.ts`, content: signalContent },
@@ -12462,13 +13127,13 @@ class ModuleRunner extends runner("module") {
12462
13127
  async createComponentTemplate(module, type) {
12463
13128
  await module.sys.applyTemplate({
12464
13129
  basePath: `./lib/${module.name}`,
12465
- template: `module/__Model__.${capitalize5(type)}.tsx`,
13130
+ template: `module/__Model__.${capitalize6(type)}.tsx`,
12466
13131
  dict: { model: module.name, appName: module.sys.name }
12467
13132
  });
12468
13133
  return {
12469
13134
  component: {
12470
- filename: `${module.name}.${capitalize5(type)}.tsx`,
12471
- content: await module.sys.readFile(`lib/${module.name}/${capitalize5(module.name)}.${capitalize5(type)}.tsx`)
13135
+ filename: `${module.name}.${capitalize6(type)}.tsx`,
13136
+ content: await module.sys.readFile(`lib/${module.name}/${capitalize6(module.name)}.${capitalize6(type)}.tsx`)
12472
13137
  }
12473
13138
  };
12474
13139
  }
@@ -12480,6 +13145,7 @@ class ModuleRunner extends runner("module") {
12480
13145
  dict: { model: module.name, models: names, sysName: module.sys.name }
12481
13146
  });
12482
13147
  const [
13148
+ abstractContent,
12483
13149
  constantContent,
12484
13150
  dictionaryContent,
12485
13151
  serviceContent,
@@ -12491,6 +13157,7 @@ class ModuleRunner extends runner("module") {
12491
13157
  zoneContent,
12492
13158
  utilContent
12493
13159
  ] = await Promise.all([
13160
+ module.readFile(`${module.name}.abstract.md`),
12494
13161
  module.readFile(`${module.name}.constant.ts`),
12495
13162
  module.readFile(`${module.name}.dictionary.ts`),
12496
13163
  module.readFile(`${module.name}.service.ts`),
@@ -12503,6 +13170,7 @@ class ModuleRunner extends runner("module") {
12503
13170
  module.readFile(`${module.name}.Util.tsx`)
12504
13171
  ]);
12505
13172
  return {
13173
+ abstract: { filename: `${module.name}.abstract.md`, content: abstractContent },
12506
13174
  constant: { filename: `${module.name}.constant.ts`, content: constantContent },
12507
13175
  dictionary: { filename: `${module.name}.dictionary.ts`, content: dictionaryContent },
12508
13176
  service: { filename: `${module.name}.service.ts`, content: serviceContent },
@@ -12591,7 +13259,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
12591
13259
  async createTemplate(mod) {
12592
13260
  const { component: template } = await this.moduleRunner.createComponentTemplate(mod, "template");
12593
13261
  const templateExampleFiles = (await mod.sys.getTemplatesSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.Template.tsx`));
12594
- const Name = capitalize6(mod.name);
13262
+ const Name = capitalize7(mod.name);
12595
13263
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
12596
13264
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
12597
13265
  const session = new AiSession("createTemplate", { workspace: mod.sys.workspace, cacheKey: mod.name });
@@ -12610,7 +13278,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
12610
13278
  }
12611
13279
  async createUnit(mod) {
12612
13280
  const { component: unit } = await this.moduleRunner.createComponentTemplate(mod, "unit");
12613
- const Name = capitalize6(mod.name);
13281
+ const Name = capitalize7(mod.name);
12614
13282
  const unitExampleFiles = (await mod.sys.getUnitsSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.Unit.tsx`));
12615
13283
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
12616
13284
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
@@ -12631,7 +13299,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
12631
13299
  async createView(mod) {
12632
13300
  const { component: view } = await this.moduleRunner.createComponentTemplate(mod, "view");
12633
13301
  const viewExampleFiles = (await mod.sys.getViewsSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.View.tsx`));
12634
- const Name = capitalize6(mod.name);
13302
+ const Name = capitalize7(mod.name);
12635
13303
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
12636
13304
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
12637
13305
  const session = new AiSession("createView", { workspace: mod.sys.workspace, cacheKey: mod.name });
@@ -12902,11 +13570,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
12902
13570
  }
12903
13571
 
12904
13572
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
12905
- import path41 from "path";
12906
- import { Logger as Logger17 } from "akanjs/common";
13573
+ import path42 from "path";
13574
+ import { Logger as Logger20 } from "akanjs/common";
12907
13575
 
12908
13576
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
12909
- import path40 from "path";
13577
+ import path41 from "path";
12910
13578
  var defaultWorkspacePeerDependencies = new Set([
12911
13579
  "@react-spring/web",
12912
13580
  "@use-gesture/react",
@@ -12925,6 +13593,30 @@ var defaultWorkspacePeerDependencies = new Set([
12925
13593
  ]);
12926
13594
 
12927
13595
  class WorkspaceRunner extends runner("workspace") {
13596
+ async generateAgentRules(workspace, { overwrite = false, cursorRules = true } = {}) {
13597
+ const [appNames] = await workspace.getExecs();
13598
+ const dict = {
13599
+ repoName: workspace.repoName,
13600
+ appName: appNames[0] ?? "app"
13601
+ };
13602
+ const created = await workspace.applyTemplate({
13603
+ basePath: ".",
13604
+ template: "workspaceRoot/AGENTS.md.template",
13605
+ dict,
13606
+ overwrite
13607
+ });
13608
+ if (!cursorRules)
13609
+ return created;
13610
+ return [
13611
+ ...created,
13612
+ ...await workspace.applyTemplate({
13613
+ basePath: ".cursor/rules",
13614
+ template: "workspaceRoot/.cursor/rules/akan.mdc.template",
13615
+ dict,
13616
+ overwrite
13617
+ })
13618
+ ];
13619
+ }
12928
13620
  async createWorkspace(repoName, appName, {
12929
13621
  dirname: dirname2 = ".",
12930
13622
  init = true,
@@ -12932,7 +13624,7 @@ class WorkspaceRunner extends runner("workspace") {
12932
13624
  registryUrl
12933
13625
  }) {
12934
13626
  const cwdPath = process.cwd();
12935
- const workspaceRoot = path40.join(cwdPath, dirname2, repoName);
13627
+ const workspaceRoot = path41.join(cwdPath, dirname2, repoName);
12936
13628
  const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
12937
13629
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
12938
13630
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname2}/${repoName}...`);
@@ -12988,9 +13680,9 @@ class WorkspaceRunner extends runner("workspace") {
12988
13680
  }
12989
13681
  async#getCliPackageJson() {
12990
13682
  const packageJsonCandidates = [
12991
- path40.join(import.meta.dir, "../package.json"),
12992
- path40.join(import.meta.dir, "package.json"),
12993
- path40.join(path40.dirname(Bun.main), "package.json")
13683
+ path41.join(import.meta.dir, "../package.json"),
13684
+ path41.join(import.meta.dir, "package.json"),
13685
+ path41.join(path41.dirname(Bun.main), "package.json")
12994
13686
  ];
12995
13687
  try {
12996
13688
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -13006,9 +13698,9 @@ class WorkspaceRunner extends runner("workspace") {
13006
13698
  }
13007
13699
  async#getAkanPackageJson() {
13008
13700
  const packageJsonCandidates = [
13009
- path40.join(import.meta.dir, "../../../akanjs/package.json"),
13010
- path40.join(process.cwd(), "pkgs/akanjs/package.json"),
13011
- path40.join(path40.dirname(Bun.main), "node_modules/akanjs/package.json")
13701
+ path41.join(import.meta.dir, "../../../akanjs/package.json"),
13702
+ path41.join(process.cwd(), "pkgs/akanjs/package.json"),
13703
+ path41.join(path41.dirname(Bun.main), "node_modules/akanjs/package.json")
13012
13704
  ];
13013
13705
  try {
13014
13706
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -13022,13 +13714,13 @@ class WorkspaceRunner extends runner("workspace") {
13022
13714
  }
13023
13715
  let current = import.meta.dir;
13024
13716
  for (let depth = 0;depth < 6; depth++) {
13025
- const packageJsonPath = path40.join(current, "package.json");
13717
+ const packageJsonPath = path41.join(current, "package.json");
13026
13718
  if (await Bun.file(packageJsonPath).exists()) {
13027
13719
  const packageJson = await FileSys.readJson(packageJsonPath);
13028
13720
  if (packageJson.name === "akanjs")
13029
13721
  return packageJson;
13030
13722
  }
13031
- const parent = path40.dirname(current);
13723
+ const parent = path41.dirname(current);
13032
13724
  if (parent === current)
13033
13725
  break;
13034
13726
  current = parent;
@@ -13077,13 +13769,18 @@ class WorkspaceScript extends script("workspace", [
13077
13769
  } catch (_) {
13078
13770
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
13079
13771
  }
13080
- const workspacePath = path41.join(dirname2, repoName);
13081
- Logger17.rawLog(`
13772
+ const workspacePath = path42.join(dirname2, repoName);
13773
+ Logger20.rawLog(`
13082
13774
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname2}/${repoName}`);
13083
- Logger17.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
13084
- Logger17.rawLog(`
13775
+ Logger20.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
13776
+ Logger20.rawLog(`
13085
13777
  \uD83D\uDC4B Happy coding!`);
13086
13778
  }
13779
+ async generateAgentRules(workspace, { overwrite = false, cursorRules = true } = {}) {
13780
+ const spinner2 = workspace.spinning("Generating agent rules...");
13781
+ const files = await this.workspaceRunner.generateAgentRules(workspace, { overwrite, cursorRules });
13782
+ spinner2.succeed(`Agent rules ready (${files.length} file${files.length === 1 ? "" : "s"})`);
13783
+ }
13087
13784
  async lint(exec2, workspace, { fix = true } = {}) {
13088
13785
  if (exec2 instanceof AppExecutor)
13089
13786
  await this.applicationScript.sync(exec2);
@@ -13143,6 +13840,9 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
13143
13840
  const appName = app || "app";
13144
13841
  await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init, ...registry ? { registryUrl: registry } : {} });
13145
13842
  }),
13843
+ generateAgentRules: target({ desc: "Generate AGENTS.md and optional Cursor rules for Akan coding agents" }).option("overwrite", Boolean, { desc: "Overwrite existing agent rule files", default: false }).option("cursorRules", Boolean, { desc: "Generate .cursor/rules/akan.mdc", default: true }).with(Workspace).exec(async function(overwrite, cursorRules, workspace) {
13844
+ await this.workspaceScript.generateAgentRules(workspace, { overwrite, cursorRules });
13845
+ }),
13146
13846
  lint: target({ desc: "Lint and fix code in a specific app/lib/pkg" }).with(Exec).option("fix", Boolean, { default: true }).with(Workspace).exec(async function(exec2, fix, workspace) {
13147
13847
  await this.workspaceScript.lint(exec2, workspace, { fix });
13148
13848
  }),
@@ -13156,4 +13856,4 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
13156
13856
  }
13157
13857
 
13158
13858
  // pkgs/@akanjs/cli/index.ts
13159
- runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, LocalRegistryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
13859
+ runCommands(WorkspaceCommand, AgentCommand, ApplicationCommand, LibraryCommand, LocalRegistryCommand, PackageCommand, ModuleCommand, PageCommand, ContextCommand, CloudCommand, GuidelineCommand, ScalarCommand);