Zig 0.16 · v0.0.2 preview
File architecture rules
File rules are the general-purpose policy surface: choose project files, select a mood, and assert names, locations, dependencies, cycles, or a Zig callback.
A compiled example
The canonical example below covers an internal dependency allowlist and an approved external-module set through the public package facade.
const std = @import("std");
const archunit = @import("archunit");
test "API files depend on service files" {
var files = try archunit.files(std.testing.allocator, .{});
defer files.deinit();
var api = try files.inPath(&.{.{ .glob = "src/api/**" }});
defer api.deinit();
var should = try api.should();
defer should.deinit();
var dependency = try should.dependOnFiles();
defer dependency.deinit();
var rule = try dependency.inPath(&.{.{ .glob = "src/service/**" }});
defer rule.deinit(std.testing.allocator);
try archunit.expectPasses(&rule, .init(.init(std.testing.allocator, std.testing.io)));
}
Compiled source: test/readme/files.zig
Select subject files
Start with archunit.files or archunit.projectFiles. Narrow the owned scope using withName, inFolder, inPath, and exact inFile selectors. Pattern alternatives inside one call are OR; separate calls compose as AND. Add except immediately after a selector to keep generated or exceptional paths outside the subject.
Shipped predicates
| Predicate | Use it for |
|---|---|
haveName | Filename conventions. |
beInFolder / beInPath | Location and ownership conventions. |
dependOnFiles | Internal dependency requirements or prohibitions. |
dependOnExternalModules | Package, compiler-module, C-header, or resource policy. |
haveNoCycles | Deterministic directed-cycle detection over the selected graph. |
adhereTo | A caller-defined Zig predicate with structured custom violations. |
Dependency objects use the same grammar
After dependOnFiles, select the dependency object with the same filename, folder, path, exact-file, and exclusion vocabulary. Internal self-edges retain isolated nodes but do not count as real dependencies. A violation owns the source, target, import kinds, and source locations.
External dependency scope
Named packages are selected by default. Opt into compiler modules, C headers, or resources when the policy needs them. Resolved project aliases are internal; explicitly package-origin aliases and unresolved aliases remain external. Negated rules use the same classified facts.
Cycle results
Cycle detection works over selected internal paths and returns canonical closed paths, so the first node also appears at the end. Ordering is deterministic, and structured results keep edge evidence rather than reducing a cycle to prose.
Custom policy callbacks
adhereTo receives borrowed file information and a caller-provided type-erased context. It may return a policy result or propagate a callback error. Custom violations own their description and affected path, so formatting remains stable after callback state is gone.