@eddacraft/anvil-core 0.1.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/LICENSE +14 -0
- package/dist/antipattern/index.d.ts +11 -0
- package/dist/antipattern/index.d.ts.map +1 -0
- package/dist/antipattern/index.js +31 -0
- package/dist/antipattern/patterns-css.d.ts +17 -0
- package/dist/antipattern/patterns-css.d.ts.map +1 -0
- package/dist/antipattern/patterns-css.js +72 -0
- package/dist/antipattern/patterns-html.d.ts +21 -0
- package/dist/antipattern/patterns-html.d.ts.map +1 -0
- package/dist/antipattern/patterns-html.js +139 -0
- package/dist/antipattern/patterns.d.ts +72 -0
- package/dist/antipattern/patterns.d.ts.map +1 -0
- package/dist/antipattern/patterns.js +301 -0
- package/dist/antipattern/scanner.d.ts +32 -0
- package/dist/antipattern/scanner.d.ts.map +1 -0
- package/dist/antipattern/scanner.js +89 -0
- package/dist/antipattern/types.d.ts +318 -0
- package/dist/antipattern/types.d.ts.map +1 -0
- package/dist/antipattern/types.js +278 -0
- package/dist/architecture/analyzer.d.ts +123 -0
- package/dist/architecture/analyzer.d.ts.map +1 -0
- package/dist/architecture/analyzer.js +321 -0
- package/dist/architecture/baseline.d.ts +112 -0
- package/dist/architecture/baseline.d.ts.map +1 -0
- package/dist/architecture/baseline.js +245 -0
- package/dist/architecture/compiler.d.ts +24 -0
- package/dist/architecture/compiler.d.ts.map +1 -0
- package/dist/architecture/compiler.js +57 -0
- package/dist/architecture/context.d.ts +129 -0
- package/dist/architecture/context.d.ts.map +1 -0
- package/dist/architecture/context.js +116 -0
- package/dist/architecture/dc-generator.d.ts +9 -0
- package/dist/architecture/dc-generator.d.ts.map +1 -0
- package/dist/architecture/dc-generator.js +220 -0
- package/dist/architecture/definition-schema.d.ts +128 -0
- package/dist/architecture/definition-schema.d.ts.map +1 -0
- package/dist/architecture/definition-schema.js +94 -0
- package/dist/architecture/edge-detector-html.d.ts +6 -0
- package/dist/architecture/edge-detector-html.d.ts.map +1 -0
- package/dist/architecture/edge-detector-html.js +5 -0
- package/dist/architecture/edge-detector-web.d.ts +32 -0
- package/dist/architecture/edge-detector-web.d.ts.map +1 -0
- package/dist/architecture/edge-detector-web.js +133 -0
- package/dist/architecture/edge-detector.d.ts +116 -0
- package/dist/architecture/edge-detector.d.ts.map +1 -0
- package/dist/architecture/edge-detector.js +229 -0
- package/dist/architecture/entry-detector.d.ts +44 -0
- package/dist/architecture/entry-detector.d.ts.map +1 -0
- package/dist/architecture/entry-detector.js +263 -0
- package/dist/architecture/index.d.ts +21 -0
- package/dist/architecture/index.d.ts.map +1 -0
- package/dist/architecture/index.js +48 -0
- package/dist/architecture/layer-detector.d.ts +60 -0
- package/dist/architecture/layer-detector.d.ts.map +1 -0
- package/dist/architecture/layer-detector.js +331 -0
- package/dist/architecture/rego-generator.d.ts +25 -0
- package/dist/architecture/rego-generator.d.ts.map +1 -0
- package/dist/architecture/rego-generator.js +229 -0
- package/dist/architecture/templates/index.d.ts +39 -0
- package/dist/architecture/templates/index.d.ts.map +1 -0
- package/dist/architecture/templates/index.js +124 -0
- package/dist/architecture/types.d.ts +280 -0
- package/dist/architecture/types.d.ts.map +1 -0
- package/dist/architecture/types.js +269 -0
- package/dist/architecture/yaml-parser.d.ts +13 -0
- package/dist/architecture/yaml-parser.d.ts.map +1 -0
- package/dist/architecture/yaml-parser.js +234 -0
- package/dist/config/constants.d.ts +9 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +20 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +8 -0
- package/dist/config/loader.d.ts +41 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +76 -0
- package/dist/config/nudge-config.d.ts +35 -0
- package/dist/config/nudge-config.d.ts.map +1 -0
- package/dist/config/nudge-config.js +34 -0
- package/dist/config/types.d.ts +30 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +4 -0
- package/dist/contracts/index.d.ts +14 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +13 -0
- package/dist/contracts/schemas/aps.schema.d.ts +269 -0
- package/dist/contracts/schemas/aps.schema.d.ts.map +1 -0
- package/dist/contracts/schemas/aps.schema.js +183 -0
- package/dist/contracts/schemas/index.d.ts +12 -0
- package/dist/contracts/schemas/index.d.ts.map +1 -0
- package/dist/contracts/schemas/index.js +14 -0
- package/dist/contracts/schemas/json-schema.d.ts +14 -0
- package/dist/contracts/schemas/json-schema.d.ts.map +1 -0
- package/dist/contracts/schemas/json-schema.js +31 -0
- package/dist/contracts/schemas/warning.schema.d.ts +171 -0
- package/dist/contracts/schemas/warning.schema.d.ts.map +1 -0
- package/dist/contracts/schemas/warning.schema.js +123 -0
- package/dist/contracts/types/gate.types.d.ts +194 -0
- package/dist/contracts/types/gate.types.d.ts.map +1 -0
- package/dist/contracts/types/gate.types.js +19 -0
- package/dist/contracts/types/index.d.ts +9 -0
- package/dist/contracts/types/index.d.ts.map +1 -0
- package/dist/contracts/types/index.js +8 -0
- package/dist/crypto/hash.d.ts +47 -0
- package/dist/crypto/hash.d.ts.map +1 -0
- package/dist/crypto/hash.js +110 -0
- package/dist/crypto/index.d.ts +7 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +6 -0
- package/dist/drift/index.d.ts +6 -0
- package/dist/drift/index.d.ts.map +1 -0
- package/dist/drift/index.js +5 -0
- package/dist/drift/report-generator.d.ts +21 -0
- package/dist/drift/report-generator.d.ts.map +1 -0
- package/dist/drift/report-generator.js +240 -0
- package/dist/drift/snapshot-capture.d.ts +26 -0
- package/dist/drift/snapshot-capture.d.ts.map +1 -0
- package/dist/drift/snapshot-capture.js +195 -0
- package/dist/drift/snapshot-compare.d.ts +50 -0
- package/dist/drift/snapshot-compare.d.ts.map +1 -0
- package/dist/drift/snapshot-compare.js +142 -0
- package/dist/drift/snapshot-schema.d.ts +197 -0
- package/dist/drift/snapshot-schema.d.ts.map +1 -0
- package/dist/drift/snapshot-schema.js +193 -0
- package/dist/drift/snapshot-storage.d.ts +25 -0
- package/dist/drift/snapshot-storage.d.ts.map +1 -0
- package/dist/drift/snapshot-storage.js +179 -0
- package/dist/explain/antipattern-explainer.d.ts +4 -0
- package/dist/explain/antipattern-explainer.d.ts.map +1 -0
- package/dist/explain/antipattern-explainer.js +196 -0
- package/dist/explain/boundary-explainer.d.ts +5 -0
- package/dist/explain/boundary-explainer.d.ts.map +1 -0
- package/dist/explain/boundary-explainer.js +261 -0
- package/dist/explain/explain-service.d.ts +19 -0
- package/dist/explain/explain-service.d.ts.map +1 -0
- package/dist/explain/explain-service.js +106 -0
- package/dist/explain/index.d.ts +7 -0
- package/dist/explain/index.d.ts.map +1 -0
- package/dist/explain/index.js +5 -0
- package/dist/explain/template-loader.d.ts +9 -0
- package/dist/explain/template-loader.d.ts.map +1 -0
- package/dist/explain/template-loader.js +51 -0
- package/dist/explain/types.d.ts +46 -0
- package/dist/explain/types.d.ts.map +1 -0
- package/dist/explain/types.js +31 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/provenance/collector.d.ts +86 -0
- package/dist/provenance/collector.d.ts.map +1 -0
- package/dist/provenance/collector.js +425 -0
- package/dist/provenance/git-ai-standard/git-notes.d.ts +85 -0
- package/dist/provenance/git-ai-standard/git-notes.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/git-notes.js +292 -0
- package/dist/provenance/git-ai-standard/index.d.ts +44 -0
- package/dist/provenance/git-ai-standard/index.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/index.js +47 -0
- package/dist/provenance/git-ai-standard/serializer.d.ts +54 -0
- package/dist/provenance/git-ai-standard/serializer.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/serializer.js +224 -0
- package/dist/provenance/git-ai-standard/session.d.ts +51 -0
- package/dist/provenance/git-ai-standard/session.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/session.js +118 -0
- package/dist/provenance/git-ai-standard/types.d.ts +173 -0
- package/dist/provenance/git-ai-standard/types.d.ts.map +1 -0
- package/dist/provenance/git-ai-standard/types.js +109 -0
- package/dist/provenance/index.d.ts +5 -0
- package/dist/provenance/index.d.ts.map +1 -0
- package/dist/provenance/index.js +6 -0
- package/dist/provenance/store.d.ts +83 -0
- package/dist/provenance/store.d.ts.map +1 -0
- package/dist/provenance/store.js +248 -0
- package/dist/provenance/types.d.ts +160 -0
- package/dist/provenance/types.d.ts.map +1 -0
- package/dist/provenance/types.js +112 -0
- package/dist/suppression/index.d.ts +4 -0
- package/dist/suppression/index.d.ts.map +1 -0
- package/dist/suppression/index.js +3 -0
- package/dist/suppression/parser.d.ts +31 -0
- package/dist/suppression/parser.d.ts.map +1 -0
- package/dist/suppression/parser.js +219 -0
- package/dist/suppression/service.d.ts +29 -0
- package/dist/suppression/service.d.ts.map +1 -0
- package/dist/suppression/service.js +132 -0
- package/dist/suppression/store.d.ts +61 -0
- package/dist/suppression/store.d.ts.map +1 -0
- package/dist/suppression/store.js +169 -0
- package/dist/utils/debug.d.ts +48 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +100 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/path-safety.d.ts +21 -0
- package/dist/utils/path-safety.d.ts.map +1 -0
- package/dist/utils/path-safety.js +49 -0
- package/dist/utils/severity.d.ts +37 -0
- package/dist/utils/severity.d.ts.map +1 -0
- package/dist/utils/severity.js +22 -0
- package/dist/validation/aps-validator.d.ts +66 -0
- package/dist/validation/aps-validator.d.ts.map +1 -0
- package/dist/validation/aps-validator.js +173 -0
- package/dist/validation/errors.d.ts +52 -0
- package/dist/validation/errors.d.ts.map +1 -0
- package/dist/validation/errors.js +115 -0
- package/dist/validation/index.d.ts +8 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +13 -0
- package/dist/warnings/index.d.ts +2 -0
- package/dist/warnings/index.d.ts.map +1 -0
- package/dist/warnings/index.js +1 -0
- package/dist/warnings/warning-id.d.ts +180 -0
- package/dist/warnings/warning-id.d.ts.map +1 -0
- package/dist/warnings/warning-id.js +257 -0
- package/package.json +79 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { writeFile, mkdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import { createDebugger } from '../utils/debug.js';
|
|
6
|
+
const debug = createDebugger('compiler');
|
|
7
|
+
export const GENERATED_POLICIES_DIR = '.anvil/policies/.generated';
|
|
8
|
+
export const REGO_FILENAME = 'architecture.rego';
|
|
9
|
+
export const REGO_PACKAGE = 'anvil.policies.architecture';
|
|
10
|
+
/**
|
|
11
|
+
* Get the path to the generated Rego file
|
|
12
|
+
*/
|
|
13
|
+
export function getRegoPath(workspaceRoot) {
|
|
14
|
+
return join(workspaceRoot, GENERATED_POLICIES_DIR, REGO_FILENAME);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if generated Rego file exists
|
|
18
|
+
*/
|
|
19
|
+
export function regoExists(workspaceRoot) {
|
|
20
|
+
return existsSync(getRegoPath(workspaceRoot));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if Rego needs regeneration based on definition hash
|
|
24
|
+
*/
|
|
25
|
+
export async function needsRegoRegeneration(workspaceRoot, definition) {
|
|
26
|
+
const regoPath = getRegoPath(workspaceRoot);
|
|
27
|
+
if (!existsSync(regoPath)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
const existingContent = await readFile(regoPath, 'utf-8');
|
|
31
|
+
const hashMatch = existingContent.match(/# hash: ([a-f0-9]+)/);
|
|
32
|
+
if (!hashMatch) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
const currentHash = computeDefinitionHash(definition);
|
|
36
|
+
return hashMatch[1] !== currentHash;
|
|
37
|
+
}
|
|
38
|
+
function computeDefinitionHash(definition) {
|
|
39
|
+
const content = JSON.stringify(definition);
|
|
40
|
+
return createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Write generated Rego policy file
|
|
44
|
+
*/
|
|
45
|
+
export async function writeRegoPolicy(workspaceRoot, definition) {
|
|
46
|
+
const regoPath = getRegoPath(workspaceRoot);
|
|
47
|
+
debug('writing Rego policy', regoPath);
|
|
48
|
+
const regoDir = dirname(regoPath);
|
|
49
|
+
if (!existsSync(regoDir)) {
|
|
50
|
+
await mkdir(regoDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
const content = generateRegoPolicy(definition);
|
|
53
|
+
await writeFile(regoPath, content, 'utf-8');
|
|
54
|
+
return regoPath;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generate Rego policy content from architecture definition
|
|
58
|
+
*/
|
|
59
|
+
export function generateRegoPolicy(definition) {
|
|
60
|
+
const hash = computeDefinitionHash(definition);
|
|
61
|
+
const lines = [];
|
|
62
|
+
// Header
|
|
63
|
+
lines.push('# Auto-generated by Anvil - do not edit manually');
|
|
64
|
+
lines.push(`# hash: ${hash}`);
|
|
65
|
+
lines.push('# Generated from: .anvil/architecture.yaml');
|
|
66
|
+
lines.push('#');
|
|
67
|
+
lines.push('# This policy enforces architecture boundaries defined in architecture.yaml.');
|
|
68
|
+
lines.push('# It uses the architecture context provided by ArchitectureCheck.');
|
|
69
|
+
lines.push('');
|
|
70
|
+
lines.push(`package ${REGO_PACKAGE}`);
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push('import rego.v1');
|
|
73
|
+
lines.push('');
|
|
74
|
+
// Generate layer definitions as data
|
|
75
|
+
lines.push('# Layer definitions from architecture.yaml');
|
|
76
|
+
lines.push(`layers := ${JSON.stringify(Object.keys(definition.layers))}`);
|
|
77
|
+
lines.push('');
|
|
78
|
+
// Generate allowed dependencies map
|
|
79
|
+
const allowedDeps = {};
|
|
80
|
+
for (const [layerName, layerDef] of Object.entries(definition.layers)) {
|
|
81
|
+
allowedDeps[layerName] = layerDef.depends_on;
|
|
82
|
+
}
|
|
83
|
+
lines.push('# Allowed dependencies per layer');
|
|
84
|
+
lines.push(`allowed_deps := ${JSON.stringify(allowedDeps)}`);
|
|
85
|
+
lines.push('');
|
|
86
|
+
// Generate options
|
|
87
|
+
const options = definition.options ?? {
|
|
88
|
+
detect_circular: true,
|
|
89
|
+
default_severity: 'error',
|
|
90
|
+
};
|
|
91
|
+
lines.push('# Options');
|
|
92
|
+
lines.push(`detect_circular := ${options.detect_circular ?? true}`);
|
|
93
|
+
lines.push(`default_severity := "${options.default_severity ?? 'error'}"`);
|
|
94
|
+
lines.push('');
|
|
95
|
+
// Helper function to check if a layer can depend on another
|
|
96
|
+
lines.push('# Check if source layer is allowed to depend on target layer');
|
|
97
|
+
lines.push('layer_can_depend(source, target) if {');
|
|
98
|
+
lines.push(' source == target # Same layer is always allowed');
|
|
99
|
+
lines.push('}');
|
|
100
|
+
lines.push('');
|
|
101
|
+
lines.push('layer_can_depend(source, target) if {');
|
|
102
|
+
lines.push(' allowed := allowed_deps[source]');
|
|
103
|
+
lines.push(' target in allowed');
|
|
104
|
+
lines.push('}');
|
|
105
|
+
lines.push('');
|
|
106
|
+
// Violation rule for layer boundary violations
|
|
107
|
+
lines.push('# Detect layer boundary violations from architecture context');
|
|
108
|
+
lines.push('violation contains result if {');
|
|
109
|
+
lines.push(' some v in input.architecture.violations');
|
|
110
|
+
lines.push(' v.from_layer != null');
|
|
111
|
+
lines.push(' v.to_layer != null');
|
|
112
|
+
lines.push(' not layer_can_depend(v.from_layer, v.to_layer)');
|
|
113
|
+
lines.push(' v.is_new');
|
|
114
|
+
lines.push(' result := {');
|
|
115
|
+
lines.push(' "rule": "layer-boundary",');
|
|
116
|
+
lines.push(' "severity": v.severity,');
|
|
117
|
+
lines.push(' "message": sprintf("%s (%s) cannot depend on %s (%s)", [v.from, v.from_layer, v.to, v.to_layer]),');
|
|
118
|
+
lines.push(' "path": v.from,');
|
|
119
|
+
lines.push(' "category": "architecture",');
|
|
120
|
+
lines.push(' }');
|
|
121
|
+
lines.push('}');
|
|
122
|
+
lines.push('');
|
|
123
|
+
// Violation rule for circular dependencies
|
|
124
|
+
lines.push('# Detect circular dependencies');
|
|
125
|
+
lines.push('violation contains result if {');
|
|
126
|
+
lines.push(' detect_circular');
|
|
127
|
+
lines.push(' some v in input.architecture.violations');
|
|
128
|
+
lines.push(' v.is_circular');
|
|
129
|
+
lines.push(' v.is_new');
|
|
130
|
+
lines.push(' result := {');
|
|
131
|
+
lines.push(' "rule": "no-circular",');
|
|
132
|
+
lines.push(' "severity": default_severity,');
|
|
133
|
+
lines.push(' "message": sprintf("Circular dependency: %s -> %s", [v.from, v.to]),');
|
|
134
|
+
lines.push(' "path": v.from,');
|
|
135
|
+
lines.push(' "category": "architecture",');
|
|
136
|
+
lines.push(' }');
|
|
137
|
+
lines.push('}');
|
|
138
|
+
lines.push('');
|
|
139
|
+
// Violation rule for new violations (not in baseline)
|
|
140
|
+
lines.push('# Flag new violations (not in baseline)');
|
|
141
|
+
lines.push('violation contains result if {');
|
|
142
|
+
lines.push(' some v in input.architecture.violations');
|
|
143
|
+
lines.push(' v.is_new');
|
|
144
|
+
lines.push(' result := {');
|
|
145
|
+
lines.push(' "rule": "new-violation",');
|
|
146
|
+
lines.push(' "severity": "warning",');
|
|
147
|
+
lines.push(' "message": sprintf("New architecture violation: %s -> %s (%s)", [v.from, v.to, v.rule]),');
|
|
148
|
+
lines.push(' "path": v.from,');
|
|
149
|
+
lines.push(' "category": "architecture",');
|
|
150
|
+
lines.push(' }');
|
|
151
|
+
lines.push('}');
|
|
152
|
+
lines.push('');
|
|
153
|
+
// Generate explicit rules from definition
|
|
154
|
+
if (definition.rules.length > 0) {
|
|
155
|
+
lines.push('# Explicit rules from architecture.yaml');
|
|
156
|
+
for (const rule of definition.rules) {
|
|
157
|
+
if (!rule.allowed) {
|
|
158
|
+
// This is a forbidden dependency rule
|
|
159
|
+
const fromLayer = definition.layers[rule.from];
|
|
160
|
+
const toLayer = definition.layers[rule.to];
|
|
161
|
+
if (fromLayer && toLayer) {
|
|
162
|
+
const ruleName = sanitiseRuleName(rule.name);
|
|
163
|
+
lines.push(`# Rule: ${rule.name}`);
|
|
164
|
+
lines.push(`violation contains result if {`);
|
|
165
|
+
lines.push(` some v in input.architecture.violations`);
|
|
166
|
+
lines.push(` v.from_layer == "${rule.from}"`);
|
|
167
|
+
lines.push(` v.to_layer == "${rule.to}"`);
|
|
168
|
+
lines.push(` v.is_new`);
|
|
169
|
+
lines.push(` result := {`);
|
|
170
|
+
lines.push(` "rule": "${ruleName}",`);
|
|
171
|
+
lines.push(` "severity": "${rule.severity}",`);
|
|
172
|
+
lines.push(` "message": "${escapeString(rule.message || `${rule.from} must not depend on ${rule.to}`)}",`);
|
|
173
|
+
lines.push(` "path": v.from,`);
|
|
174
|
+
lines.push(` "category": "architecture",`);
|
|
175
|
+
lines.push(` }`);
|
|
176
|
+
lines.push(`}`);
|
|
177
|
+
lines.push('');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Summary helper for external use
|
|
183
|
+
lines.push('# Summary of architecture health');
|
|
184
|
+
lines.push('summary := {');
|
|
185
|
+
lines.push(' "total_violations": count(violation),');
|
|
186
|
+
lines.push(' "layer_violations": count([v | some v in violation; v.rule == "layer-boundary"]),');
|
|
187
|
+
lines.push(' "circular_violations": count([v | some v in violation; v.rule == "no-circular"]),');
|
|
188
|
+
lines.push(' "new_violations": count([v | some v in violation; v.rule == "new-violation"]),');
|
|
189
|
+
lines.push('}');
|
|
190
|
+
lines.push('');
|
|
191
|
+
// Deny rule for blocking on errors
|
|
192
|
+
lines.push('# Deny if any error-level violations exist');
|
|
193
|
+
lines.push('deny contains msg if {');
|
|
194
|
+
lines.push(' some v in violation');
|
|
195
|
+
lines.push(' v.severity == "error"');
|
|
196
|
+
lines.push(' msg := v.message');
|
|
197
|
+
lines.push('}');
|
|
198
|
+
lines.push('');
|
|
199
|
+
// Warn rule for warning-level violations
|
|
200
|
+
lines.push('# Warn for warning-level violations');
|
|
201
|
+
lines.push('warn contains msg if {');
|
|
202
|
+
lines.push(' some v in violation');
|
|
203
|
+
lines.push(' v.severity == "warn"');
|
|
204
|
+
lines.push(' msg := v.message');
|
|
205
|
+
lines.push('}');
|
|
206
|
+
lines.push('');
|
|
207
|
+
lines.push('warn contains msg if {');
|
|
208
|
+
lines.push(' some v in violation');
|
|
209
|
+
lines.push(' v.severity == "warning"');
|
|
210
|
+
lines.push(' msg := v.message');
|
|
211
|
+
lines.push('}');
|
|
212
|
+
lines.push('');
|
|
213
|
+
return lines.join('\n');
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Sanitise rule name for use in Rego
|
|
217
|
+
*/
|
|
218
|
+
function sanitiseRuleName(name) {
|
|
219
|
+
return name
|
|
220
|
+
.toLowerCase()
|
|
221
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
222
|
+
.replace(/^-|-$/g, '');
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Escape string for Rego string literal
|
|
226
|
+
*/
|
|
227
|
+
function escapeString(str) {
|
|
228
|
+
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
229
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ArchitectureTemplate, LayerDefinition } from '../definition-schema.js';
|
|
3
|
+
declare const TemplateFileSchema: z.ZodObject<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
description: z.ZodString;
|
|
6
|
+
layers: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
7
|
+
patterns: z.ZodArray<z.ZodString>;
|
|
8
|
+
depends_on: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
9
|
+
description: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, z.core.$strip>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export type TemplateFile = z.infer<typeof TemplateFileSchema>;
|
|
13
|
+
export interface LoadedTemplate {
|
|
14
|
+
name: ArchitectureTemplate;
|
|
15
|
+
description: string;
|
|
16
|
+
layers: Record<string, LayerDefinition>;
|
|
17
|
+
}
|
|
18
|
+
export declare class TemplateLoader {
|
|
19
|
+
private cache;
|
|
20
|
+
private templatesDir;
|
|
21
|
+
constructor(templatesDir?: string);
|
|
22
|
+
list(): Promise<ArchitectureTemplate[]>;
|
|
23
|
+
get(name: ArchitectureTemplate): Promise<LoadedTemplate>;
|
|
24
|
+
validate(name: ArchitectureTemplate): Promise<{
|
|
25
|
+
valid: boolean;
|
|
26
|
+
errors: string[];
|
|
27
|
+
}>;
|
|
28
|
+
getAll(): Promise<LoadedTemplate[]>;
|
|
29
|
+
clearCache(): void;
|
|
30
|
+
}
|
|
31
|
+
export declare function getTemplateLoader(): TemplateLoader;
|
|
32
|
+
export declare function listTemplates(): Promise<ArchitectureTemplate[]>;
|
|
33
|
+
export declare function getTemplate(name: ArchitectureTemplate): Promise<LoadedTemplate>;
|
|
34
|
+
export declare function validateTemplate(name: ArchitectureTemplate): Promise<{
|
|
35
|
+
valid: boolean;
|
|
36
|
+
errors: string[];
|
|
37
|
+
}>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/architecture/templates/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAWrF,QAAA,MAAM,kBAAkB;;;;;;;;iBAItB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACzC;AAaD,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,CAAC,EAAE,MAAM;IAI3B,IAAI,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAcvC,GAAG,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAsCxD,QAAQ,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IA0BnF,MAAM,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAKzC,UAAU,IAAI,IAAI;CAGnB;AAID,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAErE;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAErF;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAE/C"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import YAML from 'yaml';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const TemplateLayerSchema = z.object({
|
|
9
|
+
patterns: z.array(z.string()),
|
|
10
|
+
depends_on: z.array(z.string()).default([]),
|
|
11
|
+
description: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
const TemplateFileSchema = z.object({
|
|
14
|
+
name: z.string(),
|
|
15
|
+
description: z.string(),
|
|
16
|
+
layers: z.record(z.string(), TemplateLayerSchema),
|
|
17
|
+
});
|
|
18
|
+
const TEMPLATE_FILES = {
|
|
19
|
+
starter: 'starter.yaml',
|
|
20
|
+
layered: 'layered.yaml',
|
|
21
|
+
hexagonal: 'hexagonal.yaml',
|
|
22
|
+
clean: 'clean.yaml',
|
|
23
|
+
ddd: 'ddd.yaml',
|
|
24
|
+
monorepo: 'monorepo.yaml',
|
|
25
|
+
serverless: 'serverless.yaml',
|
|
26
|
+
'nx-workspace': 'nx-workspace.yaml',
|
|
27
|
+
};
|
|
28
|
+
export class TemplateLoader {
|
|
29
|
+
cache = new Map();
|
|
30
|
+
templatesDir;
|
|
31
|
+
constructor(templatesDir) {
|
|
32
|
+
this.templatesDir = templatesDir ?? __dirname;
|
|
33
|
+
}
|
|
34
|
+
async list() {
|
|
35
|
+
return [
|
|
36
|
+
'starter',
|
|
37
|
+
'layered',
|
|
38
|
+
'hexagonal',
|
|
39
|
+
'clean',
|
|
40
|
+
'ddd',
|
|
41
|
+
'monorepo',
|
|
42
|
+
'serverless',
|
|
43
|
+
'nx-workspace',
|
|
44
|
+
'custom',
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
async get(name) {
|
|
48
|
+
if (name === 'custom') {
|
|
49
|
+
return {
|
|
50
|
+
name: 'custom',
|
|
51
|
+
description: 'Empty template for custom architecture definitions',
|
|
52
|
+
layers: {},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const cached = this.cache.get(name);
|
|
56
|
+
if (cached) {
|
|
57
|
+
return cached;
|
|
58
|
+
}
|
|
59
|
+
const filename = TEMPLATE_FILES[name];
|
|
60
|
+
if (!filename) {
|
|
61
|
+
throw new Error(`Unknown template: ${name}`);
|
|
62
|
+
}
|
|
63
|
+
const filePath = join(this.templatesDir, filename);
|
|
64
|
+
const content = await readFile(filePath, 'utf-8');
|
|
65
|
+
const parsed = YAML.parse(content);
|
|
66
|
+
const validated = TemplateFileSchema.safeParse(parsed);
|
|
67
|
+
if (!validated.success) {
|
|
68
|
+
throw new Error(`Invalid template file ${filename}: ${validated.error.message}`);
|
|
69
|
+
}
|
|
70
|
+
const template = {
|
|
71
|
+
name,
|
|
72
|
+
description: validated.data.description,
|
|
73
|
+
layers: validated.data.layers,
|
|
74
|
+
};
|
|
75
|
+
this.cache.set(name, template);
|
|
76
|
+
return template;
|
|
77
|
+
}
|
|
78
|
+
async validate(name) {
|
|
79
|
+
try {
|
|
80
|
+
const template = await this.get(name);
|
|
81
|
+
const errors = [];
|
|
82
|
+
for (const [layerName, layer] of Object.entries(template.layers)) {
|
|
83
|
+
for (const dep of layer.depends_on) {
|
|
84
|
+
if (!template.layers[dep]) {
|
|
85
|
+
errors.push(`Layer "${layerName}" depends on unknown layer "${dep}"`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (layer.patterns.length === 0) {
|
|
89
|
+
errors.push(`Layer "${layerName}" has no patterns defined`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { valid: errors.length === 0, errors };
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
return {
|
|
96
|
+
valid: false,
|
|
97
|
+
errors: [err instanceof Error ? err.message : 'Unknown error'],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async getAll() {
|
|
102
|
+
const names = await this.list();
|
|
103
|
+
return Promise.all(names.map((name) => this.get(name)));
|
|
104
|
+
}
|
|
105
|
+
clearCache() {
|
|
106
|
+
this.cache.clear();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
let defaultLoader = null;
|
|
110
|
+
export function getTemplateLoader() {
|
|
111
|
+
if (!defaultLoader) {
|
|
112
|
+
defaultLoader = new TemplateLoader();
|
|
113
|
+
}
|
|
114
|
+
return defaultLoader;
|
|
115
|
+
}
|
|
116
|
+
export async function listTemplates() {
|
|
117
|
+
return getTemplateLoader().list();
|
|
118
|
+
}
|
|
119
|
+
export async function getTemplate(name) {
|
|
120
|
+
return getTemplateLoader().get(name);
|
|
121
|
+
}
|
|
122
|
+
export async function validateTemplate(name) {
|
|
123
|
+
return getTemplateLoader().validate(name);
|
|
124
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture baseline types
|
|
3
|
+
*
|
|
4
|
+
* Defines the schema for .anvil/architecture.json - the architecture baseline
|
|
5
|
+
* that enables NEW vs existing violation detection.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/**
|
|
9
|
+
* Entry point types detected in the codebase
|
|
10
|
+
*/
|
|
11
|
+
export declare const EntryPointTypeSchema: z.ZodEnum<{
|
|
12
|
+
unknown: "unknown";
|
|
13
|
+
cli: "cli";
|
|
14
|
+
api: "api";
|
|
15
|
+
test: "test";
|
|
16
|
+
package: "package";
|
|
17
|
+
application: "application";
|
|
18
|
+
http: "http";
|
|
19
|
+
worker: "worker";
|
|
20
|
+
}>;
|
|
21
|
+
export type EntryPointType = z.infer<typeof EntryPointTypeSchema>;
|
|
22
|
+
/**
|
|
23
|
+
* Confidence level for detection
|
|
24
|
+
*/
|
|
25
|
+
export declare const DetectionConfidenceSchema: z.ZodEnum<{
|
|
26
|
+
high: "high";
|
|
27
|
+
medium: "medium";
|
|
28
|
+
low: "low";
|
|
29
|
+
}>;
|
|
30
|
+
export type DetectionConfidence = z.infer<typeof DetectionConfidenceSchema>;
|
|
31
|
+
/**
|
|
32
|
+
* A detected entry point in the codebase
|
|
33
|
+
*/
|
|
34
|
+
export declare const EntryPointSchema: z.ZodObject<{
|
|
35
|
+
path: z.ZodString;
|
|
36
|
+
type: z.ZodEnum<{
|
|
37
|
+
unknown: "unknown";
|
|
38
|
+
cli: "cli";
|
|
39
|
+
api: "api";
|
|
40
|
+
test: "test";
|
|
41
|
+
package: "package";
|
|
42
|
+
application: "application";
|
|
43
|
+
http: "http";
|
|
44
|
+
worker: "worker";
|
|
45
|
+
}>;
|
|
46
|
+
confidence: z.ZodEnum<{
|
|
47
|
+
high: "high";
|
|
48
|
+
medium: "medium";
|
|
49
|
+
low: "low";
|
|
50
|
+
}>;
|
|
51
|
+
exports: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
export type EntryPoint = z.infer<typeof EntryPointSchema>;
|
|
54
|
+
/**
|
|
55
|
+
* Standard layer names (can be extended)
|
|
56
|
+
*/
|
|
57
|
+
export declare const StandardLayerSchema: z.ZodEnum<{
|
|
58
|
+
application: "application";
|
|
59
|
+
presentation: "presentation";
|
|
60
|
+
domain: "domain";
|
|
61
|
+
infrastructure: "infrastructure";
|
|
62
|
+
shared: "shared";
|
|
63
|
+
}>;
|
|
64
|
+
export type StandardLayer = z.infer<typeof StandardLayerSchema>;
|
|
65
|
+
/**
|
|
66
|
+
* Layer definition with dependency rules
|
|
67
|
+
*/
|
|
68
|
+
export declare const LayerSchema: z.ZodObject<{
|
|
69
|
+
patterns: z.ZodArray<z.ZodString>;
|
|
70
|
+
depends_on: z.ZodArray<z.ZodString>;
|
|
71
|
+
description: z.ZodOptional<z.ZodString>;
|
|
72
|
+
}, z.core.$strip>;
|
|
73
|
+
export type Layer = z.infer<typeof LayerSchema>;
|
|
74
|
+
/**
|
|
75
|
+
* Map of layer name to layer definition
|
|
76
|
+
*/
|
|
77
|
+
export declare const LayersSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
78
|
+
patterns: z.ZodArray<z.ZodString>;
|
|
79
|
+
depends_on: z.ZodArray<z.ZodString>;
|
|
80
|
+
description: z.ZodOptional<z.ZodString>;
|
|
81
|
+
}, z.core.$strip>>;
|
|
82
|
+
export type Layers = z.infer<typeof LayersSchema>;
|
|
83
|
+
/**
|
|
84
|
+
* Explicit boundary rule
|
|
85
|
+
*/
|
|
86
|
+
export declare const BoundarySchema: z.ZodObject<{
|
|
87
|
+
name: z.ZodString;
|
|
88
|
+
from: z.ZodString;
|
|
89
|
+
to: z.ZodString;
|
|
90
|
+
severity: z.ZodEnum<{
|
|
91
|
+
warning: "warning";
|
|
92
|
+
error: "error";
|
|
93
|
+
info: "info";
|
|
94
|
+
}>;
|
|
95
|
+
message: z.ZodString;
|
|
96
|
+
confidence: z.ZodOptional<z.ZodEnum<{
|
|
97
|
+
high: "high";
|
|
98
|
+
medium: "medium";
|
|
99
|
+
low: "low";
|
|
100
|
+
}>>;
|
|
101
|
+
}, z.core.$strip>;
|
|
102
|
+
export type Boundary = z.infer<typeof BoundarySchema>;
|
|
103
|
+
/**
|
|
104
|
+
* A recorded violation in the baseline
|
|
105
|
+
*/
|
|
106
|
+
export declare const BaselineViolationSchema: z.ZodObject<{
|
|
107
|
+
id: z.ZodString;
|
|
108
|
+
from_layer: z.ZodString;
|
|
109
|
+
to_layer: z.ZodString;
|
|
110
|
+
from_file: z.ZodString;
|
|
111
|
+
to_file: z.ZodString;
|
|
112
|
+
import_line: z.ZodNumber;
|
|
113
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
114
|
+
}, z.core.$strip>;
|
|
115
|
+
export type BaselineViolation = z.infer<typeof BaselineViolationSchema>;
|
|
116
|
+
/**
|
|
117
|
+
* Snapshot of the architecture state at baseline time
|
|
118
|
+
*/
|
|
119
|
+
export declare const BaselineSnapshotSchema: z.ZodObject<{
|
|
120
|
+
module_count: z.ZodNumber;
|
|
121
|
+
timestamp: z.ZodString;
|
|
122
|
+
violations: z.ZodArray<z.ZodObject<{
|
|
123
|
+
id: z.ZodString;
|
|
124
|
+
from_layer: z.ZodString;
|
|
125
|
+
to_layer: z.ZodString;
|
|
126
|
+
from_file: z.ZodString;
|
|
127
|
+
to_file: z.ZodString;
|
|
128
|
+
import_line: z.ZodNumber;
|
|
129
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
130
|
+
}, z.core.$strip>>;
|
|
131
|
+
}, z.core.$strip>;
|
|
132
|
+
export type BaselineSnapshot = z.infer<typeof BaselineSnapshotSchema>;
|
|
133
|
+
/**
|
|
134
|
+
* Complete architecture baseline stored in .anvil/architecture.json
|
|
135
|
+
*/
|
|
136
|
+
export declare const ArchitectureBaselineSchema: z.ZodObject<{
|
|
137
|
+
schema_version: z.ZodLiteral<"0.1.0">;
|
|
138
|
+
created_at: z.ZodString;
|
|
139
|
+
updated_at: z.ZodString;
|
|
140
|
+
entry_points: z.ZodArray<z.ZodObject<{
|
|
141
|
+
path: z.ZodString;
|
|
142
|
+
type: z.ZodEnum<{
|
|
143
|
+
unknown: "unknown";
|
|
144
|
+
cli: "cli";
|
|
145
|
+
api: "api";
|
|
146
|
+
test: "test";
|
|
147
|
+
package: "package";
|
|
148
|
+
application: "application";
|
|
149
|
+
http: "http";
|
|
150
|
+
worker: "worker";
|
|
151
|
+
}>;
|
|
152
|
+
confidence: z.ZodEnum<{
|
|
153
|
+
high: "high";
|
|
154
|
+
medium: "medium";
|
|
155
|
+
low: "low";
|
|
156
|
+
}>;
|
|
157
|
+
exports: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
158
|
+
}, z.core.$strip>>;
|
|
159
|
+
layers: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
160
|
+
patterns: z.ZodArray<z.ZodString>;
|
|
161
|
+
depends_on: z.ZodArray<z.ZodString>;
|
|
162
|
+
description: z.ZodOptional<z.ZodString>;
|
|
163
|
+
}, z.core.$strip>>;
|
|
164
|
+
boundaries: z.ZodArray<z.ZodObject<{
|
|
165
|
+
name: z.ZodString;
|
|
166
|
+
from: z.ZodString;
|
|
167
|
+
to: z.ZodString;
|
|
168
|
+
severity: z.ZodEnum<{
|
|
169
|
+
warning: "warning";
|
|
170
|
+
error: "error";
|
|
171
|
+
info: "info";
|
|
172
|
+
}>;
|
|
173
|
+
message: z.ZodString;
|
|
174
|
+
confidence: z.ZodOptional<z.ZodEnum<{
|
|
175
|
+
high: "high";
|
|
176
|
+
medium: "medium";
|
|
177
|
+
low: "low";
|
|
178
|
+
}>>;
|
|
179
|
+
}, z.core.$strip>>;
|
|
180
|
+
baseline_snapshot: z.ZodObject<{
|
|
181
|
+
module_count: z.ZodNumber;
|
|
182
|
+
timestamp: z.ZodString;
|
|
183
|
+
violations: z.ZodArray<z.ZodObject<{
|
|
184
|
+
id: z.ZodString;
|
|
185
|
+
from_layer: z.ZodString;
|
|
186
|
+
to_layer: z.ZodString;
|
|
187
|
+
from_file: z.ZodString;
|
|
188
|
+
to_file: z.ZodString;
|
|
189
|
+
import_line: z.ZodNumber;
|
|
190
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
191
|
+
}, z.core.$strip>>;
|
|
192
|
+
}, z.core.$strip>;
|
|
193
|
+
}, z.core.$strip>;
|
|
194
|
+
export type ArchitectureBaseline = z.infer<typeof ArchitectureBaselineSchema>;
|
|
195
|
+
/**
|
|
196
|
+
* Result of layer detection for a file
|
|
197
|
+
*/
|
|
198
|
+
export declare const LayerAssignmentSchema: z.ZodObject<{
|
|
199
|
+
file: z.ZodString;
|
|
200
|
+
layer: z.ZodNullable<z.ZodString>;
|
|
201
|
+
confidence: z.ZodEnum<{
|
|
202
|
+
high: "high";
|
|
203
|
+
medium: "medium";
|
|
204
|
+
low: "low";
|
|
205
|
+
}>;
|
|
206
|
+
matched_pattern: z.ZodOptional<z.ZodString>;
|
|
207
|
+
}, z.core.$strip>;
|
|
208
|
+
export type LayerAssignment = z.infer<typeof LayerAssignmentSchema>;
|
|
209
|
+
/**
|
|
210
|
+
* A dependency edge between two files
|
|
211
|
+
*/
|
|
212
|
+
export declare const DependencyEdgeSchema: z.ZodObject<{
|
|
213
|
+
from: z.ZodString;
|
|
214
|
+
to: z.ZodString;
|
|
215
|
+
from_layer: z.ZodNullable<z.ZodString>;
|
|
216
|
+
to_layer: z.ZodNullable<z.ZodString>;
|
|
217
|
+
line: z.ZodNumber;
|
|
218
|
+
type: z.ZodEnum<{
|
|
219
|
+
import: "import";
|
|
220
|
+
require: "require";
|
|
221
|
+
dynamic: "dynamic";
|
|
222
|
+
}>;
|
|
223
|
+
}, z.core.$strip>;
|
|
224
|
+
export type DependencyEdge = z.infer<typeof DependencyEdgeSchema>;
|
|
225
|
+
/**
|
|
226
|
+
* A detected boundary violation
|
|
227
|
+
*/
|
|
228
|
+
export declare const BoundaryViolationSchema: z.ZodObject<{
|
|
229
|
+
edge: z.ZodObject<{
|
|
230
|
+
from: z.ZodString;
|
|
231
|
+
to: z.ZodString;
|
|
232
|
+
from_layer: z.ZodNullable<z.ZodString>;
|
|
233
|
+
to_layer: z.ZodNullable<z.ZodString>;
|
|
234
|
+
line: z.ZodNumber;
|
|
235
|
+
type: z.ZodEnum<{
|
|
236
|
+
import: "import";
|
|
237
|
+
require: "require";
|
|
238
|
+
dynamic: "dynamic";
|
|
239
|
+
}>;
|
|
240
|
+
}, z.core.$strip>;
|
|
241
|
+
boundary: z.ZodOptional<z.ZodObject<{
|
|
242
|
+
name: z.ZodString;
|
|
243
|
+
from: z.ZodString;
|
|
244
|
+
to: z.ZodString;
|
|
245
|
+
severity: z.ZodEnum<{
|
|
246
|
+
warning: "warning";
|
|
247
|
+
error: "error";
|
|
248
|
+
info: "info";
|
|
249
|
+
}>;
|
|
250
|
+
message: z.ZodString;
|
|
251
|
+
confidence: z.ZodOptional<z.ZodEnum<{
|
|
252
|
+
high: "high";
|
|
253
|
+
medium: "medium";
|
|
254
|
+
low: "low";
|
|
255
|
+
}>>;
|
|
256
|
+
}, z.core.$strip>>;
|
|
257
|
+
is_new: z.ZodBoolean;
|
|
258
|
+
baseline_id: z.ZodOptional<z.ZodString>;
|
|
259
|
+
}, z.core.$strip>;
|
|
260
|
+
export type BoundaryViolation = z.infer<typeof BoundaryViolationSchema>;
|
|
261
|
+
/**
|
|
262
|
+
* Create a violation ID from edge details
|
|
263
|
+
*/
|
|
264
|
+
export declare function createViolationId(fromFile: string, toFile: string, line: number): string;
|
|
265
|
+
/**
|
|
266
|
+
* Check if a violation exists in the baseline
|
|
267
|
+
*/
|
|
268
|
+
export declare function isExistingViolation(violation: BoundaryViolation, baseline: BaselineSnapshot): boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Create default layer structure for common patterns.
|
|
271
|
+
*
|
|
272
|
+
* Patterns use **\/ prefix to match files in any directory structure,
|
|
273
|
+
* supporting both single-app (src/) and monorepo (packages/star/src/) layouts.
|
|
274
|
+
*/
|
|
275
|
+
export declare function createDefaultLayers(): Layers;
|
|
276
|
+
/**
|
|
277
|
+
* Create default boundaries from layer structure
|
|
278
|
+
*/
|
|
279
|
+
export declare function createDefaultBoundaries(layers: Layers): Boundary[];
|
|
280
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/architecture/types.ts"],"names":[],"mappings":"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"}
|