@konvert7/klint 0.1.0 → 0.3.0
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/cli.ts +5 -0
- package/core/arch.ts +15 -8
- package/package.json +1 -1
package/cli.ts
CHANGED
|
@@ -24,6 +24,11 @@ interface CliOptions {
|
|
|
24
24
|
export async function main(opts: CliOptions = {}): Promise<void> {
|
|
25
25
|
const args = process.argv.slice(2);
|
|
26
26
|
|
|
27
|
+
if (args[0] === "help" || args[0] === "h") {
|
|
28
|
+
printHelp();
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
if (args[0] === "install-skill") {
|
|
28
33
|
await installSkill(args.slice(1));
|
|
29
34
|
return;
|
package/core/arch.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { dirname, relative, resolve } from "node:path";
|
|
1
|
+
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
import { walkAst } from "./ast";
|
|
4
4
|
import type { ArchConfig, Severity, Violation } from "./types";
|
|
5
5
|
|
|
6
|
+
const toSlash = (p: string) => p.replaceAll("\\", "/");
|
|
7
|
+
|
|
6
8
|
interface AliasEntry {
|
|
7
9
|
/** The prefix to match (pattern with `/*` stripped, e.g. `"@"` from `"@/*"`). */
|
|
8
10
|
prefix: string;
|
|
@@ -29,7 +31,7 @@ function loadPathAliases(root: string): AliasEntry[] {
|
|
|
29
31
|
const prefix = isWildcard ? pattern.slice(0, -2) : pattern;
|
|
30
32
|
const targetStr = targets[0];
|
|
31
33
|
const targetBase = targetStr.endsWith("/*") ? targetStr.slice(0, -2) : targetStr;
|
|
32
|
-
entries.push({ prefix, base: resolve(base, targetBase), isWildcard });
|
|
34
|
+
entries.push({ prefix, base: toSlash(resolve(base, targetBase)), isWildcard });
|
|
33
35
|
}
|
|
34
36
|
return entries;
|
|
35
37
|
}
|
|
@@ -39,7 +41,7 @@ function resolveAlias(importPath: string, aliases: AliasEntry[]): string | undef
|
|
|
39
41
|
if (alias.isWildcard) {
|
|
40
42
|
const matchPrefix = `${alias.prefix}/`;
|
|
41
43
|
if (importPath.startsWith(matchPrefix)) {
|
|
42
|
-
return resolve(alias.base, importPath.slice(matchPrefix.length));
|
|
44
|
+
return toSlash(resolve(alias.base, importPath.slice(matchPrefix.length)));
|
|
43
45
|
}
|
|
44
46
|
} else if (importPath === alias.prefix) {
|
|
45
47
|
return alias.base;
|
|
@@ -56,11 +58,11 @@ interface ImportRecord {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
function isBareSpecifier(path: string): boolean {
|
|
59
|
-
return !path.startsWith(".") && !path
|
|
61
|
+
return !path.startsWith(".") && !isAbsolute(path);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
function globToPrefix(glob: string, root: string): string {
|
|
63
|
-
return resolve(root, glob.split("/**")[0].split("/*")[0].split("*")[0]);
|
|
65
|
+
return toSlash(resolve(root, glob.split("/**")[0].split("/*")[0].split("*")[0]));
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
function resolveGlobs(
|
|
@@ -90,7 +92,12 @@ function resolveLayerFiles(
|
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
function inPrefixes(absPath: string, prefixes: string[]): boolean {
|
|
93
|
-
return prefixes.some((p) =>
|
|
95
|
+
return prefixes.some((p) => {
|
|
96
|
+
if (absPath === p || absPath.startsWith(`${p}/`)) return true;
|
|
97
|
+
// Extension-less imports ("../cli") won't match a prefix like "{root}/cli.ts"
|
|
98
|
+
const bare = p.replace(/\.(tsx?|jsx?|mts|cts)$/, "");
|
|
99
|
+
return bare !== p && (absPath === bare || absPath.startsWith(`${bare}/`));
|
|
100
|
+
});
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
function scanImports(
|
|
@@ -126,7 +133,7 @@ function scanImports(
|
|
|
126
133
|
if (isBareSpecifier(path)) {
|
|
127
134
|
resolved = resolveAlias(path, aliases) ?? path;
|
|
128
135
|
} else {
|
|
129
|
-
resolved = resolve(fileDir, path);
|
|
136
|
+
resolved = toSlash(resolve(fileDir, path));
|
|
130
137
|
}
|
|
131
138
|
const { line } = src.getLineAndCharacterOfPosition(specifierNode.getStart());
|
|
132
139
|
records.push({ path, resolved, isTypeOnly, line: line + 1 });
|
|
@@ -210,7 +217,7 @@ export function runArchRules(
|
|
|
210
217
|
|
|
211
218
|
for (const rule of arch.singleton ?? []) {
|
|
212
219
|
const severity: Severity = rule.severity ?? "error";
|
|
213
|
-
const onlyFile = resolve(root, rule.only);
|
|
220
|
+
const onlyFile = toSlash(resolve(root, rule.only));
|
|
214
221
|
const inFiles = rule.in
|
|
215
222
|
? resolveLayerFiles(rule.in, layers, root, allFiles)
|
|
216
223
|
: allFiles;
|
package/package.json
CHANGED