lamps-code-review 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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -0
  3. package/bin/lamps-review.js +7 -0
  4. package/dist/cli/commands/review.d.ts +9 -0
  5. package/dist/cli/commands/review.d.ts.map +1 -0
  6. package/dist/cli/commands/review.js +149 -0
  7. package/dist/cli/commands/review.js.map +1 -0
  8. package/dist/cli/index.d.ts +7 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +41 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/core/analyzer/ai/index.d.ts +28 -0
  13. package/dist/core/analyzer/ai/index.d.ts.map +1 -0
  14. package/dist/core/analyzer/ai/index.js +171 -0
  15. package/dist/core/analyzer/ai/index.js.map +1 -0
  16. package/dist/core/analyzer/ai/openrouter.d.ts +26 -0
  17. package/dist/core/analyzer/ai/openrouter.d.ts.map +1 -0
  18. package/dist/core/analyzer/ai/openrouter.js +77 -0
  19. package/dist/core/analyzer/ai/openrouter.js.map +1 -0
  20. package/dist/core/analyzer/ai/prompts.d.ts +32 -0
  21. package/dist/core/analyzer/ai/prompts.d.ts.map +1 -0
  22. package/dist/core/analyzer/ai/prompts.js +171 -0
  23. package/dist/core/analyzer/ai/prompts.js.map +1 -0
  24. package/dist/core/analyzer/index.d.ts +67 -0
  25. package/dist/core/analyzer/index.d.ts.map +1 -0
  26. package/dist/core/analyzer/index.js +224 -0
  27. package/dist/core/analyzer/index.js.map +1 -0
  28. package/dist/core/analyzer/static/index.d.ts +21 -0
  29. package/dist/core/analyzer/static/index.d.ts.map +1 -0
  30. package/dist/core/analyzer/static/index.js +69 -0
  31. package/dist/core/analyzer/static/index.js.map +1 -0
  32. package/dist/core/analyzer/types.d.ts +70 -0
  33. package/dist/core/analyzer/types.d.ts.map +1 -0
  34. package/dist/core/analyzer/types.js +27 -0
  35. package/dist/core/analyzer/types.js.map +1 -0
  36. package/dist/core/config/index.d.ts +28 -0
  37. package/dist/core/config/index.d.ts.map +1 -0
  38. package/dist/core/config/index.js +109 -0
  39. package/dist/core/config/index.js.map +1 -0
  40. package/dist/core/detector/index.d.ts +10 -0
  41. package/dist/core/detector/index.d.ts.map +1 -0
  42. package/dist/core/detector/index.js +306 -0
  43. package/dist/core/detector/index.js.map +1 -0
  44. package/dist/core/reporter/formats/json.d.ts +13 -0
  45. package/dist/core/reporter/formats/json.d.ts.map +1 -0
  46. package/dist/core/reporter/formats/json.js +23 -0
  47. package/dist/core/reporter/formats/json.js.map +1 -0
  48. package/dist/core/reporter/index.d.ts +15 -0
  49. package/dist/core/reporter/index.d.ts.map +1 -0
  50. package/dist/core/reporter/index.js +183 -0
  51. package/dist/core/reporter/index.js.map +1 -0
  52. package/dist/core/scanner/ignore-rules.d.ts +13 -0
  53. package/dist/core/scanner/ignore-rules.d.ts.map +1 -0
  54. package/dist/core/scanner/ignore-rules.js +162 -0
  55. package/dist/core/scanner/ignore-rules.js.map +1 -0
  56. package/dist/core/scanner/index.d.ts +16 -0
  57. package/dist/core/scanner/index.d.ts.map +1 -0
  58. package/dist/core/scanner/index.js +191 -0
  59. package/dist/core/scanner/index.js.map +1 -0
  60. package/dist/index.d.ts +51 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +126 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/types/index.d.ts +188 -0
  65. package/dist/types/index.d.ts.map +1 -0
  66. package/dist/types/index.js +13 -0
  67. package/dist/types/index.js.map +1 -0
  68. package/dist/utils/index.d.ts +54 -0
  69. package/dist/utils/index.d.ts.map +1 -0
  70. package/dist/utils/index.js +159 -0
  71. package/dist/utils/index.js.map +1 -0
  72. package/package.json +61 -0
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * Ignore rules handling for repository scanning
4
+ * Parses .gitignore files and custom ignore patterns
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.loadIgnoreRules = loadIgnoreRules;
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ /** Default patterns to always ignore */
44
+ const DEFAULT_IGNORE_PATTERNS = [
45
+ 'node_modules',
46
+ '.git',
47
+ 'dist',
48
+ 'build',
49
+ '.next',
50
+ '__pycache__',
51
+ '.pytest_cache',
52
+ 'venv',
53
+ '.venv',
54
+ 'env',
55
+ '.env',
56
+ '*.log',
57
+ '.DS_Store',
58
+ 'Thumbs.db',
59
+ 'coverage',
60
+ '.nyc_output',
61
+ ];
62
+ /**
63
+ * Load ignore rules from .gitignore and combine with custom patterns
64
+ */
65
+ async function loadIgnoreRules(rootPath, customPatterns = []) {
66
+ const patterns = [...DEFAULT_IGNORE_PATTERNS];
67
+ // Try to load .gitignore
68
+ const gitignorePath = path.join(rootPath, '.gitignore');
69
+ try {
70
+ const content = await fs.promises.readFile(gitignorePath, 'utf-8');
71
+ const gitignorePatterns = parseGitignore(content);
72
+ patterns.push(...gitignorePatterns);
73
+ }
74
+ catch {
75
+ // .gitignore doesn't exist or can't be read, continue without it
76
+ }
77
+ // Add custom patterns
78
+ patterns.push(...customPatterns);
79
+ return {
80
+ patterns,
81
+ isIgnored: (filePath) => shouldIgnore(filePath, patterns),
82
+ };
83
+ }
84
+ /**
85
+ * Parse .gitignore content into patterns
86
+ */
87
+ function parseGitignore(content) {
88
+ return content
89
+ .split('\n')
90
+ .map((line) => line.trim())
91
+ .filter((line) => line && !line.startsWith('#'));
92
+ }
93
+ /**
94
+ * Check if a file path should be ignored based on patterns
95
+ */
96
+ function shouldIgnore(filePath, patterns) {
97
+ const normalizedPath = filePath.replace(/\\/g, '/');
98
+ const pathParts = normalizedPath.split('/');
99
+ for (const pattern of patterns) {
100
+ // Check if any path segment matches the pattern
101
+ if (matchesPattern(normalizedPath, pattern, pathParts)) {
102
+ return true;
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+ /**
108
+ * Match a file path against a single pattern
109
+ */
110
+ function matchesPattern(filePath, pattern, pathParts) {
111
+ const normalizedPattern = pattern.replace(/\\/g, '/');
112
+ // Handle negation patterns (we don't support them yet)
113
+ if (normalizedPattern.startsWith('!')) {
114
+ // TODO(feature): Support negation patterns
115
+ return false;
116
+ }
117
+ // Handle directory-specific patterns (ending with /)
118
+ const isDirectoryPattern = normalizedPattern.endsWith('/');
119
+ const cleanPattern = isDirectoryPattern
120
+ ? normalizedPattern.slice(0, -1)
121
+ : normalizedPattern;
122
+ // Simple exact match on path segments
123
+ for (const part of pathParts) {
124
+ if (simpleMatch(part, cleanPattern)) {
125
+ return true;
126
+ }
127
+ }
128
+ // Full path match
129
+ if (simpleMatch(filePath, cleanPattern)) {
130
+ return true;
131
+ }
132
+ // Check if pattern matches end of path
133
+ if (filePath.endsWith('/' + cleanPattern) || filePath.endsWith(cleanPattern)) {
134
+ return true;
135
+ }
136
+ return false;
137
+ }
138
+ /**
139
+ * Simple glob matching supporting * and **
140
+ */
141
+ function simpleMatch(text, pattern) {
142
+ // Exact match
143
+ if (text === pattern)
144
+ return true;
145
+ // Handle ** (match any path)
146
+ if (pattern.includes('**')) {
147
+ const regex = new RegExp('^' +
148
+ pattern
149
+ .replace(/\./g, '\\.')
150
+ .replace(/\*\*/g, '.*')
151
+ .replace(/(?<!\.)(\*)(?!\*)/g, '[^/]*') +
152
+ '$');
153
+ return regex.test(text);
154
+ }
155
+ // Handle single * (match anything except /)
156
+ if (pattern.includes('*')) {
157
+ const regex = new RegExp('^' + pattern.replace(/\./g, '\\.').replace(/\*/g, '[^/]*') + '$');
158
+ return regex.test(text);
159
+ }
160
+ return false;
161
+ }
162
+ //# sourceMappingURL=ignore-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore-rules.js","sourceRoot":"","sources":["../../../src/core/scanner/ignore-rules.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCH,0CAuBC;AAtDD,4CAA8B;AAC9B,gDAAkC;AAOlC,wCAAwC;AACxC,MAAM,uBAAuB,GAAG;IAC9B,cAAc;IACd,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,aAAa;IACb,eAAe;IACf,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,OAAO;IACP,WAAW;IACX,WAAW;IACX,UAAU;IACV,aAAa;CACd,CAAC;AAEF;;GAEG;AACI,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,iBAA2B,EAAE;IAE7B,MAAM,QAAQ,GAAa,CAAC,GAAG,uBAAuB,CAAC,CAAC;IAExD,yBAAyB;IACzB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QAClD,QAAQ,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IAED,sBAAsB;IACtB,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;IAEjC,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC;KAClE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,OAAO,OAAO;SACX,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,QAAgB,EAAE,QAAkB;IACxD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE5C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,gDAAgD;QAChD,IAAI,cAAc,CAAC,cAAc,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,QAAgB,EAChB,OAAe,EACf,SAAmB;IAEnB,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEtD,uDAAuD;IACvD,IAAI,iBAAiB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,2CAA2C;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,qDAAqD;IACrD,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,kBAAkB;QACrC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,iBAAiB,CAAC;IAEtB,sCAAsC;IACtC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IAAI,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,IAAI,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,YAAY,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAY,EAAE,OAAe;IAChD,cAAc;IACd,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAElC,6BAA6B;IAC7B,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,GAAG;YACD,OAAO;iBACJ,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;iBACrB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;iBACtB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;YACzC,GAAG,CACN,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,4CAA4C;IAC5C,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,GAAG,CAClE,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Repository scanner module
3
+ * Walks directory tree and returns file information
4
+ */
5
+ import type { FileInfo, ScanConfig, ScanResult } from '../../types/index.js';
6
+ import { loadIgnoreRules, type IgnoreRules } from './ignore-rules.js';
7
+ /**
8
+ * Scan a repository and return file information
9
+ */
10
+ export declare function scanRepository(rootPath: string, config?: ScanConfig): Promise<ScanResult>;
11
+ /**
12
+ * Load content for a file (on-demand loading)
13
+ */
14
+ export declare function loadFileContent(file: FileInfo): Promise<string>;
15
+ export { loadIgnoreRules, type IgnoreRules };
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/scanner/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAa,MAAM,sBAAsB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAgCtE;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,UAAe,GACtB,OAAO,CAAC,UAAU,CAAC,CA0BrB;AAuGD;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrE;AAGD,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,CAAC"}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * Repository scanner module
4
+ * Walks directory tree and returns file information
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.loadIgnoreRules = void 0;
41
+ exports.scanRepository = scanRepository;
42
+ exports.loadFileContent = loadFileContent;
43
+ const fs = __importStar(require("node:fs"));
44
+ const path = __importStar(require("node:path"));
45
+ const index_js_1 = require("../../utils/index.js");
46
+ const ignore_rules_js_1 = require("./ignore-rules.js");
47
+ Object.defineProperty(exports, "loadIgnoreRules", { enumerable: true, get: function () { return ignore_rules_js_1.loadIgnoreRules; } });
48
+ /** Default scan configuration */
49
+ const DEFAULT_SCAN_CONFIG = {
50
+ ignorePatterns: [],
51
+ useGitignore: true,
52
+ maxFileSize: 1024 * 1024, // 1MB
53
+ includeExtensions: [],
54
+ };
55
+ /** Extensions commonly associated with code files */
56
+ const CODE_EXTENSIONS = new Set([
57
+ '.ts',
58
+ '.tsx',
59
+ '.js',
60
+ '.jsx',
61
+ '.mjs',
62
+ '.cjs',
63
+ '.py',
64
+ '.json',
65
+ '.md',
66
+ '.yaml',
67
+ '.yml',
68
+ '.toml',
69
+ '.css',
70
+ '.scss',
71
+ '.less',
72
+ '.html',
73
+ '.vue',
74
+ '.svelte',
75
+ ]);
76
+ /**
77
+ * Scan a repository and return file information
78
+ */
79
+ async function scanRepository(rootPath, config = {}) {
80
+ const resolvedRoot = (0, index_js_1.normalizePath)(rootPath);
81
+ const mergedConfig = { ...DEFAULT_SCAN_CONFIG, ...config };
82
+ // Load ignore rules
83
+ const ignoreRules = await (0, ignore_rules_js_1.loadIgnoreRules)(resolvedRoot, mergedConfig.ignorePatterns);
84
+ // Collect files
85
+ const files = [];
86
+ const stats = {
87
+ totalFiles: 0,
88
+ totalSize: 0,
89
+ skippedFiles: 0,
90
+ byExtension: {},
91
+ };
92
+ await walkDirectory(resolvedRoot, resolvedRoot, mergedConfig, ignoreRules, files, stats);
93
+ return {
94
+ files,
95
+ stats,
96
+ rootPath: resolvedRoot,
97
+ };
98
+ }
99
+ /**
100
+ * Recursively walk a directory and collect file information
101
+ */
102
+ async function walkDirectory(currentPath, rootPath, config, ignoreRules, files, stats) {
103
+ let entries;
104
+ try {
105
+ entries = await fs.promises.readdir(currentPath, { withFileTypes: true });
106
+ }
107
+ catch {
108
+ // Directory can't be read, skip it
109
+ return;
110
+ }
111
+ // TODO(feature): Add parallel scanning for better performance on large repos
112
+ for (const entry of entries) {
113
+ const fullPath = path.join(currentPath, entry.name);
114
+ const relativePath = (0, index_js_1.getRelativePath)(rootPath, fullPath);
115
+ // Check if should be ignored
116
+ if (ignoreRules.isIgnored(relativePath)) {
117
+ stats.skippedFiles++;
118
+ continue;
119
+ }
120
+ if (entry.isDirectory()) {
121
+ // Recurse into subdirectory
122
+ await walkDirectory(fullPath, rootPath, config, ignoreRules, files, stats);
123
+ }
124
+ else if (entry.isFile()) {
125
+ // Process file
126
+ const fileInfo = await processFile(fullPath, rootPath, config);
127
+ if (fileInfo) {
128
+ files.push(fileInfo);
129
+ stats.totalFiles++;
130
+ stats.totalSize += fileInfo.size;
131
+ // Track by extension
132
+ const ext = fileInfo.extension || '(none)';
133
+ stats.byExtension[ext] = (stats.byExtension[ext] || 0) + 1;
134
+ }
135
+ else {
136
+ stats.skippedFiles++;
137
+ }
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Process a single file and return FileInfo if it should be included
143
+ */
144
+ async function processFile(filePath, rootPath, config) {
145
+ const extension = (0, index_js_1.getExtension)(filePath);
146
+ // Check extension filter
147
+ if (config.includeExtensions.length > 0) {
148
+ if (!config.includeExtensions.includes(extension)) {
149
+ return null;
150
+ }
151
+ }
152
+ else {
153
+ // Default: only include known code extensions
154
+ if (!CODE_EXTENSIONS.has(extension)) {
155
+ return null;
156
+ }
157
+ }
158
+ // Get file stats
159
+ let fileStats;
160
+ try {
161
+ fileStats = await fs.promises.stat(filePath);
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ // Check file size
167
+ if (fileStats.size > config.maxFileSize) {
168
+ return null;
169
+ }
170
+ // TODO(feature): Add binary file detection to skip non-text files
171
+ return {
172
+ path: (0, index_js_1.normalizePath)(filePath),
173
+ relativePath: (0, index_js_1.getRelativePath)(rootPath, filePath),
174
+ extension,
175
+ size: fileStats.size,
176
+ // Content is loaded on-demand, not during scanning
177
+ content: undefined,
178
+ };
179
+ }
180
+ /**
181
+ * Load content for a file (on-demand loading)
182
+ */
183
+ async function loadFileContent(file) {
184
+ if (file.content !== undefined) {
185
+ return file.content;
186
+ }
187
+ const content = await fs.promises.readFile(file.path, 'utf-8');
188
+ file.content = content;
189
+ return content;
190
+ }
191
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/scanner/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * LampsCodeReview SDK
3
+ * AI-powered code review for modern web codebases
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { LampsCodeReview } from 'lamps-code-review';
8
+ *
9
+ * const reviewer = new LampsCodeReview();
10
+ * const report = await reviewer.review('./my-project');
11
+ * console.log(report.summary.healthScore);
12
+ * ```
13
+ */
14
+ import type { ReviewConfig, ReviewReport, Analyzer } from './types/index.js';
15
+ /**
16
+ * Main SDK class for running code reviews
17
+ */
18
+ export declare class LampsCodeReview {
19
+ private config;
20
+ private customAnalyzers;
21
+ constructor(config?: ReviewConfig);
22
+ /**
23
+ * Run a code review on a repository
24
+ * @param repoPath - Path to the repository to review
25
+ * @returns Structured review report
26
+ */
27
+ review(repoPath: string): Promise<ReviewReport>;
28
+ /**
29
+ * Register a custom analyzer
30
+ * @param analyzer - Analyzer instance to register
31
+ */
32
+ registerAnalyzer(analyzer: Analyzer): void;
33
+ /**
34
+ * Get registered custom analyzers
35
+ */
36
+ getCustomAnalyzers(): Analyzer[];
37
+ /**
38
+ * Format a report to a specific output format
39
+ * @param report - Report to format
40
+ * @param format - Output format ('json', 'markdown', 'html')
41
+ */
42
+ formatReport(report: ReviewReport, format?: ReviewConfig['format']): string;
43
+ }
44
+ export type { ReviewConfig, ReviewReport, ReportSummary, Finding, Severity, Analyzer, AnalyzerPhase, AnalysisContext, AnalysisResult, Framework, DetectionResult, FrameworkDetection, FileInfo, ScanConfig, ScanResult, ReportFormat, CLIOptions, AIConfig, LampsConfig, } from './types/index.js';
45
+ export { DEFAULT_AI_CONFIG } from './types/index.js';
46
+ export { scanRepository, loadFileContent } from './core/scanner/index.js';
47
+ export { detectFrameworks } from './core/detector/index.js';
48
+ export { AnalyzerPipeline, BaseAnalyzer } from './core/analyzer/index.js';
49
+ export { generateReport, formatReport } from './core/reporter/index.js';
50
+ export { loadConfig, mergeAIConfig } from './core/config/index.js';
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,QAAQ,EAGT,MAAM,kBAAkB,CAAC;AAG1B;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAAkB;gBAE7B,MAAM,GAAE,YAAiB;IAIrC;;;;OAIG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAmErD;;;OAGG;IACH,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAI1C;;OAEG;IACH,kBAAkB,IAAI,QAAQ,EAAE;IAIhC;;;;OAIG;IACH,YAAY,CACV,MAAM,EAAE,YAAY,EACpB,MAAM,GAAE,YAAY,CAAC,QAAQ,CAAU,GACtC,MAAM;CAGV;AAGD,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,eAAe,EACf,cAAc,EACd,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * LampsCodeReview SDK
4
+ * AI-powered code review for modern web codebases
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { LampsCodeReview } from 'lamps-code-review';
9
+ *
10
+ * const reviewer = new LampsCodeReview();
11
+ * const report = await reviewer.review('./my-project');
12
+ * console.log(report.summary.healthScore);
13
+ * ```
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.mergeAIConfig = exports.loadConfig = exports.formatReport = exports.generateReport = exports.BaseAnalyzer = exports.AnalyzerPipeline = exports.detectFrameworks = exports.loadFileContent = exports.scanRepository = exports.DEFAULT_AI_CONFIG = exports.LampsCodeReview = void 0;
17
+ const index_js_1 = require("./core/scanner/index.js");
18
+ const index_js_2 = require("./core/detector/index.js");
19
+ const index_js_3 = require("./core/analyzer/index.js");
20
+ const index_js_4 = require("./core/reporter/index.js");
21
+ const index_js_5 = require("./core/config/index.js");
22
+ const index_js_6 = require("./utils/index.js");
23
+ /**
24
+ * Main SDK class for running code reviews
25
+ */
26
+ class LampsCodeReview {
27
+ constructor(config = {}) {
28
+ this.customAnalyzers = [];
29
+ this.config = config;
30
+ }
31
+ /**
32
+ * Run a code review on a repository
33
+ * @param repoPath - Path to the repository to review
34
+ * @returns Structured review report
35
+ */
36
+ async review(repoPath) {
37
+ const logger = (0, index_js_6.createLogger)(this.config.verbose);
38
+ logger.debug(`Starting review of: ${repoPath}`);
39
+ // Load config file from repo (if exists)
40
+ const fileConfig = await (0, index_js_5.loadConfig)(repoPath);
41
+ // Merge configs: file config < constructor config (constructor takes priority)
42
+ const mergedConfig = {
43
+ ...fileConfig,
44
+ ...this.config,
45
+ ai: { ...fileConfig.ai, ...this.config.ai },
46
+ scan: { ...fileConfig.scan, ...this.config.scan },
47
+ };
48
+ // Build AI config
49
+ const aiConfig = (0, index_js_5.mergeAIConfig)(mergedConfig.ai);
50
+ logger.debug(`AI model: ${aiConfig.model}`);
51
+ // Create pipeline with AI config
52
+ const pipeline = new index_js_3.AnalyzerPipeline({}, aiConfig);
53
+ // Register custom analyzers
54
+ for (const analyzer of this.customAnalyzers) {
55
+ pipeline.registerAnalyzer(analyzer);
56
+ }
57
+ // Phase 1: Scan repository
58
+ logger.debug('Scanning repository...');
59
+ const scanResult = await (0, index_js_1.scanRepository)(repoPath, mergedConfig.scan);
60
+ logger.debug(`Found ${scanResult.files.length} files`);
61
+ // Phase 2: Detect frameworks
62
+ logger.debug('Detecting frameworks...');
63
+ const frameworks = await (0, index_js_2.detectFrameworks)(scanResult.files, scanResult.rootPath);
64
+ logger.debug(`Primary framework: ${frameworks.primary || 'unknown'}`);
65
+ // Phase 3: Run analyzers
66
+ logger.debug('Running analyzers...');
67
+ const context = {
68
+ files: scanResult.files,
69
+ frameworks,
70
+ config: mergedConfig,
71
+ rootPath: scanResult.rootPath,
72
+ };
73
+ const pipelineResult = await pipeline.run(context);
74
+ logger.debug(`Analysis complete in ${pipelineResult.duration}ms`);
75
+ if (pipelineResult.hasErrors) {
76
+ for (const error of pipelineResult.errors) {
77
+ logger.warn(`Analyzer error: ${error}`);
78
+ }
79
+ }
80
+ // Phase 4: Generate report
81
+ logger.debug('Generating report...');
82
+ const report = (0, index_js_4.generateReport)(scanResult.rootPath, scanResult.files.length, frameworks, pipelineResult.results);
83
+ return report;
84
+ }
85
+ /**
86
+ * Register a custom analyzer
87
+ * @param analyzer - Analyzer instance to register
88
+ */
89
+ registerAnalyzer(analyzer) {
90
+ this.customAnalyzers.push(analyzer);
91
+ }
92
+ /**
93
+ * Get registered custom analyzers
94
+ */
95
+ getCustomAnalyzers() {
96
+ return [...this.customAnalyzers];
97
+ }
98
+ /**
99
+ * Format a report to a specific output format
100
+ * @param report - Report to format
101
+ * @param format - Output format ('json', 'markdown', 'html')
102
+ */
103
+ formatReport(report, format = 'json') {
104
+ return (0, index_js_4.formatReport)(report, format || 'json');
105
+ }
106
+ }
107
+ exports.LampsCodeReview = LampsCodeReview;
108
+ // Re-export default config
109
+ var index_js_7 = require("./types/index.js");
110
+ Object.defineProperty(exports, "DEFAULT_AI_CONFIG", { enumerable: true, get: function () { return index_js_7.DEFAULT_AI_CONFIG; } });
111
+ // Re-export core modules for advanced usage
112
+ var index_js_8 = require("./core/scanner/index.js");
113
+ Object.defineProperty(exports, "scanRepository", { enumerable: true, get: function () { return index_js_8.scanRepository; } });
114
+ Object.defineProperty(exports, "loadFileContent", { enumerable: true, get: function () { return index_js_8.loadFileContent; } });
115
+ var index_js_9 = require("./core/detector/index.js");
116
+ Object.defineProperty(exports, "detectFrameworks", { enumerable: true, get: function () { return index_js_9.detectFrameworks; } });
117
+ var index_js_10 = require("./core/analyzer/index.js");
118
+ Object.defineProperty(exports, "AnalyzerPipeline", { enumerable: true, get: function () { return index_js_10.AnalyzerPipeline; } });
119
+ Object.defineProperty(exports, "BaseAnalyzer", { enumerable: true, get: function () { return index_js_10.BaseAnalyzer; } });
120
+ var index_js_11 = require("./core/reporter/index.js");
121
+ Object.defineProperty(exports, "generateReport", { enumerable: true, get: function () { return index_js_11.generateReport; } });
122
+ Object.defineProperty(exports, "formatReport", { enumerable: true, get: function () { return index_js_11.formatReport; } });
123
+ var index_js_12 = require("./core/config/index.js");
124
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return index_js_12.loadConfig; } });
125
+ Object.defineProperty(exports, "mergeAIConfig", { enumerable: true, get: function () { return index_js_12.mergeAIConfig; } });
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}