@behavioral-contracts/verify-cli 1.0.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.
Files changed (80) hide show
  1. package/LICENSE +119 -0
  2. package/README.md +694 -0
  3. package/dist/analyze-results.js +253 -0
  4. package/dist/analyzer.d.ts +366 -0
  5. package/dist/analyzer.d.ts.map +1 -0
  6. package/dist/analyzer.js +2592 -0
  7. package/dist/analyzer.js.map +1 -0
  8. package/dist/analyzers/async-error-analyzer.d.ts +72 -0
  9. package/dist/analyzers/async-error-analyzer.d.ts.map +1 -0
  10. package/dist/analyzers/async-error-analyzer.js +243 -0
  11. package/dist/analyzers/async-error-analyzer.js.map +1 -0
  12. package/dist/analyzers/event-listener-analyzer.d.ts +102 -0
  13. package/dist/analyzers/event-listener-analyzer.d.ts.map +1 -0
  14. package/dist/analyzers/event-listener-analyzer.js +253 -0
  15. package/dist/analyzers/event-listener-analyzer.js.map +1 -0
  16. package/dist/analyzers/react-query-analyzer.d.ts +66 -0
  17. package/dist/analyzers/react-query-analyzer.d.ts.map +1 -0
  18. package/dist/analyzers/react-query-analyzer.js +341 -0
  19. package/dist/analyzers/react-query-analyzer.js.map +1 -0
  20. package/dist/analyzers/return-value-analyzer.d.ts +61 -0
  21. package/dist/analyzers/return-value-analyzer.d.ts.map +1 -0
  22. package/dist/analyzers/return-value-analyzer.js +225 -0
  23. package/dist/analyzers/return-value-analyzer.js.map +1 -0
  24. package/dist/code-snippet.d.ts +48 -0
  25. package/dist/code-snippet.d.ts.map +1 -0
  26. package/dist/code-snippet.js +84 -0
  27. package/dist/code-snippet.js.map +1 -0
  28. package/dist/corpus-loader.d.ts +33 -0
  29. package/dist/corpus-loader.d.ts.map +1 -0
  30. package/dist/corpus-loader.js +155 -0
  31. package/dist/corpus-loader.js.map +1 -0
  32. package/dist/fixture-tester.d.ts +28 -0
  33. package/dist/fixture-tester.d.ts.map +1 -0
  34. package/dist/fixture-tester.js +176 -0
  35. package/dist/fixture-tester.js.map +1 -0
  36. package/dist/index.d.ts +6 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +375 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/package-discovery.d.ts +62 -0
  41. package/dist/package-discovery.d.ts.map +1 -0
  42. package/dist/package-discovery.js +299 -0
  43. package/dist/package-discovery.js.map +1 -0
  44. package/dist/reporter.d.ts +43 -0
  45. package/dist/reporter.d.ts.map +1 -0
  46. package/dist/reporter.js +347 -0
  47. package/dist/reporter.js.map +1 -0
  48. package/dist/reporters/benchmarking.d.ts +70 -0
  49. package/dist/reporters/benchmarking.d.ts.map +1 -0
  50. package/dist/reporters/benchmarking.js +191 -0
  51. package/dist/reporters/benchmarking.js.map +1 -0
  52. package/dist/reporters/d3-visualizer.d.ts +40 -0
  53. package/dist/reporters/d3-visualizer.d.ts.map +1 -0
  54. package/dist/reporters/d3-visualizer.js +803 -0
  55. package/dist/reporters/d3-visualizer.js.map +1 -0
  56. package/dist/reporters/health-score.d.ts +33 -0
  57. package/dist/reporters/health-score.d.ts.map +1 -0
  58. package/dist/reporters/health-score.js +149 -0
  59. package/dist/reporters/health-score.js.map +1 -0
  60. package/dist/reporters/index.d.ts +11 -0
  61. package/dist/reporters/index.d.ts.map +1 -0
  62. package/dist/reporters/index.js +11 -0
  63. package/dist/reporters/index.js.map +1 -0
  64. package/dist/reporters/package-breakdown.d.ts +48 -0
  65. package/dist/reporters/package-breakdown.d.ts.map +1 -0
  66. package/dist/reporters/package-breakdown.js +185 -0
  67. package/dist/reporters/package-breakdown.js.map +1 -0
  68. package/dist/reporters/positive-evidence.d.ts +42 -0
  69. package/dist/reporters/positive-evidence.d.ts.map +1 -0
  70. package/dist/reporters/positive-evidence.js +436 -0
  71. package/dist/reporters/positive-evidence.js.map +1 -0
  72. package/dist/tsconfig-generator.d.ts +17 -0
  73. package/dist/tsconfig-generator.d.ts.map +1 -0
  74. package/dist/tsconfig-generator.js +107 -0
  75. package/dist/tsconfig-generator.js.map +1 -0
  76. package/dist/types.d.ts +298 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +5 -0
  79. package/dist/types.js.map +1 -0
  80. package/package.json +59 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-query-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/react-query-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Return Value Analyzer
3
+ * Detects unprotected error checks on function return values
4
+ *
5
+ * This analyzer tracks:
6
+ * 1. Variable assignments from contract functions
7
+ * 2. Error checks on those return values (null, false, error properties)
8
+ * 3. Whether those checks are protected by try-catch
9
+ *
10
+ * Related: dev-notes/analyzer-enhancement/RETURN_VALUE_RESEARCH.md
11
+ */
12
+ import * as ts from 'typescript';
13
+ import type { PackageContract, Postcondition } from '../types.js';
14
+ export interface ReturnValueCheck {
15
+ /** Variable name holding the return value */
16
+ variableName: string;
17
+ /** Package the function belongs to */
18
+ packageName: string;
19
+ /** Function name that returned the value */
20
+ functionName: string;
21
+ /** Postcondition that requires error handling */
22
+ postcondition: Postcondition;
23
+ /** AST node where variable was declared */
24
+ declarationNode: ts.Node;
25
+ /** AST node where error check occurs (if any) */
26
+ checkNode?: ts.Node;
27
+ /** Whether the error check is protected by try-catch */
28
+ isProtected: boolean;
29
+ }
30
+ export declare class ReturnValueAnalyzer {
31
+ private sourceFile;
32
+ private contracts;
33
+ private trackedReturnValues;
34
+ constructor(sourceFile: ts.SourceFile, contracts: Map<string, PackageContract>, _typeChecker: ts.TypeChecker);
35
+ /**
36
+ * Analyzes a function scope for unprotected return value checks
37
+ */
38
+ analyze(functionNode: ts.Node): ReturnValueCheck[];
39
+ /**
40
+ * Finds variable declarations that assign return values from contract functions
41
+ */
42
+ private findReturnValueDeclarations;
43
+ /**
44
+ * Extracts contract function information from a call expression
45
+ */
46
+ private extractContractFunctionCall;
47
+ /**
48
+ * Finds error check on a tracked return value
49
+ * Looks for patterns like: if (!result), if (result.error), if (!result.success)
50
+ */
51
+ private findErrorCheck;
52
+ /**
53
+ * Checks if a node is protected by try-catch
54
+ */
55
+ private isNodeProtected;
56
+ /**
57
+ * Checks if child is a descendant of parent node
58
+ */
59
+ private isDescendantOf;
60
+ }
61
+ //# sourceMappingURL=return-value-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-value-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/return-value-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,aAAa,EAAE,aAAa,CAAC;IAC7B,2CAA2C;IAC3C,eAAe,EAAE,EAAE,CAAC,IAAI,CAAC;IACzB,iDAAiD;IACjD,SAAS,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;IACpB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,SAAS,CAA+B;IAIhD,OAAO,CAAC,mBAAmB,CAKZ;gBAGb,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,YAAY,EAAE,EAAE,CAAC,WAAW;IAO9B;;OAEG;IACH,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,GAAG,gBAAgB,EAAE;IA6ClD;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAwBnC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAuDnC;;;OAGG;IACH,OAAO,CAAC,cAAc;IA6DtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,cAAc;CAYvB"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Return Value Analyzer
3
+ * Detects unprotected error checks on function return values
4
+ *
5
+ * This analyzer tracks:
6
+ * 1. Variable assignments from contract functions
7
+ * 2. Error checks on those return values (null, false, error properties)
8
+ * 3. Whether those checks are protected by try-catch
9
+ *
10
+ * Related: dev-notes/analyzer-enhancement/RETURN_VALUE_RESEARCH.md
11
+ */
12
+ import * as ts from 'typescript';
13
+ export class ReturnValueAnalyzer {
14
+ sourceFile;
15
+ contracts;
16
+ // private typeChecker: ts.TypeChecker; // Reserved for future type-aware detection
17
+ // Track return values that need error checking
18
+ trackedReturnValues = new Map();
19
+ constructor(sourceFile, contracts, _typeChecker // Reserved for future type-aware detection
20
+ ) {
21
+ this.sourceFile = sourceFile;
22
+ this.contracts = contracts;
23
+ // this.typeChecker = typeChecker; // Reserved for future type-aware detection
24
+ }
25
+ /**
26
+ * Analyzes a function scope for unprotected return value checks
27
+ */
28
+ analyze(functionNode) {
29
+ const violations = [];
30
+ // Step 1: Find all variable declarations from contract functions
31
+ this.findReturnValueDeclarations(functionNode);
32
+ // Step 2: For each tracked return value, find error checks
33
+ for (const [varName, info] of this.trackedReturnValues.entries()) {
34
+ const errorCheck = this.findErrorCheck(varName, functionNode);
35
+ if (!errorCheck) {
36
+ // No error check found - violation
37
+ violations.push({
38
+ variableName: varName,
39
+ packageName: info.packageName,
40
+ functionName: info.functionName,
41
+ postcondition: info.postcondition,
42
+ declarationNode: info.declarationNode,
43
+ isProtected: false,
44
+ });
45
+ }
46
+ else {
47
+ // Error check found - verify it's in try-catch
48
+ const isProtected = this.isNodeProtected(errorCheck, functionNode);
49
+ if (!isProtected) {
50
+ // Error check exists but not in try-catch - violation
51
+ violations.push({
52
+ variableName: varName,
53
+ packageName: info.packageName,
54
+ functionName: info.functionName,
55
+ postcondition: info.postcondition,
56
+ declarationNode: info.declarationNode,
57
+ checkNode: errorCheck,
58
+ isProtected: false,
59
+ });
60
+ }
61
+ }
62
+ }
63
+ // Clear for next function
64
+ this.trackedReturnValues.clear();
65
+ return violations;
66
+ }
67
+ /**
68
+ * Finds variable declarations that assign return values from contract functions
69
+ */
70
+ findReturnValueDeclarations(scope) {
71
+ const visit = (node) => {
72
+ // Pattern: const result = validator.normalizeEmail(email)
73
+ if (ts.isVariableDeclaration(node) && node.initializer) {
74
+ const callInfo = this.extractContractFunctionCall(node.initializer);
75
+ if (callInfo) {
76
+ const varName = node.name.getText(this.sourceFile);
77
+ this.trackedReturnValues.set(varName, {
78
+ packageName: callInfo.packageName,
79
+ functionName: callInfo.functionName,
80
+ postcondition: callInfo.postcondition,
81
+ declarationNode: node,
82
+ });
83
+ }
84
+ }
85
+ // Continue visiting children
86
+ ts.forEachChild(node, visit);
87
+ };
88
+ visit(scope);
89
+ }
90
+ /**
91
+ * Extracts contract function information from a call expression
92
+ */
93
+ extractContractFunctionCall(node) {
94
+ if (!ts.isCallExpression(node)) {
95
+ return null;
96
+ }
97
+ let functionName = null;
98
+ let objectName = null;
99
+ // Pattern: validator.normalizeEmail(...)
100
+ if (ts.isPropertyAccessExpression(node.expression)) {
101
+ functionName = node.expression.name.text;
102
+ if (ts.isIdentifier(node.expression.expression)) {
103
+ objectName = node.expression.expression.text;
104
+ }
105
+ }
106
+ // Pattern: normalizeEmail(...) - direct call
107
+ if (ts.isIdentifier(node.expression)) {
108
+ functionName = node.expression.text;
109
+ }
110
+ if (!functionName) {
111
+ return null;
112
+ }
113
+ // Check if this function belongs to any contract
114
+ for (const [packageName, contract] of this.contracts.entries()) {
115
+ // Simple heuristic: if objectName matches package name or is similar
116
+ const packageMatches = objectName === packageName ||
117
+ objectName === packageName.split('/').pop() ||
118
+ objectName === packageName.replace(/@/g, '').replace(/\//g, '-');
119
+ if (packageMatches || !objectName) {
120
+ // Check if function exists in contract
121
+ const func = contract.functions?.find(f => f.name === functionName);
122
+ if (func && func.postconditions && func.postconditions.length > 0) {
123
+ return {
124
+ packageName,
125
+ functionName,
126
+ postcondition: func.postconditions[0], // Use first postcondition
127
+ };
128
+ }
129
+ }
130
+ }
131
+ return null;
132
+ }
133
+ /**
134
+ * Finds error check on a tracked return value
135
+ * Looks for patterns like: if (!result), if (result.error), if (!result.success)
136
+ */
137
+ findErrorCheck(varName, scope) {
138
+ let checkNode = null;
139
+ const visit = (node) => {
140
+ // Pattern: if (!result) { ... }
141
+ if (ts.isIfStatement(node)) {
142
+ const condition = node.expression;
143
+ // Check for: !variable
144
+ if (ts.isPrefixUnaryExpression(condition) &&
145
+ condition.operator === ts.SyntaxKind.ExclamationToken &&
146
+ ts.isIdentifier(condition.operand) &&
147
+ condition.operand.text === varName) {
148
+ checkNode = node;
149
+ return;
150
+ }
151
+ // Check for: variable (boolean check)
152
+ if (ts.isIdentifier(condition) && condition.text === varName) {
153
+ checkNode = node;
154
+ return;
155
+ }
156
+ // Check for: !variable.property
157
+ if (ts.isPrefixUnaryExpression(condition) &&
158
+ condition.operator === ts.SyntaxKind.ExclamationToken &&
159
+ ts.isPropertyAccessExpression(condition.operand) &&
160
+ ts.isIdentifier(condition.operand.expression) &&
161
+ condition.operand.expression.text === varName) {
162
+ checkNode = node;
163
+ return;
164
+ }
165
+ // Check for: variable.error or variable.success
166
+ if (ts.isPropertyAccessExpression(condition) &&
167
+ ts.isIdentifier(condition.expression) &&
168
+ condition.expression.text === varName) {
169
+ checkNode = node;
170
+ return;
171
+ }
172
+ }
173
+ // Pattern: result || defaultValue
174
+ if (ts.isBinaryExpression(node) &&
175
+ node.operatorToken.kind === ts.SyntaxKind.BarBarToken &&
176
+ ts.isIdentifier(node.left) &&
177
+ node.left.text === varName) {
178
+ checkNode = node;
179
+ return;
180
+ }
181
+ // Continue searching if not found
182
+ if (!checkNode) {
183
+ ts.forEachChild(node, visit);
184
+ }
185
+ };
186
+ visit(scope);
187
+ return checkNode;
188
+ }
189
+ /**
190
+ * Checks if a node is protected by try-catch
191
+ */
192
+ isNodeProtected(node, functionScope) {
193
+ let current = node;
194
+ // Walk up the AST until we find a try block or reach function boundary
195
+ while (current && current !== functionScope) {
196
+ const parent = current.parent;
197
+ if (!parent) {
198
+ break;
199
+ }
200
+ // Check if we're inside a try block
201
+ if (ts.isTryStatement(parent)) {
202
+ // Check if current node is within the try block (not catch or finally)
203
+ if (parent.tryBlock === current || this.isDescendantOf(node, parent.tryBlock)) {
204
+ return true;
205
+ }
206
+ }
207
+ current = parent;
208
+ }
209
+ return false;
210
+ }
211
+ /**
212
+ * Checks if child is a descendant of parent node
213
+ */
214
+ isDescendantOf(child, parent) {
215
+ let current = child;
216
+ while (current) {
217
+ if (current === parent) {
218
+ return true;
219
+ }
220
+ current = current.parent;
221
+ }
222
+ return false;
223
+ }
224
+ }
225
+ //# sourceMappingURL=return-value-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-value-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/return-value-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Code Snippet Extraction Module
3
+ *
4
+ * Extracts code snippets around violation locations with context lines.
5
+ */
6
+ export interface CodeSnippet {
7
+ lines: CodeLine[];
8
+ startLine: number;
9
+ endLine: number;
10
+ }
11
+ export interface CodeLine {
12
+ lineNumber: number;
13
+ content: string;
14
+ isViolation: boolean;
15
+ }
16
+ /**
17
+ * Extracts a code snippet from a file around a specific line
18
+ *
19
+ * @param filePath - Path to the source file
20
+ * @param violationLine - Line number where the violation occurred
21
+ * @param contextLines - Number of lines to show before and after (default: 4)
22
+ * @returns Code snippet with context
23
+ */
24
+ export declare function extractCodeSnippet(filePath: string, violationLine: number, contextLines?: number): Promise<CodeSnippet | null>;
25
+ /**
26
+ * Formats a code snippet for terminal display
27
+ *
28
+ * @param snippet - Code snippet to format
29
+ * @param maxLineLength - Maximum length of a line (truncate longer lines)
30
+ * @returns Formatted string array
31
+ */
32
+ export declare function formatSnippetForTerminal(snippet: CodeSnippet, maxLineLength?: number): string[];
33
+ /**
34
+ * Formats a code snippet for JSON export
35
+ *
36
+ * @param snippet - Code snippet to format
37
+ * @returns Object suitable for JSON serialization
38
+ */
39
+ export declare function formatSnippetForJSON(snippet: CodeSnippet): {
40
+ startLine: number;
41
+ endLine: number;
42
+ lines: Array<{
43
+ line: number;
44
+ content: string;
45
+ highlighted: boolean;
46
+ }>;
47
+ };
48
+ //# sourceMappingURL=code-snippet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-snippet.d.ts","sourceRoot":"","sources":["../src/code-snippet.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,YAAY,GAAE,MAAU,GACvB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA8B7B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,WAAW,EACpB,aAAa,GAAE,MAAY,GAC1B,MAAM,EAAE,CAmBV;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACvE,CAUA"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Code Snippet Extraction Module
3
+ *
4
+ * Extracts code snippets around violation locations with context lines.
5
+ */
6
+ import * as fs from 'fs/promises';
7
+ /**
8
+ * Extracts a code snippet from a file around a specific line
9
+ *
10
+ * @param filePath - Path to the source file
11
+ * @param violationLine - Line number where the violation occurred
12
+ * @param contextLines - Number of lines to show before and after (default: 4)
13
+ * @returns Code snippet with context
14
+ */
15
+ export async function extractCodeSnippet(filePath, violationLine, contextLines = 4) {
16
+ try {
17
+ // Read the entire file
18
+ const content = await fs.readFile(filePath, 'utf-8');
19
+ const lines = content.split('\n');
20
+ // Calculate range (1-indexed line numbers)
21
+ const startLine = Math.max(1, violationLine - contextLines);
22
+ const endLine = Math.min(lines.length, violationLine + contextLines);
23
+ // Extract lines (convert to 0-indexed for array access)
24
+ const snippetLines = [];
25
+ for (let i = startLine; i <= endLine; i++) {
26
+ const lineContent = lines[i - 1]; // Convert to 0-indexed
27
+ snippetLines.push({
28
+ lineNumber: i,
29
+ content: lineContent,
30
+ isViolation: i === violationLine,
31
+ });
32
+ }
33
+ return {
34
+ lines: snippetLines,
35
+ startLine,
36
+ endLine,
37
+ };
38
+ }
39
+ catch (error) {
40
+ // File might not be accessible, return null
41
+ return null;
42
+ }
43
+ }
44
+ /**
45
+ * Formats a code snippet for terminal display
46
+ *
47
+ * @param snippet - Code snippet to format
48
+ * @param maxLineLength - Maximum length of a line (truncate longer lines)
49
+ * @returns Formatted string array
50
+ */
51
+ export function formatSnippetForTerminal(snippet, maxLineLength = 120) {
52
+ const output = [];
53
+ const maxLineNumWidth = String(snippet.endLine).length;
54
+ for (const line of snippet.lines) {
55
+ const lineNum = String(line.lineNumber).padStart(maxLineNumWidth, ' ');
56
+ let content = line.content;
57
+ // Truncate long lines
58
+ if (content.length > maxLineLength) {
59
+ content = content.substring(0, maxLineLength - 3) + '...';
60
+ }
61
+ // Add line prefix
62
+ const prefix = line.isViolation ? '>' : ' ';
63
+ output.push(`${prefix} ${lineNum} | ${content}`);
64
+ }
65
+ return output;
66
+ }
67
+ /**
68
+ * Formats a code snippet for JSON export
69
+ *
70
+ * @param snippet - Code snippet to format
71
+ * @returns Object suitable for JSON serialization
72
+ */
73
+ export function formatSnippetForJSON(snippet) {
74
+ return {
75
+ startLine: snippet.startLine,
76
+ endLine: snippet.endLine,
77
+ lines: snippet.lines.map(line => ({
78
+ line: line.lineNumber,
79
+ content: line.content,
80
+ highlighted: line.isViolation,
81
+ })),
82
+ };
83
+ }
84
+ //# sourceMappingURL=code-snippet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-snippet.js","sourceRoot":"","sources":["../src/code-snippet.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAclC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,aAAqB,EACrB,eAAuB,CAAC;IAExB,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,2CAA2C;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,CAAC,CAAC;QAErE,wDAAwD;QACxD,MAAM,YAAY,GAAe,EAAE,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB;YACzD,YAAY,CAAC,IAAI,CAAC;gBAChB,UAAU,EAAE,CAAC;gBACb,OAAO,EAAE,WAAW;gBACpB,WAAW,EAAE,CAAC,KAAK,aAAa;aACjC,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,SAAS;YACT,OAAO;SACR,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4CAA4C;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAoB,EACpB,gBAAwB,GAAG;IAE3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAEvD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;QACvE,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAE3B,sBAAsB;QACtB,IAAI,OAAO,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YACnC,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAC5D,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,OAAO,MAAM,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoB;IAKvD,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,IAAI,CAAC,UAAU;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Corpus Loader - loads and validates behavioral contract files
3
+ */
4
+ import type { PackageContract, CorpusLoadResult } from './types.js';
5
+ export interface LoadCorpusOptions {
6
+ includeDrafts?: boolean;
7
+ includeDeprecated?: boolean;
8
+ includeInDevelopment?: boolean;
9
+ }
10
+ /**
11
+ * Loads all behavioral contracts from the corpus directory
12
+ */
13
+ export declare function loadCorpus(corpusPath: string, options?: LoadCorpusOptions): Promise<CorpusLoadResult>;
14
+ /**
15
+ * Loads a single contract file (for testing)
16
+ */
17
+ export declare function loadContractFile(filePath: string): PackageContract;
18
+ /**
19
+ * Validates a contract object against the schema
20
+ */
21
+ export declare function validateContract(contract: PackageContract, schemaPath: string): {
22
+ valid: boolean;
23
+ errors: string[];
24
+ };
25
+ /**
26
+ * Gets the list of packages that have contracts in the corpus
27
+ */
28
+ export declare function getAvailablePackages(corpusPath: string): string[];
29
+ /**
30
+ * Finds which packages from the corpus are actually used in a TypeScript project
31
+ */
32
+ export declare function findUsedPackages(projectPackageJson: string, availableContracts: Map<string, PackageContract>): string[];
33
+ //# sourceMappingURL=corpus-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"corpus-loader.d.ts","sourceRoot":"","sources":["../src/corpus-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKpE,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAyG3B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAGlE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAatC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAWjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/C,MAAM,EAAE,CAeV"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Corpus Loader - loads and validates behavioral contract files
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ import { glob } from 'glob';
7
+ import * as YAML from 'yaml';
8
+ import AjvModule from 'ajv';
9
+ // Handle ESM/CJS interop for Ajv
10
+ const Ajv = AjvModule.default || AjvModule;
11
+ /**
12
+ * Loads all behavioral contracts from the corpus directory
13
+ */
14
+ export async function loadCorpus(corpusPath, options = {}) {
15
+ const contracts = new Map();
16
+ const errors = [];
17
+ const skipped = [];
18
+ // Find all contract.yaml files
19
+ const contractFiles = await glob('**/contract.yaml', {
20
+ cwd: path.join(corpusPath, 'packages'),
21
+ absolute: true,
22
+ });
23
+ if (contractFiles.length === 0) {
24
+ errors.push(`No contract files found in ${corpusPath}/packages`);
25
+ return { contracts, errors };
26
+ }
27
+ // Load JSON Schema for validation
28
+ const schemaPath = path.join(corpusPath, 'schema', 'contract.schema.json');
29
+ let schema;
30
+ try {
31
+ const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
32
+ schema = JSON.parse(schemaContent);
33
+ }
34
+ catch (err) {
35
+ errors.push(`Failed to load schema from ${schemaPath}: ${err}`);
36
+ return { contracts, errors };
37
+ }
38
+ const ajv = new Ajv({ allErrors: true, strict: false });
39
+ const validate = ajv.compile(schema);
40
+ // Load and validate each contract
41
+ for (const filePath of contractFiles) {
42
+ try {
43
+ const content = fs.readFileSync(filePath, 'utf-8');
44
+ const contract = YAML.parse(content);
45
+ // Get contract status (default to 'production' if not specified)
46
+ const status = contract.status || 'production';
47
+ // Skip in-development contracts silently (to avoid errors during development)
48
+ if (status === 'in-development' && !options.includeInDevelopment) {
49
+ skipped.push({
50
+ package: contract.package || path.basename(path.dirname(filePath)),
51
+ status: 'in-development',
52
+ reason: 'Contract is in development (use --include-drafts to include)'
53
+ });
54
+ continue;
55
+ }
56
+ // Validate against JSON Schema
57
+ const valid = validate(contract);
58
+ if (!valid) {
59
+ // If it's in-development and validation fails, skip silently
60
+ if (status === 'in-development') {
61
+ skipped.push({
62
+ package: contract.package || path.basename(path.dirname(filePath)),
63
+ status: 'in-development',
64
+ reason: 'Contract validation failed (in-development)'
65
+ });
66
+ continue;
67
+ }
68
+ const validationErrors = validate.errors
69
+ ?.map((err) => ` ${err.instancePath} ${err.message}`)
70
+ .join('\n');
71
+ errors.push(`Invalid contract ${filePath}:\n${validationErrors}`);
72
+ continue;
73
+ }
74
+ // Filter by status
75
+ if (status === 'draft' && !options.includeDrafts) {
76
+ skipped.push({
77
+ package: contract.package,
78
+ status: 'draft',
79
+ reason: 'Draft contract excluded (use --include-drafts to include)'
80
+ });
81
+ continue;
82
+ }
83
+ if (status === 'deprecated' && !options.includeDeprecated) {
84
+ skipped.push({
85
+ package: contract.package,
86
+ status: 'deprecated',
87
+ reason: 'Deprecated contract excluded (use --include-deprecated to include)'
88
+ });
89
+ continue;
90
+ }
91
+ // Check for duplicate package names
92
+ if (contracts.has(contract.package)) {
93
+ errors.push(`Duplicate contract for package "${contract.package}" found at ${filePath}`);
94
+ continue;
95
+ }
96
+ contracts.set(contract.package, contract);
97
+ }
98
+ catch (err) {
99
+ errors.push(`Failed to load contract ${filePath}: ${err}`);
100
+ }
101
+ }
102
+ return { contracts, errors, skipped };
103
+ }
104
+ /**
105
+ * Loads a single contract file (for testing)
106
+ */
107
+ export function loadContractFile(filePath) {
108
+ const content = fs.readFileSync(filePath, 'utf-8');
109
+ return YAML.parse(content);
110
+ }
111
+ /**
112
+ * Validates a contract object against the schema
113
+ */
114
+ export function validateContract(contract, schemaPath) {
115
+ const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
116
+ const schema = JSON.parse(schemaContent);
117
+ const ajv = new Ajv({ allErrors: true, strict: false });
118
+ const validate = ajv.compile(schema);
119
+ const valid = validate(contract);
120
+ const errors = valid
121
+ ? []
122
+ : (validate.errors?.map((err) => `${err.instancePath} ${err.message}`) || []);
123
+ return { valid, errors };
124
+ }
125
+ /**
126
+ * Gets the list of packages that have contracts in the corpus
127
+ */
128
+ export function getAvailablePackages(corpusPath) {
129
+ const packagesDir = path.join(corpusPath, 'packages');
130
+ if (!fs.existsSync(packagesDir)) {
131
+ return [];
132
+ }
133
+ return fs
134
+ .readdirSync(packagesDir, { withFileTypes: true })
135
+ .filter(dirent => dirent.isDirectory())
136
+ .map(dirent => dirent.name);
137
+ }
138
+ /**
139
+ * Finds which packages from the corpus are actually used in a TypeScript project
140
+ */
141
+ export function findUsedPackages(projectPackageJson, availableContracts) {
142
+ try {
143
+ const packageJson = JSON.parse(fs.readFileSync(projectPackageJson, 'utf-8'));
144
+ const dependencies = {
145
+ ...packageJson.dependencies,
146
+ ...packageJson.devDependencies,
147
+ };
148
+ return Array.from(availableContracts.keys()).filter(packageName => packageName in dependencies);
149
+ }
150
+ catch (err) {
151
+ console.warn(`Could not read ${projectPackageJson}: ${err}`);
152
+ return [];
153
+ }
154
+ }
155
+ //# sourceMappingURL=corpus-loader.js.map