@makinzm/mille 0.0.10 → 0.0.12
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 +162 -11
- package/mille.wasm +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,11 +18,11 @@ One TOML config. Rust-powered. CI-ready. Supports multiple languages from a sing
|
|
|
18
18
|
|
|
19
19
|
## What it checks
|
|
20
20
|
|
|
21
|
-
| Check | Rust | Go | TypeScript | JavaScript | Python |
|
|
22
|
-
|
|
23
|
-
| Layer dependency rules (`dependency_mode`) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
24
|
-
| External library rules (`external_mode`) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
25
|
-
| DI method call rules (`allow_call_patterns`) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
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`) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
26
26
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
@@ -114,6 +114,32 @@ Generated 'mille.toml'
|
|
|
114
114
|
|
|
115
115
|
The generated config includes `allow` (inferred internal dependencies) and `external_allow` (detected external packages) per layer. After generating, review the config and run `mille check` to see results.
|
|
116
116
|
|
|
117
|
+
**Naming in monorepos**: When multiple sub-projects contain a directory with the same name (e.g. `crawler/src/domain` and `server/src/domain`), `mille init` gives each its own layer with a distinguishing prefix (`crawler_domain`, `server_domain`). Merging is left to you.
|
|
118
|
+
|
|
119
|
+
**Excluded paths**: `mille check` automatically skips `.venv`, `venv`, `node_modules`, `target`, `dist`, `build`, and similar build/dependency directories, so generated `paths` patterns like `apps/**` are safe to use.
|
|
120
|
+
|
|
121
|
+
**Python submodule imports**: `external_allow = ["matplotlib"]` correctly allows both `import matplotlib` and `import matplotlib.pyplot`.
|
|
122
|
+
|
|
123
|
+
**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
|
+
|
|
125
|
+
**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"`.
|
|
126
|
+
|
|
127
|
+
**Java/Kotlin projects**: `mille init` uses `package` declarations — not directory depth — to detect layers. This works correctly for Maven's `src/main/java/com/example/myapp/domain/` as well as flat `src/domain/` layouts. `pom.xml` (Maven) and `build.gradle` + `settings.gradle` (Gradle) are read automatically to generate `[resolve.java] module_name`. Layer paths use `**/layer/**` globs so `mille check` matches regardless of the source root depth.
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Detected languages: java
|
|
131
|
+
Scanning imports...
|
|
132
|
+
|
|
133
|
+
Inferred layer structure:
|
|
134
|
+
domain ← (no internal dependencies)
|
|
135
|
+
infrastructure → domain
|
|
136
|
+
external: java.util.List
|
|
137
|
+
usecase → domain
|
|
138
|
+
main → domain, infrastructure, usecase
|
|
139
|
+
|
|
140
|
+
Generated 'mille.toml'
|
|
141
|
+
```
|
|
142
|
+
|
|
117
143
|
### 2. (Or) Create `mille.toml` manually
|
|
118
144
|
|
|
119
145
|
Place `mille.toml` in your project root:
|
|
@@ -274,7 +300,85 @@ external_mode = "opt-out"
|
|
|
274
300
|
external_deny = []
|
|
275
301
|
```
|
|
276
302
|
|
|
277
|
-
|
|
303
|
+
**Java / Kotlin:**
|
|
304
|
+
|
|
305
|
+
```toml
|
|
306
|
+
[project]
|
|
307
|
+
name = "my-java-app"
|
|
308
|
+
root = "."
|
|
309
|
+
languages = ["java"] # or ["kotlin"] for Kotlin projects
|
|
310
|
+
|
|
311
|
+
[resolve.java]
|
|
312
|
+
module_name = "com.example.myapp"
|
|
313
|
+
|
|
314
|
+
[[layers]]
|
|
315
|
+
name = "domain"
|
|
316
|
+
paths = ["src/domain/**"]
|
|
317
|
+
dependency_mode = "opt-in"
|
|
318
|
+
allow = []
|
|
319
|
+
external_mode = "opt-out"
|
|
320
|
+
|
|
321
|
+
[[layers]]
|
|
322
|
+
name = "usecase"
|
|
323
|
+
paths = ["src/usecase/**"]
|
|
324
|
+
dependency_mode = "opt-in"
|
|
325
|
+
allow = ["domain"]
|
|
326
|
+
external_mode = "opt-out"
|
|
327
|
+
|
|
328
|
+
[[layers]]
|
|
329
|
+
name = "infrastructure"
|
|
330
|
+
paths = ["src/infrastructure/**"]
|
|
331
|
+
dependency_mode = "opt-in"
|
|
332
|
+
allow = ["domain"]
|
|
333
|
+
external_mode = "opt-in"
|
|
334
|
+
external_allow = ["java.util.List", "java.util.Map"]
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
> `module_name` is the base package of your project (e.g. `com.example.myapp`). Imports starting with this prefix are classified as **Internal** and matched against layer globs. All other imports (including `java.util.*` stdlib) are classified as **External** and subject to `external_allow` / `external_deny` rules.
|
|
338
|
+
|
|
339
|
+
### 2. Visualize with `mille analyze`
|
|
340
|
+
|
|
341
|
+
Before enforcing rules, you can inspect the actual dependency graph:
|
|
342
|
+
|
|
343
|
+
```sh
|
|
344
|
+
mille analyze # human-readable terminal output (default)
|
|
345
|
+
mille analyze --format json # machine-readable JSON graph
|
|
346
|
+
mille analyze --format dot # Graphviz DOT (pipe to: dot -Tsvg -o graph.svg)
|
|
347
|
+
mille analyze --format svg # self-contained SVG image (open in a browser)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Example SVG output (dark theme, green edges):
|
|
351
|
+
|
|
352
|
+
```sh
|
|
353
|
+
mille analyze --format svg > graph.svg && open graph.svg
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
`mille analyze` always exits `0` — it only visualizes, never enforces rules.
|
|
357
|
+
|
|
358
|
+
### 3. Inspect external dependencies with `mille report external`
|
|
359
|
+
|
|
360
|
+
```sh
|
|
361
|
+
mille report external # human-readable table (default)
|
|
362
|
+
mille report external --format json # machine-readable JSON
|
|
363
|
+
mille report external --output report.json --format json # write to file
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Shows which external packages each layer actually imports — useful for auditing `external_allow` lists or documenting your dependency footprint.
|
|
367
|
+
|
|
368
|
+
Example output:
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
External Dependencies by Layer
|
|
372
|
+
|
|
373
|
+
domain (none)
|
|
374
|
+
usecase (none)
|
|
375
|
+
infrastructure database/sql
|
|
376
|
+
cmd fmt, os
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
`mille report external` always exits `0` — it only reports, never enforces rules.
|
|
380
|
+
|
|
381
|
+
### 4. Run `mille check`
|
|
278
382
|
|
|
279
383
|
```sh
|
|
280
384
|
mille check
|
|
@@ -288,12 +392,20 @@ mille check --format github-actions # GitHub Actions annotations (::error file=
|
|
|
288
392
|
mille check --format json # machine-readable JSON
|
|
289
393
|
```
|
|
290
394
|
|
|
395
|
+
Fail threshold:
|
|
396
|
+
|
|
397
|
+
```sh
|
|
398
|
+
mille check # exit 1 on error-severity violations only (default)
|
|
399
|
+
mille check --fail-on warning # exit 1 on any violation (error or warning)
|
|
400
|
+
mille check --fail-on error # explicit default — same as no flag
|
|
401
|
+
```
|
|
402
|
+
|
|
291
403
|
Exit codes:
|
|
292
404
|
|
|
293
405
|
| Code | Meaning |
|
|
294
406
|
|---|---|
|
|
295
|
-
| `0` | No violations |
|
|
296
|
-
| `1` | One or more violations
|
|
407
|
+
| `0` | No violations (or only warnings without `--fail-on warning`) |
|
|
408
|
+
| `1` | One or more violations at the configured fail threshold |
|
|
297
409
|
| `3` | Configuration file error |
|
|
298
410
|
|
|
299
411
|
## Configuration Reference
|
|
@@ -304,7 +416,7 @@ Exit codes:
|
|
|
304
416
|
|---|---|
|
|
305
417
|
| `name` | Project name |
|
|
306
418
|
| `root` | Root directory for analysis |
|
|
307
|
-
| `languages` | Languages to check: `"rust"`, `"go"`, `"typescript"`, `"javascript"`, `"python"` |
|
|
419
|
+
| `languages` | Languages to check: `"rust"`, `"go"`, `"typescript"`, `"javascript"`, `"python"`, `"java"`, `"kotlin"` |
|
|
308
420
|
|
|
309
421
|
### `[[layers]]`
|
|
310
422
|
|
|
@@ -348,6 +460,27 @@ test_patterns = ["**/*_test.go", "**/*.spec.ts", "**/*.test.ts"]
|
|
|
348
460
|
- `paths`: Files that should not be analyzed at all (generated code, vendor directories, mocks)
|
|
349
461
|
- `test_patterns`: Test files that intentionally import across layers (e.g., integration tests that import both domain and infrastructure)
|
|
350
462
|
|
|
463
|
+
### `[severity]`
|
|
464
|
+
|
|
465
|
+
Control the severity level of each violation type. Violations can be `"error"`, `"warning"`, or `"info"`.
|
|
466
|
+
|
|
467
|
+
| Key | Default | Description |
|
|
468
|
+
|---|---|---|
|
|
469
|
+
| `dependency_violation` | `"error"` | Layer dependency rule violated |
|
|
470
|
+
| `external_violation` | `"error"` | External library rule violated |
|
|
471
|
+
| `call_pattern_violation` | `"error"` | DI entrypoint method call rule violated |
|
|
472
|
+
| `unknown_import` | `"warning"` | Import that could not be classified |
|
|
473
|
+
|
|
474
|
+
```toml
|
|
475
|
+
[severity]
|
|
476
|
+
dependency_violation = "warning" # treat as warning for gradual adoption
|
|
477
|
+
external_violation = "error"
|
|
478
|
+
call_pattern_violation = "error"
|
|
479
|
+
unknown_import = "warning"
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
Use `--fail-on warning` to exit 1 even for warnings when integrating into CI gradually.
|
|
483
|
+
|
|
351
484
|
### `[resolve.typescript]`
|
|
352
485
|
|
|
353
486
|
| Key | Description |
|
|
@@ -368,7 +501,7 @@ test_patterns = ["**/*_test.go", "**/*.spec.ts", "**/*.test.ts"]
|
|
|
368
501
|
|
|
369
502
|
| Key | Description |
|
|
370
503
|
|---|---|
|
|
371
|
-
| `module_name` | Go module name (matches `go.mod`) |
|
|
504
|
+
| `module_name` | Go module name (matches `go.mod`). `mille init` generates this automatically from `go.mod`. |
|
|
372
505
|
|
|
373
506
|
### `[resolve.python]`
|
|
374
507
|
|
|
@@ -385,6 +518,24 @@ test_patterns = ["**/*_test.go", "**/*.spec.ts", "**/*.test.ts"]
|
|
|
385
518
|
| `import domain.entity` (matches `package_names`) | Internal |
|
|
386
519
|
| `import os`, `import sqlalchemy` | External |
|
|
387
520
|
|
|
521
|
+
### `[resolve.java]`
|
|
522
|
+
|
|
523
|
+
| Key | Description |
|
|
524
|
+
|---|---|
|
|
525
|
+
| `module_name` | Base package of your project (e.g. `com.example.myapp`). Imports starting with this prefix are classified as Internal. Generated automatically by `mille init`. |
|
|
526
|
+
| `pom_xml` | Path to `pom.xml` (relative to `mille.toml`). `groupId.artifactId` is used as `module_name` when `module_name` is not set. |
|
|
527
|
+
| `build_gradle` | Path to `build.gradle` (relative to `mille.toml`). `group` + `rootProject.name` from `settings.gradle` is used as `module_name` when `module_name` is not set. |
|
|
528
|
+
|
|
529
|
+
**How Java imports are classified:**
|
|
530
|
+
|
|
531
|
+
| Import | Classification |
|
|
532
|
+
|---|---|
|
|
533
|
+
| `import com.example.myapp.domain.User` (starts with `module_name`) | Internal |
|
|
534
|
+
| `import static com.example.myapp.util.Helper.method` | Internal |
|
|
535
|
+
| `import java.util.List`, `import org.springframework.*` | External |
|
|
536
|
+
|
|
537
|
+
> Both regular and static imports are supported. Wildcard imports (`import java.util.*`) are not yet extracted by the parser.
|
|
538
|
+
|
|
388
539
|
## How it Works
|
|
389
540
|
|
|
390
541
|
mille uses [tree-sitter](https://tree-sitter.github.io/) for AST-based import extraction — no regex heuristics.
|
|
@@ -395,7 +546,7 @@ mille.toml
|
|
|
395
546
|
▼
|
|
396
547
|
Layer definitions
|
|
397
548
|
│
|
|
398
|
-
Source files (*.rs, *.go, *.py, *.ts, *.js, ...)
|
|
549
|
+
Source files (*.rs, *.go, *.py, *.ts, *.js, *.java, ...)
|
|
399
550
|
│ tree-sitter parse
|
|
400
551
|
▼
|
|
401
552
|
RawImport list
|
package/mille.wasm
CHANGED
|
Binary file
|