@akanjs/cli 2.1.0-rc.0 → 2.1.0-rc.10
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/incrementalBuilder.proc.js +9670 -0
- package/index.js +336 -118
- package/package.json +4 -2
- package/templates/facetIndex/index.ts +1 -1
- package/templates/workspaceRoot/.gitignore.template +2 -1
- package/typecheck.proc.js +208 -0
- /package/templates/workspaceRoot/{bunfig.toml → bunfig.toml.template} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/cli",
|
|
3
|
-
"version": "2.1.0-rc.
|
|
3
|
+
"version": "2.1.0-rc.10",
|
|
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.
|
|
37
|
+
"akanjs": "2.1.0-rc.9",
|
|
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
|
},
|
|
@@ -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
|
+
}
|
|
File without changes
|