@konvert7/klint 0.19.0 → 0.19.2
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/README.md +39 -1
- package/cli.ts +7 -0
- package/core/native-binary.ts +25 -1
- package/package.json +5 -5
- package/tools/semantic-release-root-npm.js +11 -0
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ Rules give agents room to move quickly because the unsafe moves are blocked stru
|
|
|
98
98
|
## CLI
|
|
99
99
|
|
|
100
100
|
```sh
|
|
101
|
-
klint [--config <dir>] [--rules <file>] [--fix] [--json]
|
|
101
|
+
klint [--config <dir>] [--rules <file>] [--engine ts|rust|compare|auto] [--fix] [--json]
|
|
102
102
|
klint install-skill [--agents <list>] [--symlink | --copy]
|
|
103
103
|
```
|
|
104
104
|
|
|
@@ -106,6 +106,7 @@ klint install-skill [--agents <list>] [--symlink | --copy]
|
|
|
106
106
|
|------|-------------|
|
|
107
107
|
| `--config <dir>` | Directory containing `klint.yaml` or `klint.config.json` (default: cwd) |
|
|
108
108
|
| `--rules <file>` | Path to custom rules file (default: `<configDir>/klint.rules.ts` when present) |
|
|
109
|
+
| `--engine <name>` | Engine mode: `ts` (default), `rust`, `compare`, or `auto` |
|
|
109
110
|
| `--fix` | Apply auto-fixes for fixable violations in-place |
|
|
110
111
|
| `--json` | Emit structured JSON to stdout for agents and CI |
|
|
111
112
|
|
|
@@ -115,6 +116,43 @@ klint install-skill [--agents <list>] [--symlink | --copy]
|
|
|
115
116
|
klint install-skill --agents claude,opencode,cursor,codex --copy
|
|
116
117
|
```
|
|
117
118
|
|
|
119
|
+
## Engines
|
|
120
|
+
|
|
121
|
+
klint currently ships a TypeScript engine and an experimental Rust engine. The Rust path is built for portable architecture checks and syntax-local rules; type-aware checks stay in TypeScript for now.
|
|
122
|
+
|
|
123
|
+
Maintainer migration notes live in [`docs/rust-engine.md`](docs/rust-engine.md).
|
|
124
|
+
|
|
125
|
+
| Engine | What it does | When to use it |
|
|
126
|
+
|--------|--------------|----------------|
|
|
127
|
+
| `ts` | Runs the full TypeScript implementation. This is the default. | Maximum compatibility |
|
|
128
|
+
| `rust` | Runs only rules supported by the Rust engine. Unsupported TS-only rules are rejected. | Strict Rust smoke tests and native-engine debugging |
|
|
129
|
+
| `compare` | Runs TS and Rust on the same supported config and fails if JSON output differs. Requires `--json`. | Parity verification while porting rules |
|
|
130
|
+
| `auto` | Runs Rust-supported rules in Rust, TS-only rules in TypeScript, then merges output. | Recommended experimental migration path |
|
|
131
|
+
|
|
132
|
+
Examples:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
klint --engine auto
|
|
136
|
+
klint --engine rust --json # strict Rust-only run; rejects unsupported TS-only rules
|
|
137
|
+
klint --engine compare --json # parity check; rejects unsupported TS-only rules
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Rust currently supports:
|
|
141
|
+
|
|
142
|
+
- `arch` rules: imports, forbidden patterns, singleton locations
|
|
143
|
+
- `no-unguarded-json-parse`
|
|
144
|
+
- `no-nested-template-literals`
|
|
145
|
+
- `no-consecutive-array-push`
|
|
146
|
+
- `no-string-match`
|
|
147
|
+
|
|
148
|
+
These rules remain TypeScript-owned because they need TypeScript semantic information:
|
|
149
|
+
|
|
150
|
+
- `no-floating-promise`
|
|
151
|
+
- `no-misused-promises`
|
|
152
|
+
- `no-date-equality`
|
|
153
|
+
- `no-optional-chain-on-non-nullable`
|
|
154
|
+
- `no-object-in-template`
|
|
155
|
+
|
|
118
156
|
## Configuration
|
|
119
157
|
|
|
120
158
|
`klint.yaml` lives at your project root alongside tools like `biome.json`, `tsconfig.json`, and `knip.json`.
|
package/cli.ts
CHANGED
|
@@ -610,6 +610,13 @@ function resolveRustEngineCommand(configDir: string): RustEngineCommand {
|
|
|
610
610
|
return { bin: nativePackageBin, args };
|
|
611
611
|
}
|
|
612
612
|
|
|
613
|
+
if (!isSourceCheckout()) {
|
|
614
|
+
process.stderr.write(
|
|
615
|
+
"klint: native Rust engine binary is unavailable for this package version\n"
|
|
616
|
+
);
|
|
617
|
+
process.exit(1);
|
|
618
|
+
}
|
|
619
|
+
|
|
613
620
|
return {
|
|
614
621
|
bin: "cargo",
|
|
615
622
|
args: ["run", "--quiet", "-p", "klint-rs", "--", ...args],
|
package/core/native-binary.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
|
|
@@ -44,6 +44,7 @@ interface NativeBinaryOptions {
|
|
|
44
44
|
platform?: string;
|
|
45
45
|
arch?: string;
|
|
46
46
|
exists?: (path: string) => boolean;
|
|
47
|
+
readPackageJson?: (path: string) => { version?: string };
|
|
47
48
|
resolvePackageJson?: (packageName: string) => string;
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -63,6 +64,7 @@ export function resolveNativePackageBinary({
|
|
|
63
64
|
platform = process.platform,
|
|
64
65
|
arch = process.arch,
|
|
65
66
|
exists = existsSync,
|
|
67
|
+
readPackageJson = readJsonFile,
|
|
66
68
|
resolvePackageJson,
|
|
67
69
|
}: NativeBinaryOptions): string | undefined {
|
|
68
70
|
const nativePackage = nativePackageForPlatform(platform, arch);
|
|
@@ -74,11 +76,33 @@ export function resolveNativePackageBinary({
|
|
|
74
76
|
resolvePackageJson
|
|
75
77
|
);
|
|
76
78
|
if (!packageJsonPath) return undefined;
|
|
79
|
+
if (!nativePackageVersionMatches(packageRoot, packageJsonPath, readPackageJson)) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
77
82
|
|
|
78
83
|
const binaryPath = join(dirname(packageJsonPath), nativePackage.binaryPath);
|
|
79
84
|
return exists(binaryPath) ? binaryPath : undefined;
|
|
80
85
|
}
|
|
81
86
|
|
|
87
|
+
function nativePackageVersionMatches(
|
|
88
|
+
packageRoot: string,
|
|
89
|
+
nativePackageJsonPath: string,
|
|
90
|
+
readPackageJson: (path: string) => { version?: string }
|
|
91
|
+
): boolean {
|
|
92
|
+
try {
|
|
93
|
+
const rootVersion = readPackageJson(join(packageRoot, "package.json")).version;
|
|
94
|
+
const nativeVersion = readPackageJson(nativePackageJsonPath).version;
|
|
95
|
+
if (!rootVersion || !nativeVersion) return true;
|
|
96
|
+
return rootVersion === nativeVersion;
|
|
97
|
+
} catch {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function readJsonFile(path: string): { version?: string } {
|
|
103
|
+
return JSON.parse(readFileSync(path, "utf-8")) as { version?: string };
|
|
104
|
+
}
|
|
105
|
+
|
|
82
106
|
function resolveOptionalPackageJson(
|
|
83
107
|
packageRoot: string,
|
|
84
108
|
packageName: string,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@konvert7/klint",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.2",
|
|
4
4
|
"description": "Architecture-as-Code linter for TypeScript. Enforce layer boundaries, import rules, and singleton patterns in YAML.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
"zod": "^4.4.3"
|
|
63
63
|
},
|
|
64
64
|
"optionalDependencies": {
|
|
65
|
-
"@konvert7/klint-darwin-arm64": "
|
|
66
|
-
"@konvert7/klint-darwin-x64": "
|
|
67
|
-
"@konvert7/klint-linux-x64": "
|
|
68
|
-
"@konvert7/klint-win32-x64": "
|
|
65
|
+
"@konvert7/klint-darwin-arm64": "0.19.2",
|
|
66
|
+
"@konvert7/klint-darwin-x64": "0.19.2",
|
|
67
|
+
"@konvert7/klint-linux-x64": "0.19.2",
|
|
68
|
+
"@konvert7/klint-win32-x64": "0.19.2"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@biomejs/biome": "2.4.7",
|
|
@@ -2,6 +2,13 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
|
|
5
|
+
const NATIVE_PACKAGE_NAMES = [
|
|
6
|
+
"@konvert7/klint-darwin-arm64",
|
|
7
|
+
"@konvert7/klint-darwin-x64",
|
|
8
|
+
"@konvert7/klint-linux-x64",
|
|
9
|
+
"@konvert7/klint-win32-x64",
|
|
10
|
+
];
|
|
11
|
+
|
|
5
12
|
export async function verifyConditions(_, context) {
|
|
6
13
|
const cwd = context.cwd ?? process.cwd();
|
|
7
14
|
const packageJson = readPackageJson(cwd);
|
|
@@ -21,6 +28,10 @@ export async function prepare(_, context) {
|
|
|
21
28
|
|
|
22
29
|
const packageJson = readPackageJson(cwd);
|
|
23
30
|
packageJson.version = version;
|
|
31
|
+
packageJson.optionalDependencies ??= {};
|
|
32
|
+
for (const packageName of NATIVE_PACKAGE_NAMES) {
|
|
33
|
+
packageJson.optionalDependencies[packageName] = version;
|
|
34
|
+
}
|
|
24
35
|
writePackageJson(cwd, packageJson);
|
|
25
36
|
}
|
|
26
37
|
|