@konvert7/klint 0.22.0 → 0.24.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/README.md CHANGED
@@ -1,14 +1,21 @@
1
1
  # klint
2
2
 
3
- Architecture and type-aware linting for TypeScript projects.
3
+ Architecture-as-Code linting for TypeScript, Python, and Swift projects.
4
4
 
5
- Biome and oxlint are excellent at syntax, style, and fast local correctness. klint handles the rules that need project context: layer boundaries, singleton ownership, forbidden patterns, custom repository policies, and type-aware checks that should block an AI agent or CI run before code lands.
5
+ Biome, oxlint, Ruff, and SwiftLint are excellent at syntax, style, and fast local correctness. klint handles the rules that need project context: layer boundaries, singleton ownership, forbidden patterns, custom repository policies, and type-aware TypeScript checks that should block an AI agent or CI run before code lands.
6
6
 
7
7
  Use klint when "please follow AGENTS.md" is not strong enough. Put the rule in `klint.yaml`, run `klint`, and make the constraint executable.
8
8
 
9
9
  ## Install
10
10
 
11
- klint currently runs on Bun.
11
+ For macOS native CLI usage:
12
+
13
+ ```sh
14
+ brew tap konvert7/tap
15
+ brew install klint
16
+ ```
17
+
18
+ For TypeScript projects using Bun:
12
19
 
13
20
  ```sh
14
21
  bun add -d @konvert7/klint
@@ -190,7 +197,7 @@ arch:
190
197
  message: "Client code must not import server-only modules"
191
198
  ```
192
199
 
193
- `include` selects `.ts` files to lint. Patterns support `**` globs and `!` negation.
200
+ `include` selects source files to lint. Patterns support `**` globs and `!` negation.
194
201
 
195
202
  `plugins` enables bundled rule groups. Today, `sonar` provides focused code-quality rules.
196
203
 
@@ -279,6 +286,83 @@ arch:
279
286
  message: "Use the auth module"
280
287
  ```
281
288
 
289
+ ### Python Architecture Checks
290
+
291
+ The Rust engine can apply architecture rules to Python projects:
292
+
293
+ ```yaml
294
+ include: ["src"]
295
+
296
+ rules: {}
297
+
298
+ arch:
299
+ layers:
300
+ jobs: ["src/app/jobs/**"]
301
+ lib: ["src/app/lib/**"]
302
+ config: ["src/app/config.py"]
303
+
304
+ imports:
305
+ - from: jobs
306
+ deny: lib
307
+ message: "Jobs must use service APIs, not import lib directly"
308
+
309
+ forbidden:
310
+ - pattern: "print("
311
+ in: jobs
312
+ message: "Use the logger"
313
+
314
+ singleton:
315
+ - pattern: "os.environ[\"API_KEY\"]"
316
+ only: "src/app/config.py"
317
+ in: ["src/**"]
318
+ message: "Use app config"
319
+ ```
320
+
321
+ Python import checks support relative imports such as
322
+ `from ..lib.auth import load_key` and project-resolvable absolute imports such
323
+ as `from app.lib.auth import load_key`. External packages that do not resolve to
324
+ project files, such as `requests`, are ignored. This is architecture
325
+ enforcement, not full packaging or virtual-environment analysis.
326
+
327
+ ### Swift Architecture Checks
328
+
329
+ The Rust engine can apply architecture rules to Swift projects:
330
+
331
+ ```yaml
332
+ include: ["Sources"]
333
+
334
+ rules: {}
335
+
336
+ arch:
337
+ layers:
338
+ ui: ["Sources/App/UI/**"]
339
+ core: ["Sources/App/Core/**"]
340
+ config: ["Sources/App/Config/**"]
341
+
342
+ imports:
343
+ - from: ui
344
+ deny: core
345
+ message: "UI must use app services, not import Core directly"
346
+
347
+ forbidden:
348
+ - pattern: "URLSession.shared"
349
+ in: ui
350
+ message: "Use the networking client"
351
+
352
+ singleton:
353
+ - pattern: "ProcessInfo.processInfo.environment[\"API_KEY\"]"
354
+ only: "Sources/App/Config/AppConfig.swift"
355
+ in: ["Sources/**"]
356
+ message: "Use AppConfig"
357
+ ```
358
+
359
+ Swift import checks parse declarations such as `import Core`,
360
+ `@_exported import Core`, and `import struct Models.User`. Imported modules
361
+ resolve against discovered project Swift directories and file stems. System or
362
+ package modules that are not present in the project, such as `Foundation`, are
363
+ ignored. This is architecture enforcement, not full SwiftPM or Xcode build graph
364
+ analysis.
365
+
282
366
  ## Built-in Rules
283
367
 
284
368
  | Rule | Type-aware | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konvert7/klint",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
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": {
@@ -64,10 +64,10 @@
64
64
  "zod": "^4.4.3"
65
65
  },
66
66
  "optionalDependencies": {
67
- "@konvert7/klint-darwin-arm64": "0.22.0",
68
- "@konvert7/klint-darwin-x64": "0.22.0",
69
- "@konvert7/klint-linux-x64": "0.22.0",
70
- "@konvert7/klint-win32-x64": "0.22.0"
67
+ "@konvert7/klint-darwin-arm64": "0.24.0",
68
+ "@konvert7/klint-darwin-x64": "0.24.0",
69
+ "@konvert7/klint-linux-x64": "0.24.0",
70
+ "@konvert7/klint-win32-x64": "0.24.0"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@biomejs/biome": "2.4.7",
@@ -0,0 +1,68 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+
4
+ interface FormulaOptions {
5
+ version: string;
6
+ darwinArm64Sha: string;
7
+ darwinX64Sha: string;
8
+ }
9
+
10
+ export function homebrewFormula(options: FormulaOptions): string {
11
+ const version = options.version.replace(/^v/, "");
12
+
13
+ return `# typed: false
14
+ # frozen_string_literal: true
15
+
16
+ class Klint < Formula
17
+ desc "Architecture-as-Code linter for TypeScript, Python, and Swift projects"
18
+ homepage "https://github.com/konvert7/klint"
19
+ version "${version}"
20
+ license "MIT"
21
+
22
+ on_macos do
23
+ on_arm do
24
+ url "https://github.com/konvert7/klint/releases/download/native-v${version}/klint-${version}-darwin-arm64.tar.gz"
25
+ sha256 "${options.darwinArm64Sha}"
26
+ end
27
+
28
+ on_intel do
29
+ url "https://github.com/konvert7/klint/releases/download/native-v${version}/klint-${version}-darwin-x64.tar.gz"
30
+ sha256 "${options.darwinX64Sha}"
31
+ end
32
+ end
33
+
34
+ def install
35
+ binary = File.exist?("klint") ? "klint" : Dir["klint-*/klint"].first
36
+ odie "klint binary not found" unless binary
37
+ bin.install binary => "klint"
38
+ end
39
+
40
+ test do
41
+ assert_match "klint-rs", shell_output("#{bin}/klint --version")
42
+ end
43
+ end
44
+ `;
45
+ }
46
+
47
+ if (import.meta.main) {
48
+ const args = process.argv.slice(2);
49
+ const output = requireValue(args, "--output");
50
+ const formula = homebrewFormula({
51
+ version: requireValue(args, "--version"),
52
+ darwinArm64Sha: requireValue(args, "--darwin-arm64-sha"),
53
+ darwinX64Sha: requireValue(args, "--darwin-x64-sha"),
54
+ });
55
+
56
+ const path = resolve(output);
57
+ mkdirSync(dirname(path), { recursive: true });
58
+ writeFileSync(path, formula);
59
+ }
60
+
61
+ function requireValue(args: string[], name: string): string {
62
+ const index = args.indexOf(name);
63
+ const value = index >= 0 ? args[index + 1] : undefined;
64
+ if (!value) {
65
+ throw new Error(`${name} is required`);
66
+ }
67
+ return value;
68
+ }