@makinzm/mille 0.0.12 → 0.0.14

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.
Files changed (3) hide show
  1. package/README.md +129 -16
  2. package/mille.wasm +0 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,27 +2,20 @@
2
2
 
3
3
  > Like a mille crêpe — your architecture, one clean layer at a time.
4
4
 
5
- ```
6
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ presentation
7
- · · · · · · · · · · · · · · · · · · (deps only flow inward)
8
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ infrastructure
9
- · · · · · · · · · · · · · · · · · ·
10
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ usecase
11
- · · · · · · · · · · · · · · · · · ·
12
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ domain
13
- ```
14
-
15
5
  `mille` is a static analysis CLI that enforces **dependency rules for layered architectures** — Clean Architecture, Onion Architecture, Hexagonal Architecture, and more.
16
6
 
17
7
  One TOML config. Rust-powered. CI-ready. Supports multiple languages from a single config file.
18
8
 
19
9
  ## What it checks
20
10
 
21
- | Check | Rust | Go | TypeScript | JavaScript | Python | Java | Kotlin |
22
- |---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
23
- | Layer dependency rules (`dependency_mode`) | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
24
- | External library rules (`external_mode`) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
25
- | DI method call rules (`allow_call_patterns`) | | | | | | | ✅ |
11
+ **Languages:** Rust, Go, TypeScript, JavaScript, Python, Java, Kotlin, PHP, C
12
+
13
+ | Check | Description |
14
+ |---|---|
15
+ | `dependency_mode` | Layer dependency rules control which layers can import from which |
16
+ | `external_mode` | External library rules — restrict third-party package usage per layer |
17
+ | `allow_call_patterns` | DI method call rules — limit which methods may be called on injected types |
18
+ | `name_deny` | Naming convention rules — forbid infrastructure keywords in domain/usecase |
26
19
 
27
20
  ## Install
28
21
 
@@ -120,6 +113,8 @@ The generated config includes `allow` (inferred internal dependencies) and `exte
120
113
 
121
114
  **Python submodule imports**: `external_allow = ["matplotlib"]` correctly allows both `import matplotlib` and `import matplotlib.pyplot`.
122
115
 
116
+ **Python `src/` layout (namespace packages)**: When your project uses a `src/` layout and imports like `from src.domain.entity import Foo`, `mille init` detects that `src` is used as a top-level import prefix and automatically adds it to `package_names`. This means `from src.domain...` is classified as Internal and `src` does not appear in `external_allow`. Cross-layer imports like `from src.domain.entity import Foo` (written in `src/infrastructure/`) are correctly resolved to the `src/domain` layer and appear as an `allow` dependency in the generated `mille.toml`. Files at the project root of a sub-tree (e.g. `src/main.py`) are included in the `src` layer rather than being silently skipped.
117
+
123
118
  **Go projects**: `mille init` reads `go.mod` and generates `[resolve.go] module_name` automatically — internal module imports are classified correctly during `mille check`. External packages appear in `external_allow` with their full import paths (e.g. `"github.com/cilium/ebpf"`, `"fmt"`, `"net/http"`).
124
119
 
125
120
  **TypeScript/JavaScript subpath imports**: `external_allow = ["vitest"]` correctly allows both `import "vitest"` and `import "vitest/config"`. Scoped packages (`@scope/name/sub`) are matched by `"@scope/name"`.
@@ -416,7 +411,7 @@ Exit codes:
416
411
  |---|---|
417
412
  | `name` | Project name |
418
413
  | `root` | Root directory for analysis |
419
- | `languages` | Languages to check: `"rust"`, `"go"`, `"typescript"`, `"javascript"`, `"python"`, `"java"`, `"kotlin"` |
414
+ | `languages` | Languages to check: `"rust"`, `"go"`, `"typescript"`, `"javascript"`, `"python"`, `"java"`, `"kotlin"`, `"php"`, `"c"` |
420
415
 
421
416
  ### `[[layers]]`
422
417
 
@@ -430,6 +425,45 @@ Exit codes:
430
425
  | `external_mode` | `"opt-in"` or `"opt-out"` for external library usage |
431
426
  | `external_allow` | Allowed external packages (when `external_mode = "opt-in"`) |
432
427
  | `external_deny` | Forbidden external packages (when `external_mode = "opt-out"`) |
428
+ | `name_deny` | Forbidden keywords for naming convention check (case-insensitive partial match) |
429
+ | `name_allow` | Substrings to strip before `name_deny` check (e.g. `"category"` prevents `"go"` match inside it) |
430
+ | `name_targets` | Targets to check: `"file"`, `"symbol"`, `"variable"`, `"comment"`, `"string_literal"`, `"identifier"` (default: all) |
431
+ | `name_deny_ignore` | Glob patterns for files to exclude from naming checks (e.g. `"**/test_*.rs"`) |
432
+
433
+ #### Naming Convention Check (`name_deny`)
434
+
435
+ Forbid infrastructure-specific keywords from appearing in a layer's names.
436
+
437
+ ```toml
438
+ [[layers]]
439
+ name = "usecase"
440
+ paths = ["src/usecase/**"]
441
+ dependency_mode = "opt-out"
442
+ deny = []
443
+ external_mode = "opt-out"
444
+ external_deny = []
445
+
446
+ # Usecase layer must not reference specific infrastructure technologies
447
+ name_deny = ["gcp", "aws", "azure", "mysql", "postgres"]
448
+ name_allow = ["category"] # "category" contains "go" but should not be flagged
449
+ name_targets = ["file", "symbol", "variable", "comment", "string_literal", "identifier"] # default: all targets
450
+ name_deny_ignore = ["**/test_*.rs", "tests/**"] # exclude test files from naming checks
451
+ ```
452
+
453
+ **Rules:**
454
+ - Case-insensitive (`GCP` = `gcp` = `Gcp`)
455
+ - Partial match (`ManageGcp` also matches `gcp`)
456
+ - `name_allow` strips listed substrings before matching (e.g. `"category"` prevents false positive on `"go"`)
457
+ - `name_deny_ignore` excludes files matching glob patterns from naming checks entirely
458
+ - `name_targets` restricts which entity types are checked:
459
+ - `"file"`: file basename (e.g. `aws_client.rs`)
460
+ - `"symbol"`: function, class, struct, enum, trait, interface, type alias names
461
+ - `"variable"`: variable, const, let, static declaration names
462
+ - `"comment"`: inline comment content
463
+ - `"string_literal"`: string literal content
464
+ - `"identifier"`: attribute/field access identifiers (e.g. `gcp` in `cfg.gcp.bucket`)
465
+ - Supported languages: Rust, TypeScript, JavaScript, Python, Go, Java, Kotlin, PHP, C
466
+ - Severity is controlled by `severity.naming_violation` (default: `"error"`)
433
467
 
434
468
  ### `[[layers.allow_call_patterns]]`
435
469
 
@@ -470,6 +504,7 @@ Control the severity level of each violation type. Violations can be `"error"`,
470
504
  | `external_violation` | `"error"` | External library rule violated |
471
505
  | `call_pattern_violation` | `"error"` | DI entrypoint method call rule violated |
472
506
  | `unknown_import` | `"warning"` | Import that could not be classified |
507
+ | `naming_violation` | `"error"` | Naming convention rule violated (`name_deny`) |
473
508
 
474
509
  ```toml
475
510
  [severity]
@@ -477,6 +512,7 @@ dependency_violation = "warning" # treat as warning for gradual adoption
477
512
  external_violation = "error"
478
513
  call_pattern_violation = "error"
479
514
  unknown_import = "warning"
515
+ naming_violation = "warning" # treat as warning while rolling out naming rules
480
516
  ```
481
517
 
482
518
  Use `--fail-on warning` to exit 1 even for warnings when integrating into CI gradually.
@@ -536,6 +572,83 @@ Use `--fail-on warning` to exit 1 even for warnings when integrating into CI gra
536
572
 
537
573
  > Both regular and static imports are supported. Wildcard imports (`import java.util.*`) are not yet extracted by the parser.
538
574
 
575
+ ### `[resolve.php]`
576
+
577
+ | Key | Description |
578
+ |---|---|
579
+ | `namespace` | Base namespace of your project (e.g. `App`). Imports starting with this prefix are classified as Internal. |
580
+ | `composer_json` | Path to `composer.json` (relative to `mille.toml`). The first PSR-4 key in `autoload.psr-4` is used as the base namespace when `namespace` is not set. |
581
+
582
+ **How PHP imports are classified:**
583
+
584
+ | Import | Classification |
585
+ |---|---|
586
+ | `use App\Models\User` (starts with `namespace`) | Internal |
587
+ | `use App\Services\{Auth, Logger}` (group use, expanded) | Internal |
588
+ | `use function App\Helpers\format_date` | Internal |
589
+ | `use DateTime`, `use PDO`, `use Exception` | Stdlib |
590
+ | `use Illuminate\Http\Request` | External |
591
+
592
+ > Supported use forms: simple, aliased (`as`), grouped (`{}`), `use function`, `use const`.
593
+ > PHP stdlib classes (DateTime, PDO, Exception, etc.) are automatically classified as Stdlib without any configuration.
594
+
595
+ **Example `mille.toml` for a Laravel project:**
596
+
597
+ ```toml
598
+ [project]
599
+ name = "my-laravel-app"
600
+ root = "."
601
+ languages = ["php"]
602
+
603
+ [[layers]]
604
+ name = "domain"
605
+ paths = ["app/Domain/**"]
606
+
607
+ [[layers]]
608
+ name = "application"
609
+ paths = ["app/Application/**"]
610
+ dependency_mode = "opt-in"
611
+ allow = ["domain"]
612
+
613
+ [[layers]]
614
+ name = "infrastructure"
615
+ paths = ["app/Infrastructure/**"]
616
+ dependency_mode = "opt-in"
617
+ allow = ["domain", "application"]
618
+
619
+ [resolve.php]
620
+ composer_json = "composer.json" # auto-detects "App\\" from autoload.psr-4
621
+ ```
622
+
623
+ ### C
624
+
625
+ > `#include "..."` is classified as Internal (project header). `#include <...>` is classified as Stdlib (standard/POSIX headers) or External (third-party libraries).
626
+
627
+ **Example `mille.toml` for a C project:**
628
+
629
+ ```toml
630
+ [project]
631
+ name = "my-c-app"
632
+ root = "."
633
+ languages = ["c"]
634
+
635
+ [[layers]]
636
+ name = "domain"
637
+ paths = ["src/domain/**"]
638
+
639
+ [[layers]]
640
+ name = "usecase"
641
+ paths = ["src/usecase/**"]
642
+ dependency_mode = "opt-in"
643
+ allow = ["domain"]
644
+
645
+ [[layers]]
646
+ name = "infrastructure"
647
+ paths = ["src/infrastructure/**"]
648
+ dependency_mode = "opt-in"
649
+ allow = ["domain"]
650
+ ```
651
+
539
652
  ## How it Works
540
653
 
541
654
  mille uses [tree-sitter](https://tree-sitter.github.io/) for AST-based import extraction — no regex heuristics.
package/mille.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makinzm/mille",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Architecture Checker — Rust-based multi-language architecture linter",
5
5
  "main": "index.js",
6
6
  "bin": {