@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,195 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { execFile } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { createDebugger } from '../utils/debug.js';
|
|
6
|
+
import { SNAPSHOT_SCHEMA_VERSION, } from './snapshot-schema.js';
|
|
7
|
+
import { loadBaseline, } from '../architecture/index.js';
|
|
8
|
+
import { scanFiles } from '../antipattern/index.js';
|
|
9
|
+
import { SuppressionService } from '../suppression/index.js';
|
|
10
|
+
import { generateHash } from '../crypto/index.js';
|
|
11
|
+
const debug = createDebugger('drift');
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
async function getGitRef(workspaceRoot) {
|
|
14
|
+
try {
|
|
15
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', 'HEAD'], { cwd: workspaceRoot });
|
|
16
|
+
return stdout.trim();
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
debug('failed to get git ref for workspace', err);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function baselineViolationToSnapshot(violation) {
|
|
24
|
+
return {
|
|
25
|
+
id: violation.id,
|
|
26
|
+
type: 'boundary',
|
|
27
|
+
from_file: violation.from_file,
|
|
28
|
+
to_file: violation.to_file,
|
|
29
|
+
from_layer: violation.from_layer,
|
|
30
|
+
to_layer: violation.to_layer,
|
|
31
|
+
line: violation.import_line,
|
|
32
|
+
rule: violation.rule,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function extractAntiPatterns(scanResults) {
|
|
36
|
+
const antipatterns = [];
|
|
37
|
+
for (const result of scanResults) {
|
|
38
|
+
for (const warning of result.warnings) {
|
|
39
|
+
if (warning.category !== 'anti-pattern')
|
|
40
|
+
continue;
|
|
41
|
+
if (warning.suppressed)
|
|
42
|
+
continue;
|
|
43
|
+
antipatterns.push({
|
|
44
|
+
id: warning.id,
|
|
45
|
+
file: warning.location.file,
|
|
46
|
+
line: warning.location.line,
|
|
47
|
+
pattern: warning.pattern ?? warning.id,
|
|
48
|
+
severity: warning.severity,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return antipatterns;
|
|
53
|
+
}
|
|
54
|
+
function extractSuppressions(fileSuppressions, now = new Date()) {
|
|
55
|
+
const suppressions = [];
|
|
56
|
+
for (const { file, suppressions: fileSupprs } of fileSuppressions) {
|
|
57
|
+
for (const s of fileSupprs) {
|
|
58
|
+
const isExpired = s.expiresAt ? s.expiresAt < now : false;
|
|
59
|
+
suppressions.push({
|
|
60
|
+
id: `${file}:${s.line}:${s.warningId}`,
|
|
61
|
+
pattern_id: s.warningId,
|
|
62
|
+
file,
|
|
63
|
+
line: s.line,
|
|
64
|
+
reason: s.reason,
|
|
65
|
+
scope: s.scope,
|
|
66
|
+
expires_at: s.expiresAt?.toISOString(),
|
|
67
|
+
is_expired: isExpired,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return suppressions;
|
|
72
|
+
}
|
|
73
|
+
function calculateAntiPatternBreakdown(antipatterns) {
|
|
74
|
+
const breakdown = {};
|
|
75
|
+
for (const ap of antipatterns) {
|
|
76
|
+
breakdown[ap.id] = (breakdown[ap.id] ?? 0) + 1;
|
|
77
|
+
}
|
|
78
|
+
return breakdown;
|
|
79
|
+
}
|
|
80
|
+
function calculateHotspots(violations, antipatterns, topN = 5) {
|
|
81
|
+
const pathCounts = new Map();
|
|
82
|
+
for (const v of violations) {
|
|
83
|
+
const dir = path.dirname(v.from_file);
|
|
84
|
+
const existing = pathCounts.get(dir) ?? { count: 0, types: new Set() };
|
|
85
|
+
existing.count++;
|
|
86
|
+
existing.types.add('boundary');
|
|
87
|
+
pathCounts.set(dir, existing);
|
|
88
|
+
}
|
|
89
|
+
for (const ap of antipatterns) {
|
|
90
|
+
const dir = path.dirname(ap.file);
|
|
91
|
+
const existing = pathCounts.get(dir) ?? { count: 0, types: new Set() };
|
|
92
|
+
existing.count++;
|
|
93
|
+
existing.types.add(ap.id);
|
|
94
|
+
pathCounts.set(dir, existing);
|
|
95
|
+
}
|
|
96
|
+
return Array.from(pathCounts.entries())
|
|
97
|
+
.filter(([_, data]) => data.count > 1)
|
|
98
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
99
|
+
.slice(0, topN)
|
|
100
|
+
.map(([dirPath, data]) => ({
|
|
101
|
+
path: dirPath,
|
|
102
|
+
violation_count: data.count,
|
|
103
|
+
types: Array.from(data.types),
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
function calculateMetrics(violations, antipatterns, suppressions, filesAnalysed) {
|
|
107
|
+
const expiredSuppressions = suppressions.filter((s) => s.is_expired).length;
|
|
108
|
+
return {
|
|
109
|
+
boundary_violations: violations.length,
|
|
110
|
+
antipattern_count: antipatterns.length,
|
|
111
|
+
suppression_count: suppressions.filter((s) => !s.is_expired).length,
|
|
112
|
+
expired_suppressions: expiredSuppressions,
|
|
113
|
+
files_analysed: filesAnalysed,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function generateBaselineHash(baseline) {
|
|
117
|
+
if (!baseline)
|
|
118
|
+
return undefined;
|
|
119
|
+
return generateHash(JSON.stringify(baseline));
|
|
120
|
+
}
|
|
121
|
+
export async function captureSnapshot(context, options = {}) {
|
|
122
|
+
const { files, baseline, scanResults, suppressions, gitRef } = context;
|
|
123
|
+
const violations = baseline
|
|
124
|
+
? baseline.baseline_snapshot.violations.map(baselineViolationToSnapshot)
|
|
125
|
+
: [];
|
|
126
|
+
const antipatterns = extractAntiPatterns(scanResults);
|
|
127
|
+
const snapshotSuppressions = extractSuppressions(suppressions);
|
|
128
|
+
const metrics = calculateMetrics(violations, antipatterns, snapshotSuppressions, files.length);
|
|
129
|
+
const breakdown = calculateAntiPatternBreakdown(antipatterns);
|
|
130
|
+
const hotspots = calculateHotspots(violations, antipatterns);
|
|
131
|
+
return {
|
|
132
|
+
schema_version: SNAPSHOT_SCHEMA_VERSION,
|
|
133
|
+
created_at: new Date().toISOString(),
|
|
134
|
+
name: options.name,
|
|
135
|
+
metrics,
|
|
136
|
+
antipattern_breakdown: Object.keys(breakdown).length > 0 ? breakdown : undefined,
|
|
137
|
+
hotspots: hotspots.length > 0 ? hotspots : undefined,
|
|
138
|
+
violations,
|
|
139
|
+
antipatterns,
|
|
140
|
+
suppressions: snapshotSuppressions,
|
|
141
|
+
baseline_hash: generateBaselineHash(baseline),
|
|
142
|
+
git_ref: gitRef,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export class SnapshotCaptureService {
|
|
146
|
+
workspaceRoot;
|
|
147
|
+
constructor(workspaceRoot) {
|
|
148
|
+
this.workspaceRoot = workspaceRoot;
|
|
149
|
+
}
|
|
150
|
+
async capture(files, options = {}) {
|
|
151
|
+
const baseline = loadBaseline(this.workspaceRoot);
|
|
152
|
+
const filesWithContent = await Promise.all(files.map(async (filePath) => {
|
|
153
|
+
const fullPath = path.isAbsolute(filePath)
|
|
154
|
+
? filePath
|
|
155
|
+
: path.join(this.workspaceRoot, filePath);
|
|
156
|
+
try {
|
|
157
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
158
|
+
return { path: filePath, content };
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
debug('failed to read file for snapshot capture: %s', err);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}));
|
|
165
|
+
const validFiles = filesWithContent.filter((f) => f !== null);
|
|
166
|
+
const scanResults = scanFiles(validFiles, { includeOptIn: options.includeOptInPatterns });
|
|
167
|
+
const suppressionService = new SuppressionService(this.workspaceRoot);
|
|
168
|
+
await suppressionService.initialize();
|
|
169
|
+
const suppressions = await suppressionService.processFiles(files);
|
|
170
|
+
const gitRef = await getGitRef(this.workspaceRoot);
|
|
171
|
+
const context = {
|
|
172
|
+
workspaceRoot: this.workspaceRoot,
|
|
173
|
+
files,
|
|
174
|
+
baseline,
|
|
175
|
+
scanResults,
|
|
176
|
+
suppressions,
|
|
177
|
+
gitRef,
|
|
178
|
+
};
|
|
179
|
+
return captureSnapshot(context, options);
|
|
180
|
+
}
|
|
181
|
+
async captureWithContext(context, options = {}) {
|
|
182
|
+
const fullContext = {
|
|
183
|
+
workspaceRoot: context.workspaceRoot ?? this.workspaceRoot,
|
|
184
|
+
files: context.files ?? [],
|
|
185
|
+
baseline: context.baseline ?? null,
|
|
186
|
+
scanResults: context.scanResults ?? [],
|
|
187
|
+
suppressions: context.suppressions ?? [],
|
|
188
|
+
gitRef: context.gitRef,
|
|
189
|
+
};
|
|
190
|
+
return captureSnapshot(fullContext, options);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export function createSnapshotCaptureService(workspaceRoot) {
|
|
194
|
+
return new SnapshotCaptureService(workspaceRoot);
|
|
195
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DriftSnapshot, SnapshotViolation, SnapshotAntiPattern, SnapshotSuppression } from './snapshot-schema.js';
|
|
2
|
+
export interface ItemChange<T> {
|
|
3
|
+
added: T[];
|
|
4
|
+
removed: T[];
|
|
5
|
+
unchanged: T[];
|
|
6
|
+
}
|
|
7
|
+
export interface MetricChange {
|
|
8
|
+
before: number;
|
|
9
|
+
after: number;
|
|
10
|
+
delta: number;
|
|
11
|
+
trend: 'increasing' | 'decreasing' | 'stable';
|
|
12
|
+
}
|
|
13
|
+
export interface MetricsComparison {
|
|
14
|
+
boundary_violations: MetricChange;
|
|
15
|
+
antipattern_count: MetricChange;
|
|
16
|
+
suppression_count: MetricChange;
|
|
17
|
+
expired_suppressions: MetricChange;
|
|
18
|
+
files_analysed: MetricChange;
|
|
19
|
+
}
|
|
20
|
+
export interface AntiPatternChange {
|
|
21
|
+
id: string;
|
|
22
|
+
before: number;
|
|
23
|
+
after: number;
|
|
24
|
+
delta: number;
|
|
25
|
+
}
|
|
26
|
+
export interface SnapshotComparison {
|
|
27
|
+
before: {
|
|
28
|
+
name?: string;
|
|
29
|
+
created_at: string;
|
|
30
|
+
};
|
|
31
|
+
after: {
|
|
32
|
+
name?: string;
|
|
33
|
+
created_at: string;
|
|
34
|
+
};
|
|
35
|
+
duration_days: number;
|
|
36
|
+
metrics: MetricsComparison;
|
|
37
|
+
net_change: {
|
|
38
|
+
violations: number;
|
|
39
|
+
antipatterns: number;
|
|
40
|
+
suppressions: number;
|
|
41
|
+
};
|
|
42
|
+
violations: ItemChange<SnapshotViolation>;
|
|
43
|
+
antipatterns: ItemChange<SnapshotAntiPattern>;
|
|
44
|
+
suppressions: ItemChange<SnapshotSuppression>;
|
|
45
|
+
antipattern_changes: AntiPatternChange[];
|
|
46
|
+
overall_trend: 'improving' | 'stable' | 'degrading';
|
|
47
|
+
}
|
|
48
|
+
export declare function compareSnapshots(before: DriftSnapshot, after: DriftSnapshot): SnapshotComparison;
|
|
49
|
+
export declare function formatComparisonSummary(comparison: SnapshotComparison): string;
|
|
50
|
+
//# sourceMappingURL=snapshot-compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-compare.d.ts","sourceRoot":"","sources":["../../src/drift/snapshot-compare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,sBAAsB,CAAC;AAK9B,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,SAAS,EAAE,CAAC,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,EAAE,YAAY,CAAC;IAClC,iBAAiB,EAAE,YAAY,CAAC;IAChC,iBAAiB,EAAE,YAAY,CAAC;IAChC,oBAAoB,EAAE,YAAY,CAAC;IACnC,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,aAAa,EAAE,MAAM,CAAC;IAEtB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,UAAU,EAAE;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IAEF,UAAU,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC1C,YAAY,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAC9C,YAAY,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAE9C,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;IAEzC,aAAa,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;CACrD;AA0HD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,kBAAkB,CAqChG;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAoC9E"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createDebugger } from '../utils/debug.js';
|
|
2
|
+
const debug = createDebugger('drift');
|
|
3
|
+
function calculateMetricChange(before, after) {
|
|
4
|
+
const delta = after - before;
|
|
5
|
+
let trend;
|
|
6
|
+
if (delta > 0) {
|
|
7
|
+
trend = 'increasing';
|
|
8
|
+
}
|
|
9
|
+
else if (delta < 0) {
|
|
10
|
+
trend = 'decreasing';
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
trend = 'stable';
|
|
14
|
+
}
|
|
15
|
+
return { before, after, delta, trend };
|
|
16
|
+
}
|
|
17
|
+
function compareMetrics(before, after) {
|
|
18
|
+
return {
|
|
19
|
+
boundary_violations: calculateMetricChange(before.boundary_violations, after.boundary_violations),
|
|
20
|
+
antipattern_count: calculateMetricChange(before.antipattern_count, after.antipattern_count),
|
|
21
|
+
suppression_count: calculateMetricChange(before.suppression_count, after.suppression_count),
|
|
22
|
+
expired_suppressions: calculateMetricChange(before.expired_suppressions, after.expired_suppressions),
|
|
23
|
+
files_analysed: calculateMetricChange(before.files_analysed, after.files_analysed),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function compareViolations(before, after) {
|
|
27
|
+
const beforeIds = new Set(before.map((v) => v.id));
|
|
28
|
+
const afterIds = new Set(after.map((v) => v.id));
|
|
29
|
+
const added = after.filter((v) => !beforeIds.has(v.id));
|
|
30
|
+
const removed = before.filter((v) => !afterIds.has(v.id));
|
|
31
|
+
const unchanged = after.filter((v) => beforeIds.has(v.id));
|
|
32
|
+
return { added, removed, unchanged };
|
|
33
|
+
}
|
|
34
|
+
function compareAntiPatterns(before, after) {
|
|
35
|
+
const fingerprint = (ap) => `${ap.file}:${ap.line}:${ap.id}`;
|
|
36
|
+
const beforeFingerprints = new Set(before.map(fingerprint));
|
|
37
|
+
const afterFingerprints = new Set(after.map(fingerprint));
|
|
38
|
+
const added = after.filter((ap) => !beforeFingerprints.has(fingerprint(ap)));
|
|
39
|
+
const removed = before.filter((ap) => !afterFingerprints.has(fingerprint(ap)));
|
|
40
|
+
const unchanged = after.filter((ap) => beforeFingerprints.has(fingerprint(ap)));
|
|
41
|
+
return { added, removed, unchanged };
|
|
42
|
+
}
|
|
43
|
+
function compareSuppressions(before, after) {
|
|
44
|
+
const beforeIds = new Set(before.map((s) => s.id));
|
|
45
|
+
const afterIds = new Set(after.map((s) => s.id));
|
|
46
|
+
const added = after.filter((s) => !beforeIds.has(s.id));
|
|
47
|
+
const removed = before.filter((s) => !afterIds.has(s.id));
|
|
48
|
+
const unchanged = after.filter((s) => beforeIds.has(s.id));
|
|
49
|
+
return { added, removed, unchanged };
|
|
50
|
+
}
|
|
51
|
+
function calculateAntiPatternChanges(before, after) {
|
|
52
|
+
const beforeBreakdown = before.antipattern_breakdown ?? {};
|
|
53
|
+
const afterBreakdown = after.antipattern_breakdown ?? {};
|
|
54
|
+
const allIds = new Set([...Object.keys(beforeBreakdown), ...Object.keys(afterBreakdown)]);
|
|
55
|
+
const changes = [];
|
|
56
|
+
for (const id of allIds) {
|
|
57
|
+
const beforeCount = beforeBreakdown[id] ?? 0;
|
|
58
|
+
const afterCount = afterBreakdown[id] ?? 0;
|
|
59
|
+
const delta = afterCount - beforeCount;
|
|
60
|
+
if (delta !== 0) {
|
|
61
|
+
changes.push({ id, before: beforeCount, after: afterCount, delta });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return changes.sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));
|
|
65
|
+
}
|
|
66
|
+
function calculateDurationDays(before, after) {
|
|
67
|
+
const beforeDate = new Date(before);
|
|
68
|
+
const afterDate = new Date(after);
|
|
69
|
+
const diffMs = afterDate.getTime() - beforeDate.getTime();
|
|
70
|
+
return Math.round(diffMs / (1000 * 60 * 60 * 24));
|
|
71
|
+
}
|
|
72
|
+
function determineOverallTrend(metrics) {
|
|
73
|
+
const violationsTrend = metrics.boundary_violations.delta;
|
|
74
|
+
const antipatternsTrend = metrics.antipattern_count.delta;
|
|
75
|
+
const totalChange = violationsTrend + antipatternsTrend;
|
|
76
|
+
if (totalChange < 0) {
|
|
77
|
+
return 'improving';
|
|
78
|
+
}
|
|
79
|
+
else if (totalChange > 0) {
|
|
80
|
+
return 'degrading';
|
|
81
|
+
}
|
|
82
|
+
return 'stable';
|
|
83
|
+
}
|
|
84
|
+
export function compareSnapshots(before, after) {
|
|
85
|
+
debug('comparing snapshots', {
|
|
86
|
+
before: before.name ?? before.created_at,
|
|
87
|
+
after: after.name ?? after.created_at,
|
|
88
|
+
});
|
|
89
|
+
const metrics = compareMetrics(before.metrics, after.metrics);
|
|
90
|
+
const violations = compareViolations(before.violations, after.violations);
|
|
91
|
+
const antipatterns = compareAntiPatterns(before.antipatterns, after.antipatterns);
|
|
92
|
+
const suppressions = compareSuppressions(before.suppressions, after.suppressions);
|
|
93
|
+
const antipatternChanges = calculateAntiPatternChanges(before, after);
|
|
94
|
+
return {
|
|
95
|
+
before: {
|
|
96
|
+
name: before.name,
|
|
97
|
+
created_at: before.created_at,
|
|
98
|
+
},
|
|
99
|
+
after: {
|
|
100
|
+
name: after.name,
|
|
101
|
+
created_at: after.created_at,
|
|
102
|
+
},
|
|
103
|
+
duration_days: calculateDurationDays(before.created_at, after.created_at),
|
|
104
|
+
metrics,
|
|
105
|
+
net_change: {
|
|
106
|
+
violations: violations.added.length - violations.removed.length,
|
|
107
|
+
antipatterns: antipatterns.added.length - antipatterns.removed.length,
|
|
108
|
+
suppressions: suppressions.added.length - suppressions.removed.length,
|
|
109
|
+
},
|
|
110
|
+
violations,
|
|
111
|
+
antipatterns,
|
|
112
|
+
suppressions,
|
|
113
|
+
antipattern_changes: antipatternChanges,
|
|
114
|
+
overall_trend: determineOverallTrend(metrics),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function formatComparisonSummary(comparison) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
const beforeName = comparison.before.name ?? comparison.before.created_at.split('T')[0];
|
|
120
|
+
const afterName = comparison.after.name ?? comparison.after.created_at.split('T')[0];
|
|
121
|
+
lines.push(`Comparing: ${beforeName} → ${afterName} (${comparison.duration_days} days)`);
|
|
122
|
+
lines.push('');
|
|
123
|
+
lines.push('Metrics:');
|
|
124
|
+
lines.push(` Boundary violations: ${comparison.metrics.boundary_violations.before} → ${comparison.metrics.boundary_violations.after} (${formatDelta(comparison.metrics.boundary_violations.delta)})`);
|
|
125
|
+
lines.push(` Anti-patterns: ${comparison.metrics.antipattern_count.before} → ${comparison.metrics.antipattern_count.after} (${formatDelta(comparison.metrics.antipattern_count.delta)})`);
|
|
126
|
+
lines.push(` Suppressions: ${comparison.metrics.suppression_count.before} → ${comparison.metrics.suppression_count.after} (${formatDelta(comparison.metrics.suppression_count.delta)})`);
|
|
127
|
+
lines.push('');
|
|
128
|
+
lines.push('Changes:');
|
|
129
|
+
lines.push(` Violations: +${comparison.violations.added.length} added, -${comparison.violations.removed.length} removed`);
|
|
130
|
+
lines.push(` Anti-patterns: +${comparison.antipatterns.added.length} added, -${comparison.antipatterns.removed.length} removed`);
|
|
131
|
+
lines.push(` Suppressions: +${comparison.suppressions.added.length} added, -${comparison.suppressions.removed.length} removed`);
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push(`Overall trend: ${comparison.overall_trend.toUpperCase()}`);
|
|
134
|
+
return lines.join('\n');
|
|
135
|
+
}
|
|
136
|
+
function formatDelta(delta) {
|
|
137
|
+
if (delta > 0)
|
|
138
|
+
return `+${delta}`;
|
|
139
|
+
if (delta < 0)
|
|
140
|
+
return `${delta}`;
|
|
141
|
+
return '0';
|
|
142
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drift snapshot schema
|
|
3
|
+
*
|
|
4
|
+
* Defines the structure for point-in-time drift snapshots used to track
|
|
5
|
+
* architecture evolution over time. Follows Zod-first approach per ADR-0001.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export declare const SNAPSHOT_SCHEMA_VERSION = "1.0.0";
|
|
9
|
+
/**
|
|
10
|
+
* A recorded boundary violation in the snapshot
|
|
11
|
+
*/
|
|
12
|
+
export declare const SnapshotViolationSchema: z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
type: z.ZodEnum<{
|
|
15
|
+
boundary: "boundary";
|
|
16
|
+
architecture: "architecture";
|
|
17
|
+
}>;
|
|
18
|
+
from_file: z.ZodString;
|
|
19
|
+
to_file: z.ZodString;
|
|
20
|
+
from_layer: z.ZodNullable<z.ZodString>;
|
|
21
|
+
to_layer: z.ZodNullable<z.ZodString>;
|
|
22
|
+
line: z.ZodNumber;
|
|
23
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
24
|
+
message: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
export type SnapshotViolation = z.infer<typeof SnapshotViolationSchema>;
|
|
27
|
+
/**
|
|
28
|
+
* A recorded anti-pattern occurrence in the snapshot
|
|
29
|
+
*/
|
|
30
|
+
export declare const SnapshotAntiPatternSchema: z.ZodObject<{
|
|
31
|
+
id: z.ZodString;
|
|
32
|
+
file: z.ZodString;
|
|
33
|
+
line: z.ZodNumber;
|
|
34
|
+
pattern: z.ZodString;
|
|
35
|
+
severity: z.ZodEnum<{
|
|
36
|
+
warning: "warning";
|
|
37
|
+
error: "error";
|
|
38
|
+
info: "info";
|
|
39
|
+
}>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
export type SnapshotAntiPattern = z.infer<typeof SnapshotAntiPatternSchema>;
|
|
42
|
+
/**
|
|
43
|
+
* A recorded suppression in the snapshot
|
|
44
|
+
*/
|
|
45
|
+
export declare const SnapshotSuppressionSchema: z.ZodObject<{
|
|
46
|
+
id: z.ZodString;
|
|
47
|
+
pattern_id: z.ZodString;
|
|
48
|
+
file: z.ZodString;
|
|
49
|
+
line: z.ZodNumber;
|
|
50
|
+
reason: z.ZodString;
|
|
51
|
+
scope: z.ZodEnum<{
|
|
52
|
+
file: "file";
|
|
53
|
+
line: "line";
|
|
54
|
+
statement: "statement";
|
|
55
|
+
import: "import";
|
|
56
|
+
}>;
|
|
57
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
58
|
+
is_expired: z.ZodOptional<z.ZodBoolean>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
export type SnapshotSuppression = z.infer<typeof SnapshotSuppressionSchema>;
|
|
61
|
+
/**
|
|
62
|
+
* Aggregate metrics for quick comparison
|
|
63
|
+
*/
|
|
64
|
+
export declare const SnapshotMetricsSchema: z.ZodObject<{
|
|
65
|
+
boundary_violations: z.ZodNumber;
|
|
66
|
+
antipattern_count: z.ZodNumber;
|
|
67
|
+
suppression_count: z.ZodNumber;
|
|
68
|
+
expired_suppressions: z.ZodNumber;
|
|
69
|
+
files_analysed: z.ZodNumber;
|
|
70
|
+
}, z.core.$strip>;
|
|
71
|
+
export type SnapshotMetrics = z.infer<typeof SnapshotMetricsSchema>;
|
|
72
|
+
/**
|
|
73
|
+
* Breakdown of anti-patterns by type
|
|
74
|
+
*/
|
|
75
|
+
export declare const AntiPatternBreakdownSchema: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
76
|
+
export type AntiPatternBreakdown = z.infer<typeof AntiPatternBreakdownSchema>;
|
|
77
|
+
/**
|
|
78
|
+
* A file or directory with high violation concentration
|
|
79
|
+
*/
|
|
80
|
+
export declare const HotspotSchema: z.ZodObject<{
|
|
81
|
+
path: z.ZodString;
|
|
82
|
+
violation_count: z.ZodNumber;
|
|
83
|
+
types: z.ZodArray<z.ZodString>;
|
|
84
|
+
}, z.core.$strip>;
|
|
85
|
+
export type Hotspot = z.infer<typeof HotspotSchema>;
|
|
86
|
+
/**
|
|
87
|
+
* Complete drift snapshot for point-in-time state capture
|
|
88
|
+
*/
|
|
89
|
+
export declare const DriftSnapshotSchema: z.ZodObject<{
|
|
90
|
+
schema_version: z.ZodString;
|
|
91
|
+
created_at: z.ZodString;
|
|
92
|
+
name: z.ZodOptional<z.ZodString>;
|
|
93
|
+
metrics: z.ZodObject<{
|
|
94
|
+
boundary_violations: z.ZodNumber;
|
|
95
|
+
antipattern_count: z.ZodNumber;
|
|
96
|
+
suppression_count: z.ZodNumber;
|
|
97
|
+
expired_suppressions: z.ZodNumber;
|
|
98
|
+
files_analysed: z.ZodNumber;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
antipattern_breakdown: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
101
|
+
hotspots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
102
|
+
path: z.ZodString;
|
|
103
|
+
violation_count: z.ZodNumber;
|
|
104
|
+
types: z.ZodArray<z.ZodString>;
|
|
105
|
+
}, z.core.$strip>>>;
|
|
106
|
+
violations: z.ZodArray<z.ZodObject<{
|
|
107
|
+
id: z.ZodString;
|
|
108
|
+
type: z.ZodEnum<{
|
|
109
|
+
boundary: "boundary";
|
|
110
|
+
architecture: "architecture";
|
|
111
|
+
}>;
|
|
112
|
+
from_file: z.ZodString;
|
|
113
|
+
to_file: z.ZodString;
|
|
114
|
+
from_layer: z.ZodNullable<z.ZodString>;
|
|
115
|
+
to_layer: z.ZodNullable<z.ZodString>;
|
|
116
|
+
line: z.ZodNumber;
|
|
117
|
+
rule: z.ZodOptional<z.ZodString>;
|
|
118
|
+
message: z.ZodOptional<z.ZodString>;
|
|
119
|
+
}, z.core.$strip>>;
|
|
120
|
+
antipatterns: z.ZodArray<z.ZodObject<{
|
|
121
|
+
id: z.ZodString;
|
|
122
|
+
file: z.ZodString;
|
|
123
|
+
line: z.ZodNumber;
|
|
124
|
+
pattern: z.ZodString;
|
|
125
|
+
severity: z.ZodEnum<{
|
|
126
|
+
warning: "warning";
|
|
127
|
+
error: "error";
|
|
128
|
+
info: "info";
|
|
129
|
+
}>;
|
|
130
|
+
}, z.core.$strip>>;
|
|
131
|
+
suppressions: z.ZodArray<z.ZodObject<{
|
|
132
|
+
id: z.ZodString;
|
|
133
|
+
pattern_id: z.ZodString;
|
|
134
|
+
file: z.ZodString;
|
|
135
|
+
line: z.ZodNumber;
|
|
136
|
+
reason: z.ZodString;
|
|
137
|
+
scope: z.ZodEnum<{
|
|
138
|
+
file: "file";
|
|
139
|
+
line: "line";
|
|
140
|
+
statement: "statement";
|
|
141
|
+
import: "import";
|
|
142
|
+
}>;
|
|
143
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
144
|
+
is_expired: z.ZodOptional<z.ZodBoolean>;
|
|
145
|
+
}, z.core.$strip>>;
|
|
146
|
+
baseline_hash: z.ZodOptional<z.ZodString>;
|
|
147
|
+
git_ref: z.ZodOptional<z.ZodString>;
|
|
148
|
+
}, z.core.$strip>;
|
|
149
|
+
export type DriftSnapshot = z.infer<typeof DriftSnapshotSchema>;
|
|
150
|
+
/**
|
|
151
|
+
* Metadata for listing snapshots
|
|
152
|
+
*/
|
|
153
|
+
export declare const SnapshotMetadataSchema: z.ZodObject<{
|
|
154
|
+
filename: z.ZodString;
|
|
155
|
+
name: z.ZodOptional<z.ZodString>;
|
|
156
|
+
created_at: z.ZodString;
|
|
157
|
+
metrics: z.ZodObject<{
|
|
158
|
+
boundary_violations: z.ZodNumber;
|
|
159
|
+
antipattern_count: z.ZodNumber;
|
|
160
|
+
suppression_count: z.ZodNumber;
|
|
161
|
+
expired_suppressions: z.ZodNumber;
|
|
162
|
+
files_analysed: z.ZodNumber;
|
|
163
|
+
}, z.core.$strip>;
|
|
164
|
+
}, z.core.$strip>;
|
|
165
|
+
export type SnapshotMetadata = z.infer<typeof SnapshotMetadataSchema>;
|
|
166
|
+
/**
|
|
167
|
+
* Generate a snapshot filename from timestamp
|
|
168
|
+
*/
|
|
169
|
+
export declare function generateSnapshotFilename(date?: Date): string;
|
|
170
|
+
/**
|
|
171
|
+
* Generate a snapshot filename from a custom name
|
|
172
|
+
*/
|
|
173
|
+
export declare function generateNamedSnapshotFilename(name: string): string;
|
|
174
|
+
/**
|
|
175
|
+
* Parse snapshot name from filename
|
|
176
|
+
*/
|
|
177
|
+
export declare function parseSnapshotFilename(filename: string): {
|
|
178
|
+
isNamed: boolean;
|
|
179
|
+
nameOrTimestamp: string;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Create an empty snapshot with default values
|
|
183
|
+
*/
|
|
184
|
+
export declare function createEmptySnapshot(options?: {
|
|
185
|
+
name?: string;
|
|
186
|
+
baselineHash?: string;
|
|
187
|
+
gitRef?: string;
|
|
188
|
+
}): DriftSnapshot;
|
|
189
|
+
/**
|
|
190
|
+
* Validate a snapshot against the schema
|
|
191
|
+
*/
|
|
192
|
+
export declare function validateSnapshot(data: unknown): {
|
|
193
|
+
success: boolean;
|
|
194
|
+
data?: DriftSnapshot;
|
|
195
|
+
error?: string;
|
|
196
|
+
};
|
|
197
|
+
//# sourceMappingURL=snapshot-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-schema.d.ts","sourceRoot":"","sources":["../../src/drift/snapshot-schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAM/C;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;iBAUlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAMxE;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;iBAMpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAM5E;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBASpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAM5E;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;iBAMhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMpE;;GAEG;AACH,eAAO,MAAM,0BAA0B,uCAE4C,CAAC;AAEpF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAM9E;;GAEG;AACH,eAAO,MAAM,aAAa;;;;iBAIxB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAMpD;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2B9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAMhE;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;iBAKjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAMtE;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,IAAiB,GAAG,MAAM,CAGxE;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB,CAcA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,aAAa,CAkBhB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAMA"}
|