archicore 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 (118) hide show
  1. package/README.md +530 -0
  2. package/dist/analyzers/dead-code.d.ts +95 -0
  3. package/dist/analyzers/dead-code.js +327 -0
  4. package/dist/analyzers/duplication.d.ts +90 -0
  5. package/dist/analyzers/duplication.js +344 -0
  6. package/dist/analyzers/security.d.ts +79 -0
  7. package/dist/analyzers/security.js +484 -0
  8. package/dist/architecture/index.d.ts +35 -0
  9. package/dist/architecture/index.js +249 -0
  10. package/dist/cli/commands/analyzers.d.ts +6 -0
  11. package/dist/cli/commands/analyzers.js +431 -0
  12. package/dist/cli/commands/export.d.ts +6 -0
  13. package/dist/cli/commands/export.js +78 -0
  14. package/dist/cli/commands/index.d.ts +8 -0
  15. package/dist/cli/commands/index.js +8 -0
  16. package/dist/cli/commands/init.d.ts +26 -0
  17. package/dist/cli/commands/init.js +140 -0
  18. package/dist/cli/commands/interactive.d.ts +7 -0
  19. package/dist/cli/commands/interactive.js +522 -0
  20. package/dist/cli/commands/projects.d.ts +6 -0
  21. package/dist/cli/commands/projects.js +249 -0
  22. package/dist/cli/index.d.ts +7 -0
  23. package/dist/cli/index.js +7 -0
  24. package/dist/cli/ui/box.d.ts +17 -0
  25. package/dist/cli/ui/box.js +62 -0
  26. package/dist/cli/ui/colors.d.ts +49 -0
  27. package/dist/cli/ui/colors.js +86 -0
  28. package/dist/cli/ui/index.d.ts +9 -0
  29. package/dist/cli/ui/index.js +9 -0
  30. package/dist/cli/ui/prompt.d.ts +34 -0
  31. package/dist/cli/ui/prompt.js +122 -0
  32. package/dist/cli/ui/spinner.d.ts +29 -0
  33. package/dist/cli/ui/spinner.js +80 -0
  34. package/dist/cli/ui/table.d.ts +33 -0
  35. package/dist/cli/ui/table.js +84 -0
  36. package/dist/cli/utils/config.d.ts +23 -0
  37. package/dist/cli/utils/config.js +73 -0
  38. package/dist/cli/utils/index.d.ts +6 -0
  39. package/dist/cli/utils/index.js +6 -0
  40. package/dist/cli/utils/session.d.ts +27 -0
  41. package/dist/cli/utils/session.js +117 -0
  42. package/dist/cli.d.ts +8 -0
  43. package/dist/cli.js +295 -0
  44. package/dist/code-index/ast-parser.d.ts +16 -0
  45. package/dist/code-index/ast-parser.js +330 -0
  46. package/dist/code-index/dependency-graph.d.ts +16 -0
  47. package/dist/code-index/dependency-graph.js +161 -0
  48. package/dist/code-index/index.d.ts +44 -0
  49. package/dist/code-index/index.js +124 -0
  50. package/dist/code-index/symbol-extractor.d.ts +13 -0
  51. package/dist/code-index/symbol-extractor.js +150 -0
  52. package/dist/export/index.d.ts +92 -0
  53. package/dist/export/index.js +676 -0
  54. package/dist/github/github-service.d.ts +146 -0
  55. package/dist/github/github-service.js +609 -0
  56. package/dist/impact-engine/index.d.ts +25 -0
  57. package/dist/impact-engine/index.js +284 -0
  58. package/dist/index.d.ts +60 -0
  59. package/dist/index.js +149 -0
  60. package/dist/metrics/index.d.ts +136 -0
  61. package/dist/metrics/index.js +525 -0
  62. package/dist/orchestrator/deepseek-optimizer.d.ts +67 -0
  63. package/dist/orchestrator/deepseek-optimizer.js +320 -0
  64. package/dist/orchestrator/index.d.ts +34 -0
  65. package/dist/orchestrator/index.js +305 -0
  66. package/dist/pr-guardian/index.d.ts +143 -0
  67. package/dist/pr-guardian/index.js +553 -0
  68. package/dist/refactoring/index.d.ts +108 -0
  69. package/dist/refactoring/index.js +580 -0
  70. package/dist/rules-engine/index.d.ts +129 -0
  71. package/dist/rules-engine/index.js +482 -0
  72. package/dist/semantic-memory/embedding-service.d.ts +24 -0
  73. package/dist/semantic-memory/embedding-service.js +120 -0
  74. package/dist/semantic-memory/index.d.ts +45 -0
  75. package/dist/semantic-memory/index.js +206 -0
  76. package/dist/semantic-memory/vector-store.d.ts +27 -0
  77. package/dist/semantic-memory/vector-store.js +166 -0
  78. package/dist/server/index.d.ts +28 -0
  79. package/dist/server/index.js +141 -0
  80. package/dist/server/middleware/api-auth.d.ts +43 -0
  81. package/dist/server/middleware/api-auth.js +256 -0
  82. package/dist/server/routes/admin.d.ts +5 -0
  83. package/dist/server/routes/admin.js +123 -0
  84. package/dist/server/routes/api.d.ts +7 -0
  85. package/dist/server/routes/api.js +362 -0
  86. package/dist/server/routes/auth.d.ts +16 -0
  87. package/dist/server/routes/auth.js +191 -0
  88. package/dist/server/routes/developer.d.ts +8 -0
  89. package/dist/server/routes/developer.js +439 -0
  90. package/dist/server/routes/github.d.ts +7 -0
  91. package/dist/server/routes/github.js +495 -0
  92. package/dist/server/routes/upload.d.ts +7 -0
  93. package/dist/server/routes/upload.js +196 -0
  94. package/dist/server/services/api-key-service.d.ts +81 -0
  95. package/dist/server/services/api-key-service.js +281 -0
  96. package/dist/server/services/auth-service.d.ts +40 -0
  97. package/dist/server/services/auth-service.js +315 -0
  98. package/dist/server/services/project-service.d.ts +123 -0
  99. package/dist/server/services/project-service.js +533 -0
  100. package/dist/server/services/token-service.d.ts +107 -0
  101. package/dist/server/services/token-service.js +416 -0
  102. package/dist/server/services/upload-service.d.ts +93 -0
  103. package/dist/server/services/upload-service.js +464 -0
  104. package/dist/types/api.d.ts +188 -0
  105. package/dist/types/api.js +86 -0
  106. package/dist/types/github.d.ts +335 -0
  107. package/dist/types/github.js +5 -0
  108. package/dist/types/index.d.ts +265 -0
  109. package/dist/types/index.js +32 -0
  110. package/dist/types/user.d.ts +69 -0
  111. package/dist/types/user.js +42 -0
  112. package/dist/utils/file-utils.d.ts +20 -0
  113. package/dist/utils/file-utils.js +163 -0
  114. package/dist/utils/logger.d.ts +17 -0
  115. package/dist/utils/logger.js +41 -0
  116. package/dist/watcher/index.d.ts +125 -0
  117. package/dist/watcher/index.js +397 -0
  118. package/package.json +71 -0
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Architecture Rules Engine
3
+ *
4
+ * Определение и проверка архитектурных правил:
5
+ * - Запрет импортов между слоями
6
+ * - Циклические зависимости
7
+ * - Naming conventions
8
+ * - Layer boundaries
9
+ */
10
+ import { DependencyGraph, Symbol } from '../types/index.js';
11
+ export type RuleType = 'no-import' | 'must-import' | 'no-circular' | 'layer-boundary' | 'naming-convention' | 'max-dependencies' | 'max-file-size' | 'max-function-length' | 'no-god-class' | 'single-responsibility';
12
+ export type RuleSeverity = 'error' | 'warning' | 'info';
13
+ export interface ArchitectureRule {
14
+ id: string;
15
+ name: string;
16
+ description: string;
17
+ type: RuleType;
18
+ severity: RuleSeverity;
19
+ enabled: boolean;
20
+ config: RuleConfig;
21
+ }
22
+ export interface RuleConfig {
23
+ sourcePattern?: string;
24
+ targetPattern?: string;
25
+ layers?: LayerDefinition[];
26
+ pattern?: string;
27
+ filePattern?: string;
28
+ maxValue?: number;
29
+ customCheck?: string;
30
+ }
31
+ export interface LayerDefinition {
32
+ name: string;
33
+ pattern: string;
34
+ allowedDependencies: string[];
35
+ }
36
+ export interface RuleViolation {
37
+ ruleId: string;
38
+ ruleName: string;
39
+ severity: RuleSeverity;
40
+ message: string;
41
+ file: string;
42
+ line?: number;
43
+ column?: number;
44
+ suggestion?: string;
45
+ }
46
+ export interface RulesCheckResult {
47
+ passed: boolean;
48
+ violations: RuleViolation[];
49
+ summary: {
50
+ total: number;
51
+ errors: number;
52
+ warnings: number;
53
+ infos: number;
54
+ };
55
+ }
56
+ export declare const DEFAULT_RULES: ArchitectureRule[];
57
+ export declare class RulesEngine {
58
+ private rules;
59
+ constructor(customRules?: ArchitectureRule[]);
60
+ /**
61
+ * Добавить или обновить правило
62
+ */
63
+ addRule(rule: ArchitectureRule): void;
64
+ /**
65
+ * Удалить правило
66
+ */
67
+ removeRule(ruleId: string): void;
68
+ /**
69
+ * Включить/выключить правило
70
+ */
71
+ toggleRule(ruleId: string, enabled: boolean): void;
72
+ /**
73
+ * Получить все правила
74
+ */
75
+ getRules(): ArchitectureRule[];
76
+ /**
77
+ * Получить включённые правила
78
+ */
79
+ getEnabledRules(): ArchitectureRule[];
80
+ /**
81
+ * Проверить проект на соответствие правилам
82
+ */
83
+ check(graph: DependencyGraph, symbols: Map<string, Symbol>, fileContents: Map<string, string>): Promise<RulesCheckResult>;
84
+ /**
85
+ * Проверить одно правило
86
+ */
87
+ private checkRule;
88
+ /**
89
+ * Проверка на циклические зависимости
90
+ */
91
+ private checkNoCircular;
92
+ /**
93
+ * Проверка запрета импорта
94
+ */
95
+ private checkNoImport;
96
+ /**
97
+ * Проверка границ слоёв
98
+ */
99
+ private checkLayerBoundary;
100
+ /**
101
+ * Проверка максимального количества зависимостей
102
+ */
103
+ private checkMaxDependencies;
104
+ /**
105
+ * Проверка максимального размера файла
106
+ */
107
+ private checkMaxFileSize;
108
+ /**
109
+ * Проверка максимальной длины функции
110
+ */
111
+ private checkMaxFunctionLength;
112
+ /**
113
+ * Проверка на God Class
114
+ */
115
+ private checkNoGodClass;
116
+ /**
117
+ * Проверка соглашений об именовании
118
+ */
119
+ private checkNamingConvention;
120
+ /**
121
+ * Экспорт правил в JSON
122
+ */
123
+ exportRules(): string;
124
+ /**
125
+ * Импорт правил из JSON
126
+ */
127
+ importRules(json: string): void;
128
+ }
129
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,482 @@
1
+ /**
2
+ * Architecture Rules Engine
3
+ *
4
+ * Определение и проверка архитектурных правил:
5
+ * - Запрет импортов между слоями
6
+ * - Циклические зависимости
7
+ * - Naming conventions
8
+ * - Layer boundaries
9
+ */
10
+ import { SymbolKind } from '../types/index.js';
11
+ import { Logger } from '../utils/logger.js';
12
+ // Предустановленные правила
13
+ export const DEFAULT_RULES = [
14
+ {
15
+ id: 'no-circular-deps',
16
+ name: 'No Circular Dependencies',
17
+ description: 'Запрет циклических зависимостей между модулями',
18
+ type: 'no-circular',
19
+ severity: 'error',
20
+ enabled: true,
21
+ config: {}
22
+ },
23
+ {
24
+ id: 'layer-boundary-clean',
25
+ name: 'Clean Architecture Layers',
26
+ description: 'Проверка границ слоёв Clean Architecture',
27
+ type: 'layer-boundary',
28
+ severity: 'error',
29
+ enabled: false,
30
+ config: {
31
+ layers: [
32
+ { name: 'domain', pattern: '(domain|entities)', allowedDependencies: [] },
33
+ { name: 'application', pattern: '(application|usecases|services)', allowedDependencies: ['domain'] },
34
+ { name: 'infrastructure', pattern: '(infrastructure|adapters)', allowedDependencies: ['domain', 'application'] },
35
+ { name: 'presentation', pattern: '(presentation|controllers|views)', allowedDependencies: ['domain', 'application'] }
36
+ ]
37
+ }
38
+ },
39
+ {
40
+ id: 'no-utils-in-domain',
41
+ name: 'No Utils in Domain',
42
+ description: 'Domain не должен импортировать utils',
43
+ type: 'no-import',
44
+ severity: 'warning',
45
+ enabled: true,
46
+ config: {
47
+ sourcePattern: 'domain',
48
+ targetPattern: 'utils'
49
+ }
50
+ },
51
+ {
52
+ id: 'max-dependencies-10',
53
+ name: 'Max 10 Dependencies',
54
+ description: 'Файл не должен иметь более 10 зависимостей',
55
+ type: 'max-dependencies',
56
+ severity: 'warning',
57
+ enabled: true,
58
+ config: {
59
+ maxValue: 10
60
+ }
61
+ },
62
+ {
63
+ id: 'max-file-size-500',
64
+ name: 'Max 500 Lines',
65
+ description: 'Файл не должен превышать 500 строк',
66
+ type: 'max-file-size',
67
+ severity: 'warning',
68
+ enabled: true,
69
+ config: {
70
+ maxValue: 500
71
+ }
72
+ },
73
+ {
74
+ id: 'max-function-length-50',
75
+ name: 'Max 50 Lines per Function',
76
+ description: 'Функция не должна превышать 50 строк',
77
+ type: 'max-function-length',
78
+ severity: 'warning',
79
+ enabled: true,
80
+ config: {
81
+ maxValue: 50
82
+ }
83
+ },
84
+ {
85
+ id: 'no-god-class-20',
86
+ name: 'No God Class',
87
+ description: 'Класс не должен иметь более 20 методов',
88
+ type: 'no-god-class',
89
+ severity: 'warning',
90
+ enabled: true,
91
+ config: {
92
+ maxValue: 20
93
+ }
94
+ },
95
+ {
96
+ id: 'component-naming',
97
+ name: 'Component Naming Convention',
98
+ description: 'React компоненты должны быть в PascalCase',
99
+ type: 'naming-convention',
100
+ severity: 'info',
101
+ enabled: false,
102
+ config: {
103
+ filePattern: '\\.tsx$',
104
+ pattern: '^[A-Z][a-zA-Z0-9]*$'
105
+ }
106
+ }
107
+ ];
108
+ export class RulesEngine {
109
+ rules = new Map();
110
+ constructor(customRules) {
111
+ // Загружаем дефолтные правила
112
+ DEFAULT_RULES.forEach(rule => this.rules.set(rule.id, rule));
113
+ // Добавляем кастомные
114
+ if (customRules) {
115
+ customRules.forEach(rule => this.rules.set(rule.id, rule));
116
+ }
117
+ }
118
+ /**
119
+ * Добавить или обновить правило
120
+ */
121
+ addRule(rule) {
122
+ this.rules.set(rule.id, rule);
123
+ }
124
+ /**
125
+ * Удалить правило
126
+ */
127
+ removeRule(ruleId) {
128
+ this.rules.delete(ruleId);
129
+ }
130
+ /**
131
+ * Включить/выключить правило
132
+ */
133
+ toggleRule(ruleId, enabled) {
134
+ const rule = this.rules.get(ruleId);
135
+ if (rule) {
136
+ rule.enabled = enabled;
137
+ }
138
+ }
139
+ /**
140
+ * Получить все правила
141
+ */
142
+ getRules() {
143
+ return Array.from(this.rules.values());
144
+ }
145
+ /**
146
+ * Получить включённые правила
147
+ */
148
+ getEnabledRules() {
149
+ return this.getRules().filter(r => r.enabled);
150
+ }
151
+ /**
152
+ * Проверить проект на соответствие правилам
153
+ */
154
+ async check(graph, symbols, fileContents) {
155
+ const violations = [];
156
+ const enabledRules = this.getEnabledRules();
157
+ Logger.progress(`Checking ${enabledRules.length} architecture rules...`);
158
+ for (const rule of enabledRules) {
159
+ const ruleViolations = await this.checkRule(rule, graph, symbols, fileContents);
160
+ violations.push(...ruleViolations);
161
+ }
162
+ const summary = {
163
+ total: violations.length,
164
+ errors: violations.filter(v => v.severity === 'error').length,
165
+ warnings: violations.filter(v => v.severity === 'warning').length,
166
+ infos: violations.filter(v => v.severity === 'info').length
167
+ };
168
+ const passed = summary.errors === 0;
169
+ if (passed) {
170
+ Logger.success(`All architecture rules passed (${summary.warnings} warnings)`);
171
+ }
172
+ else {
173
+ Logger.error(`Architecture rules check failed: ${summary.errors} errors, ${summary.warnings} warnings`);
174
+ }
175
+ return { passed, violations, summary };
176
+ }
177
+ /**
178
+ * Проверить одно правило
179
+ */
180
+ async checkRule(rule, graph, symbols, fileContents) {
181
+ switch (rule.type) {
182
+ case 'no-circular':
183
+ return this.checkNoCircular(rule, graph);
184
+ case 'no-import':
185
+ return this.checkNoImport(rule, graph);
186
+ case 'layer-boundary':
187
+ return this.checkLayerBoundary(rule, graph);
188
+ case 'max-dependencies':
189
+ return this.checkMaxDependencies(rule, graph);
190
+ case 'max-file-size':
191
+ return this.checkMaxFileSize(rule, fileContents);
192
+ case 'max-function-length':
193
+ return this.checkMaxFunctionLength(rule, symbols);
194
+ case 'no-god-class':
195
+ return this.checkNoGodClass(rule, symbols);
196
+ case 'naming-convention':
197
+ return this.checkNamingConvention(rule, symbols, fileContents);
198
+ default:
199
+ return [];
200
+ }
201
+ }
202
+ /**
203
+ * Проверка на циклические зависимости
204
+ */
205
+ checkNoCircular(rule, graph) {
206
+ const violations = [];
207
+ const visited = new Set();
208
+ const recursionStack = new Set();
209
+ const cycles = [];
210
+ const dfs = (nodeId, path) => {
211
+ visited.add(nodeId);
212
+ recursionStack.add(nodeId);
213
+ path.push(nodeId);
214
+ const edges = graph.edges.get(nodeId) || [];
215
+ for (const edge of edges) {
216
+ if (!visited.has(edge.to)) {
217
+ dfs(edge.to, [...path]);
218
+ }
219
+ else if (recursionStack.has(edge.to)) {
220
+ // Нашли цикл
221
+ const cycleStart = path.indexOf(edge.to);
222
+ const cycle = path.slice(cycleStart);
223
+ cycle.push(edge.to);
224
+ cycles.push(cycle);
225
+ }
226
+ }
227
+ recursionStack.delete(nodeId);
228
+ };
229
+ for (const nodeId of graph.nodes.keys()) {
230
+ if (!visited.has(nodeId)) {
231
+ dfs(nodeId, []);
232
+ }
233
+ }
234
+ // Убираем дубликаты циклов
235
+ const uniqueCycles = new Set();
236
+ for (const cycle of cycles) {
237
+ const normalized = [...cycle].sort().join(' -> ');
238
+ if (!uniqueCycles.has(normalized)) {
239
+ uniqueCycles.add(normalized);
240
+ const node = graph.nodes.get(cycle[0]);
241
+ violations.push({
242
+ ruleId: rule.id,
243
+ ruleName: rule.name,
244
+ severity: rule.severity,
245
+ message: `Circular dependency detected: ${cycle.join(' -> ')}`,
246
+ file: node?.filePath || cycle[0],
247
+ suggestion: 'Рассмотрите введение интерфейса или перенос общего кода в отдельный модуль'
248
+ });
249
+ }
250
+ }
251
+ return violations;
252
+ }
253
+ /**
254
+ * Проверка запрета импорта
255
+ */
256
+ checkNoImport(rule, graph) {
257
+ const violations = [];
258
+ const { sourcePattern, targetPattern } = rule.config;
259
+ if (!sourcePattern || !targetPattern)
260
+ return violations;
261
+ const sourceRegex = new RegExp(sourcePattern, 'i');
262
+ const targetRegex = new RegExp(targetPattern, 'i');
263
+ for (const [nodeId, edges] of graph.edges) {
264
+ const sourceNode = graph.nodes.get(nodeId);
265
+ if (!sourceNode || !sourceRegex.test(sourceNode.filePath))
266
+ continue;
267
+ for (const edge of edges) {
268
+ const targetNode = graph.nodes.get(edge.to);
269
+ if (targetNode && targetRegex.test(targetNode.filePath)) {
270
+ violations.push({
271
+ ruleId: rule.id,
272
+ ruleName: rule.name,
273
+ severity: rule.severity,
274
+ message: `Forbidden import: ${sourceNode.filePath} -> ${targetNode.filePath}`,
275
+ file: sourceNode.filePath,
276
+ suggestion: `Перенесите необходимую логику или используйте dependency injection`
277
+ });
278
+ }
279
+ }
280
+ }
281
+ return violations;
282
+ }
283
+ /**
284
+ * Проверка границ слоёв
285
+ */
286
+ checkLayerBoundary(rule, graph) {
287
+ const violations = [];
288
+ const { layers } = rule.config;
289
+ if (!layers)
290
+ return violations;
291
+ // Определяем слой для каждого файла
292
+ const getLayer = (filePath) => {
293
+ return layers.find(layer => new RegExp(layer.pattern, 'i').test(filePath));
294
+ };
295
+ for (const [nodeId, edges] of graph.edges) {
296
+ const sourceNode = graph.nodes.get(nodeId);
297
+ if (!sourceNode)
298
+ continue;
299
+ const sourceLayer = getLayer(sourceNode.filePath);
300
+ if (!sourceLayer)
301
+ continue;
302
+ for (const edge of edges) {
303
+ const targetNode = graph.nodes.get(edge.to);
304
+ if (!targetNode)
305
+ continue;
306
+ const targetLayer = getLayer(targetNode.filePath);
307
+ if (!targetLayer)
308
+ continue;
309
+ // Проверяем, разрешена ли зависимость
310
+ if (sourceLayer.name !== targetLayer.name &&
311
+ !sourceLayer.allowedDependencies.includes(targetLayer.name)) {
312
+ violations.push({
313
+ ruleId: rule.id,
314
+ ruleName: rule.name,
315
+ severity: rule.severity,
316
+ message: `Layer violation: ${sourceLayer.name} -> ${targetLayer.name} (${sourceNode.filePath} -> ${targetNode.filePath})`,
317
+ file: sourceNode.filePath,
318
+ suggestion: `Слой "${sourceLayer.name}" не должен зависеть от "${targetLayer.name}". Разрешено: ${sourceLayer.allowedDependencies.join(', ') || 'ничего'}`
319
+ });
320
+ }
321
+ }
322
+ }
323
+ return violations;
324
+ }
325
+ /**
326
+ * Проверка максимального количества зависимостей
327
+ */
328
+ checkMaxDependencies(rule, graph) {
329
+ const violations = [];
330
+ const maxDeps = rule.config.maxValue || 10;
331
+ for (const [nodeId, edges] of graph.edges) {
332
+ if (edges.length > maxDeps) {
333
+ const node = graph.nodes.get(nodeId);
334
+ violations.push({
335
+ ruleId: rule.id,
336
+ ruleName: rule.name,
337
+ severity: rule.severity,
338
+ message: `Too many dependencies: ${edges.length} (max: ${maxDeps})`,
339
+ file: node?.filePath || nodeId,
340
+ suggestion: 'Рассмотрите разделение модуля на более мелкие части или использование фасада'
341
+ });
342
+ }
343
+ }
344
+ return violations;
345
+ }
346
+ /**
347
+ * Проверка максимального размера файла
348
+ */
349
+ checkMaxFileSize(rule, fileContents) {
350
+ const violations = [];
351
+ const maxLines = rule.config.maxValue || 500;
352
+ for (const [filePath, content] of fileContents) {
353
+ const lines = content.split('\n').length;
354
+ if (lines > maxLines) {
355
+ violations.push({
356
+ ruleId: rule.id,
357
+ ruleName: rule.name,
358
+ severity: rule.severity,
359
+ message: `File too large: ${lines} lines (max: ${maxLines})`,
360
+ file: filePath,
361
+ suggestion: 'Разделите файл на несколько модулей по функциональности'
362
+ });
363
+ }
364
+ }
365
+ return violations;
366
+ }
367
+ /**
368
+ * Проверка максимальной длины функции
369
+ */
370
+ checkMaxFunctionLength(rule, symbols) {
371
+ const violations = [];
372
+ const maxLines = rule.config.maxValue || 50;
373
+ for (const [, symbol] of symbols) {
374
+ if (symbol.kind === SymbolKind.Function) {
375
+ const lines = symbol.location.endLine - symbol.location.startLine;
376
+ if (lines > maxLines) {
377
+ violations.push({
378
+ ruleId: rule.id,
379
+ ruleName: rule.name,
380
+ severity: rule.severity,
381
+ message: `Function "${symbol.name}" too long: ${lines} lines (max: ${maxLines})`,
382
+ file: symbol.location.filePath,
383
+ line: symbol.location.startLine,
384
+ suggestion: 'Разбейте функцию на более мелкие, каждая с одной ответственностью'
385
+ });
386
+ }
387
+ }
388
+ }
389
+ return violations;
390
+ }
391
+ /**
392
+ * Проверка на God Class
393
+ */
394
+ checkNoGodClass(rule, symbols) {
395
+ const violations = [];
396
+ const maxMethods = rule.config.maxValue || 20;
397
+ // Группируем методы по классам (по файлу)
398
+ const classMethods = new Map();
399
+ for (const [, symbol] of symbols) {
400
+ if (symbol.kind === SymbolKind.Class) {
401
+ classMethods.set(symbol.name, 0);
402
+ }
403
+ }
404
+ // Count functions per file as approximation
405
+ for (const [, symbol] of symbols) {
406
+ if (symbol.kind === SymbolKind.Function) {
407
+ // Approximate: count functions in same file as a class
408
+ for (const [className] of classMethods) {
409
+ const classSymbol = Array.from(symbols.values()).find(s => s.kind === SymbolKind.Class && s.name === className);
410
+ if (classSymbol && symbol.location.filePath === classSymbol.location.filePath) {
411
+ classMethods.set(className, (classMethods.get(className) || 0) + 1);
412
+ }
413
+ }
414
+ }
415
+ }
416
+ for (const [className, methodCount] of classMethods) {
417
+ if (methodCount > maxMethods) {
418
+ const classSymbol = Array.from(symbols.values()).find(s => s.kind === SymbolKind.Class && s.name === className);
419
+ violations.push({
420
+ ruleId: rule.id,
421
+ ruleName: rule.name,
422
+ severity: rule.severity,
423
+ message: `God Class detected: "${className}" has ${methodCount} methods (max: ${maxMethods})`,
424
+ file: classSymbol?.location.filePath || '',
425
+ line: classSymbol?.location.startLine,
426
+ suggestion: 'Разделите класс на несколько классов, каждый с чёткой ответственностью'
427
+ });
428
+ }
429
+ }
430
+ return violations;
431
+ }
432
+ /**
433
+ * Проверка соглашений об именовании
434
+ */
435
+ checkNamingConvention(rule, symbols, _fileContents) {
436
+ const violations = [];
437
+ const { pattern, filePattern } = rule.config;
438
+ if (!pattern)
439
+ return violations;
440
+ const nameRegex = new RegExp(pattern);
441
+ const fileRegex = filePattern ? new RegExp(filePattern) : null;
442
+ for (const [, symbol] of symbols) {
443
+ // Пропускаем если файл не соответствует паттерну
444
+ if (fileRegex && !fileRegex.test(symbol.location.filePath))
445
+ continue;
446
+ // Проверяем только экспортируемые символы
447
+ if (!symbol.exports)
448
+ continue;
449
+ if (!nameRegex.test(symbol.name)) {
450
+ violations.push({
451
+ ruleId: rule.id,
452
+ ruleName: rule.name,
453
+ severity: rule.severity,
454
+ message: `Naming violation: "${symbol.name}" doesn't match pattern ${pattern}`,
455
+ file: symbol.location.filePath,
456
+ line: symbol.location.startLine,
457
+ suggestion: `Переименуйте в соответствии с паттерном: ${pattern}`
458
+ });
459
+ }
460
+ }
461
+ return violations;
462
+ }
463
+ /**
464
+ * Экспорт правил в JSON
465
+ */
466
+ exportRules() {
467
+ return JSON.stringify(this.getRules(), null, 2);
468
+ }
469
+ /**
470
+ * Импорт правил из JSON
471
+ */
472
+ importRules(json) {
473
+ try {
474
+ const rules = JSON.parse(json);
475
+ rules.forEach(rule => this.rules.set(rule.id, rule));
476
+ }
477
+ catch (error) {
478
+ Logger.error('Failed to import rules:', error);
479
+ }
480
+ }
481
+ }
482
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,24 @@
1
+ export interface EmbeddingConfig {
2
+ provider: 'anthropic' | 'openai' | 'deepseek' | 'none';
3
+ model?: string;
4
+ }
5
+ export declare class EmbeddingService {
6
+ private openai?;
7
+ private config;
8
+ private initialized;
9
+ private _isAvailable;
10
+ constructor(config: EmbeddingConfig);
11
+ private ensureInitialized;
12
+ isAvailable(): boolean;
13
+ generateEmbedding(text: string): Promise<number[]>;
14
+ generateBatchEmbeddings(texts: string[]): Promise<number[][]>;
15
+ private generateOpenAIEmbedding;
16
+ prepareCodeForEmbedding(code: string, context?: string): string;
17
+ generateCodeEmbedding(code: string, metadata: {
18
+ filePath?: string;
19
+ symbolName?: string;
20
+ symbolType?: string;
21
+ purpose?: string;
22
+ }): Promise<number[]>;
23
+ }
24
+ //# sourceMappingURL=embedding-service.d.ts.map