@akanjs/cli 2.1.0-rc.1 → 2.1.0-rc.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/cli",
3
- "version": "2.1.0-rc.1",
3
+ "version": "2.1.0-rc.11",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -34,9 +34,10 @@
34
34
  "@langchain/deepseek": "^1.0.26",
35
35
  "@langchain/openai": "^1.4.6",
36
36
  "@trapezedev/project": "^7.1.4",
37
- "akanjs": "2.1.0-rc.0",
37
+ "akanjs": "2.1.0-rc.10",
38
38
  "chalk": "^5.6.2",
39
39
  "commander": "^14.0.3",
40
+ "daisyui": "^5.5.20",
40
41
  "fontaine": "^0.8.0",
41
42
  "fonteditor-core": "^2.6.3",
42
43
  "ignore": "^7.0.5",
@@ -47,6 +48,7 @@
47
48
  "react": "19.2.6",
48
49
  "ssh2": "^1.17.0",
49
50
  "subset-font": "^2.5.0",
51
+ "tailwind-scrollbar": "^4.0.2",
50
52
  "tailwindcss": "^4.3.0",
51
53
  "typescript": "^6.0.3"
52
54
  },
@@ -1,5 +1,5 @@
1
- import type { AppInfo, LibInfo } from "akanjs";
2
1
  import type { SysExecutor } from "@akanjs/devkit";
2
+ import type { AppInfo, LibInfo } from "akanjs";
3
3
 
4
4
  interface Dict {
5
5
  [key: string]: string;
@@ -117,4 +117,5 @@ libs/*/common/index.ts
117
117
  libs/*/client.ts
118
118
  libs/*/server.ts
119
119
  libs/*/index.ts
120
- **/.akan
120
+ **/.akan
121
+ **/bun.lock
@@ -0,0 +1,208 @@
1
+ // @bun
2
+ var __require = import.meta.require;
3
+
4
+ // pkgs/@akanjs/devkit/typeChecker.ts
5
+ import { readFileSync } from "fs";
6
+ import * as path from "path";
7
+ import chalk from "chalk";
8
+ import * as ts from "typescript";
9
+
10
+ class TypeChecker {
11
+ configPath;
12
+ configFile;
13
+ config;
14
+ constructor(executor) {
15
+ const configPath = this.#findConfigFile(executor.cwdPath);
16
+ if (!configPath)
17
+ throw new Error("No tsconfig.json found in the project");
18
+ this.configPath = configPath;
19
+ this.configFile = ts.readConfigFile(this.configPath, (fileName) => ts.sys.readFile(fileName));
20
+ const parsedConfig = ts.parseJsonConfigFileContent(this.configFile.config, ts.sys, path.dirname(this.configPath), undefined, this.configPath);
21
+ if (parsedConfig.errors.length > 0) {
22
+ const errorMessages = parsedConfig.errors.map((error) => ts.flattenDiagnosticMessageText(error.messageText, `
23
+ `)).join(`
24
+ `);
25
+ throw new Error(`Error parsing tsconfig.json:
26
+ ${errorMessages}`);
27
+ }
28
+ this.config = parsedConfig;
29
+ }
30
+ #findConfigFile(searchPath) {
31
+ return ts.findConfigFile(searchPath, (fileName) => ts.sys.fileExists(fileName), "tsconfig.json");
32
+ }
33
+ check(filePath) {
34
+ const program = ts.createProgram([filePath], this.config.options);
35
+ const diagnostics = [
36
+ ...program.getSemanticDiagnostics(),
37
+ ...program.getSyntacticDiagnostics(),
38
+ ...this.config.options.declaration ? program.getDeclarationDiagnostics() : []
39
+ ];
40
+ const errors = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
41
+ const warnings = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Warning);
42
+ const fileDiagnostics = diagnostics.filter((diagnostic) => diagnostic.file?.fileName === filePath);
43
+ const fileErrors = fileDiagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
44
+ const fileWarnings = fileDiagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Warning);
45
+ return { diagnostics, errors, warnings, fileDiagnostics, fileErrors, fileWarnings };
46
+ }
47
+ formatDiagnostics(diagnostics) {
48
+ if (diagnostics.length === 0)
49
+ return chalk.bold("\u2705 No type errors found");
50
+ const output = [];
51
+ let errorCount = 0;
52
+ let warningCount = 0;
53
+ let suggestionCount = 0;
54
+ const diagnosticsByFile = new Map;
55
+ diagnostics.forEach((diagnostic) => {
56
+ if (diagnostic.category === ts.DiagnosticCategory.Error)
57
+ errorCount++;
58
+ else if (diagnostic.category === ts.DiagnosticCategory.Warning)
59
+ warningCount++;
60
+ else if (diagnostic.category === ts.DiagnosticCategory.Suggestion)
61
+ suggestionCount++;
62
+ if (diagnostic.file) {
63
+ const fileName = diagnostic.file.fileName;
64
+ if (!diagnosticsByFile.has(fileName))
65
+ diagnosticsByFile.set(fileName, []);
66
+ const fileDiagnostics = diagnosticsByFile.get(fileName);
67
+ if (fileDiagnostics)
68
+ fileDiagnostics.push(diagnostic);
69
+ } else {
70
+ if (!diagnosticsByFile.has(""))
71
+ diagnosticsByFile.set("", []);
72
+ const fileDiagnostics = diagnosticsByFile.get("");
73
+ if (fileDiagnostics)
74
+ fileDiagnostics.push(diagnostic);
75
+ }
76
+ });
77
+ diagnosticsByFile.forEach((fileDiagnostics, fileName) => {
78
+ if (fileName)
79
+ output.push(`
80
+ ${chalk.cyan(fileName)}`);
81
+ fileDiagnostics.forEach((diagnostic) => {
82
+ const categoryText = diagnostic.category === ts.DiagnosticCategory.Error ? "error" : diagnostic.category === ts.DiagnosticCategory.Warning ? "warning" : "suggestion";
83
+ const categoryColor = diagnostic.category === ts.DiagnosticCategory.Error ? chalk.red : diagnostic.category === ts.DiagnosticCategory.Warning ? chalk.yellow : chalk.blue;
84
+ const icon = diagnostic.category === ts.DiagnosticCategory.Error ? "\u274C" : diagnostic.category === ts.DiagnosticCategory.Warning ? "\u26A0\uFE0F" : "\uD83D\uDCA1";
85
+ const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, `
86
+ `);
87
+ const tsCode = chalk.dim(`(TS${diagnostic.code})`);
88
+ if (diagnostic.file && diagnostic.start !== undefined) {
89
+ const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
90
+ output.push(`
91
+ ${icon} ${categoryColor(categoryText)}: ${message} ${tsCode}`);
92
+ output.push(` ${chalk.gray("at")} ${fileName}:${chalk.bold(`${line + 1}:${character + 1}`)}`);
93
+ const sourceLines = diagnostic.file.text.split(`
94
+ `);
95
+ if (line < sourceLines.length) {
96
+ const sourceLine = sourceLines[line];
97
+ const lineNumber = (line + 1).toString().padStart(5, " ");
98
+ output.push(`
99
+ ${chalk.dim(`${lineNumber} |`)} ${sourceLine}`);
100
+ const underlinePrefix = " ".repeat(character);
101
+ const length = diagnostic.length ?? 1;
102
+ const underline = "~".repeat(Math.max(1, length));
103
+ output.push(`${chalk.dim(`${" ".repeat(lineNumber.length)} |`)} ${underlinePrefix}${categoryColor(underline)}`);
104
+ }
105
+ } else
106
+ output.push(`
107
+ ${icon} ${categoryColor(categoryText)}: ${message} ${tsCode}`);
108
+ });
109
+ });
110
+ const summary = [];
111
+ if (errorCount > 0)
112
+ summary.push(chalk.red(`${errorCount} error(s)`));
113
+ if (warningCount > 0)
114
+ summary.push(chalk.yellow(`${warningCount} warning(s)`));
115
+ if (suggestionCount > 0)
116
+ summary.push(chalk.blue(`${suggestionCount} suggestion(s)`));
117
+ return `
118
+ ${summary.join(", ")} found${output.join(`
119
+ `)}`;
120
+ }
121
+ getDetailedDiagnostics(filePath) {
122
+ const { diagnostics } = this.check(filePath);
123
+ const sourceFile = ts.createSourceFile(filePath, readFileSync(filePath, "utf8"), ts.ScriptTarget.Latest, true);
124
+ const details = diagnostics.map((diagnostic) => {
125
+ if (diagnostic.file && diagnostic.start !== undefined) {
126
+ const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
127
+ const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, `
128
+ `);
129
+ const lines = sourceFile.text.split(`
130
+ `);
131
+ const codeSnippet = line < lines.length ? lines[line] : undefined;
132
+ return { line: line + 1, column: character + 1, message, code: diagnostic.code, codeSnippet };
133
+ }
134
+ return {
135
+ line: 0,
136
+ column: 0,
137
+ message: ts.flattenDiagnosticMessageText(diagnostic.messageText, `
138
+ `),
139
+ code: diagnostic.code
140
+ };
141
+ });
142
+ return { diagnostics, details };
143
+ }
144
+ hasNoTypeErrors(filePath) {
145
+ try {
146
+ const { diagnostics } = this.check(filePath);
147
+ return diagnostics.length === 0;
148
+ } catch (error) {
149
+ return false;
150
+ }
151
+ }
152
+ static checkProject(configPath) {
153
+ const parsedConfig = TypeChecker.parseConfig(configPath);
154
+ const host = ts.createIncrementalCompilerHost(parsedConfig.options);
155
+ const builderProgram = ts.createIncrementalProgram({
156
+ rootNames: parsedConfig.fileNames,
157
+ options: parsedConfig.options,
158
+ projectReferences: parsedConfig.projectReferences,
159
+ configFileParsingDiagnostics: parsedConfig.errors,
160
+ host
161
+ });
162
+ const program = builderProgram.getProgram();
163
+ const diagnostics = [...ts.getPreEmitDiagnostics(program), ...builderProgram.emit().diagnostics];
164
+ const errors = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
165
+ const warnings = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Warning);
166
+ return {
167
+ configPath,
168
+ diagnostics,
169
+ errors,
170
+ warnings,
171
+ message: TypeChecker.formatDiagnosticMessages(diagnostics)
172
+ };
173
+ }
174
+ static parseConfig(configPath) {
175
+ const configFile = ts.readConfigFile(configPath, (fileName) => ts.sys.readFile(fileName));
176
+ const configDiagnostics = configFile.error ? [configFile.error] : [];
177
+ if (!configFile.config) {
178
+ const message = TypeChecker.formatDiagnosticMessages(configDiagnostics);
179
+ throw new Error(message || `Error reading tsconfig.json: ${configPath}`);
180
+ }
181
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath), undefined, configPath);
182
+ if (parsedConfig.errors.length > 0)
183
+ throw new Error(TypeChecker.formatDiagnosticMessages(parsedConfig.errors));
184
+ return parsedConfig;
185
+ }
186
+ static formatDiagnosticMessages(diagnostics) {
187
+ return ts.formatDiagnosticsWithColorAndContext(diagnostics, {
188
+ getCanonicalFileName: (fileName) => fileName,
189
+ getCurrentDirectory: () => process.cwd(),
190
+ getNewLine: () => ts.sys.newLine
191
+ });
192
+ }
193
+ }
194
+
195
+ // pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts
196
+ try {
197
+ const configPath = process.env.AKAN_TYPECHECK_TSCONFIG;
198
+ if (!configPath)
199
+ throw new Error("AKAN_TYPECHECK_TSCONFIG is required");
200
+ const result = TypeChecker.checkProject(configPath);
201
+ if (result.errors.length > 0) {
202
+ console.error(result.message);
203
+ process.exit(1);
204
+ }
205
+ } catch (error) {
206
+ console.error(error instanceof Error ? error.message : String(error));
207
+ process.exit(1);
208
+ }