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,315 @@
1
+ /**
2
+ * Authentication Service for ArchiCore
3
+ */
4
+ import { randomUUID } from 'crypto';
5
+ import { createHash } from 'crypto';
6
+ import { readFile, writeFile, mkdir } from 'fs/promises';
7
+ import { join } from 'path';
8
+ import { TIER_LIMITS } from '../../types/user.js';
9
+ const DATA_DIR = '.archicore';
10
+ const USERS_FILE = 'users.json';
11
+ const SESSIONS_FILE = 'sessions.json';
12
+ export class AuthService {
13
+ dataDir;
14
+ users = [];
15
+ sessions = [];
16
+ initialized = false;
17
+ constructor(dataDir = DATA_DIR) {
18
+ this.dataDir = dataDir;
19
+ }
20
+ async ensureInitialized() {
21
+ if (this.initialized)
22
+ return;
23
+ try {
24
+ await mkdir(this.dataDir, { recursive: true });
25
+ }
26
+ catch { }
27
+ // Load users
28
+ try {
29
+ const usersPath = join(this.dataDir, USERS_FILE);
30
+ const data = await readFile(usersPath, 'utf-8');
31
+ const parsed = JSON.parse(data);
32
+ this.users = parsed.users || [];
33
+ }
34
+ catch {
35
+ this.users = [];
36
+ // Create default admin user
37
+ await this.createDefaultAdmin();
38
+ }
39
+ // Load sessions
40
+ try {
41
+ const sessionsPath = join(this.dataDir, SESSIONS_FILE);
42
+ const data = await readFile(sessionsPath, 'utf-8');
43
+ const parsed = JSON.parse(data);
44
+ this.sessions = parsed.sessions || [];
45
+ }
46
+ catch {
47
+ this.sessions = [];
48
+ }
49
+ this.initialized = true;
50
+ }
51
+ async createDefaultAdmin() {
52
+ const admin = {
53
+ id: 'admin-' + randomUUID(),
54
+ email: 'admin@archicore.io',
55
+ username: 'Administrator',
56
+ passwordHash: this.hashPassword('admin123'),
57
+ tier: 'admin',
58
+ provider: 'email',
59
+ createdAt: new Date(),
60
+ lastLoginAt: new Date(),
61
+ usage: this.createEmptyUsage()
62
+ };
63
+ this.users.push(admin);
64
+ await this.saveUsers();
65
+ }
66
+ async saveUsers() {
67
+ const usersPath = join(this.dataDir, USERS_FILE);
68
+ await writeFile(usersPath, JSON.stringify({ users: this.users }, null, 2));
69
+ }
70
+ async saveSessions() {
71
+ const sessionsPath = join(this.dataDir, SESSIONS_FILE);
72
+ await writeFile(sessionsPath, JSON.stringify({ sessions: this.sessions }, null, 2));
73
+ }
74
+ hashPassword(password) {
75
+ return createHash('sha256').update(password + 'archicore-salt-2024').digest('hex');
76
+ }
77
+ createEmptyUsage() {
78
+ return {
79
+ requestsToday: 0,
80
+ fullAnalysisToday: 0,
81
+ projectsToday: 0,
82
+ lastResetDate: new Date().toISOString().split('T')[0]
83
+ };
84
+ }
85
+ generateToken() {
86
+ return randomUUID() + '-' + randomUUID();
87
+ }
88
+ sanitizeUser(user) {
89
+ const { passwordHash, ...sanitized } = user;
90
+ return sanitized;
91
+ }
92
+ async register(email, username, password) {
93
+ await this.ensureInitialized();
94
+ // Check if email already exists
95
+ if (this.users.find(u => u.email.toLowerCase() === email.toLowerCase())) {
96
+ return { success: false, error: 'Email already registered' };
97
+ }
98
+ // Check if username already exists
99
+ if (this.users.find(u => u.username.toLowerCase() === username.toLowerCase())) {
100
+ return { success: false, error: 'Username already taken' };
101
+ }
102
+ const user = {
103
+ id: 'user-' + randomUUID(),
104
+ email: email.toLowerCase(),
105
+ username,
106
+ passwordHash: this.hashPassword(password),
107
+ tier: 'free',
108
+ provider: 'email',
109
+ createdAt: new Date(),
110
+ lastLoginAt: new Date(),
111
+ usage: this.createEmptyUsage()
112
+ };
113
+ this.users.push(user);
114
+ await this.saveUsers();
115
+ // Create session
116
+ const token = this.generateToken();
117
+ const session = {
118
+ token,
119
+ userId: user.id,
120
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days
121
+ };
122
+ this.sessions.push(session);
123
+ await this.saveSessions();
124
+ return {
125
+ success: true,
126
+ token,
127
+ user: this.sanitizeUser(user)
128
+ };
129
+ }
130
+ async login(email, password) {
131
+ await this.ensureInitialized();
132
+ const user = this.users.find(u => u.email.toLowerCase() === email.toLowerCase());
133
+ if (!user) {
134
+ return { success: false, error: 'Invalid email or password' };
135
+ }
136
+ if (user.passwordHash !== this.hashPassword(password)) {
137
+ return { success: false, error: 'Invalid email or password' };
138
+ }
139
+ // Update last login
140
+ user.lastLoginAt = new Date();
141
+ await this.saveUsers();
142
+ // Create session
143
+ const token = this.generateToken();
144
+ const session = {
145
+ token,
146
+ userId: user.id,
147
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
148
+ };
149
+ this.sessions.push(session);
150
+ await this.saveSessions();
151
+ return {
152
+ success: true,
153
+ token,
154
+ user: this.sanitizeUser(user)
155
+ };
156
+ }
157
+ async oauthLogin(provider, profile) {
158
+ await this.ensureInitialized();
159
+ // Find existing user by provider ID or email
160
+ let user = this.users.find(u => (u.provider === provider && u.providerId === profile.id) ||
161
+ u.email.toLowerCase() === profile.email.toLowerCase());
162
+ if (!user) {
163
+ // Create new user
164
+ user = {
165
+ id: 'user-' + randomUUID(),
166
+ email: profile.email.toLowerCase(),
167
+ username: profile.name || profile.email.split('@')[0],
168
+ avatar: profile.avatar,
169
+ tier: 'free',
170
+ provider,
171
+ providerId: profile.id,
172
+ createdAt: new Date(),
173
+ lastLoginAt: new Date(),
174
+ usage: this.createEmptyUsage()
175
+ };
176
+ this.users.push(user);
177
+ }
178
+ else {
179
+ // Update existing user
180
+ user.lastLoginAt = new Date();
181
+ if (profile.avatar)
182
+ user.avatar = profile.avatar;
183
+ if (!user.providerId) {
184
+ user.provider = provider;
185
+ user.providerId = profile.id;
186
+ }
187
+ }
188
+ await this.saveUsers();
189
+ // Create session
190
+ const token = this.generateToken();
191
+ const session = {
192
+ token,
193
+ userId: user.id,
194
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
195
+ };
196
+ this.sessions.push(session);
197
+ await this.saveSessions();
198
+ return {
199
+ success: true,
200
+ token,
201
+ user: this.sanitizeUser(user)
202
+ };
203
+ }
204
+ async validateToken(token) {
205
+ await this.ensureInitialized();
206
+ const session = this.sessions.find(s => s.token === token);
207
+ if (!session)
208
+ return null;
209
+ if (new Date(session.expiresAt) < new Date()) {
210
+ // Session expired, remove it
211
+ this.sessions = this.sessions.filter(s => s.token !== token);
212
+ await this.saveSessions();
213
+ return null;
214
+ }
215
+ const user = this.users.find(u => u.id === session.userId);
216
+ return user || null;
217
+ }
218
+ async logout(token) {
219
+ await this.ensureInitialized();
220
+ this.sessions = this.sessions.filter(s => s.token !== token);
221
+ await this.saveSessions();
222
+ }
223
+ async getUser(userId) {
224
+ await this.ensureInitialized();
225
+ return this.users.find(u => u.id === userId) || null;
226
+ }
227
+ async updateUserTier(userId, tier) {
228
+ await this.ensureInitialized();
229
+ const user = this.users.find(u => u.id === userId);
230
+ if (!user)
231
+ return false;
232
+ user.tier = tier;
233
+ await this.saveUsers();
234
+ return true;
235
+ }
236
+ async checkAndUpdateUsage(userId, type) {
237
+ await this.ensureInitialized();
238
+ const user = this.users.find(u => u.id === userId);
239
+ if (!user)
240
+ return { allowed: false, remaining: 0, limit: 0 };
241
+ const today = new Date().toISOString().split('T')[0];
242
+ // Reset usage if new day
243
+ if (user.usage.lastResetDate !== today) {
244
+ user.usage = this.createEmptyUsage();
245
+ }
246
+ const limits = TIER_LIMITS[user.tier];
247
+ let current;
248
+ let limit;
249
+ switch (type) {
250
+ case 'request':
251
+ current = user.usage.requestsToday;
252
+ limit = limits.requestsPerDay;
253
+ break;
254
+ case 'analysis':
255
+ current = user.usage.fullAnalysisToday;
256
+ limit = limits.fullAnalysisPerDay;
257
+ break;
258
+ case 'project':
259
+ current = user.usage.projectsToday;
260
+ limit = limits.projectsPerDay;
261
+ break;
262
+ }
263
+ if (current >= limit && limit !== Infinity) {
264
+ return { allowed: false, remaining: 0, limit };
265
+ }
266
+ // Increment usage
267
+ switch (type) {
268
+ case 'request':
269
+ user.usage.requestsToday++;
270
+ break;
271
+ case 'analysis':
272
+ user.usage.fullAnalysisToday++;
273
+ break;
274
+ case 'project':
275
+ user.usage.projectsToday++;
276
+ break;
277
+ }
278
+ await this.saveUsers();
279
+ const remaining = limit === Infinity ? Infinity : limit - current - 1;
280
+ return { allowed: true, remaining, limit };
281
+ }
282
+ async getAllUsers() {
283
+ await this.ensureInitialized();
284
+ return this.users.map(u => this.sanitizeUser(u));
285
+ }
286
+ async deleteUser(userId) {
287
+ await this.ensureInitialized();
288
+ const index = this.users.findIndex(u => u.id === userId);
289
+ if (index === -1)
290
+ return false;
291
+ // Don't delete admin
292
+ if (this.users[index].tier === 'admin')
293
+ return false;
294
+ this.users.splice(index, 1);
295
+ this.sessions = this.sessions.filter(s => s.userId !== userId);
296
+ await this.saveUsers();
297
+ await this.saveSessions();
298
+ return true;
299
+ }
300
+ async updateUser(userId, updates) {
301
+ await this.ensureInitialized();
302
+ const user = this.users.find(u => u.id === userId);
303
+ if (!user)
304
+ return false;
305
+ if (updates.username)
306
+ user.username = updates.username;
307
+ if (updates.email)
308
+ user.email = updates.email;
309
+ if (updates.avatar)
310
+ user.avatar = updates.avatar;
311
+ await this.saveUsers();
312
+ return true;
313
+ }
314
+ }
315
+ //# sourceMappingURL=auth-service.js.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Project Service
3
+ *
4
+ * Сервис для управления проектами в ArchiCore.
5
+ * Связывает API с основными модулями системы.
6
+ */
7
+ import { ChangeImpact } from '../../types/index.js';
8
+ import { RulesCheckResult } from '../../rules-engine/index.js';
9
+ import { ProjectMetrics } from '../../metrics/index.js';
10
+ import { DeadCodeResult } from '../../analyzers/dead-code.js';
11
+ import { DuplicationResult } from '../../analyzers/duplication.js';
12
+ import { SecurityResult } from '../../analyzers/security.js';
13
+ import { RefactoringResult } from '../../refactoring/index.js';
14
+ import { ExportData } from '../../export/index.js';
15
+ export interface Project {
16
+ id: string;
17
+ name: string;
18
+ path: string;
19
+ createdAt: string;
20
+ lastIndexedAt?: string;
21
+ status: 'pending' | 'indexing' | 'ready' | 'error';
22
+ stats?: ProjectStats;
23
+ }
24
+ export interface ProjectStats {
25
+ filesCount: number;
26
+ symbolsCount: number;
27
+ nodesCount: number;
28
+ edgesCount: number;
29
+ }
30
+ export declare class ProjectService {
31
+ private projects;
32
+ private projectData;
33
+ private dataDir;
34
+ constructor();
35
+ private loadProjects;
36
+ private saveProjects;
37
+ listProjects(): Promise<Project[]>;
38
+ createProject(name: string, projectPath: string): Promise<Project>;
39
+ getProject(id: string): Promise<Project | null>;
40
+ private initializeProjectData;
41
+ private getProjectData;
42
+ indexProject(projectId: string): Promise<{
43
+ success: boolean;
44
+ stats: ProjectStats;
45
+ }>;
46
+ getArchitecture(projectId: string): Promise<{
47
+ boundedContexts: unknown[];
48
+ entities: unknown[];
49
+ rules: unknown[];
50
+ graph: {
51
+ nodes: unknown[];
52
+ edges: unknown[];
53
+ };
54
+ }>;
55
+ getDependencyGraph(projectId: string): Promise<{
56
+ nodes: unknown[];
57
+ edges: unknown[];
58
+ }>;
59
+ private convertGraphForVisualization;
60
+ analyzeImpact(projectId: string, change: {
61
+ description: string;
62
+ files: string[];
63
+ symbols: string[];
64
+ type: 'add' | 'modify' | 'delete' | 'refactor';
65
+ }): Promise<ChangeImpact>;
66
+ simulateChange(projectId: string, changeDescription: string): Promise<{
67
+ impact: ChangeImpact;
68
+ aiAnalysis: string;
69
+ recommendations: string[];
70
+ }>;
71
+ semanticSearch(projectId: string, query: string, limit?: number): Promise<unknown[]>;
72
+ askArchitect(projectId: string, question: string, language?: 'en' | 'ru'): Promise<string>;
73
+ getStatistics(projectId: string): Promise<{
74
+ project: Project;
75
+ indexStats: ProjectStats | null;
76
+ memoryStats: unknown;
77
+ }>;
78
+ deleteProject(projectId: string): Promise<void>;
79
+ /**
80
+ * Получить метрики кода
81
+ */
82
+ getMetrics(projectId: string): Promise<ProjectMetrics>;
83
+ /**
84
+ * Проверить правила архитектуры
85
+ */
86
+ checkRules(projectId: string): Promise<RulesCheckResult>;
87
+ /**
88
+ * Найти мёртвый код
89
+ */
90
+ findDeadCode(projectId: string): Promise<DeadCodeResult>;
91
+ /**
92
+ * Найти дублирование кода
93
+ */
94
+ findDuplication(projectId: string): Promise<DuplicationResult>;
95
+ /**
96
+ * Анализ безопасности
97
+ */
98
+ analyzeSecurity(projectId: string): Promise<SecurityResult>;
99
+ /**
100
+ * Получить предложения по рефакторингу
101
+ */
102
+ getRefactoringSuggestions(projectId: string): Promise<RefactoringResult>;
103
+ /**
104
+ * Получить данные для экспорта
105
+ */
106
+ getExportData(projectId: string): Promise<ExportData>;
107
+ /**
108
+ * Полный анализ проекта
109
+ */
110
+ runFullAnalysis(projectId: string): Promise<{
111
+ metrics: ProjectMetrics;
112
+ rules: RulesCheckResult;
113
+ deadCode: DeadCodeResult;
114
+ duplication: DuplicationResult;
115
+ security: SecurityResult;
116
+ refactoring: RefactoringResult;
117
+ }>;
118
+ /**
119
+ * Получить содержимое файлов проекта
120
+ */
121
+ private getFileContents;
122
+ }
123
+ //# sourceMappingURL=project-service.d.ts.map