@akanjs/cli 2.1.1-rc.2 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -327,6 +327,31 @@ var supportedLlmModels = [
327
327
  "deepseek-chat",
328
328
  "deepseek-reasoner"
329
329
  ];
330
+ var parseTypescriptFileBlocks = (text) => {
331
+ const fileBlocks = [];
332
+ const codeBlockRegex = /```(?:typescript|ts|tsx)\s*\n([\s\S]*?)```/gi;
333
+ const filePathRegex = /^\s*\/\/\s*File:\s*(.+?)\s*$/im;
334
+ for (const codeBlock of text.matchAll(codeBlockRegex)) {
335
+ const content = codeBlock[1]?.trim();
336
+ if (!content)
337
+ continue;
338
+ const filePath = filePathRegex.exec(content)?.[1]?.trim();
339
+ if (!filePath)
340
+ continue;
341
+ fileBlocks.push({
342
+ filePath,
343
+ content: content.replace(filePathRegex, "").trim()
344
+ });
345
+ }
346
+ return fileBlocks;
347
+ };
348
+ var preserveTypescriptResponseContent = (previousContent, nextContent) => {
349
+ const previousWrites = parseTypescriptFileBlocks(previousContent);
350
+ const nextWrites = parseTypescriptFileBlocks(nextContent);
351
+ if (previousWrites.length > 0 && nextWrites.length === 0)
352
+ return previousContent;
353
+ return nextContent;
354
+ };
330
355
 
331
356
  class AiSession {
332
357
  static #cacheDir = "node_modules/.cache/akan/aiSession";
@@ -446,7 +471,7 @@ class AiSession {
446
471
  const humanMessage = new HumanMessage(question);
447
472
  this.messageHistory.push(humanMessage);
448
473
  const stream = await AiSession.#chat.stream(this.messageHistory);
449
- let reasoningResponse = "", fullResponse = "", tokenIdx = 0;
474
+ let reasoningResponse = "", fullResponse = "";
450
475
  for await (const chunk of stream) {
451
476
  if (loader.isSpinning())
452
477
  loader.succeed(`${AiSession.#chat.model} responded`);
@@ -467,7 +492,6 @@ class AiSession {
467
492
  fullResponse += content;
468
493
  onChunk(content);
469
494
  }
470
- tokenIdx++;
471
495
  }
472
496
  fullResponse += `
473
497
  `;
@@ -475,7 +499,7 @@ class AiSession {
475
499
  `);
476
500
  this.messageHistory.push(new AIMessage(fullResponse));
477
501
  return { content: fullResponse, messageHistory: this.messageHistory };
478
- } catch (error) {
502
+ } catch {
479
503
  loader.fail(`${AiSession.#chat.model} failed to respond`);
480
504
  throw new Error("Failed to stream response");
481
505
  }
@@ -485,7 +509,8 @@ class AiSession {
485
509
  onReasoning,
486
510
  maxTry = MAX_ASK_TRY,
487
511
  validate,
488
- approve
512
+ approve,
513
+ fallbackToPreviousTypescript
489
514
  } = {}) {
490
515
  for (let tryCount = 0;tryCount < maxTry; tryCount++) {
491
516
  let response = await this.ask(question, { onChunk, onReasoning });
@@ -493,7 +518,14 @@ class AiSession {
493
518
  const validateQuestion = `Double check if the response meets the requirements and conditions, and follow the instructions. If not, rewrite it.
494
519
  ${validate.map((v) => `- ${v}`).join(`
495
520
  `)}`;
496
- response = await this.ask(validateQuestion, { onChunk, onReasoning });
521
+ const validateResponse = await this.ask(validateQuestion, {
522
+ onChunk,
523
+ onReasoning
524
+ });
525
+ response = {
526
+ ...validateResponse,
527
+ content: fallbackToPreviousTypescript ? preserveTypescriptResponseContent(response.content, validateResponse.content) : validateResponse.content
528
+ };
497
529
  }
498
530
  const isConfirmed = approve ? true : await select({
499
531
  message: "Do you want to edit the response?",
@@ -526,15 +558,28 @@ ${validate.map((v) => `- ${v}`).join(`
526
558
  return this;
527
559
  }
528
560
  async writeTypescripts(question, executor, options = {}) {
529
- const content = await this.edit(question, options);
561
+ const content = await this.edit(question, {
562
+ ...options,
563
+ fallbackToPreviousTypescript: true
564
+ });
530
565
  const writes = this.#getTypescriptCodes(content);
566
+ if (!writes.length)
567
+ throw new Error("No parseable TypeScript file blocks were found in the AI response. Include `// File: <path>` in each code block.");
531
568
  for (const write of writes)
532
569
  await executor.writeFile(write.filePath, write.content);
533
570
  return await this.#tryFixTypescripts(writes, executor, options);
534
571
  }
535
- async#editTypescripts(question, options = {}) {
536
- const content = await this.edit(question, options);
537
- return this.#getTypescriptCodes(content);
572
+ async#editTypescripts(question, options = {}, fallbackWrites) {
573
+ const content = await this.edit(question, {
574
+ ...options,
575
+ fallbackToPreviousTypescript: true
576
+ });
577
+ const writes = this.#getTypescriptCodes(content);
578
+ if (!writes.length && fallbackWrites?.length)
579
+ return fallbackWrites;
580
+ if (!writes.length)
581
+ throw new Error("No parseable TypeScript file blocks were found in the AI response. Include `// File: <path>` in each code block.");
582
+ return writes;
538
583
  }
539
584
  async#tryFixTypescripts(writes, executor, options = {}) {
540
585
  const MAX_EDIT_TRY = 5;
@@ -543,13 +588,15 @@ ${validate.map((v) => `- ${v}`).join(`
543
588
  prefix: `\uD83E\uDD16akan-editor`
544
589
  }).start();
545
590
  const fileChecks = await Promise.all(writes.map(async ({ filePath }) => {
546
- const typeCheckResult = executor.typeCheck(filePath);
547
- const lintResult = await executor.lint(filePath);
548
- const needFix2 = !!typeCheckResult.fileErrors.length || !!lintResult.errors.length;
549
- return { filePath, typeCheckResult, lintResult, needFix: needFix2 };
591
+ const lintResult = await executor.lint(filePath, { fix: true });
592
+ const typeCheckResult = await executor.typeCheckAsync(filePath);
593
+ const hasTypeErrors = typeCheckResult.fileErrors.length > 0;
594
+ const hasLintErrors = lintResult.errors.length > 0;
595
+ const needFix = hasTypeErrors || hasLintErrors;
596
+ return { filePath, typeCheckResult, lintResult, needFix };
550
597
  }));
551
- const needFix = fileChecks.some((fileCheck) => fileCheck.needFix);
552
- if (needFix) {
598
+ const hasAnyFix = fileChecks.some((fileCheck) => fileCheck.needFix);
599
+ if (hasAnyFix) {
553
600
  loader.fail("Type checking and linting has some errors, try to fix them");
554
601
  fileChecks.forEach((fileCheck) => {
555
602
  Logger2.rawLog(`TypeCheck Result
@@ -565,7 +612,7 @@ ${fileCheck.lintResult.message}`);
565
612
  ...options,
566
613
  validate: undefined,
567
614
  approve: true
568
- });
615
+ }, writes);
569
616
  for (const write of writes)
570
617
  await executor.writeFile(write.filePath, write.content);
571
618
  } else {
@@ -576,21 +623,7 @@ ${fileCheck.lintResult.message}`);
576
623
  throw new Error("Failed to create scalar");
577
624
  }
578
625
  #getTypescriptCodes(text) {
579
- const codes = text.match(/```(typescript|tsx)([\s\S]*?)```/g);
580
- if (!codes)
581
- return [];
582
- const result = codes.map((code) => {
583
- const content = /```(typescript|tsx)([\s\S]*?)```/.exec(code)?.[2];
584
- if (!content)
585
- return null;
586
- const filePath = /\/\/ File: (.*?)(?:\n|$)/.exec(content)?.[1]?.trim();
587
- if (!filePath)
588
- return null;
589
- const contentWithoutFilepath = content.replace(`// File: ${filePath}
590
- `, "").trim();
591
- return { filePath, content: contentWithoutFilepath };
592
- });
593
- return result.filter((code) => code !== null);
626
+ return parseTypescriptFileBlocks(text);
594
627
  }
595
628
  async editMarkdown(request, options = {}) {
596
629
  const content = await this.edit(request, options);
@@ -608,21 +641,26 @@ ${fileCheck.lintResult.message}`);
608
641
  }
609
642
  // pkgs/@akanjs/devkit/akanApp/akanApp.host.ts
610
643
  import path9 from "path";
611
- import { Logger as Logger6 } from "akanjs/common";
644
+ import { Logger as Logger5 } from "akanjs/common";
612
645
 
613
646
  // pkgs/@akanjs/devkit/executors.ts
614
647
  import {
615
648
  exec,
616
649
  fork,
617
- spawn
650
+ spawn as spawn2
618
651
  } from "child_process";
619
652
  import { readFileSync as readFileSync3 } from "fs";
620
- import { copyFile, mkdir as mkdir2, readdir as readDirEntries, stat as stat2 } from "fs/promises";
653
+ import {
654
+ copyFile,
655
+ mkdir as mkdir2,
656
+ readdir as readDirEntries,
657
+ stat as stat2
658
+ } from "fs/promises";
621
659
  import path7 from "path";
622
660
  import {
623
661
  capitalize,
624
662
  isRouteSourceFile,
625
- Logger as Logger4,
663
+ Logger as Logger3,
626
664
  parseRouteModuleKey,
627
665
  validatePageSourceFile,
628
666
  validateSubRoutePageKey
@@ -985,23 +1023,146 @@ import path2 from "path";
985
1023
  var getDirname = (url) => path2.dirname(new URL(url).pathname);
986
1024
 
987
1025
  // pkgs/@akanjs/devkit/linter.ts
1026
+ import { spawn } from "child_process";
988
1027
  import { existsSync, readFileSync } from "fs";
989
- import * as path3 from "path";
990
- import { Logger as Logger3 } from "akanjs/common";
1028
+ import path3 from "path";
991
1029
  import chalk2 from "chalk";
992
1030
 
993
1031
  class Linter {
994
- #logger = new Logger3("Linter");
995
1032
  lintRoot;
1033
+ #biomeBin;
996
1034
  constructor(cwdPath) {
997
- this.lintRoot = this.#findEslintRootPath(cwdPath);
1035
+ this.lintRoot = this.#findBiomeRootPath(cwdPath);
1036
+ const localBiomeBin = path3.join(this.lintRoot, "node_modules/.bin/biome");
1037
+ this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
998
1038
  }
999
- #findEslintRootPath(dir) {
1000
- const configPath2 = path3.join(dir, "eslint.config.ts");
1039
+ #findBiomeRootPath(dir) {
1040
+ const configPath2 = path3.join(dir, "biome.json");
1001
1041
  if (existsSync(configPath2))
1002
1042
  return dir;
1003
1043
  const parentDir = path3.dirname(dir);
1004
- return this.#findEslintRootPath(parentDir);
1044
+ if (parentDir === dir)
1045
+ throw new Error(`biome.json not found from ${dir}`);
1046
+ return this.#findBiomeRootPath(parentDir);
1047
+ }
1048
+ #toBiomePath(filePath) {
1049
+ const relativePath = path3.relative(this.lintRoot, filePath);
1050
+ if (!relativePath.startsWith("..") && !path3.isAbsolute(relativePath))
1051
+ return relativePath;
1052
+ return filePath;
1053
+ }
1054
+ #resolveFilePath(filePath) {
1055
+ return path3.isAbsolute(filePath) ? filePath : path3.join(this.lintRoot, filePath);
1056
+ }
1057
+ async#runBiome(args, input2) {
1058
+ return await new Promise((resolve, reject) => {
1059
+ const proc = spawn(this.#biomeBin, args, {
1060
+ cwd: this.lintRoot,
1061
+ stdio: ["pipe", "pipe", "pipe"]
1062
+ });
1063
+ let stdout = "";
1064
+ let stderr = "";
1065
+ proc.stdout.on("data", (data) => {
1066
+ stdout += data.toString();
1067
+ });
1068
+ proc.stderr.on("data", (data) => {
1069
+ stderr += data.toString();
1070
+ });
1071
+ proc.on("error", reject);
1072
+ proc.on("close", (code) => resolve({ stdout, stderr, code }));
1073
+ proc.stdin.end(input2);
1074
+ });
1075
+ }
1076
+ #parseBiomeReport(output) {
1077
+ const jsonStart = output.indexOf("{");
1078
+ const jsonEnd = output.lastIndexOf("}");
1079
+ if (jsonStart === -1 || jsonEnd === -1 || jsonEnd < jsonStart)
1080
+ throw new Error(output.trim() || "No Biome JSON output");
1081
+ return JSON.parse(output.slice(jsonStart, jsonEnd + 1));
1082
+ }
1083
+ #diagnosticFilePath(diagnostic, fallbackFilePath) {
1084
+ const diagnosticPath = diagnostic.location?.path;
1085
+ if (!diagnosticPath)
1086
+ return fallbackFilePath;
1087
+ return path3.isAbsolute(diagnosticPath) ? diagnosticPath : path3.join(this.lintRoot, diagnosticPath);
1088
+ }
1089
+ #createLintMessage(diagnostic) {
1090
+ const start = diagnostic.location?.start;
1091
+ const end = diagnostic.location?.end;
1092
+ return {
1093
+ line: Math.max(1, start?.line ?? 1),
1094
+ column: Math.max(1, start?.column ?? 1),
1095
+ endLine: end?.line,
1096
+ endColumn: end?.column,
1097
+ message: diagnostic.message,
1098
+ ruleId: diagnostic.category ?? null,
1099
+ severity: diagnostic.severity === "error" ? 2 : 1
1100
+ };
1101
+ }
1102
+ #toLintResults(report, filePath) {
1103
+ const resultsByPath = new Map;
1104
+ for (const diagnostic of report.diagnostics ?? []) {
1105
+ if (diagnostic.severity !== "error" && diagnostic.severity !== "warning")
1106
+ continue;
1107
+ const diagnosticFilePath = this.#diagnosticFilePath(diagnostic, filePath);
1108
+ const result = resultsByPath.get(diagnosticFilePath) ?? {
1109
+ filePath: diagnosticFilePath,
1110
+ messages: [],
1111
+ errorCount: 0,
1112
+ warningCount: 0,
1113
+ fixableErrorCount: 0,
1114
+ fixableWarningCount: 0
1115
+ };
1116
+ const message = this.#createLintMessage(diagnostic);
1117
+ result.messages.push(message);
1118
+ if (message.severity === 2)
1119
+ result.errorCount += 1;
1120
+ else
1121
+ result.warningCount += 1;
1122
+ resultsByPath.set(diagnosticFilePath, result);
1123
+ }
1124
+ return [
1125
+ resultsByPath.get(filePath) ?? {
1126
+ filePath,
1127
+ messages: [],
1128
+ errorCount: 0,
1129
+ warningCount: 0,
1130
+ fixableErrorCount: 0,
1131
+ fixableWarningCount: 0
1132
+ },
1133
+ ...[...resultsByPath.entries()].filter(([resultPath]) => resultPath !== filePath).map(([, result]) => result)
1134
+ ];
1135
+ }
1136
+ #splitMessages(results) {
1137
+ const messages = results.flatMap((result) => result.messages);
1138
+ return {
1139
+ errors: messages.filter((message) => message.severity === 2),
1140
+ warnings: messages.filter((message) => message.severity === 1)
1141
+ };
1142
+ }
1143
+ async#checkFile(filePath, { write = false } = {}) {
1144
+ const originalContent = existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
1145
+ const { stdout, stderr } = await this.#runBiome([
1146
+ "check",
1147
+ ...write ? ["--write"] : [],
1148
+ "--reporter=json",
1149
+ "--max-diagnostics=none",
1150
+ "--no-errors-on-unmatched",
1151
+ "--config-path",
1152
+ path3.join(this.lintRoot, "biome.json"),
1153
+ this.#toBiomePath(filePath)
1154
+ ]);
1155
+ const report = this.#parseBiomeReport(stdout || stderr);
1156
+ const results = this.#toLintResults(report, filePath);
1157
+ const { errors, warnings } = this.#splitMessages(results);
1158
+ const output = write && existsSync(filePath) ? readFileSync(filePath, "utf8") : undefined;
1159
+ return {
1160
+ fixed: write && output !== originalContent,
1161
+ output,
1162
+ results,
1163
+ errors,
1164
+ warnings
1165
+ };
1005
1166
  }
1006
1167
  async lint(filePath, { fix = false, dryRun = false } = {}) {
1007
1168
  if (fix)
@@ -1009,9 +1170,10 @@ class Linter {
1009
1170
  return await this.lintFile(filePath);
1010
1171
  }
1011
1172
  async lintFile(filePath) {
1012
- if (!existsSync(filePath))
1173
+ const resolvedFilePath = this.#resolveFilePath(filePath);
1174
+ if (!existsSync(resolvedFilePath))
1013
1175
  throw new Error(`File not found: ${filePath}`);
1014
- return { fixed: false, results: [], errors: [], warnings: [] };
1176
+ return await this.#checkFile(resolvedFilePath);
1015
1177
  }
1016
1178
  formatLintResults(results) {
1017
1179
  if (results.length === 0)
@@ -1031,12 +1193,12 @@ ${chalk2.cyan(result.filePath)}`);
1031
1193
  const sourceContent = readFileSync(result.filePath, "utf8");
1032
1194
  sourceLines = sourceContent.split(`
1033
1195
  `);
1034
- } catch (error) {}
1196
+ } catch {}
1035
1197
  }
1036
1198
  result.messages.forEach((message) => {
1037
1199
  const type = message.severity === 2 ? "error" : "warning";
1038
1200
  const typeColor = message.severity === 2 ? chalk2.red : chalk2.yellow;
1039
- const icon = message.severity === 2 ? "\u274C" : "\u26A0\uFE0F";
1201
+ const icon = message.severity === 2 ? "x" : "!";
1040
1202
  const ruleInfo = message.ruleId ? chalk2.dim(` (${message.ruleId})`) : "";
1041
1203
  output.push(`
1042
1204
  ${icon} ${typeColor(type)}: ${message.message}${ruleInfo}`);
@@ -1055,7 +1217,7 @@ ${chalk2.dim(`${lineNumber} |`)} ${sourceLine}`);
1055
1217
  }
1056
1218
  });
1057
1219
  if (totalErrors === 0 && totalWarnings === 0)
1058
- return chalk2.bold("\u2705 No ESLint errors or warnings found");
1220
+ return chalk2.bold("No Biome errors or warnings found");
1059
1221
  const errorText = totalErrors > 0 ? chalk2.red(`${totalErrors} error(s)`) : "0 errors";
1060
1222
  const warningText = totalWarnings > 0 ? chalk2.yellow(`${totalWarnings} warning(s)`) : "0 warnings";
1061
1223
  const summary = [`
@@ -1070,23 +1232,26 @@ ${errorText}, ${warningText} found`];
1070
1232
  column: message.column,
1071
1233
  message: message.message,
1072
1234
  ruleId: message.ruleId,
1073
- severity: message.severity === 2 ? "error" : "warning",
1074
- fix: message.fix,
1075
- suggestions: message.suggestions
1235
+ severity: message.severity === 2 ? "error" : "warning"
1076
1236
  })));
1077
1237
  const stats = results.reduce((acc, result) => ({
1078
1238
  errorCount: acc.errorCount + result.errorCount,
1079
1239
  warningCount: acc.warningCount + result.warningCount,
1080
1240
  fixableErrorCount: acc.fixableErrorCount + result.fixableErrorCount,
1081
1241
  fixableWarningCount: acc.fixableWarningCount + result.fixableWarningCount
1082
- }), { errorCount: 0, warningCount: 0, fixableErrorCount: 0, fixableWarningCount: 0 });
1242
+ }), {
1243
+ errorCount: 0,
1244
+ warningCount: 0,
1245
+ fixableErrorCount: 0,
1246
+ fixableWarningCount: 0
1247
+ });
1083
1248
  return { results, details, stats };
1084
1249
  }
1085
1250
  async hasNoLintErrors(filePath) {
1086
1251
  try {
1087
1252
  const { results } = await this.lintFile(filePath);
1088
1253
  return results.every((result) => result.errorCount === 0);
1089
- } catch (error) {
1254
+ } catch {
1090
1255
  return false;
1091
1256
  }
1092
1257
  }
@@ -1099,12 +1264,28 @@ ${errorText}, ${warningText} found`];
1099
1264
  return results.flatMap((result) => result.messages.filter((message) => message.severity === 1));
1100
1265
  }
1101
1266
  async fixFile(filePath, dryRun = false) {
1102
- if (!existsSync(filePath))
1267
+ const resolvedFilePath = this.#resolveFilePath(filePath);
1268
+ if (!existsSync(resolvedFilePath))
1103
1269
  throw new Error(`File not found: ${filePath}`);
1104
- return { fixed: false, output: undefined, results: [], errors: [], warnings: [] };
1270
+ if (!dryRun)
1271
+ return await this.#checkFile(resolvedFilePath, { write: true });
1272
+ const source = readFileSync(resolvedFilePath, "utf8");
1273
+ const { stdout } = await this.#runBiome([
1274
+ "check",
1275
+ "--write",
1276
+ "--config-path",
1277
+ path3.join(this.lintRoot, "biome.json"),
1278
+ "--stdin-file-path",
1279
+ this.#toBiomePath(resolvedFilePath)
1280
+ ], source);
1281
+ const lintResult = await this.lintFile(resolvedFilePath);
1282
+ return { ...lintResult, fixed: stdout !== source, output: stdout };
1105
1283
  }
1106
1284
  async getConfigForFile(filePath) {
1107
- return {};
1285
+ const resolvedFilePath = this.#resolveFilePath(filePath);
1286
+ if (!existsSync(resolvedFilePath))
1287
+ throw new Error(`File not found: ${filePath}`);
1288
+ return JSON.parse(readFileSync(path3.join(this.lintRoot, "biome.json"), "utf8"));
1108
1289
  }
1109
1290
  async getProblematicRules(filePath) {
1110
1291
  const { results } = await this.lintFile(filePath);
@@ -1494,23 +1675,23 @@ async function assertScanConvention(exec, libRoot) {
1494
1675
  files.filter((filename) => !appRootAllowedFiles.has(filename)).forEach((filename) => {
1495
1676
  addViolation(filename, "unsupported app root file");
1496
1677
  });
1497
- dirs.filter((dirname2) => !appRootAllowedDirs.has(dirname2)).forEach((dirname2) => {
1498
- addViolation(dirname2, "unsupported app root folder");
1678
+ dirs.filter((dirname) => !appRootAllowedDirs.has(dirname)).forEach((dirname) => {
1679
+ addViolation(dirname, "unsupported app root folder");
1499
1680
  });
1500
1681
  }
1501
1682
  libRoot.files.filter((filename) => !isAllowedLibRootFile(filename)).forEach((filename) => {
1502
1683
  addViolation(path5.join("lib", filename), "unsupported lib root file");
1503
1684
  });
1504
- libRoot.dirs.filter((dirname2) => dirname2.startsWith("__") && !internalLibDirs.has(dirname2)).forEach((dirname2) => {
1505
- addViolation(path5.join("lib", dirname2), "unsupported internal lib folder");
1685
+ libRoot.dirs.filter((dirname) => dirname.startsWith("__") && !internalLibDirs.has(dirname)).forEach((dirname) => {
1686
+ addViolation(path5.join("lib", dirname), "unsupported internal lib folder");
1506
1687
  });
1507
- const databaseDirs = libRoot.dirs.filter((dirname2) => !dirname2.startsWith("_"));
1508
- const serviceDirs = libRoot.dirs.filter((dirname2) => dirname2.startsWith("_") && !dirname2.startsWith("__"));
1688
+ const databaseDirs = libRoot.dirs.filter((dirname) => !dirname.startsWith("_"));
1689
+ const serviceDirs = libRoot.dirs.filter((dirname) => dirname.startsWith("_") && !dirname.startsWith("__"));
1509
1690
  const scalarDirs = await exec.readdir("lib/__scalar");
1510
1691
  await Promise.all([
1511
- ...databaseDirs.map((dirname2) => validateModuleFiles(exec, violations, "database", path5.join("lib", dirname2))),
1512
- ...serviceDirs.map((dirname2) => validateModuleFiles(exec, violations, "service", path5.join("lib", dirname2))),
1513
- ...scalarDirs.map((dirname2) => validateModuleFiles(exec, violations, "scalar", path5.join("lib/__scalar", dirname2)))
1692
+ ...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path5.join("lib", dirname))),
1693
+ ...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path5.join("lib", dirname))),
1694
+ ...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path5.join("lib/__scalar", dirname)))
1514
1695
  ]);
1515
1696
  if (violations.length > 0) {
1516
1697
  throw new Error(`[scan-convention]
@@ -1520,8 +1701,8 @@ ${violations.sort().map((violation) => `- ${violation}`).join(`
1520
1701
  }
1521
1702
  async function validateModuleFiles(exec, violations, kind, modulePath) {
1522
1703
  const { files, dirs } = await exec.getFilesAndDirs(modulePath);
1523
- dirs.forEach((dirname2) => {
1524
- violations.push(`${getScanPath(exec, path5.join(modulePath, dirname2))}: unsupported module folder`);
1704
+ dirs.forEach((dirname) => {
1705
+ violations.push(`${getScanPath(exec, path5.join(modulePath, dirname))}: unsupported module folder`);
1525
1706
  });
1526
1707
  files.forEach((filename) => {
1527
1708
  const filePath = path5.join(modulePath, filename);
@@ -1620,9 +1801,9 @@ class ScanInfo {
1620
1801
  files.zone.databases.push(name);
1621
1802
  });
1622
1803
  }),
1623
- ...serviceDirs.map(async (dirname2) => {
1624
- const name = dirname2.slice(1);
1625
- const filenames = await exec.readdir(path5.join("lib", dirname2));
1804
+ ...serviceDirs.map(async (dirname) => {
1805
+ const name = dirname.slice(1);
1806
+ const filenames = await exec.readdir(path5.join("lib", dirname));
1626
1807
  filenames.forEach((filename) => {
1627
1808
  if (filename.endsWith(".dictionary.ts"))
1628
1809
  files.dictionary.services.push(name);
@@ -2191,8 +2372,13 @@ class CommandExecutionError extends Error {
2191
2372
  const displayCommand = formatCommandForDisplay(command, args);
2192
2373
  const status = signal ? `signal: ${signal}` : `exit code: ${code ?? "unknown"}`;
2193
2374
  const output = (stderr || stdout).trim();
2194
- super([`Command failed: ${displayCommand}`, `cwd: ${cwd}`, status, output ? `
2195
- ${output}` : ""].join(`
2375
+ super([
2376
+ `Command failed: ${displayCommand}`,
2377
+ `cwd: ${cwd}`,
2378
+ status,
2379
+ output ? `
2380
+ ${output}` : ""
2381
+ ].join(`
2196
2382
  `), {
2197
2383
  cause
2198
2384
  });
@@ -2241,7 +2427,13 @@ var parseEnvFile = (envPath) => {
2241
2427
  }
2242
2428
  return env;
2243
2429
  };
2244
- var PAGE_ROUTE_EXPORTS = new Set(["default", "pageConfig", "head", "generateHead", "Loading"]);
2430
+ var PAGE_ROUTE_EXPORTS = new Set([
2431
+ "default",
2432
+ "pageConfig",
2433
+ "head",
2434
+ "generateHead",
2435
+ "Loading"
2436
+ ]);
2245
2437
  var ROOT_LAYOUT_EXPORTS = new Set([
2246
2438
  "default",
2247
2439
  "head",
@@ -2254,7 +2446,12 @@ var ROOT_LAYOUT_EXPORTS = new Set([
2254
2446
  "gaTrackingId",
2255
2447
  "Loading"
2256
2448
  ]);
2257
- var LAYOUT_ROUTE_EXPORTS = new Set(["default", "head", "generateHead", "Loading"]);
2449
+ var LAYOUT_ROUTE_EXPORTS = new Set([
2450
+ "default",
2451
+ "head",
2452
+ "generateHead",
2453
+ "Loading"
2454
+ ]);
2258
2455
  function validateRouteSourceExports(source, filePath, kind, options = {}) {
2259
2456
  const sourceFile = ts3.createSourceFile(filePath, source, ts3.ScriptTarget.Latest, true, ts3.ScriptKind.TSX);
2260
2457
  const allowed = kind === "page" ? PAGE_ROUTE_EXPORTS : options.rootLayout ? ROOT_LAYOUT_EXPORTS : LAYOUT_ROUTE_EXPORTS;
@@ -2323,16 +2520,16 @@ class Executor {
2323
2520
  linter = null;
2324
2521
  constructor(name, cwdPath) {
2325
2522
  this.name = name;
2326
- this.logger = new Logger4(name);
2523
+ this.logger = new Logger3(name);
2327
2524
  this.logs = [];
2328
2525
  this.cwdPath = cwdPath;
2329
2526
  }
2330
2527
  #stdout(data) {
2331
2528
  if (Executor.verbose)
2332
- Logger4.raw(chalk4.dim(data.toString()));
2529
+ Logger3.raw(chalk4.dim(data.toString()));
2333
2530
  }
2334
2531
  #stderr(data) {
2335
- Logger4.raw(chalk4.red(data.toString()));
2532
+ Logger3.raw(chalk4.red(data.toString()));
2336
2533
  }
2337
2534
  exec(command, options = {}) {
2338
2535
  const cwd = options.cwd?.toString() ?? this.cwdPath;
@@ -2376,7 +2573,7 @@ class Executor {
2376
2573
  }
2377
2574
  spawn(command, args = [], options = {}) {
2378
2575
  const cwd = options.cwd?.toString() ?? this.cwdPath;
2379
- const proc = spawn(command, args, {
2576
+ const proc = spawn2(command, args, {
2380
2577
  cwd: this.cwdPath,
2381
2578
  ...options
2382
2579
  });
@@ -2422,7 +2619,7 @@ class Executor {
2422
2619
  });
2423
2620
  }
2424
2621
  spawnSync(command, args = [], options = {}) {
2425
- const proc = spawn(command, args, {
2622
+ const proc = spawn2(command, args, {
2426
2623
  cwd: this.cwdPath,
2427
2624
  ...options
2428
2625
  });
@@ -2554,7 +2751,7 @@ class Executor {
2554
2751
  contentStr = currentContent;
2555
2752
  } else {
2556
2753
  await FileSys.writeText(writePath, contentStr);
2557
- if (Logger4.isVerbose())
2754
+ if (Logger3.isVerbose())
2558
2755
  this.logger.rawLog(chalk4.yellow(`File Update: ${filePath}`));
2559
2756
  }
2560
2757
  } else {
@@ -2601,7 +2798,11 @@ class Executor {
2601
2798
  this.logger.debug(msg);
2602
2799
  return this;
2603
2800
  }
2604
- spinning(msg, { prefix = `${this.emoji}${this.name}`, indent = 0, enableSpin = !Executor.verbose } = {}) {
2801
+ spinning(msg, {
2802
+ prefix = `${this.emoji}${this.name}`,
2803
+ indent = 0,
2804
+ enableSpin = !Executor.verbose
2805
+ } = {}) {
2605
2806
  return new Spinner(msg, { prefix, indent, enableSpin }).start();
2606
2807
  }
2607
2808
  #tsconfig = null;
@@ -2630,7 +2831,9 @@ class Executor {
2630
2831
  this.#tsconfig = tsconfig;
2631
2832
  }
2632
2833
  #packageJson = null;
2633
- async getPackageJson({ refresh } = {}) {
2834
+ async getPackageJson({
2835
+ refresh
2836
+ } = {}) {
2634
2837
  if (this.#packageJson && !refresh)
2635
2838
  return this.#packageJson;
2636
2839
  const packageJson = await this.readJson("package.json");
@@ -2663,8 +2866,8 @@ class Executor {
2663
2866
  return null;
2664
2867
  const filename = typeof result === "object" ? result.filename : path7.basename(targetPath).replace(".js", ".ts");
2665
2868
  const content = typeof result === "object" ? result.content : result;
2666
- const dirname3 = path7.dirname(targetPath);
2667
- const convertedTargetPath = Object.entries(dict).reduce((path8, [key, value]) => path8.replace(new RegExp(`__${key}__`, "g"), value), `${dirname3}/${filename}`);
2869
+ const dirname2 = path7.dirname(targetPath);
2870
+ const convertedTargetPath = Object.entries(dict).reduce((path8, [key, value]) => path8.replace(new RegExp(`__${key}__`, "g"), value), `${dirname2}/${filename}`);
2668
2871
  this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
2669
2872
  return this.writeFile(convertedTargetPath, content, { overwrite });
2670
2873
  } else if (targetPath.endsWith(".template")) {
@@ -2678,9 +2881,9 @@ class Executor {
2678
2881
  } else if (staticTemplateFileExtensions.has(path7.extname(targetPath).toLowerCase())) {
2679
2882
  const convertedTargetPath = Object.entries(dict).reduce((path8, [key, value]) => path8.replace(new RegExp(`__${key}__`, "g"), value), targetPath);
2680
2883
  const writePath = this.getPath(convertedTargetPath);
2681
- const dirname3 = path7.dirname(writePath);
2682
- if (!await FileSys.dirExists(dirname3))
2683
- await mkdir2(dirname3, { recursive: true });
2884
+ const dirname2 = path7.dirname(writePath);
2885
+ if (!await FileSys.dirExists(dirname2))
2886
+ await mkdir2(dirname2, { recursive: true });
2684
2887
  await copyFile(templatePath, writePath);
2685
2888
  this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
2686
2889
  return { filePath: writePath, content: "" };
@@ -2746,7 +2949,10 @@ class Executor {
2746
2949
  async applyTemplate(options) {
2747
2950
  const dict = {
2748
2951
  ...options.dict ?? {},
2749
- ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]))
2952
+ ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [
2953
+ capitalize(key),
2954
+ capitalize(value)
2955
+ ]))
2750
2956
  };
2751
2957
  return this._applyTemplate({ ...options, dict });
2752
2958
  }
@@ -2761,6 +2967,48 @@ class Executor {
2761
2967
  const message = typeChecker.formatDiagnostics(fileDiagnostics);
2762
2968
  return { fileDiagnostics, fileErrors, fileWarnings, message };
2763
2969
  }
2970
+ async typeCheckAsync(filePath) {
2971
+ const path8 = this.getPath(filePath);
2972
+ const entry = await this.#resolveTypecheckWorkerEntry();
2973
+ const proc = Bun.spawn([process.execPath, entry], {
2974
+ cwd: this.cwdPath,
2975
+ env: {
2976
+ ...process.env,
2977
+ AKAN_TYPECHECK_CWD: this.cwdPath,
2978
+ AKAN_TYPECHECK_FILE: path8
2979
+ },
2980
+ stdout: "pipe",
2981
+ stderr: "pipe"
2982
+ });
2983
+ const [stdout, stderr, exitCode] = await Promise.all([
2984
+ new Response(proc.stdout).text(),
2985
+ new Response(proc.stderr).text(),
2986
+ proc.exited
2987
+ ]);
2988
+ if (exitCode !== 0)
2989
+ throw new Error((stderr || stdout).trim() || `Typecheck failed with exit code ${exitCode}`);
2990
+ const result = JSON.parse(stdout);
2991
+ return {
2992
+ fileDiagnostics: Array.from({ length: result.fileDiagnosticsCount }),
2993
+ fileErrors: Array.from({ length: result.fileErrorsCount }),
2994
+ fileWarnings: Array.from({ length: result.fileWarningsCount }),
2995
+ message: result.message
2996
+ };
2997
+ }
2998
+ async#resolveTypecheckWorkerEntry() {
2999
+ const dirname2 = getDirname(import.meta.url);
3000
+ const candidates = [
3001
+ path7.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
3002
+ path7.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
3003
+ path7.join(dirname2, "typecheck/typecheck.proc.ts"),
3004
+ path7.join(dirname2, "typecheck.proc.js"),
3005
+ path7.join(dirname2, "typecheck.proc.ts")
3006
+ ];
3007
+ for (const candidate of candidates)
3008
+ if (await Bun.file(candidate).exists())
3009
+ return candidate;
3010
+ throw new Error(`[devkit] typecheck worker entry not found; looked in: ${candidates.join(", ")}`);
3011
+ }
2764
3012
  getLinter() {
2765
3013
  this.linter ??= new Linter(this.cwdPath);
2766
3014
  return this.linter;
@@ -2808,7 +3056,15 @@ class WorkspaceExecutor extends Executor {
2808
3056
  const env = sourceEnv.AKAN_PUBLIC_ENV ?? "debug";
2809
3057
  if (!env)
2810
3058
  throw new Error("AKAN_PUBLIC_ENV is not set");
2811
- return { ...appName ? { appName } : {}, workspaceRoot, repoName, serveDomain, env, portOffset, workspaceId };
3059
+ return {
3060
+ ...appName ? { appName } : {},
3061
+ workspaceRoot,
3062
+ repoName,
3063
+ serveDomain,
3064
+ env,
3065
+ portOffset,
3066
+ workspaceId
3067
+ };
2812
3068
  }
2813
3069
  getWorkspaceId({
2814
3070
  allowEmpty
@@ -2832,7 +3088,10 @@ class WorkspaceExecutor extends Executor {
2832
3088
  return await this.#getDirHasFile(`${this.workspaceRoot}/libs`, "akan.config.ts");
2833
3089
  }
2834
3090
  async getSyss() {
2835
- const [appNames, libNames] = await Promise.all([this.getApps(), this.getLibs()]);
3091
+ const [appNames, libNames] = await Promise.all([
3092
+ this.getApps(),
3093
+ this.getLibs()
3094
+ ]);
2836
3095
  return [appNames, libNames];
2837
3096
  }
2838
3097
  async getPkgs() {
@@ -2841,7 +3100,11 @@ class WorkspaceExecutor extends Executor {
2841
3100
  return await this.#getDirHasFile(`${this.workspaceRoot}/pkgs`, "package.json");
2842
3101
  }
2843
3102
  async getExecs() {
2844
- const [appNames, libNames, pkgNames] = await Promise.all([this.getApps(), this.getLibs(), this.getPkgs()]);
3103
+ const [appNames, libNames, pkgNames] = await Promise.all([
3104
+ this.getApps(),
3105
+ this.getLibs(),
3106
+ this.getPkgs()
3107
+ ]);
2845
3108
  return [appNames, libNames, pkgNames];
2846
3109
  }
2847
3110
  async setPkgTsPaths(name) {
@@ -2859,7 +3122,10 @@ class WorkspaceExecutor extends Executor {
2859
3122
  async unsetPkgTsPaths(name) {
2860
3123
  const rootTsConfig = await this.readJson("tsconfig.json");
2861
3124
  const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter((key) => key !== name && key !== `${name}/*`);
2862
- rootTsConfig.compilerOptions.paths = Object.fromEntries(filteredKeys.map((key) => [key, rootTsConfig.compilerOptions.paths?.[key] ?? []]));
3125
+ rootTsConfig.compilerOptions.paths = Object.fromEntries(filteredKeys.map((key) => [
3126
+ key,
3127
+ rootTsConfig.compilerOptions.paths?.[key] ?? []
3128
+ ]));
2863
3129
  if (rootTsConfig.references) {
2864
3130
  rootTsConfig.references = rootTsConfig.references.filter((ref) => ref.path !== `./pkgs/${name}/tsconfig.json`);
2865
3131
  }
@@ -2868,12 +3134,12 @@ class WorkspaceExecutor extends Executor {
2868
3134
  }
2869
3135
  async getDirInModule(basePath2, name) {
2870
3136
  const AVOID_DIRS = ["__lib", "__scalar", `_`, `_${name}`];
2871
- const getDirs = async (dirname3, maxDepth = 3, results = [], prefix = "") => {
2872
- const dirs = await this.readdir(dirname3);
3137
+ const getDirs = async (dirname2, maxDepth = 3, results = [], prefix = "") => {
3138
+ const dirs = await this.readdir(dirname2);
2873
3139
  await Promise.all(dirs.map(async (dir) => {
2874
3140
  if (dir.includes("_") || AVOID_DIRS.includes(dir))
2875
3141
  return;
2876
- const dirPath = path7.join(dirname3, dir);
3142
+ const dirPath = path7.join(dirname2, dir);
2877
3143
  if ((await stat2(dirPath)).isDirectory()) {
2878
3144
  results.push(`${prefix}${dir}`);
2879
3145
  if (maxDepth > 0)
@@ -2893,12 +3159,12 @@ class WorkspaceExecutor extends Executor {
2893
3159
  }
2894
3160
  async#getDirHasFile(basePath2, targetFilename) {
2895
3161
  const AVOID_DIRS = ["node_modules", "dist", "public", "webkit"];
2896
- const getDirs = async (dirname3, maxDepth = 3, results = [], prefix = "") => {
2897
- const dirs = await this.readdir(dirname3);
3162
+ const getDirs = async (dirname2, maxDepth = 3, results = [], prefix = "") => {
3163
+ const dirs = await this.readdir(dirname2);
2898
3164
  await Promise.all(dirs.map(async (dir) => {
2899
3165
  if (AVOID_DIRS.includes(dir))
2900
3166
  return;
2901
- const dirPath = path7.join(dirname3, dir);
3167
+ const dirPath = path7.join(dirname2, dir);
2902
3168
  if ((await stat2(dirPath)).isDirectory()) {
2903
3169
  const hasTargetFile = await FileSys.fileExists(path7.join(dirPath, targetFilename));
2904
3170
  if (hasTargetFile)
@@ -2951,7 +3217,11 @@ class SysExecutor extends Executor {
2951
3217
  name;
2952
3218
  type;
2953
3219
  emoji;
2954
- constructor({ workspace = WorkspaceExecutor.fromRoot(), name, type }) {
3220
+ constructor({
3221
+ workspace = WorkspaceExecutor.fromRoot(),
3222
+ name,
3223
+ type
3224
+ }) {
2955
3225
  super(name, `${workspace.workspaceRoot}/${type}s/${name}`);
2956
3226
  this.workspace = workspace;
2957
3227
  this.name = name;
@@ -3054,7 +3324,10 @@ class SysExecutor extends Executor {
3054
3324
  },
3055
3325
  devDependencies: {
3056
3326
  ...Object.fromEntries(Object.entries(libPackageJson.devDependencies ?? {}).filter(([dep]) => !dependencySet.has(dep))),
3057
- ...Object.fromEntries(devDependencies.filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep]).sort().map((dep) => [dep, rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]]))
3327
+ ...Object.fromEntries(devDependencies.filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep]).sort().map((dep) => [
3328
+ dep,
3329
+ rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]
3330
+ ]))
3058
3331
  }
3059
3332
  };
3060
3333
  await this.setPackageJson(libPkgJsonWithDeps);
@@ -3121,7 +3394,11 @@ class SysExecutor extends Executor {
3121
3394
  ...await LibExecutor.from(this, lib).getConstantFiles(),
3122
3395
  ...await LibExecutor.from(this, lib).getScalarConstantFiles()
3123
3396
  ]));
3124
- return [...sysContantFiles, ...sysScalarConstantFiles, ...libConstantFiles.flat()];
3397
+ return [
3398
+ ...sysContantFiles,
3399
+ ...sysScalarConstantFiles,
3400
+ ...libConstantFiles.flat()
3401
+ ];
3125
3402
  }
3126
3403
  async getDictionaryFiles() {
3127
3404
  const modules = await this.getModules();
@@ -3130,7 +3407,10 @@ class SysExecutor extends Executor {
3130
3407
  async applyTemplate(options) {
3131
3408
  const dict = {
3132
3409
  ...options.dict ?? {},
3133
- ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]))
3410
+ ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [
3411
+ capitalize(key),
3412
+ capitalize(value)
3413
+ ]))
3134
3414
  };
3135
3415
  const scanInfo = await this.scan();
3136
3416
  const fileContents = await this._applyTemplate({
@@ -3189,7 +3469,10 @@ class AppExecutor extends SysExecutor {
3189
3469
  if (type === "build") {
3190
3470
  if (await this.exists(this.dist.cwdPath))
3191
3471
  await this.dist.exec(`rm -rf ${this.dist.cwdPath}`);
3192
- await Promise.all([this.dist.mkdir("private"), this.dist.mkdir("public")]);
3472
+ await Promise.all([
3473
+ this.dist.mkdir("private"),
3474
+ this.dist.mkdir("public")
3475
+ ]);
3193
3476
  await Promise.all([
3194
3477
  this.cp("private", `${this.dist.cwdPath}/private`),
3195
3478
  this.cp("public", `${this.dist.cwdPath}/public`)
@@ -3232,7 +3515,9 @@ class AppExecutor extends SysExecutor {
3232
3515
  return this.#akanConfig;
3233
3516
  }
3234
3517
  #pageKeys = null;
3235
- async getPageKeys({ refresh } = {}) {
3518
+ async getPageKeys({
3519
+ refresh
3520
+ } = {}) {
3236
3521
  if (this.#pageKeys && !refresh)
3237
3522
  return this.#pageKeys;
3238
3523
  const akanConfig2 = await this.getConfig();
@@ -3281,7 +3566,10 @@ class AppExecutor extends SysExecutor {
3281
3566
  const projectAssetsPath = `${this.cwdPath}/private`;
3282
3567
  const projectPublicLibPath = `${projectPublicPath}/libs`;
3283
3568
  const projectAssetsLibPath = `${projectAssetsPath}/libs`;
3284
- await Promise.all([this.removeDir(projectPublicLibPath), this.removeDir(projectAssetsLibPath)]);
3569
+ await Promise.all([
3570
+ this.removeDir(projectPublicLibPath),
3571
+ this.removeDir(projectAssetsLibPath)
3572
+ ]);
3285
3573
  const targetPublicDeps = [];
3286
3574
  for (const dep of libDeps) {
3287
3575
  if (await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/public`))
@@ -3299,7 +3587,10 @@ class AppExecutor extends SysExecutor {
3299
3587
  ...targetAssetsDeps.map((dep) => this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/private`, `${projectAssetsLibPath}/${dep}`))
3300
3588
  ]);
3301
3589
  }
3302
- async scanSync({ refresh = false, write = true } = {}) {
3590
+ async scanSync({
3591
+ refresh = false,
3592
+ write = true
3593
+ } = {}) {
3303
3594
  const scanInfo = await this.scan({
3304
3595
  refresh,
3305
3596
  write,
@@ -3348,7 +3639,10 @@ class PkgExecutor extends Executor {
3348
3639
  name;
3349
3640
  dist;
3350
3641
  emoji = execEmoji.pkg;
3351
- constructor({ workspace = WorkspaceExecutor.fromRoot(), name }) {
3642
+ constructor({
3643
+ workspace = WorkspaceExecutor.fromRoot(),
3644
+ name
3645
+ }) {
3352
3646
  super(name, `${workspace.workspaceRoot}/pkgs/${name}`);
3353
3647
  this.workspace = workspace;
3354
3648
  this.name = name;
@@ -3412,7 +3706,10 @@ class PkgExecutor extends Executor {
3412
3706
  };
3413
3707
  }
3414
3708
  async updatePackageJsonDependencies(dependencies = [], devDependencies = []) {
3415
- const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
3709
+ const [rootPackageJson, pkgJson] = await Promise.all([
3710
+ this.workspace.getPackageJson(),
3711
+ this.getPackageJson()
3712
+ ]);
3416
3713
  const dependencyMaps = await this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
3417
3714
  const newPkgJson = {
3418
3715
  ...pkgJson,
@@ -3422,7 +3719,10 @@ class PkgExecutor extends Executor {
3422
3719
  return newPkgJson;
3423
3720
  }
3424
3721
  async generateDistPackageJson(dependencies = [], devDependencies = []) {
3425
- const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
3722
+ const [rootPackageJson, pkgJson] = await Promise.all([
3723
+ this.workspace.getPackageJson(),
3724
+ this.getPackageJson()
3725
+ ]);
3426
3726
  const dependencyMaps = await this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
3427
3727
  const distPkgJson = {
3428
3728
  ...pkgJson,
@@ -3438,7 +3738,10 @@ class PkgExecutor extends Executor {
3438
3738
  engines: { bun: ">=1.3.13" },
3439
3739
  ...dependencyMaps
3440
3740
  };
3441
- await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
3741
+ await Promise.all([
3742
+ this.dist.writeJson("package.json", distPkgJson),
3743
+ this.writeJson("package.json", distPkgJson)
3744
+ ]);
3442
3745
  return distPkgJson;
3443
3746
  }
3444
3747
  async build() {
@@ -3451,7 +3754,10 @@ class PkgExecutor extends Executor {
3451
3754
  await this.cp(`${this.cwdPath}/dist`, this.dist.cwdPath);
3452
3755
  }
3453
3756
  async generateTsconfigJson() {
3454
- const [rootTsconfig, pkgTsconfig] = await Promise.all([this.workspace.getTsConfig(), this.getTsConfig()]);
3757
+ const [rootTsconfig, pkgTsconfig] = await Promise.all([
3758
+ this.workspace.getTsConfig(),
3759
+ this.getTsConfig()
3760
+ ]);
3455
3761
  const tsconfig = {
3456
3762
  ...rootTsconfig,
3457
3763
  ...pkgTsconfig,
@@ -3615,7 +3921,7 @@ var createTunnel = async (service, { app, environment, port = service === "postg
3615
3921
 
3616
3922
  // pkgs/@akanjs/devkit/incrementalBuilder/incrementalBuilder.host.ts
3617
3923
  import path8 from "path";
3618
- import { Logger as Logger5 } from "akanjs/common";
3924
+ import { Logger as Logger4 } from "akanjs/common";
3619
3925
  var builderMsgTypeSet = new Set([
3620
3926
  "build-route-res",
3621
3927
  "builder-ready",
@@ -3627,7 +3933,7 @@ var builderMsgTypeSet = new Set([
3627
3933
  class IncrementalBuilderHost {
3628
3934
  static #restartBaseDelayMs = 1000;
3629
3935
  static #restartMaxDelayMs = 30000;
3630
- logger = new Logger5("IncrementalBuilderHost");
3936
+ logger = new Logger4("IncrementalBuilderHost");
3631
3937
  entry;
3632
3938
  env;
3633
3939
  app;
@@ -3875,7 +4181,7 @@ class BackendImportGraph {
3875
4181
 
3876
4182
  class AkanAppHost {
3877
4183
  app;
3878
- logger = new Logger6("AkanAppHost");
4184
+ logger = new Logger5("AkanAppHost");
3879
4185
  withInk;
3880
4186
  env;
3881
4187
  #backend = null;
@@ -4158,19 +4464,19 @@ class AkanAppHost {
4158
4464
  }
4159
4465
  }
4160
4466
  // pkgs/@akanjs/devkit/applicationBuildReporter.ts
4161
- import { Logger as Logger7 } from "akanjs/common";
4467
+ import { Logger as Logger6 } from "akanjs/common";
4162
4468
 
4163
4469
  class ApplicationBuildReporter {
4164
4470
  static create() {
4165
4471
  return {
4166
- phaseDone: (phase) => Logger7.rawLog(ApplicationBuildReporter.formatPhaseLine(phase))
4472
+ phaseDone: (phase) => Logger6.rawLog(ApplicationBuildReporter.formatPhaseLine(phase))
4167
4473
  };
4168
4474
  }
4169
4475
  static printSummary(result) {
4170
- Logger7.rawLog("");
4171
- Logger7.rawLog(`Route artifacts: ${result.artifactDir}`);
4172
- Logger7.rawLog(`Server output: ${result.outputDir}`);
4173
- Logger7.rawLog(`Done in ${ApplicationBuildReporter.formatDuration(result.durationMs)}`);
4476
+ Logger6.rawLog("");
4477
+ Logger6.rawLog(`Route artifacts: ${result.artifactDir}`);
4478
+ Logger6.rawLog(`Server output: ${result.outputDir}`);
4479
+ Logger6.rawLog(`Done in ${ApplicationBuildReporter.formatDuration(result.durationMs)}`);
4174
4480
  }
4175
4481
  static formatError(error) {
4176
4482
  if (error instanceof AggregateError) {
@@ -4469,13 +4775,13 @@ import path14 from "path";
4469
4775
 
4470
4776
  // pkgs/@akanjs/devkit/transforms/barrelAnalyzer.ts
4471
4777
  import path12 from "path";
4472
- import { Logger as Logger8 } from "akanjs/common";
4778
+ import { Logger as Logger7 } from "akanjs/common";
4473
4779
  var REEXPORT_RE = /(?:^|\n)\s*export\s+(?:type\s+)?(?:(\*)(?:\s+as\s+(\w+))?|\{\s*([^}]*?)\s*\})\s+from\s+(["'])([^"']+)\4;?/g;
4474
4780
  var LOCAL_NAMED_RE = /(?:^|\n)\s*export\s+\{\s*([^}]*?)\s*\}(?!\s*from)/g;
4475
4781
  var CANDIDATE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
4476
4782
 
4477
4783
  class BarrelAnalyzer {
4478
- #logger = new Logger8("BarrelAnalyzer");
4784
+ #logger = new Logger7("BarrelAnalyzer");
4479
4785
  #opts;
4480
4786
  #cache = new Map;
4481
4787
  #tsTranspiler = new Bun.Transpiler({ loader: "ts" });
@@ -6175,7 +6481,7 @@ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
6175
6481
  }
6176
6482
  // pkgs/@akanjs/devkit/frontendBuild/cssCompiler.ts
6177
6483
  import path23 from "path";
6178
- import { Logger as Logger9 } from "akanjs/common";
6484
+ import { Logger as Logger8 } from "akanjs/common";
6179
6485
  import { compile } from "tailwindcss";
6180
6486
 
6181
6487
  // pkgs/@akanjs/devkit/frontendBuild/cssImportResolver.ts
@@ -6320,7 +6626,7 @@ var NODE_MODULES_RE3 = /[\\/]node_modules[\\/]/;
6320
6626
  var AKANJS_NODE_MODULE_RE3 = /[\\/]node_modules[\\/]akanjs[\\/]/;
6321
6627
 
6322
6628
  class CssCompiler {
6323
- #logger = new Logger9("CssCompiler");
6629
+ #logger = new Logger8("CssCompiler");
6324
6630
  #transpiler = new Bun.Transpiler({ loader: "tsx" });
6325
6631
  #app;
6326
6632
  #cssImportResolver = null;
@@ -7728,7 +8034,7 @@ class ApplicationBuildRunner {
7728
8034
  import { cp, mkdir as mkdir8, rm as rm3 } from "fs/promises";
7729
8035
 
7730
8036
  // pkgs/@akanjs/devkit/uploadRelease.ts
7731
- import { HttpClient as HttpClient2, Logger as Logger10 } from "akanjs/common";
8037
+ import { HttpClient as HttpClient2, Logger as Logger9 } from "akanjs/common";
7732
8038
  var spinning = (message) => {
7733
8039
  const spinner = new Spinner(message, { prefix: message, enableSpin: true }).start();
7734
8040
  return spinner;
@@ -7741,7 +8047,7 @@ var uploadRelease = async (appName, {
7741
8047
  os,
7742
8048
  local
7743
8049
  }) => {
7744
- const logger = new Logger10("uploadRelease");
8050
+ const logger = new Logger9("uploadRelease");
7745
8051
  const basePath2 = local ? "http://localhost:8282/backend" : "https://cloud.akanjs.com/backend";
7746
8052
  const httpClient = new HttpClient2(basePath2);
7747
8053
  const buildPath = `${workspaceRoot}/releases/builds/${appName}-release.tar.gz`;
@@ -8727,7 +9033,7 @@ var Workspace = createInternalArgToken("Workspace");
8727
9033
  // pkgs/@akanjs/devkit/commandDecorators/command.ts
8728
9034
  import path36 from "path";
8729
9035
  import { confirm, input as input2, select as select2 } from "@inquirer/prompts";
8730
- import { Logger as Logger11 } from "akanjs/common";
9036
+ import { Logger as Logger10 } from "akanjs/common";
8731
9037
  import chalk6 from "chalk";
8732
9038
  import { program } from "commander";
8733
9039
 
@@ -9012,7 +9318,7 @@ var printCliError = (error) => {
9012
9318
  if (loggedCliErrorMessages.has(message))
9013
9319
  return;
9014
9320
  loggedCliErrorMessages.add(message);
9015
- Logger11.rawLog(`
9321
+ Logger10.rawLog(`
9016
9322
  ${chalk6.red(message)}`);
9017
9323
  };
9018
9324
  var handleOption = (programCommand, argMeta) => {
@@ -9241,7 +9547,7 @@ var runCommands = async (...commands) => {
9241
9547
  const hasCommand = process.argv.length > 2 && !process.argv[2]?.startsWith("-");
9242
9548
  if (hasHelpFlag || !hasCommand) {
9243
9549
  if (process.argv.length === 2 || process.argv.length === 3 && hasHelpFlag) {
9244
- Logger11.rawLog(formatHelp(commands, process.env.AKAN_VERSION));
9550
+ Logger10.rawLog(formatHelp(commands, process.env.AKAN_VERSION));
9245
9551
  process.exit(0);
9246
9552
  }
9247
9553
  }
@@ -9250,7 +9556,7 @@ var runCommands = async (...commands) => {
9250
9556
  });
9251
9557
  const installedAkanPackageJson = await FileSys.fileExists("./node_modules/akanjs/package.json") ? await FileSys.readJson("./node_modules/akanjs/package.json") : null;
9252
9558
  if (installedAkanPackageJson && installedAkanPackageJson.version !== process.env.AKAN_VERSION) {
9253
- Logger11.rawLog(chalk6.yellow(`
9559
+ Logger10.rawLog(chalk6.yellow(`
9254
9560
  Akan CLI version is mismatch with installed package. ${process.env.AKAN_VERSION} (global) vs ${installedAkanPackageJson.version} (akanjs)
9255
9561
  It may cause unexpected behavior. Run \`akan update\` to update latest akanjs.`));
9256
9562
  }
@@ -9286,7 +9592,7 @@ It may cause unexpected behavior. Run \`akan update\` to update latest akanjs.`)
9286
9592
  return formatCommandHelp(command, targetMeta.key);
9287
9593
  };
9288
9594
  programCommand.action(async (...args) => {
9289
- Logger11.rawLog();
9595
+ Logger10.rawLog();
9290
9596
  const cmdArgs = args.slice(0, args.length - 2);
9291
9597
  const opt = args[args.length - 2];
9292
9598
  const commandArgs = [];
@@ -9310,7 +9616,7 @@ It may cause unexpected behavior. Run \`akan update\` to update latest akanjs.`)
9310
9616
  const cmd = CommandContainer.get(command);
9311
9617
  try {
9312
9618
  await targetMeta.handler.call(cmd, ...commandArgs);
9313
- Logger11.rawLog();
9619
+ Logger10.rawLog();
9314
9620
  } catch (e) {
9315
9621
  printCliError(e);
9316
9622
  throw e;
@@ -9650,8 +9956,11 @@ import fsPromise from "fs/promises";
9650
9956
  import { input as input3, select as select3 } from "@inquirer/prompts";
9651
9957
  class Prompter {
9652
9958
  static async#getGuidelineRoot() {
9653
- const dirname3 = getDirname(import.meta.url);
9654
- const candidates = [`${dirname3}/guidelines`, `${dirname3}/../cli/guidelines`];
9959
+ const dirname2 = getDirname(import.meta.url);
9960
+ const candidates = [
9961
+ `${dirname2}/guidelines`,
9962
+ `${dirname2}/../cli/guidelines`
9963
+ ];
9655
9964
  for (const candidate of candidates) {
9656
9965
  try {
9657
9966
  await fsPromise.access(candidate);
@@ -9663,7 +9972,10 @@ class Prompter {
9663
9972
  static async selectGuideline() {
9664
9973
  const guidelineRoot = await Prompter.#getGuidelineRoot();
9665
9974
  const guideNames = (await fsPromise.readdir(guidelineRoot)).filter((name) => !name.startsWith("_"));
9666
- return await select3({ message: "Select a guideline", choices: guideNames.map((name) => ({ name, value: name })) });
9975
+ return await select3({
9976
+ message: "Select a guideline",
9977
+ choices: guideNames.map((name) => ({ name, value: name }))
9978
+ });
9667
9979
  }
9668
9980
  static async getGuideJson(guideName) {
9669
9981
  const guidelineRoot = await Prompter.#getGuidelineRoot();
@@ -9678,13 +9990,18 @@ class Prompter {
9678
9990
  return content;
9679
9991
  }
9680
9992
  static async getUpdateRequest(guideName) {
9681
- return await input3({ message: `What do you want to update in ${guideName}?` });
9993
+ return await input3({
9994
+ message: `What do you want to update in ${guideName}?`
9995
+ });
9682
9996
  }
9683
9997
  async makeTsFileUpdatePrompt({ context, request }) {
9684
9998
  return `You are a senior developer writing TypeScript-based programs using Akan.js, an in-house framework. Here's an overview of the Akan.js framework:
9685
9999
  ${await this.getDocumentation("framework")}
9686
10000
  Please understand the following background information, write code that meets the requirements, verify that it satisfies the validation conditions, and return the result.
9687
10001
 
10002
+ # Code Style
10003
+ - Use double quotes for all string literals in TypeScript/TSX code. Do not use single quotes.
10004
+
9688
10005
  # Background Information
9689
10006
  \`\`\`markdown
9690
10007
  ${context}
@@ -9734,7 +10051,7 @@ import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime"
9734
10051
  import { select as select6 } from "@inquirer/prompts";
9735
10052
 
9736
10053
  // pkgs/@akanjs/cli/application/application.script.ts
9737
- import { Logger as Logger13 } from "akanjs/common";
10054
+ import { Logger as Logger12 } from "akanjs/common";
9738
10055
 
9739
10056
  // pkgs/@akanjs/cli/semver.ts
9740
10057
  function parseVersion(version) {
@@ -9852,14 +10169,14 @@ import { StringOutputParser } from "@langchain/core/output_parsers";
9852
10169
  import { PromptTemplate as PromptTemplate2 } from "@langchain/core/prompts";
9853
10170
  import { RunnableSequence as RunnableSequence2 } from "@langchain/core/runnables";
9854
10171
  import { ChatOpenAI as ChatOpenAI3 } from "@langchain/openai";
9855
- import { Logger as Logger12 } from "akanjs/common";
10172
+ import { Logger as Logger11 } from "akanjs/common";
9856
10173
  import ora3 from "ora";
9857
10174
 
9858
10175
  // pkgs/@akanjs/cli/openBrowser.ts
9859
- import { spawn as spawn2 } from "child_process";
10176
+ import { spawn as spawn3 } from "child_process";
9860
10177
  function openBrowser(url) {
9861
10178
  const command3 = process.platform === "darwin" ? ["open", url] : process.platform === "win32" ? ["cmd", "/c", "start", "", url] : ["xdg-open", url];
9862
- const child = spawn2(command3[0], command3.slice(1), { detached: true, stdio: "ignore" });
10179
+ const child = spawn3(command3[0], command3.slice(1), { detached: true, stdio: "ignore" });
9863
10180
  child.on("error", () => {});
9864
10181
  child.unref();
9865
10182
  return Promise.resolve();
@@ -10045,7 +10362,7 @@ class ApplicationRunner extends runner("application") {
10045
10362
  return;
10046
10363
  for (const failure of failures) {
10047
10364
  const message = failure.error instanceof Error ? failure.error.message : String(failure.error);
10048
- Logger12.rawLog(`Mobile target ${failure.target} failed: ${message}`, undefined, "error");
10365
+ Logger11.rawLog(`Mobile target ${failure.target} failed: ${message}`, undefined, "error");
10049
10366
  }
10050
10367
  throw new Error(`${failures.length}/${results.length} mobile targets failed`);
10051
10368
  }
@@ -10190,18 +10507,18 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10190
10507
  async build(app, { write = true, fast = false, quiet = false } = {}) {
10191
10508
  await app.scanSync({ write });
10192
10509
  if (!quiet)
10193
- Logger13.rawLog(`Creating an optimized production build for ${app.name}...`);
10510
+ Logger12.rawLog(`Creating an optimized production build for ${app.name}...`);
10194
10511
  try {
10195
10512
  const result = await this.applicationRunner.build(app, {
10196
10513
  fast,
10197
10514
  spinner: !quiet
10198
10515
  });
10199
- Logger13.rawLog(`${app.name} built in dist/apps/${app.name}`);
10516
+ Logger12.rawLog(`${app.name} built in dist/apps/${app.name}`);
10200
10517
  if (!quiet)
10201
10518
  ApplicationBuildReporter.printSummary(result);
10202
10519
  } catch (error) {
10203
- Logger13.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
10204
- Logger13.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
10520
+ Logger12.rawLog(`${app.name} build failed in dist/apps/${app.name}`, undefined, "error");
10521
+ Logger12.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
10205
10522
  throw error;
10206
10523
  }
10207
10524
  }
@@ -10213,7 +10530,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10213
10530
  spinner2.succeed(`${app.name} typechecked`);
10214
10531
  } catch (error) {
10215
10532
  spinner2.fail(`${app.name} typecheck failed`);
10216
- Logger13.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
10533
+ Logger12.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
10217
10534
  throw error;
10218
10535
  }
10219
10536
  }
@@ -10477,11 +10794,11 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
10477
10794
  }
10478
10795
 
10479
10796
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
10480
- import { Logger as Logger16 } from "akanjs/common";
10797
+ import { Logger as Logger15 } from "akanjs/common";
10481
10798
 
10482
10799
  // pkgs/@akanjs/cli/package/package.runner.ts
10483
10800
  import path37 from "path";
10484
- import { Logger as Logger14 } from "akanjs/common";
10801
+ import { Logger as Logger13 } from "akanjs/common";
10485
10802
  var {$: $2 } = globalThis.Bun;
10486
10803
 
10487
10804
  class PackageRunner extends runner("package") {
@@ -10489,7 +10806,7 @@ class PackageRunner extends runner("package") {
10489
10806
  const pkgJson = process.env.USE_AKANJS_PKGS === "true" ? await FileSys.readJson(`${workspace?.workspaceRoot ?? process.cwd()}/pkgs/akanjs/package.json`) : await this.#getInstalledPackageJson();
10490
10807
  const version = pkgJson.name === "akanjs" ? pkgJson.version : pkgJson.dependencies?.akanjs ?? pkgJson.version;
10491
10808
  if (log)
10492
- Logger14.rawLog(`akanjs@${version}`);
10809
+ Logger13.rawLog(`akanjs@${version}`);
10493
10810
  return version;
10494
10811
  }
10495
10812
  async#getInstalledPackageJson() {
@@ -10617,7 +10934,7 @@ class PackageScript extends script("package", [PackageRunner]) {
10617
10934
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
10618
10935
  import path38 from "path";
10619
10936
  import { confirm as confirm3, input as input5, select as select7 } from "@inquirer/prompts";
10620
- import { Logger as Logger15, sleep } from "akanjs/common";
10937
+ import { Logger as Logger14, sleep } from "akanjs/common";
10621
10938
  import chalk7 from "chalk";
10622
10939
  import * as QRcode from "qrcode";
10623
10940
 
@@ -10697,7 +11014,7 @@ class CloudRunner extends runner("cloud") {
10697
11014
  const servers = await GlobalConfig.getRemoteEnvServers();
10698
11015
  const serverEntries = Object.entries(servers).sort(([nameA], [nameB]) => nameA.localeCompare(nameB));
10699
11016
  if (serverEntries.length === 0) {
10700
- Logger15.info("No remote env servers configured. Add the first remote server for SCP mode.");
11017
+ Logger14.info("No remote env servers configured. Add the first remote server for SCP mode.");
10701
11018
  return await this.#addRemoteEnvServer();
10702
11019
  }
10703
11020
  const selectedName = await select7({
@@ -10737,7 +11054,7 @@ class CloudRunner extends runner("cloud") {
10737
11054
  if (!shouldRemove)
10738
11055
  return;
10739
11056
  await GlobalConfig.removeRemoteEnvServer(selectedName);
10740
- Logger15.info(`Removed remote env server "${selectedName}"`);
11057
+ Logger14.info(`Removed remote env server "${selectedName}"`);
10741
11058
  }
10742
11059
  async#getRemoteEnvServerWithUsername() {
10743
11060
  const remoteServer = await this.#selectRemoteEnvServer();
@@ -10786,17 +11103,17 @@ class CloudRunner extends runner("cloud") {
10786
11103
  const cloudApi2 = new CloudApi(config);
10787
11104
  const self = config.auth ? await cloudApi2.getRemoteSelf() : null;
10788
11105
  if (self) {
10789
- Logger15.rawLog(chalk7.green(`
11106
+ Logger14.rawLog(chalk7.green(`
10790
11107
  \u2713 Already logged in akan cloud as ${self.nickname}
10791
11108
  `));
10792
11109
  return true;
10793
11110
  }
10794
11111
  const remoteId = crypto.randomUUID();
10795
11112
  const signinUrl = `${akanCloudUrl}/signin?remoteId=${remoteId}`;
10796
- Logger15.rawLog(chalk7.bold(`
11113
+ Logger14.rawLog(chalk7.bold(`
10797
11114
  ${chalk7.green("\u27A4")} Authentication Required`));
10798
- Logger15.rawLog(chalk7.dim("Please visit or click the following URL:"));
10799
- Logger15.rawLog(`${chalk7.cyan.underline(signinUrl)}
11115
+ Logger14.rawLog(chalk7.dim("Please visit or click the following URL:"));
11116
+ Logger14.rawLog(`${chalk7.cyan.underline(signinUrl)}
10800
11117
  `);
10801
11118
  try {
10802
11119
  const qrcode = await new Promise((resolve, reject) => {
@@ -10806,13 +11123,13 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10806
11123
  resolve(data);
10807
11124
  });
10808
11125
  });
10809
- Logger15.rawLog(qrcode);
11126
+ Logger14.rawLog(qrcode);
10810
11127
  await openBrowser(signinUrl);
10811
- Logger15.rawLog(chalk7.dim("Opening browser..."));
11128
+ Logger14.rawLog(chalk7.dim("Opening browser..."));
10812
11129
  } catch {
10813
- Logger15.rawLog(chalk7.yellow("Could not open browser. Please visit the URL manually."));
11130
+ Logger14.rawLog(chalk7.yellow("Could not open browser. Please visit the URL manually."));
10814
11131
  }
10815
- Logger15.rawLog(chalk7.dim("Waiting for authentication..."));
11132
+ Logger14.rawLog(chalk7.dim("Waiting for authentication..."));
10816
11133
  const MAX_RETRY = 300;
10817
11134
  for (let i = 0;i < MAX_RETRY; i++) {
10818
11135
  const accessToken = await cloudApi2.getRemoteAuthToken(remoteId);
@@ -10821,10 +11138,10 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10821
11138
  await GlobalConfig.setHostConfig(akanCloudHost, {
10822
11139
  auth: { accessToken, self: self2 }
10823
11140
  });
10824
- Logger15.rawLog(chalk7.green(`\r\u2713 Authentication successful!`));
10825
- Logger15.rawLog(chalk7.green.bold(`
11141
+ Logger14.rawLog(chalk7.green(`\r\u2713 Authentication successful!`));
11142
+ Logger14.rawLog(chalk7.green.bold(`
10826
11143
  \u2728 Welcome aboard, ${self2.nickname}!`));
10827
- Logger15.rawLog(chalk7.dim(`You're now ready to use Akan CLI!
11144
+ Logger14.rawLog(chalk7.dim(`You're now ready to use Akan CLI!
10828
11145
  `));
10829
11146
  return true;
10830
11147
  }
@@ -10836,17 +11153,17 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10836
11153
  const config = await GlobalConfig.getHostConfig();
10837
11154
  if (config.auth?.self) {
10838
11155
  await GlobalConfig.setHostConfig(akanCloudHost, {});
10839
- Logger15.rawLog(chalk7.magenta.bold(`
11156
+ Logger14.rawLog(chalk7.magenta.bold(`
10840
11157
  \uD83D\uDC4B Goodbye, ${config.auth.self.nickname}!`));
10841
- 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
11158
+ 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
10842
11159
  `));
10843
- Logger15.rawLog(chalk7.cyan("You have been successfully logged out."));
10844
- Logger15.rawLog(chalk7.dim(`Thank you for using Akan CLI. Come back soon! \uD83C\uDF1F
11160
+ Logger14.rawLog(chalk7.cyan("You have been successfully logged out."));
11161
+ Logger14.rawLog(chalk7.dim(`Thank you for using Akan CLI. Come back soon! \uD83C\uDF1F
10845
11162
  `));
10846
11163
  } else {
10847
- Logger15.rawLog(chalk7.yellow.bold(`
11164
+ Logger14.rawLog(chalk7.yellow.bold(`
10848
11165
  \u26A0\uFE0F No active session found`));
10849
- Logger15.rawLog(chalk7.dim(`You were not logged in to begin with
11166
+ Logger14.rawLog(chalk7.dim(`You were not logged in to begin with
10850
11167
  `));
10851
11168
  }
10852
11169
  }
@@ -10855,7 +11172,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10855
11172
  }
10856
11173
  resetLlm() {
10857
11174
  AiSession.setLlmConfig(null);
10858
- Logger15.rawLog(chalk7.green("\u2611\uFE0F LLM model config is cleared. Please run `akan set-llm` to set a new LLM model."));
11175
+ Logger14.rawLog(chalk7.green("\u2611\uFE0F LLM model config is cleared. Please run `akan set-llm` to set a new LLM model."));
10859
11176
  }
10860
11177
  async getAkanPkgs(workspace) {
10861
11178
  const pkgs = await workspace.getPkgs();
@@ -10879,8 +11196,8 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10879
11196
  }
10880
11197
  };
10881
11198
  const { nextVersion, latestPublishedVersion } = await getNextVersion(targetVersionPrefix, tag);
10882
- Logger15.info(`Latest published version of akanjs: ${latestPublishedVersion ?? "none"}`);
10883
- Logger15.info(`Next version of akanjs: ${nextVersion}`);
11199
+ Logger14.info(`Latest published version of akanjs: ${latestPublishedVersion ?? "none"}`);
11200
+ Logger14.info(`Next version of akanjs: ${nextVersion}`);
10884
11201
  for (const library of akanPkgs) {
10885
11202
  const packageJson = await workspace.readJson(`pkgs/${library}/package.json`);
10886
11203
  const newPackageJsonStr = JSON.stringify(this.#normalizeAkanPackageJson(packageJson, library, nextVersion), null, 2);
@@ -10894,12 +11211,12 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10894
11211
  message: "Are you sure you want to deploy the libraries?"
10895
11212
  });
10896
11213
  if (!isDeployConfirmed) {
10897
- Logger15.error("Deployment cancelled");
11214
+ Logger14.error("Deployment cancelled");
10898
11215
  return;
10899
11216
  }
10900
11217
  }
10901
11218
  await Promise.all(akanPkgs.map(async (library) => {
10902
- Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
11219
+ Logger14.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
10903
11220
  await workspace.spawn("npm", [
10904
11221
  "publish",
10905
11222
  "--tag",
@@ -10911,9 +11228,9 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10911
11228
  env: this.#getRegistryEnv(registry),
10912
11229
  stdio: "inherit"
10913
11230
  });
10914
- Logger15.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
11231
+ Logger14.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
10915
11232
  }));
10916
- Logger15.info(`All libraries are published to ${registry ?? "npm"}`);
11233
+ Logger14.info(`All libraries are published to ${registry ?? "npm"}`);
10917
11234
  }
10918
11235
  async update(workspace, tag = "latest", { registryUrl } = {}) {
10919
11236
  const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
@@ -10992,7 +11309,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10992
11309
  await workspace.mkdir("local");
10993
11310
  await workspace.remove(envArchivePath);
10994
11311
  try {
10995
- Logger15.info(`Downloading env archive from remote server "${remoteServer.name}"...`);
11312
+ Logger14.info(`Downloading env archive from remote server "${remoteServer.name}"...`);
10996
11313
  await workspace.spawn("scp", this.#getScpArgs(remoteServer.config, remoteTarget, envArchivePath), {
10997
11314
  cwd: workspace.workspaceRoot,
10998
11315
  stdio: "inherit"
@@ -11015,7 +11332,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11015
11332
  cwd: workspace.workspaceRoot,
11016
11333
  stdio: "inherit"
11017
11334
  });
11018
- Logger15.info(`Uploading env archive to remote server "${remoteServer.name}"...`);
11335
+ Logger14.info(`Uploading env archive to remote server "${remoteServer.name}"...`);
11019
11336
  await workspace.spawn("scp", this.#getScpArgs(remoteServer.config, filePath, remoteTarget), {
11020
11337
  cwd: workspace.workspaceRoot,
11021
11338
  stdio: "inherit"
@@ -11039,7 +11356,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11039
11356
  await workspace.spawn("tar", ["-cf", "local/env.tar", ...envFilePaths], {
11040
11357
  cwd: workspace.workspaceRoot
11041
11358
  });
11042
- Logger15.info(`Archived ${envFilePaths.length} environment files to local/env.tar`);
11359
+ Logger14.info(`Archived ${envFilePaths.length} environment files to local/env.tar`);
11043
11360
  return { files: envFilePaths, path: "local/env.tar" };
11044
11361
  }
11045
11362
  }
@@ -11100,7 +11417,7 @@ class CloudScript extends script("cloud", [
11100
11417
  const spinner2 = workspace.spinning("Updating Akan.js packages and CLI...");
11101
11418
  await this.cloudRunner.update(workspace, tag, { registryUrl });
11102
11419
  spinner2.succeed("Akan.js packages and CLI updated, global version is below");
11103
- Logger16.raw("> Akan version: ");
11420
+ Logger15.raw("> Akan version: ");
11104
11421
  await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
11105
11422
  }
11106
11423
  }
@@ -11499,7 +11816,7 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
11499
11816
  // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
11500
11817
  import { mkdir as mkdir11, rm as rm5 } from "fs/promises";
11501
11818
  import path39 from "path";
11502
- import { Logger as Logger17 } from "akanjs/common";
11819
+ import { Logger as Logger16 } from "akanjs/common";
11503
11820
  var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
11504
11821
  var containerName = "akan-verdaccio";
11505
11822
  var smokeRepoName = "akan-local-smoke";
@@ -11513,7 +11830,7 @@ class LocalRegistryRunner extends runner("localRegistry") {
11513
11830
  const registry = this.getRegistryUrl(registryUrl);
11514
11831
  try {
11515
11832
  await workspace.spawn("docker", ["inspect", containerName]);
11516
- Logger17.info(`Local registry is already running at ${registry}`);
11833
+ Logger16.info(`Local registry is already running at ${registry}`);
11517
11834
  return registry;
11518
11835
  } catch {}
11519
11836
  const configPath2 = path39.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
@@ -11533,7 +11850,7 @@ class LocalRegistryRunner extends runner("localRegistry") {
11533
11850
  `${storagePath}:/verdaccio/storage`,
11534
11851
  "verdaccio/verdaccio:6"
11535
11852
  ], { stdio: "inherit" });
11536
- Logger17.info(`Local registry is running at ${registry}`);
11853
+ Logger16.info(`Local registry is running at ${registry}`);
11537
11854
  return registry;
11538
11855
  }
11539
11856
  async reset(workspace) {
@@ -11541,7 +11858,7 @@ class LocalRegistryRunner extends runner("localRegistry") {
11541
11858
  await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
11542
11859
  } catch {}
11543
11860
  await rm5(path39.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
11544
- Logger17.info("Local registry storage has been reset");
11861
+ Logger16.info("Local registry storage has been reset");
11545
11862
  }
11546
11863
  async smoke(workspace, { registryUrl } = {}) {
11547
11864
  const registry = this.getRegistryUrl(registryUrl);
@@ -11567,7 +11884,7 @@ class LocalRegistryRunner extends runner("localRegistry") {
11567
11884
  env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
11568
11885
  stdio: "inherit"
11569
11886
  });
11570
- Logger17.info(`Local registry smoke test completed for ${smokeRepoName}/${smokeAppName}`);
11887
+ Logger16.info(`Local registry smoke test completed for ${smokeRepoName}/${smokeAppName}`);
11571
11888
  }
11572
11889
  }
11573
11890
 
@@ -12433,7 +12750,7 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
12433
12750
 
12434
12751
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
12435
12752
  import path41 from "path";
12436
- import { Logger as Logger18 } from "akanjs/common";
12753
+ import { Logger as Logger17 } from "akanjs/common";
12437
12754
 
12438
12755
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
12439
12756
  import path40 from "path";
@@ -12457,16 +12774,16 @@ var defaultWorkspacePeerDependencies = new Set([
12457
12774
 
12458
12775
  class WorkspaceRunner extends runner("workspace") {
12459
12776
  async createWorkspace(repoName, appName, {
12460
- dirname: dirname3 = ".",
12777
+ dirname: dirname2 = ".",
12461
12778
  init = true,
12462
12779
  akanVersion,
12463
12780
  registryUrl
12464
12781
  }) {
12465
12782
  const cwdPath = process.cwd();
12466
- const workspaceRoot = path40.join(cwdPath, dirname3, repoName);
12783
+ const workspaceRoot = path40.join(cwdPath, dirname2, repoName);
12467
12784
  const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
12468
12785
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
12469
- const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname3}/${repoName}...`);
12786
+ const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname2}/${repoName}...`);
12470
12787
  const [latestBiomeVersion, latestTypesBunVersion] = await Promise.all([
12471
12788
  getLatestPackageVersion("@biomejs/biome", "latest", normalizedRegistryUrl),
12472
12789
  getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl)
@@ -12479,7 +12796,7 @@ class WorkspaceRunner extends runner("workspace") {
12479
12796
  if (normalizedRegistryUrl)
12480
12797
  await workspace.writeFile(".npmrc", `registry=${normalizedRegistryUrl}/
12481
12798
  `);
12482
- templateSpinner.succeed(`Workspace files created in ${dirname3}/${repoName}`);
12799
+ templateSpinner.succeed(`Workspace files created in ${dirname2}/${repoName}`);
12483
12800
  const [rootPackageJson, peerDependencies] = await Promise.all([
12484
12801
  workspace.getPackageJson(),
12485
12802
  this.#getAkanPeerDependencies()
@@ -12584,14 +12901,14 @@ class WorkspaceScript extends script("workspace", [
12584
12901
  PackageScript
12585
12902
  ]) {
12586
12903
  async createWorkspace(repoName, appName, {
12587
- dirname: dirname3 = ".",
12904
+ dirname: dirname2 = ".",
12588
12905
  installLibs = false,
12589
12906
  init = true,
12590
12907
  registryUrl
12591
12908
  }) {
12592
12909
  const akanVersion = await this.packageScript.version(null, { log: false });
12593
12910
  const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
12594
- dirname: dirname3,
12911
+ dirname: dirname2,
12595
12912
  init,
12596
12913
  akanVersion,
12597
12914
  ...registryUrl ? { registryUrl } : {}
@@ -12608,11 +12925,11 @@ class WorkspaceScript extends script("workspace", [
12608
12925
  } catch (_) {
12609
12926
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
12610
12927
  }
12611
- const workspacePath = path41.join(dirname3, repoName);
12612
- Logger18.rawLog(`
12613
- \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname3}/${repoName}`);
12614
- Logger18.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
12615
- Logger18.rawLog(`
12928
+ const workspacePath = path41.join(dirname2, repoName);
12929
+ Logger17.rawLog(`
12930
+ \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname2}/${repoName}`);
12931
+ Logger17.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
12932
+ Logger17.rawLog(`
12616
12933
  \uD83D\uDC4B Happy coding!`);
12617
12934
  }
12618
12935
  async lint(exec2, workspace, { fix = true } = {}) {