@liendev/parser 0.39.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/dist/ast/chunker.d.ts +30 -0
- package/dist/ast/chunker.d.ts.map +1 -0
- package/dist/ast/chunker.js +310 -0
- package/dist/ast/chunker.js.map +1 -0
- package/dist/ast/complexity/cognitive.d.ts +16 -0
- package/dist/ast/complexity/cognitive.d.ts.map +1 -0
- package/dist/ast/complexity/cognitive.js +137 -0
- package/dist/ast/complexity/cognitive.js.map +1 -0
- package/dist/ast/complexity/cyclomatic.d.ts +12 -0
- package/dist/ast/complexity/cyclomatic.d.ts.map +1 -0
- package/dist/ast/complexity/cyclomatic.js +54 -0
- package/dist/ast/complexity/cyclomatic.js.map +1 -0
- package/dist/ast/complexity/halstead.d.ts +56 -0
- package/dist/ast/complexity/halstead.d.ts.map +1 -0
- package/dist/ast/complexity/halstead.js +196 -0
- package/dist/ast/complexity/halstead.js.map +1 -0
- package/dist/ast/complexity/index.d.ts +13 -0
- package/dist/ast/complexity/index.d.ts.map +1 -0
- package/dist/ast/complexity/index.js +12 -0
- package/dist/ast/complexity/index.js.map +1 -0
- package/dist/ast/extractors/index.d.ts +35 -0
- package/dist/ast/extractors/index.d.ts.map +1 -0
- package/dist/ast/extractors/index.js +41 -0
- package/dist/ast/extractors/index.js.map +1 -0
- package/dist/ast/extractors/symbol-helpers.d.ts +20 -0
- package/dist/ast/extractors/symbol-helpers.d.ts.map +1 -0
- package/dist/ast/extractors/symbol-helpers.js +58 -0
- package/dist/ast/extractors/symbol-helpers.js.map +1 -0
- package/dist/ast/extractors/types.d.ts +108 -0
- package/dist/ast/extractors/types.d.ts.map +1 -0
- package/dist/ast/extractors/types.js +2 -0
- package/dist/ast/extractors/types.js.map +1 -0
- package/dist/ast/languages/javascript.d.ts +134 -0
- package/dist/ast/languages/javascript.d.ts.map +1 -0
- package/dist/ast/languages/javascript.js +787 -0
- package/dist/ast/languages/javascript.js.map +1 -0
- package/dist/ast/languages/php.d.ts +84 -0
- package/dist/ast/languages/php.d.ts.map +1 -0
- package/dist/ast/languages/php.js +452 -0
- package/dist/ast/languages/php.js.map +1 -0
- package/dist/ast/languages/python.d.ts +96 -0
- package/dist/ast/languages/python.d.ts.map +1 -0
- package/dist/ast/languages/python.js +448 -0
- package/dist/ast/languages/python.js.map +1 -0
- package/dist/ast/languages/registry.d.ts +30 -0
- package/dist/ast/languages/registry.d.ts.map +1 -0
- package/dist/ast/languages/registry.js +95 -0
- package/dist/ast/languages/registry.js.map +1 -0
- package/dist/ast/languages/rust.d.ts +113 -0
- package/dist/ast/languages/rust.d.ts.map +1 -0
- package/dist/ast/languages/rust.js +614 -0
- package/dist/ast/languages/rust.js.map +1 -0
- package/dist/ast/languages/types.d.ts +52 -0
- package/dist/ast/languages/types.d.ts.map +1 -0
- package/dist/ast/languages/types.js +2 -0
- package/dist/ast/languages/types.js.map +1 -0
- package/dist/ast/languages/typescript.d.ts +3 -0
- package/dist/ast/languages/typescript.d.ts.map +1 -0
- package/dist/ast/languages/typescript.js +134 -0
- package/dist/ast/languages/typescript.js.map +1 -0
- package/dist/ast/parser.d.ts +29 -0
- package/dist/ast/parser.d.ts.map +1 -0
- package/dist/ast/parser.js +67 -0
- package/dist/ast/parser.js.map +1 -0
- package/dist/ast/symbols.d.ts +74 -0
- package/dist/ast/symbols.d.ts.map +1 -0
- package/dist/ast/symbols.js +171 -0
- package/dist/ast/symbols.js.map +1 -0
- package/dist/ast/traversers/index.d.ts +19 -0
- package/dist/ast/traversers/index.d.ts.map +1 -0
- package/dist/ast/traversers/index.js +21 -0
- package/dist/ast/traversers/index.js.map +1 -0
- package/dist/ast/traversers/types.d.ts +98 -0
- package/dist/ast/traversers/types.d.ts.map +1 -0
- package/dist/ast/traversers/types.js +2 -0
- package/dist/ast/traversers/types.js.map +1 -0
- package/dist/ast/types.d.ts +54 -0
- package/dist/ast/types.d.ts.map +1 -0
- package/dist/ast/types.js +2 -0
- package/dist/ast/types.js.map +1 -0
- package/dist/chunk-only-index.d.ts +25 -0
- package/dist/chunk-only-index.d.ts.map +1 -0
- package/dist/chunk-only-index.js +107 -0
- package/dist/chunk-only-index.js.map +1 -0
- package/dist/chunker.d.ts +12 -0
- package/dist/chunker.d.ts.map +1 -0
- package/dist/chunker.js +98 -0
- package/dist/chunker.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +11 -0
- package/dist/constants.js.map +1 -0
- package/dist/content-hash.d.ts +20 -0
- package/dist/content-hash.d.ts.map +1 -0
- package/dist/content-hash.js +91 -0
- package/dist/content-hash.js.map +1 -0
- package/dist/dependency-analyzer.d.ts +79 -0
- package/dist/dependency-analyzer.d.ts.map +1 -0
- package/dist/dependency-analyzer.js +408 -0
- package/dist/dependency-analyzer.js.map +1 -0
- package/dist/ecosystem-presets.d.ts +32 -0
- package/dist/ecosystem-presets.d.ts.map +1 -0
- package/dist/ecosystem-presets.js +325 -0
- package/dist/ecosystem-presets.js.map +1 -0
- package/dist/gitignore.d.ts +22 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +128 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/insights/chunk-complexity.d.ts +89 -0
- package/dist/insights/chunk-complexity.d.ts.map +1 -0
- package/dist/insights/chunk-complexity.js +332 -0
- package/dist/insights/chunk-complexity.js.map +1 -0
- package/dist/insights/types.d.ts +73 -0
- package/dist/insights/types.d.ts.map +1 -0
- package/dist/insights/types.js +9 -0
- package/dist/insights/types.js.map +1 -0
- package/dist/json-template-chunker.d.ts +12 -0
- package/dist/json-template-chunker.d.ts.map +1 -0
- package/dist/json-template-chunker.js +87 -0
- package/dist/json-template-chunker.js.map +1 -0
- package/dist/liquid-chunker.d.ts +16 -0
- package/dist/liquid-chunker.d.ts.map +1 -0
- package/dist/liquid-chunker.js +274 -0
- package/dist/liquid-chunker.js.map +1 -0
- package/dist/scanner.d.ts +16 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +95 -0
- package/dist/scanner.js.map +1 -0
- package/dist/symbol-extractor.d.ts +18 -0
- package/dist/symbol-extractor.d.ts.map +1 -0
- package/dist/symbol-extractor.js +343 -0
- package/dist/symbol-extractor.js.map +1 -0
- package/dist/test-associations.d.ts +16 -0
- package/dist/test-associations.d.ts.map +1 -0
- package/dist/test-associations.js +43 -0
- package/dist/test-associations.js.map +1 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/path-matching.d.ts +71 -0
- package/dist/utils/path-matching.d.ts.map +1 -0
- package/dist/utils/path-matching.js +258 -0
- package/dist/utils/path-matching.js.map +1 -0
- package/dist/utils/repo-id.d.ts +6 -0
- package/dist/utils/repo-id.d.ts.map +1 -0
- package/dist/utils/repo-id.js +12 -0
- package/dist/utils/repo-id.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ComplexityViolation, ComplexityReport, RiskLevel } from './types.js';
|
|
2
|
+
import type { ChunkMetadata, CodeChunk } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a file path to a consistent relative format.
|
|
5
|
+
* Converts absolute paths to relative paths from workspace root.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeFilePath(filepath: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Check if a chunk's file matches any of the target files.
|
|
10
|
+
* Uses exact match or suffix matching to avoid unintended matches.
|
|
11
|
+
*/
|
|
12
|
+
export declare function matchesAnyFile(chunkFile: string, targetFiles: string[]): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Create a violation if complexity exceeds threshold.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createViolation(metadata: ChunkMetadata, complexity: number, baseThreshold: number, metricType: ComplexityViolation['metricType']): ComplexityViolation | null;
|
|
17
|
+
/**
|
|
18
|
+
* Convert Halstead effort to time in minutes.
|
|
19
|
+
* Formula: Time (seconds) = Effort / 18 (Stroud number for mental discrimination)
|
|
20
|
+
* Time (minutes) = Effort / (18 * 60) = Effort / 1080
|
|
21
|
+
*/
|
|
22
|
+
export declare function effortToMinutes(effort: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Convert time in minutes to Halstead effort.
|
|
25
|
+
* Inverse of effortToMinutes().
|
|
26
|
+
*/
|
|
27
|
+
export declare function minutesToEffort(minutes: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Format minutes as human-readable time (e.g., "2h 30m" or "45m")
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatTime(minutes: number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Create a Halstead violation if metrics exceed thresholds.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createHalsteadViolation(metadata: ChunkMetadata, metricValue: number, threshold: number, metricType: 'halstead_effort' | 'halstead_bugs'): ComplexityViolation | null;
|
|
36
|
+
/**
|
|
37
|
+
* Check complexity metrics and create violations for a single chunk.
|
|
38
|
+
*/
|
|
39
|
+
export declare function checkChunkComplexity(metadata: ChunkMetadata, thresholds: {
|
|
40
|
+
testPaths: number;
|
|
41
|
+
mentalLoad: number;
|
|
42
|
+
halsteadEffort?: number;
|
|
43
|
+
estimatedBugs?: number;
|
|
44
|
+
}): ComplexityViolation[];
|
|
45
|
+
/**
|
|
46
|
+
* Deduplicate and filter chunks to only function/method types.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getUniqueFunctionChunks(chunks: Array<{
|
|
49
|
+
content: string;
|
|
50
|
+
metadata: ChunkMetadata;
|
|
51
|
+
}>): ChunkMetadata[];
|
|
52
|
+
interface ComplexityThresholds {
|
|
53
|
+
testPaths: number;
|
|
54
|
+
mentalLoad: number;
|
|
55
|
+
timeToUnderstandMinutes: number;
|
|
56
|
+
estimatedBugs: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Find all complexity violations based on thresholds.
|
|
60
|
+
*/
|
|
61
|
+
export declare function findViolations(chunks: Array<{
|
|
62
|
+
content: string;
|
|
63
|
+
metadata: ChunkMetadata;
|
|
64
|
+
}>, thresholds: ComplexityThresholds): ComplexityViolation[];
|
|
65
|
+
/**
|
|
66
|
+
* Calculate risk level based on violations.
|
|
67
|
+
*/
|
|
68
|
+
export declare function calculateRiskLevel(violations: ComplexityViolation[]): RiskLevel;
|
|
69
|
+
/**
|
|
70
|
+
* Build the final report with summary and per-file data.
|
|
71
|
+
*/
|
|
72
|
+
export declare function buildReport(violations: ComplexityViolation[], allChunks: Array<{
|
|
73
|
+
content: string;
|
|
74
|
+
metadata: ChunkMetadata;
|
|
75
|
+
}>): ComplexityReport;
|
|
76
|
+
/**
|
|
77
|
+
* Enrich files with violations with dependency data.
|
|
78
|
+
*/
|
|
79
|
+
export declare function enrichWithDependencies(report: ComplexityReport, allChunks: CodeChunk[]): void;
|
|
80
|
+
/**
|
|
81
|
+
* Analyze complexity from in-memory chunks (no VectorDB needed).
|
|
82
|
+
* Standalone replacement for ComplexityAnalyzer.analyzeFromChunks().
|
|
83
|
+
*/
|
|
84
|
+
export declare function analyzeComplexityFromChunks(chunks: CodeChunk[], files?: string[], thresholdOverrides?: {
|
|
85
|
+
testPaths?: number;
|
|
86
|
+
mentalLoad?: number;
|
|
87
|
+
}): ComplexityReport;
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=chunk-complexity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-complexity.d.ts","sourceRoot":"","sources":["../../src/insights/chunk-complexity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAEhB,SAAS,EAEV,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAmB5D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY1D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAShF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,aAAa,EACvB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,GAC5C,mBAAmB,GAAG,IAAI,CA2B5B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,iBAAiB,GAAG,eAAe,GAC9C,mBAAmB,GAAG,IAAI,CAiD5B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,aAAa,EACvB,UAAU,EAAE;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,mBAAmB,EAAE,CAuCvB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,GAC1D,aAAa,EAAE,CAejB;AAED,UAAU,oBAAoB;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,MAAM,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,EAC3D,UAAU,EAAE,oBAAoB,GAC/B,mBAAmB,EAAE,CAYvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,mBAAmB,EAAE,GAAG,SAAS,CAU/E;AAwBD;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,mBAAmB,EAAE,EACjC,SAAS,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,GAC7D,gBAAgB,CAwClB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,CA2B7F;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,SAAS,EAAE,EACnB,KAAK,CAAC,EAAE,MAAM,EAAE,EAChB,kBAAkB,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,gBAAgB,CAyBlB"}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { RISK_ORDER } from './types.js';
|
|
2
|
+
import { analyzeDependencies } from '../dependency-analyzer.js';
|
|
3
|
+
import { findTestAssociationsFromChunks } from '../test-associations.js';
|
|
4
|
+
/**
|
|
5
|
+
* Hardcoded severity multipliers:
|
|
6
|
+
* - Warning: triggers at 1x threshold (e.g., testPaths >= 15)
|
|
7
|
+
* - Error: triggers at 2x threshold (e.g., testPaths >= 30)
|
|
8
|
+
*/
|
|
9
|
+
const SEVERITY = { warning: 1.0, error: 2.0 };
|
|
10
|
+
/** Default complexity thresholds */
|
|
11
|
+
const DEFAULT_THRESHOLDS = {
|
|
12
|
+
testPaths: 15,
|
|
13
|
+
mentalLoad: 15,
|
|
14
|
+
timeToUnderstandMinutes: 60,
|
|
15
|
+
estimatedBugs: 1.5,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Normalize a file path to a consistent relative format.
|
|
19
|
+
* Converts absolute paths to relative paths from workspace root.
|
|
20
|
+
*/
|
|
21
|
+
export function normalizeFilePath(filepath) {
|
|
22
|
+
const workspaceRoot = process.cwd();
|
|
23
|
+
const normalized = filepath.replace(/\\/g, '/');
|
|
24
|
+
const normalizedRoot = workspaceRoot.replace(/\\/g, '/');
|
|
25
|
+
if (normalized.startsWith(normalizedRoot + '/')) {
|
|
26
|
+
return normalized.slice(normalizedRoot.length + 1);
|
|
27
|
+
}
|
|
28
|
+
if (normalized.startsWith(normalizedRoot)) {
|
|
29
|
+
return normalized.slice(normalizedRoot.length);
|
|
30
|
+
}
|
|
31
|
+
return normalized;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if a chunk's file matches any of the target files.
|
|
35
|
+
* Uses exact match or suffix matching to avoid unintended matches.
|
|
36
|
+
*/
|
|
37
|
+
export function matchesAnyFile(chunkFile, targetFiles) {
|
|
38
|
+
const normalizedChunkFile = chunkFile.replace(/\\/g, '/');
|
|
39
|
+
return targetFiles.some(target => {
|
|
40
|
+
const normalizedTarget = target.replace(/\\/g, '/');
|
|
41
|
+
return (normalizedChunkFile === normalizedTarget ||
|
|
42
|
+
normalizedChunkFile.endsWith('/' + normalizedTarget));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a violation if complexity exceeds threshold.
|
|
47
|
+
*/
|
|
48
|
+
export function createViolation(metadata, complexity, baseThreshold, metricType) {
|
|
49
|
+
const warningThreshold = baseThreshold * SEVERITY.warning;
|
|
50
|
+
const errorThreshold = baseThreshold * SEVERITY.error;
|
|
51
|
+
if (complexity < warningThreshold)
|
|
52
|
+
return null;
|
|
53
|
+
const violationSeverity = complexity >= errorThreshold ? 'error' : 'warning';
|
|
54
|
+
const effectiveThreshold = violationSeverity === 'error' ? errorThreshold : warningThreshold;
|
|
55
|
+
const message = metricType === 'cyclomatic'
|
|
56
|
+
? `Needs ~${complexity} test cases for full coverage (threshold: ${Math.round(effectiveThreshold)})`
|
|
57
|
+
: `Mental load ${complexity} exceeds threshold ${Math.round(effectiveThreshold)} (hard to follow)`;
|
|
58
|
+
return {
|
|
59
|
+
filepath: metadata.file,
|
|
60
|
+
startLine: metadata.startLine,
|
|
61
|
+
endLine: metadata.endLine,
|
|
62
|
+
symbolName: metadata.symbolName || 'unknown',
|
|
63
|
+
symbolType: metadata.symbolType,
|
|
64
|
+
language: metadata.language,
|
|
65
|
+
complexity,
|
|
66
|
+
threshold: Math.round(effectiveThreshold),
|
|
67
|
+
severity: violationSeverity,
|
|
68
|
+
message,
|
|
69
|
+
metricType,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Convert Halstead effort to time in minutes.
|
|
74
|
+
* Formula: Time (seconds) = Effort / 18 (Stroud number for mental discrimination)
|
|
75
|
+
* Time (minutes) = Effort / (18 * 60) = Effort / 1080
|
|
76
|
+
*/
|
|
77
|
+
export function effortToMinutes(effort) {
|
|
78
|
+
return effort / 1080;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Convert time in minutes to Halstead effort.
|
|
82
|
+
* Inverse of effortToMinutes().
|
|
83
|
+
*/
|
|
84
|
+
export function minutesToEffort(minutes) {
|
|
85
|
+
return minutes * 1080;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Format minutes as human-readable time (e.g., "2h 30m" or "45m")
|
|
89
|
+
*/
|
|
90
|
+
export function formatTime(minutes) {
|
|
91
|
+
if (minutes >= 60) {
|
|
92
|
+
const hours = Math.floor(minutes / 60);
|
|
93
|
+
const mins = Math.round(minutes % 60);
|
|
94
|
+
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
95
|
+
}
|
|
96
|
+
return `${Math.round(minutes)}m`;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a Halstead violation if metrics exceed thresholds.
|
|
100
|
+
*/
|
|
101
|
+
export function createHalsteadViolation(metadata, metricValue, threshold, metricType) {
|
|
102
|
+
const warningThreshold = threshold * SEVERITY.warning;
|
|
103
|
+
const errorThreshold = threshold * SEVERITY.error;
|
|
104
|
+
if (metricValue < warningThreshold)
|
|
105
|
+
return null;
|
|
106
|
+
const violationSeverity = metricValue >= errorThreshold ? 'error' : 'warning';
|
|
107
|
+
const effectiveThreshold = violationSeverity === 'error' ? errorThreshold : warningThreshold;
|
|
108
|
+
let message;
|
|
109
|
+
if (metricType === 'halstead_effort') {
|
|
110
|
+
const timeMinutes = effortToMinutes(metricValue);
|
|
111
|
+
const thresholdMinutes = effortToMinutes(effectiveThreshold);
|
|
112
|
+
message = `Time to understand ~${formatTime(timeMinutes)} exceeds threshold ${formatTime(thresholdMinutes)}`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
message = `Estimated bugs ${metricValue.toFixed(2)} exceeds threshold ${effectiveThreshold.toFixed(1)}`;
|
|
116
|
+
}
|
|
117
|
+
const halsteadDetails = {
|
|
118
|
+
volume: metadata.halsteadVolume || 0,
|
|
119
|
+
difficulty: metadata.halsteadDifficulty || 0,
|
|
120
|
+
effort: metadata.halsteadEffort || 0,
|
|
121
|
+
bugs: metadata.halsteadBugs || 0,
|
|
122
|
+
};
|
|
123
|
+
let complexity;
|
|
124
|
+
let displayThreshold;
|
|
125
|
+
if (metricType === 'halstead_effort') {
|
|
126
|
+
complexity = Math.round(effortToMinutes(metricValue));
|
|
127
|
+
displayThreshold = Math.round(effortToMinutes(effectiveThreshold));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
complexity = metricValue;
|
|
131
|
+
displayThreshold = effectiveThreshold;
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
filepath: metadata.file,
|
|
135
|
+
startLine: metadata.startLine,
|
|
136
|
+
endLine: metadata.endLine,
|
|
137
|
+
symbolName: metadata.symbolName || 'unknown',
|
|
138
|
+
symbolType: metadata.symbolType,
|
|
139
|
+
language: metadata.language,
|
|
140
|
+
complexity,
|
|
141
|
+
threshold: displayThreshold,
|
|
142
|
+
severity: violationSeverity,
|
|
143
|
+
message,
|
|
144
|
+
metricType,
|
|
145
|
+
halsteadDetails,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Check complexity metrics and create violations for a single chunk.
|
|
150
|
+
*/
|
|
151
|
+
export function checkChunkComplexity(metadata, thresholds) {
|
|
152
|
+
const violations = [];
|
|
153
|
+
if (metadata.complexity) {
|
|
154
|
+
const v = createViolation(metadata, metadata.complexity, thresholds.testPaths, 'cyclomatic');
|
|
155
|
+
if (v)
|
|
156
|
+
violations.push(v);
|
|
157
|
+
}
|
|
158
|
+
if (metadata.cognitiveComplexity) {
|
|
159
|
+
const v = createViolation(metadata, metadata.cognitiveComplexity, thresholds.mentalLoad, 'cognitive');
|
|
160
|
+
if (v)
|
|
161
|
+
violations.push(v);
|
|
162
|
+
}
|
|
163
|
+
if (thresholds.halsteadEffort && metadata.halsteadEffort) {
|
|
164
|
+
const v = createHalsteadViolation(metadata, metadata.halsteadEffort, thresholds.halsteadEffort, 'halstead_effort');
|
|
165
|
+
if (v)
|
|
166
|
+
violations.push(v);
|
|
167
|
+
}
|
|
168
|
+
if (thresholds.estimatedBugs && metadata.halsteadBugs) {
|
|
169
|
+
const v = createHalsteadViolation(metadata, metadata.halsteadBugs, thresholds.estimatedBugs, 'halstead_bugs');
|
|
170
|
+
if (v)
|
|
171
|
+
violations.push(v);
|
|
172
|
+
}
|
|
173
|
+
return violations;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Deduplicate and filter chunks to only function/method types.
|
|
177
|
+
*/
|
|
178
|
+
export function getUniqueFunctionChunks(chunks) {
|
|
179
|
+
const seen = new Set();
|
|
180
|
+
const result = [];
|
|
181
|
+
for (const { metadata } of chunks) {
|
|
182
|
+
if (metadata.symbolType !== 'function' && metadata.symbolType !== 'method')
|
|
183
|
+
continue;
|
|
184
|
+
const key = `${metadata.repoId ?? ''}:${normalizeFilePath(metadata.file)}:${metadata.startLine}-${metadata.endLine}`;
|
|
185
|
+
if (seen.has(key))
|
|
186
|
+
continue;
|
|
187
|
+
seen.add(key);
|
|
188
|
+
result.push(metadata);
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Find all complexity violations based on thresholds.
|
|
194
|
+
*/
|
|
195
|
+
export function findViolations(chunks, thresholds) {
|
|
196
|
+
const halsteadEffort = minutesToEffort(thresholds.timeToUnderstandMinutes);
|
|
197
|
+
const resolvedThresholds = {
|
|
198
|
+
testPaths: thresholds.testPaths,
|
|
199
|
+
mentalLoad: thresholds.mentalLoad,
|
|
200
|
+
halsteadEffort,
|
|
201
|
+
estimatedBugs: thresholds.estimatedBugs,
|
|
202
|
+
};
|
|
203
|
+
const functionChunks = getUniqueFunctionChunks(chunks);
|
|
204
|
+
return functionChunks.flatMap(metadata => checkChunkComplexity(metadata, resolvedThresholds));
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Calculate risk level based on violations.
|
|
208
|
+
*/
|
|
209
|
+
export function calculateRiskLevel(violations) {
|
|
210
|
+
if (violations.length === 0)
|
|
211
|
+
return 'low';
|
|
212
|
+
const hasErrors = violations.some(v => v.severity === 'error');
|
|
213
|
+
const errorCount = violations.filter(v => v.severity === 'error').length;
|
|
214
|
+
if (errorCount >= 3)
|
|
215
|
+
return 'critical';
|
|
216
|
+
if (hasErrors)
|
|
217
|
+
return 'high';
|
|
218
|
+
if (violations.length >= 3)
|
|
219
|
+
return 'medium';
|
|
220
|
+
return 'low';
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Compute average and max complexity from chunk metadata in a single pass.
|
|
224
|
+
*/
|
|
225
|
+
function computeComplexityStats(allChunks) {
|
|
226
|
+
let sum = 0;
|
|
227
|
+
let count = 0;
|
|
228
|
+
let max = 0;
|
|
229
|
+
for (const c of allChunks) {
|
|
230
|
+
const complexity = c.metadata.complexity;
|
|
231
|
+
if (complexity !== undefined && complexity > 0) {
|
|
232
|
+
sum += complexity;
|
|
233
|
+
count++;
|
|
234
|
+
if (complexity > max)
|
|
235
|
+
max = complexity;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const avg = count > 0 ? Math.round((sum / count) * 10) / 10 : 0;
|
|
239
|
+
return { avgComplexity: avg, maxComplexity: max };
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Build the final report with summary and per-file data.
|
|
243
|
+
*/
|
|
244
|
+
export function buildReport(violations, allChunks) {
|
|
245
|
+
// Group violations by file and count severities in a single pass
|
|
246
|
+
const fileViolationsMap = new Map();
|
|
247
|
+
let errorCount = 0;
|
|
248
|
+
let warningCount = 0;
|
|
249
|
+
for (const violation of violations) {
|
|
250
|
+
const normalizedPath = normalizeFilePath(violation.filepath);
|
|
251
|
+
violation.filepath = normalizedPath;
|
|
252
|
+
const existing = fileViolationsMap.get(normalizedPath) || [];
|
|
253
|
+
existing.push(violation);
|
|
254
|
+
fileViolationsMap.set(normalizedPath, existing);
|
|
255
|
+
if (violation.severity === 'error')
|
|
256
|
+
errorCount++;
|
|
257
|
+
else
|
|
258
|
+
warningCount++;
|
|
259
|
+
}
|
|
260
|
+
const analyzedFiles = new Set(allChunks.map(c => normalizeFilePath(c.metadata.file)));
|
|
261
|
+
const files = {};
|
|
262
|
+
for (const filepath of analyzedFiles) {
|
|
263
|
+
const fileViolations = fileViolationsMap.get(filepath) || [];
|
|
264
|
+
files[filepath] = {
|
|
265
|
+
violations: fileViolations,
|
|
266
|
+
dependents: [],
|
|
267
|
+
testAssociations: [],
|
|
268
|
+
riskLevel: calculateRiskLevel(fileViolations),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
const { avgComplexity, maxComplexity } = computeComplexityStats(allChunks);
|
|
272
|
+
return {
|
|
273
|
+
summary: {
|
|
274
|
+
filesAnalyzed: analyzedFiles.size,
|
|
275
|
+
totalViolations: violations.length,
|
|
276
|
+
bySeverity: { error: errorCount, warning: warningCount },
|
|
277
|
+
avgComplexity,
|
|
278
|
+
maxComplexity,
|
|
279
|
+
},
|
|
280
|
+
files,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Enrich files with violations with dependency data.
|
|
285
|
+
*/
|
|
286
|
+
export function enrichWithDependencies(report, allChunks) {
|
|
287
|
+
const workspaceRoot = process.cwd();
|
|
288
|
+
const filesWithViolations = Object.entries(report.files)
|
|
289
|
+
.filter(([_, data]) => data.violations.length > 0)
|
|
290
|
+
.map(([filepath, _]) => filepath);
|
|
291
|
+
for (const filepath of filesWithViolations) {
|
|
292
|
+
const fileData = report.files[filepath];
|
|
293
|
+
const depAnalysis = analyzeDependencies(filepath, allChunks, workspaceRoot);
|
|
294
|
+
fileData.dependents = depAnalysis.dependents.map(d => d.filepath);
|
|
295
|
+
fileData.dependentCount = depAnalysis.dependentCount;
|
|
296
|
+
if (RISK_ORDER[depAnalysis.riskLevel] > RISK_ORDER[fileData.riskLevel]) {
|
|
297
|
+
fileData.riskLevel = depAnalysis.riskLevel;
|
|
298
|
+
}
|
|
299
|
+
if (depAnalysis.complexityMetrics) {
|
|
300
|
+
fileData.dependentComplexityMetrics = {
|
|
301
|
+
averageComplexity: depAnalysis.complexityMetrics.averageComplexity,
|
|
302
|
+
maxComplexity: depAnalysis.complexityMetrics.maxComplexity,
|
|
303
|
+
filesWithComplexityData: depAnalysis.complexityMetrics.filesWithComplexityData,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Analyze complexity from in-memory chunks (no VectorDB needed).
|
|
310
|
+
* Standalone replacement for ComplexityAnalyzer.analyzeFromChunks().
|
|
311
|
+
*/
|
|
312
|
+
export function analyzeComplexityFromChunks(chunks, files, thresholdOverrides) {
|
|
313
|
+
const thresholds = { ...DEFAULT_THRESHOLDS, ...thresholdOverrides };
|
|
314
|
+
// Filter to specified files if provided
|
|
315
|
+
const filtered = files ? chunks.filter(c => matchesAnyFile(c.metadata.file, files)) : chunks;
|
|
316
|
+
// Find violations, build report, enrich with dependencies
|
|
317
|
+
const violations = findViolations(filtered, thresholds);
|
|
318
|
+
const report = buildReport(violations, filtered);
|
|
319
|
+
enrichWithDependencies(report, chunks);
|
|
320
|
+
// Enrich files with violations with test association data
|
|
321
|
+
const filesWithViolations = Object.keys(report.files).filter(f => report.files[f].violations.length > 0);
|
|
322
|
+
if (filesWithViolations.length > 0) {
|
|
323
|
+
const testMap = findTestAssociationsFromChunks(filesWithViolations, chunks);
|
|
324
|
+
for (const [filepath, testFiles] of testMap) {
|
|
325
|
+
if (report.files[filepath]) {
|
|
326
|
+
report.files[filepath].testAssociations = testFiles;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return report;
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=chunk-complexity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-complexity.js","sourceRoot":"","sources":["../../src/insights/chunk-complexity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Complexity analysis types for code quality insights
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Risk level ordering for comparison operations.
|
|
6
|
+
* Higher value = higher risk.
|
|
7
|
+
*/
|
|
8
|
+
export declare const RISK_ORDER: {
|
|
9
|
+
readonly low: 0;
|
|
10
|
+
readonly medium: 1;
|
|
11
|
+
readonly high: 2;
|
|
12
|
+
readonly critical: 3;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Risk level type derived from RISK_ORDER keys
|
|
16
|
+
*/
|
|
17
|
+
export type RiskLevel = keyof typeof RISK_ORDER;
|
|
18
|
+
/**
|
|
19
|
+
* Type of complexity metric being measured
|
|
20
|
+
*/
|
|
21
|
+
export type ComplexityMetricType = 'cyclomatic' | 'cognitive' | 'halstead_effort' | 'halstead_bugs';
|
|
22
|
+
/**
|
|
23
|
+
* Halstead metric details for Halstead-type violations
|
|
24
|
+
*/
|
|
25
|
+
export interface HalsteadDetails {
|
|
26
|
+
volume: number;
|
|
27
|
+
difficulty: number;
|
|
28
|
+
effort: number;
|
|
29
|
+
bugs: number;
|
|
30
|
+
}
|
|
31
|
+
export interface ComplexityViolation {
|
|
32
|
+
filepath: string;
|
|
33
|
+
startLine: number;
|
|
34
|
+
endLine: number;
|
|
35
|
+
symbolName: string;
|
|
36
|
+
symbolType: 'function' | 'method' | 'class' | 'file';
|
|
37
|
+
language: string;
|
|
38
|
+
complexity: number;
|
|
39
|
+
threshold: number;
|
|
40
|
+
severity: 'warning' | 'error';
|
|
41
|
+
message: string;
|
|
42
|
+
/** Type of complexity metric (cyclomatic vs cognitive vs halstead) */
|
|
43
|
+
metricType: ComplexityMetricType;
|
|
44
|
+
/** Halstead-specific details when metricType is halstead_* */
|
|
45
|
+
halsteadDetails?: HalsteadDetails;
|
|
46
|
+
}
|
|
47
|
+
export interface FileComplexityData {
|
|
48
|
+
violations: ComplexityViolation[];
|
|
49
|
+
dependents: string[];
|
|
50
|
+
dependentCount?: number;
|
|
51
|
+
/** Test files associated with this source file. TODO: Populate when test-to-code mapping is implemented */
|
|
52
|
+
testAssociations: string[];
|
|
53
|
+
riskLevel: RiskLevel;
|
|
54
|
+
dependentComplexityMetrics?: {
|
|
55
|
+
averageComplexity: number;
|
|
56
|
+
maxComplexity: number;
|
|
57
|
+
filesWithComplexityData: number;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface ComplexityReport {
|
|
61
|
+
summary: {
|
|
62
|
+
filesAnalyzed: number;
|
|
63
|
+
totalViolations: number;
|
|
64
|
+
bySeverity: {
|
|
65
|
+
error: number;
|
|
66
|
+
warning: number;
|
|
67
|
+
};
|
|
68
|
+
avgComplexity: number;
|
|
69
|
+
maxComplexity: number;
|
|
70
|
+
};
|
|
71
|
+
files: Record<string, FileComplexityData>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/insights/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;CAAuD,CAAC;AAE/E;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,UAAU,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,WAAW,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAEpG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,UAAU,EAAE,oBAAoB,CAAC;IACjC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2GAA2G;IAC3G,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,0BAA0B,CAAC,EAAE;QAC3B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC3C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Complexity analysis types for code quality insights
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Risk level ordering for comparison operations.
|
|
6
|
+
* Higher value = higher risk.
|
|
7
|
+
*/
|
|
8
|
+
export const RISK_ORDER = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/insights/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAW,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CodeChunk } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Chunk a Shopify JSON template file
|
|
4
|
+
*
|
|
5
|
+
* JSON templates are typically small (define section layout),
|
|
6
|
+
* so we keep them as a single chunk and extract section references.
|
|
7
|
+
*/
|
|
8
|
+
export declare function chunkJSONTemplate(filepath: string, content: string, tenantContext?: {
|
|
9
|
+
repoId?: string;
|
|
10
|
+
orgId?: string;
|
|
11
|
+
}): CodeChunk[];
|
|
12
|
+
//# sourceMappingURL=json-template-chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-template-chunker.d.ts","sourceRoot":"","sources":["../src/json-template-chunker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgE5C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD,SAAS,EAAE,CA2Bb"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shopify JSON template chunking
|
|
3
|
+
*
|
|
4
|
+
* JSON template files define which sections appear on a template page.
|
|
5
|
+
* We extract section references to track dependencies.
|
|
6
|
+
*
|
|
7
|
+
* Example structure:
|
|
8
|
+
* {
|
|
9
|
+
* "sections": {
|
|
10
|
+
* "main": { "type": "main-product", "settings": {...} },
|
|
11
|
+
* "recommendations": { "type": "product-recommendations", "settings": {...} }
|
|
12
|
+
* },
|
|
13
|
+
* "order": ["main", "recommendations"]
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Extract section types from a Shopify JSON template
|
|
18
|
+
*
|
|
19
|
+
* These are the actual section file names (e.g., "main-product" → sections/main-product.liquid)
|
|
20
|
+
*/
|
|
21
|
+
function extractSectionReferences(jsonContent) {
|
|
22
|
+
try {
|
|
23
|
+
const template = JSON.parse(jsonContent);
|
|
24
|
+
const sectionTypes = new Set();
|
|
25
|
+
// Extract from sections object
|
|
26
|
+
if (template.sections && typeof template.sections === 'object') {
|
|
27
|
+
for (const section of Object.values(template.sections)) {
|
|
28
|
+
if (typeof section === 'object' &&
|
|
29
|
+
section !== null &&
|
|
30
|
+
'type' in section &&
|
|
31
|
+
typeof section.type === 'string') {
|
|
32
|
+
sectionTypes.add(section.type);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return Array.from(sectionTypes);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// Invalid JSON - return empty array
|
|
40
|
+
console.warn(`[Lien] Failed to parse JSON template: ${error instanceof Error ? error.message : String(error)}`);
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Extract the template name from the filepath
|
|
46
|
+
*
|
|
47
|
+
* templates/customers/account.json → "customers/account"
|
|
48
|
+
* templates/product.json → "product"
|
|
49
|
+
*/
|
|
50
|
+
function extractTemplateName(filepath) {
|
|
51
|
+
// Match everything after templates/ up to .json
|
|
52
|
+
const match = filepath.match(/templates\/(.+)\.json$/);
|
|
53
|
+
return match ? match[1] : undefined;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Chunk a Shopify JSON template file
|
|
57
|
+
*
|
|
58
|
+
* JSON templates are typically small (define section layout),
|
|
59
|
+
* so we keep them as a single chunk and extract section references.
|
|
60
|
+
*/
|
|
61
|
+
export function chunkJSONTemplate(filepath, content, tenantContext) {
|
|
62
|
+
// Skip empty files
|
|
63
|
+
if (content.trim().length === 0) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
const lines = content.split('\n');
|
|
67
|
+
const templateName = extractTemplateName(filepath);
|
|
68
|
+
const sectionReferences = extractSectionReferences(content);
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
content,
|
|
72
|
+
metadata: {
|
|
73
|
+
file: filepath,
|
|
74
|
+
startLine: 1,
|
|
75
|
+
endLine: lines.length,
|
|
76
|
+
language: 'json',
|
|
77
|
+
type: 'template',
|
|
78
|
+
symbolName: templateName,
|
|
79
|
+
symbolType: 'template',
|
|
80
|
+
imports: sectionReferences.length > 0 ? sectionReferences : undefined,
|
|
81
|
+
...(tenantContext?.repoId && { repoId: tenantContext.repoId }),
|
|
82
|
+
...(tenantContext?.orgId && { orgId: tenantContext.orgId }),
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=json-template-chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-template-chunker.js","sourceRoot":"","sources":["../src/json-template-chunker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,WAAmB;IACnD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QAEvC,+BAA+B;QAC/B,IAAI,QAAQ,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/D,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvD,IACE,OAAO,OAAO,KAAK,QAAQ;oBAC3B,OAAO,KAAK,IAAI;oBAChB,MAAM,IAAI,OAAO;oBACjB,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAChC,CAAC;oBACD,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oCAAoC;QACpC,OAAO,CAAC,IAAI,CACV,yCAAyC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAClG,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,gDAAgD;IAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACvD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,OAAe,EACf,aAAmD;IAEnD,mBAAmB;IACnB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAE5D,OAAO;QACL;YACE,OAAO;YACP,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,KAAK,CAAC,MAAM;gBACrB,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,YAAY;gBACxB,UAAU,EAAE,UAAU;gBACtB,OAAO,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;gBACrE,GAAG,CAAC,aAAa,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC;gBAC9D,GAAG,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,CAAC;aAC5D;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CodeChunk } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Chunk a Liquid template file
|
|
4
|
+
*
|
|
5
|
+
* Special handling for:
|
|
6
|
+
* - {% schema %} blocks (kept together, extract section name)
|
|
7
|
+
* - {% style %} blocks (kept together)
|
|
8
|
+
* - {% javascript %} blocks (kept together)
|
|
9
|
+
* - {% render %}, {% include %}, and {% section %} tags (tracked as imports)
|
|
10
|
+
* - Regular template content (chunked by lines)
|
|
11
|
+
*/
|
|
12
|
+
export declare function chunkLiquidFile(filepath: string, content: string, chunkSize?: number, chunkOverlap?: number, tenantContext?: {
|
|
13
|
+
repoId?: string;
|
|
14
|
+
orgId?: string;
|
|
15
|
+
}): CodeChunk[];
|
|
16
|
+
//# sourceMappingURL=liquid-chunker.d.ts.map
|