archicore 0.2.8 → 0.3.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/cli/commands/analyzers.js +8 -1
- package/dist/cli/commands/projects.js +25 -1
- package/dist/cli/utils/session.js +29 -12
- package/dist/cli/utils/upload-utils.js +45 -41
- package/dist/code-index/ast-parser.js +169 -1
- package/dist/server/index.js +4 -3
- package/dist/server/routes/api.js +248 -2
- package/dist/server/routes/auth.js +2 -4
- package/dist/server/routes/github.js +0 -17
- package/dist/server/services/project-service.d.ts +3 -1
- package/dist/server/services/project-service.js +17 -6
- package/dist/server/services/task-queue.d.ts +98 -0
- package/dist/server/services/task-queue.js +240 -0
- package/dist/types/user.d.ts +0 -1
- package/dist/types/user.js +0 -5
- package/dist/utils/file-utils.js +122 -36
- package/package.json +2 -1
|
@@ -13,7 +13,11 @@ async function getProjectId() {
|
|
|
13
13
|
async function fetchAnalysis(endpoint, projectId) {
|
|
14
14
|
const config = await loadConfig();
|
|
15
15
|
const id = projectId || await getProjectId();
|
|
16
|
-
const response = await fetch(`${config.serverUrl}/api/projects/${id}/${endpoint}
|
|
16
|
+
const response = await fetch(`${config.serverUrl}/api/projects/${id}/${endpoint}`, {
|
|
17
|
+
headers: {
|
|
18
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
19
|
+
}
|
|
20
|
+
});
|
|
17
21
|
if (!response.ok) {
|
|
18
22
|
const error = await response.json();
|
|
19
23
|
throw new Error(error.error || `Failed to run ${endpoint}`);
|
|
@@ -376,6 +380,9 @@ export function registerAnalyzerCommands(program) {
|
|
|
376
380
|
}
|
|
377
381
|
const response = await fetch(`${config.serverUrl}/api/projects/${projectId}/full-analysis`, {
|
|
378
382
|
method: 'POST',
|
|
383
|
+
headers: {
|
|
384
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
385
|
+
}
|
|
379
386
|
});
|
|
380
387
|
if (!response.ok) {
|
|
381
388
|
const error = await response.json();
|
|
@@ -59,9 +59,17 @@ export function registerProjectsCommand(program) {
|
|
|
59
59
|
const spinner = createSpinner('Creating project...').start();
|
|
60
60
|
try {
|
|
61
61
|
const config = await loadConfig();
|
|
62
|
+
if (!config.accessToken) {
|
|
63
|
+
spinner.fail('Not logged in');
|
|
64
|
+
console.log(' Please run: archicore login');
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
62
67
|
const response = await fetch(`${config.serverUrl}/api/projects`, {
|
|
63
68
|
method: 'POST',
|
|
64
|
-
headers: {
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
72
|
+
},
|
|
65
73
|
body: JSON.stringify({
|
|
66
74
|
name: options.name || path.split('/').pop() || path.split('\\').pop(),
|
|
67
75
|
path: path,
|
|
@@ -112,8 +120,16 @@ export function registerProjectsCommand(program) {
|
|
|
112
120
|
const spinner = createSpinner('Deleting project...').start();
|
|
113
121
|
try {
|
|
114
122
|
const config = await loadConfig();
|
|
123
|
+
if (!config.accessToken) {
|
|
124
|
+
spinner.fail('Not logged in');
|
|
125
|
+
console.log(' Please run: archicore login');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
115
128
|
const response = await fetch(`${config.serverUrl}/api/projects/${id}`, {
|
|
116
129
|
method: 'DELETE',
|
|
130
|
+
headers: {
|
|
131
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
132
|
+
}
|
|
117
133
|
});
|
|
118
134
|
if (!response.ok) {
|
|
119
135
|
const error = await response.json();
|
|
@@ -225,8 +241,16 @@ export function registerProjectsCommand(program) {
|
|
|
225
241
|
printError('Use "archicore projects select <id>" or specify project ID');
|
|
226
242
|
process.exit(1);
|
|
227
243
|
}
|
|
244
|
+
if (!config.accessToken) {
|
|
245
|
+
spinner.fail('Not logged in');
|
|
246
|
+
console.log(' Please run: archicore login');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
228
249
|
const response = await fetch(`${config.serverUrl}/api/projects/${projectId}/index`, {
|
|
229
250
|
method: 'POST',
|
|
251
|
+
headers: {
|
|
252
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
253
|
+
}
|
|
230
254
|
});
|
|
231
255
|
if (!response.ok) {
|
|
232
256
|
const error = await response.json();
|
|
@@ -30,9 +30,13 @@ export function getSession() {
|
|
|
30
30
|
}
|
|
31
31
|
export async function selectProject(projectId) {
|
|
32
32
|
const project = await fetchProject(projectId);
|
|
33
|
-
if (project
|
|
34
|
-
|
|
33
|
+
if (project) {
|
|
34
|
+
// Always save to config, regardless of session state
|
|
35
35
|
await setActiveProject(project.id, project.path);
|
|
36
|
+
// Update session state if initialized
|
|
37
|
+
if (sessionState) {
|
|
38
|
+
sessionState.project = project;
|
|
39
|
+
}
|
|
36
40
|
}
|
|
37
41
|
return project;
|
|
38
42
|
}
|
|
@@ -43,20 +47,27 @@ export async function clearProject() {
|
|
|
43
47
|
}
|
|
44
48
|
async function fetchProject(projectId) {
|
|
45
49
|
const config = await loadConfig();
|
|
50
|
+
if (!config.accessToken)
|
|
51
|
+
return null;
|
|
46
52
|
try {
|
|
47
|
-
const response = await fetch(`${config.serverUrl}/api/projects/${projectId}
|
|
53
|
+
const response = await fetch(`${config.serverUrl}/api/projects/${projectId}`, {
|
|
54
|
+
headers: {
|
|
55
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
56
|
+
}
|
|
57
|
+
});
|
|
48
58
|
if (!response.ok)
|
|
49
59
|
return null;
|
|
50
60
|
const data = await response.json();
|
|
61
|
+
const p = data.project || data; // Handle both { project: {...} } and direct object
|
|
51
62
|
return {
|
|
52
|
-
id:
|
|
53
|
-
name:
|
|
54
|
-
path:
|
|
55
|
-
status:
|
|
56
|
-
files:
|
|
57
|
-
symbols:
|
|
58
|
-
indexed:
|
|
59
|
-
lastIndexed:
|
|
63
|
+
id: p.id,
|
|
64
|
+
name: p.name,
|
|
65
|
+
path: p.path,
|
|
66
|
+
status: p.status || 'unknown',
|
|
67
|
+
files: p.statistics?.codeIndex?.totalFiles || p.stats?.filesCount,
|
|
68
|
+
symbols: p.statistics?.codeIndex?.totalSymbols || p.stats?.symbolsCount,
|
|
69
|
+
indexed: p.status === 'indexed' || p.status === 'ready',
|
|
70
|
+
lastIndexed: p.lastIndexed ? new Date(p.lastIndexed) : undefined,
|
|
60
71
|
};
|
|
61
72
|
}
|
|
62
73
|
catch {
|
|
@@ -65,8 +76,14 @@ async function fetchProject(projectId) {
|
|
|
65
76
|
}
|
|
66
77
|
export async function fetchProjects() {
|
|
67
78
|
const config = await loadConfig();
|
|
79
|
+
if (!config.accessToken)
|
|
80
|
+
return [];
|
|
68
81
|
try {
|
|
69
|
-
const response = await fetch(`${config.serverUrl}/api/projects
|
|
82
|
+
const response = await fetch(`${config.serverUrl}/api/projects`, {
|
|
83
|
+
headers: {
|
|
84
|
+
'Authorization': `Bearer ${config.accessToken}`
|
|
85
|
+
}
|
|
86
|
+
});
|
|
70
87
|
if (!response.ok)
|
|
71
88
|
return [];
|
|
72
89
|
const data = await response.json();
|
|
@@ -7,15 +7,17 @@
|
|
|
7
7
|
* - Детальная обработка ошибок
|
|
8
8
|
*/
|
|
9
9
|
import { loadConfig } from './config.js';
|
|
10
|
-
// Лимиты для chunked upload
|
|
11
|
-
const MAX_PAYLOAD_SIZE =
|
|
12
|
-
const MAX_SYMBOLS_PER_CHUNK =
|
|
13
|
-
const MAX_FILES_PER_CHUNK =
|
|
14
|
-
const UPLOAD_TIMEOUT =
|
|
15
|
-
const MAX_RETRIES =
|
|
10
|
+
// Лимиты для chunked upload (оптимизировано для очень больших проектов)
|
|
11
|
+
const MAX_PAYLOAD_SIZE = 5 * 1024 * 1024; // 5MB per chunk (уменьшено для надёжности)
|
|
12
|
+
const MAX_SYMBOLS_PER_CHUNK = 2000; // Меньше символов на chunk
|
|
13
|
+
const MAX_FILES_PER_CHUNK = 50; // Меньше файлов на chunk
|
|
14
|
+
const UPLOAD_TIMEOUT = 180000; // 3 минуты на chunk
|
|
15
|
+
const MAX_RETRIES = 5; // Больше попыток
|
|
16
16
|
// Лимиты для минимальной загрузки
|
|
17
17
|
const MINIMAL_MAX_SYMBOLS = 10000;
|
|
18
18
|
const MINIMAL_MAX_FILES = 500;
|
|
19
|
+
// Порог для "очень большого" проекта (пропускаем fileContents)
|
|
20
|
+
const VERY_LARGE_PROJECT_SYMBOLS = 30000;
|
|
19
21
|
/**
|
|
20
22
|
* Определение размера JSON в байтах
|
|
21
23
|
*/
|
|
@@ -178,10 +180,9 @@ async function fetchWithRetry(url, options, timeout = UPLOAD_TIMEOUT, maxRetries
|
|
|
178
180
|
}
|
|
179
181
|
catch (error) {
|
|
180
182
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
181
|
-
// Не повторяем для определённых ошибок
|
|
183
|
+
// Не повторяем для определённых ошибок (кроме AbortError - таймаут можно повторить)
|
|
182
184
|
const errorStr = String(error);
|
|
183
|
-
if (errorStr.includes('
|
|
184
|
-
errorStr.includes('ENOTFOUND') ||
|
|
185
|
+
if (errorStr.includes('ENOTFOUND') ||
|
|
185
186
|
errorStr.includes('CERT')) {
|
|
186
187
|
throw error;
|
|
187
188
|
}
|
|
@@ -287,12 +288,18 @@ async function uploadSingleRequest(url, projectId, data, accessToken, onProgress
|
|
|
287
288
|
*/
|
|
288
289
|
async function uploadChunked(baseUrl, projectId, data, accessToken, onProgress) {
|
|
289
290
|
const config = await loadConfig();
|
|
291
|
+
// Для очень больших проектов пропускаем fileContents (экономим трафик и время)
|
|
292
|
+
const isVeryLargeProject = data.symbols.length > VERY_LARGE_PROJECT_SYMBOLS;
|
|
293
|
+
if (isVeryLargeProject) {
|
|
294
|
+
console.log(`[DEBUG] Very large project (${data.symbols.length} symbols), skipping fileContents upload`);
|
|
295
|
+
}
|
|
290
296
|
// Разбиваем данные на chunks
|
|
291
297
|
const symbolChunks = chunkArray(data.symbols, MAX_SYMBOLS_PER_CHUNK);
|
|
292
298
|
const astChunks = chunkArray(data.asts, MAX_FILES_PER_CHUNK);
|
|
293
|
-
const fileChunks = chunkArray(data.fileContents, MAX_FILES_PER_CHUNK);
|
|
299
|
+
const fileChunks = isVeryLargeProject ? [] : chunkArray(data.fileContents, MAX_FILES_PER_CHUNK);
|
|
294
300
|
const totalChunks = symbolChunks.length + astChunks.length + fileChunks.length + 1; // +1 for graph
|
|
295
301
|
let completedChunks = 0;
|
|
302
|
+
console.log(`[DEBUG] Chunked upload: ${symbolChunks.length} symbol chunks, ${astChunks.length} AST chunks, ${fileChunks.length} file chunks`);
|
|
296
303
|
onProgress?.({
|
|
297
304
|
phase: 'uploading',
|
|
298
305
|
current: 0,
|
|
@@ -330,28 +337,32 @@ async function uploadChunked(baseUrl, projectId, data, accessToken, onProgress)
|
|
|
330
337
|
}
|
|
331
338
|
const initResult = await initResponse.json();
|
|
332
339
|
const uploadId = initResult.uploadId;
|
|
333
|
-
//
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
});
|
|
340
|
+
// Параллельная загрузка chunks (по 3 одновременно)
|
|
341
|
+
const PARALLEL_UPLOADS = 3;
|
|
342
|
+
// Helper для параллельной загрузки
|
|
343
|
+
async function uploadChunksParallel(chunks, chunkType, label) {
|
|
344
|
+
console.log(`[DEBUG] Starting parallel upload of ${chunks.length} ${chunkType} chunks`);
|
|
345
|
+
for (let batch = 0; batch < chunks.length; batch += PARALLEL_UPLOADS) {
|
|
346
|
+
const batchChunks = chunks.slice(batch, batch + PARALLEL_UPLOADS);
|
|
347
|
+
console.log(`[DEBUG] Uploading batch ${batch / PARALLEL_UPLOADS + 1} (${batchChunks.length} chunks)`);
|
|
348
|
+
const promises = batchChunks.map((chunk, idx) => uploadChunk(config.serverUrl, projectId, uploadId, chunkType, batch + idx, chunk, accessToken).then(() => {
|
|
349
|
+
console.log(`[DEBUG] Chunk ${chunkType}[${batch + idx}] uploaded`);
|
|
350
|
+
}));
|
|
351
|
+
await Promise.all(promises);
|
|
352
|
+
completedChunks += batchChunks.length;
|
|
353
|
+
onProgress?.({
|
|
354
|
+
phase: 'uploading',
|
|
355
|
+
current: completedChunks,
|
|
356
|
+
total: totalChunks,
|
|
357
|
+
message: `${label} (${Math.min(batch + PARALLEL_UPLOADS, chunks.length)}/${chunks.length})...`,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
console.log(`[DEBUG] Finished uploading ${chunks.length} ${chunkType} chunks`);
|
|
354
361
|
}
|
|
362
|
+
// 2. Загружаем ASTs параллельно
|
|
363
|
+
await uploadChunksParallel(astChunks, 'asts', 'Uploading ASTs');
|
|
364
|
+
// 3. Загружаем символы параллельно
|
|
365
|
+
await uploadChunksParallel(symbolChunks, 'symbols', 'Uploading symbols');
|
|
355
366
|
// 4. Загружаем граф
|
|
356
367
|
await uploadChunk(config.serverUrl, projectId, uploadId, 'graph', 0, data.graph, accessToken);
|
|
357
368
|
completedChunks++;
|
|
@@ -361,16 +372,9 @@ async function uploadChunked(baseUrl, projectId, data, accessToken, onProgress)
|
|
|
361
372
|
total: totalChunks,
|
|
362
373
|
message: 'Uploading dependency graph...',
|
|
363
374
|
});
|
|
364
|
-
// 5. Загружаем содержимое файлов (опционально)
|
|
365
|
-
|
|
366
|
-
await
|
|
367
|
-
completedChunks++;
|
|
368
|
-
onProgress?.({
|
|
369
|
-
phase: 'uploading',
|
|
370
|
-
current: completedChunks,
|
|
371
|
-
total: totalChunks,
|
|
372
|
-
message: `Uploading file contents (${i + 1}/${fileChunks.length})...`,
|
|
373
|
-
});
|
|
375
|
+
// 5. Загружаем содержимое файлов параллельно (опционально)
|
|
376
|
+
if (fileChunks.length > 0) {
|
|
377
|
+
await uploadChunksParallel(fileChunks, 'fileContents', 'Uploading files');
|
|
374
378
|
}
|
|
375
379
|
// 6. Финализируем upload
|
|
376
380
|
onProgress?.({
|
|
@@ -176,7 +176,175 @@ export class ASTParser {
|
|
|
176
176
|
/^(\w+)\s*\(\)\s*\{/, // Function definitions
|
|
177
177
|
/^function\s+(\w+)/ // Function keyword
|
|
178
178
|
],
|
|
179
|
-
markdown: [] // Markdown doesn't have functions/classes
|
|
179
|
+
markdown: [], // Markdown doesn't have functions/classes
|
|
180
|
+
// Additional languages
|
|
181
|
+
kotlin: [
|
|
182
|
+
/^(?:public|private|internal|protected)?\s*(?:suspend\s+)?fun\s+(\w+)/,
|
|
183
|
+
/^(?:public|private|internal|protected)?\s*(?:data\s+|sealed\s+|open\s+)?class\s+(\w+)/,
|
|
184
|
+
/^(?:public|private|internal|protected)?\s*interface\s+(\w+)/,
|
|
185
|
+
/^(?:public|private|internal|protected)?\s*object\s+(\w+)/,
|
|
186
|
+
/^(?:public|private|internal|protected)?\s*enum\s+class\s+(\w+)/
|
|
187
|
+
],
|
|
188
|
+
swift: [
|
|
189
|
+
/^(?:public|private|internal|fileprivate|open)?\s*func\s+(\w+)/,
|
|
190
|
+
/^(?:public|private|internal|fileprivate|open)?\s*class\s+(\w+)/,
|
|
191
|
+
/^(?:public|private|internal|fileprivate|open)?\s*struct\s+(\w+)/,
|
|
192
|
+
/^(?:public|private|internal|fileprivate|open)?\s*enum\s+(\w+)/,
|
|
193
|
+
/^(?:public|private|internal|fileprivate|open)?\s*protocol\s+(\w+)/,
|
|
194
|
+
/^extension\s+(\w+)/
|
|
195
|
+
],
|
|
196
|
+
scala: [
|
|
197
|
+
/^(?:def|override\s+def)\s+(\w+)/,
|
|
198
|
+
/^(?:class|case\s+class|abstract\s+class)\s+(\w+)/,
|
|
199
|
+
/^(?:object|case\s+object)\s+(\w+)/,
|
|
200
|
+
/^trait\s+(\w+)/
|
|
201
|
+
],
|
|
202
|
+
dart: [
|
|
203
|
+
/^(?:Future<[^>]+>|void|int|String|bool|dynamic|\w+)\s+(\w+)\s*\(/,
|
|
204
|
+
/^class\s+(\w+)/,
|
|
205
|
+
/^(?:abstract\s+)?class\s+(\w+)/,
|
|
206
|
+
/^mixin\s+(\w+)/,
|
|
207
|
+
/^extension\s+(\w+)/,
|
|
208
|
+
/^enum\s+(\w+)/
|
|
209
|
+
],
|
|
210
|
+
lua: [
|
|
211
|
+
/^(?:local\s+)?function\s+(\w+)/,
|
|
212
|
+
/^(\w+)\s*=\s*function\s*\(/
|
|
213
|
+
],
|
|
214
|
+
perl: [
|
|
215
|
+
/^sub\s+(\w+)/,
|
|
216
|
+
/^package\s+(\w+)/
|
|
217
|
+
],
|
|
218
|
+
r: [
|
|
219
|
+
/^(\w+)\s*<-\s*function/,
|
|
220
|
+
/^(\w+)\s*=\s*function/
|
|
221
|
+
],
|
|
222
|
+
julia: [
|
|
223
|
+
/^function\s+(\w+)/,
|
|
224
|
+
/^(?:mutable\s+)?struct\s+(\w+)/,
|
|
225
|
+
/^abstract\s+type\s+(\w+)/,
|
|
226
|
+
/^(\w+)\(.*\)\s*=/ // Short function syntax
|
|
227
|
+
],
|
|
228
|
+
elixir: [
|
|
229
|
+
/^def\s+(\w+)/,
|
|
230
|
+
/^defp\s+(\w+)/,
|
|
231
|
+
/^defmodule\s+(\w+)/,
|
|
232
|
+
/^defmacro\s+(\w+)/
|
|
233
|
+
],
|
|
234
|
+
clojure: [
|
|
235
|
+
/^\(defn\s+(\w+)/,
|
|
236
|
+
/^\(defn-\s+(\w+)/,
|
|
237
|
+
/^\(def\s+(\w+)/,
|
|
238
|
+
/^\(defmacro\s+(\w+)/
|
|
239
|
+
],
|
|
240
|
+
haskell: [
|
|
241
|
+
/^(\w+)\s*::/, // Type signature
|
|
242
|
+
/^data\s+(\w+)/,
|
|
243
|
+
/^type\s+(\w+)/,
|
|
244
|
+
/^newtype\s+(\w+)/,
|
|
245
|
+
/^class\s+(\w+)/,
|
|
246
|
+
/^instance\s+(\w+)/
|
|
247
|
+
],
|
|
248
|
+
erlang: [
|
|
249
|
+
/^(\w+)\s*\([^)]*\)\s*->/,
|
|
250
|
+
/^-module\((\w+)\)/,
|
|
251
|
+
/^-record\((\w+)/
|
|
252
|
+
],
|
|
253
|
+
fsharp: [
|
|
254
|
+
/^let\s+(\w+)/,
|
|
255
|
+
/^type\s+(\w+)/,
|
|
256
|
+
/^module\s+(\w+)/,
|
|
257
|
+
/^member\s+(?:this|_)\.(\w+)/
|
|
258
|
+
],
|
|
259
|
+
ocaml: [
|
|
260
|
+
/^let\s+(\w+)/,
|
|
261
|
+
/^type\s+(\w+)/,
|
|
262
|
+
/^module\s+(\w+)/,
|
|
263
|
+
/^class\s+(\w+)/
|
|
264
|
+
],
|
|
265
|
+
zig: [
|
|
266
|
+
/^(?:pub\s+)?fn\s+(\w+)/,
|
|
267
|
+
/^(?:pub\s+)?const\s+(\w+)\s*=/,
|
|
268
|
+
/^(?:pub\s+)?var\s+(\w+)\s*=/
|
|
269
|
+
],
|
|
270
|
+
nim: [
|
|
271
|
+
/^proc\s+(\w+)/,
|
|
272
|
+
/^func\s+(\w+)/,
|
|
273
|
+
/^method\s+(\w+)/,
|
|
274
|
+
/^template\s+(\w+)/,
|
|
275
|
+
/^macro\s+(\w+)/,
|
|
276
|
+
/^type\s+(\w+)/
|
|
277
|
+
],
|
|
278
|
+
crystal: [
|
|
279
|
+
/^def\s+(\w+)/,
|
|
280
|
+
/^class\s+(\w+)/,
|
|
281
|
+
/^struct\s+(\w+)/,
|
|
282
|
+
/^module\s+(\w+)/,
|
|
283
|
+
/^macro\s+(\w+)/
|
|
284
|
+
],
|
|
285
|
+
groovy: [
|
|
286
|
+
/^def\s+(\w+)/,
|
|
287
|
+
/^(?:public|private|protected)?\s*(?:static\s+)?(?:\w+\s+)?(\w+)\s*\(/,
|
|
288
|
+
/^class\s+(\w+)/,
|
|
289
|
+
/^interface\s+(\w+)/
|
|
290
|
+
],
|
|
291
|
+
powershell: [
|
|
292
|
+
/^function\s+(\w+[\w-]*)/,
|
|
293
|
+
/^filter\s+(\w+[\w-]*)/,
|
|
294
|
+
/^class\s+(\w+)/
|
|
295
|
+
],
|
|
296
|
+
dockerfile: [
|
|
297
|
+
/^FROM\s+(\S+)/i,
|
|
298
|
+
/^(?:RUN|CMD|ENTRYPOINT|COPY|ADD|ENV|ARG|EXPOSE|WORKDIR|LABEL)\s/i
|
|
299
|
+
],
|
|
300
|
+
terraform: [
|
|
301
|
+
/^resource\s+"(\w+)"\s+"(\w+)"/,
|
|
302
|
+
/^data\s+"(\w+)"\s+"(\w+)"/,
|
|
303
|
+
/^module\s+"(\w+)"/,
|
|
304
|
+
/^variable\s+"(\w+)"/,
|
|
305
|
+
/^output\s+"(\w+)"/
|
|
306
|
+
],
|
|
307
|
+
graphql: [
|
|
308
|
+
/^type\s+(\w+)/,
|
|
309
|
+
/^input\s+(\w+)/,
|
|
310
|
+
/^interface\s+(\w+)/,
|
|
311
|
+
/^enum\s+(\w+)/,
|
|
312
|
+
/^scalar\s+(\w+)/,
|
|
313
|
+
/^query\s+(\w+)/,
|
|
314
|
+
/^mutation\s+(\w+)/,
|
|
315
|
+
/^subscription\s+(\w+)/
|
|
316
|
+
],
|
|
317
|
+
protobuf: [
|
|
318
|
+
/^message\s+(\w+)/,
|
|
319
|
+
/^service\s+(\w+)/,
|
|
320
|
+
/^enum\s+(\w+)/,
|
|
321
|
+
/^rpc\s+(\w+)/
|
|
322
|
+
],
|
|
323
|
+
toml: [
|
|
324
|
+
/^\[(\w+)\]/, // Section
|
|
325
|
+
/^\[\[(\w+)\]\]/ // Array of tables
|
|
326
|
+
],
|
|
327
|
+
ini: [
|
|
328
|
+
/^\[(\w+)\]/ // Section
|
|
329
|
+
],
|
|
330
|
+
make: [
|
|
331
|
+
/^(\w[\w-]*)\s*:/, // Target
|
|
332
|
+
/^\.PHONY:\s*(\w+)/ // Phony target
|
|
333
|
+
],
|
|
334
|
+
cmake: [
|
|
335
|
+
/^function\s*\(\s*(\w+)/i,
|
|
336
|
+
/^macro\s*\(\s*(\w+)/i,
|
|
337
|
+
/^(?:add_executable|add_library)\s*\(\s*(\w+)/i
|
|
338
|
+
],
|
|
339
|
+
svelte: [
|
|
340
|
+
/^(?:export\s+)?(?:async\s+)?function\s+(\w+)/,
|
|
341
|
+
/^(?:export\s+)?const\s+(\w+)\s*=/,
|
|
342
|
+
/^(?:export\s+)?let\s+(\w+)\s*=/
|
|
343
|
+
],
|
|
344
|
+
astro: [
|
|
345
|
+
/^(?:export\s+)?(?:async\s+)?function\s+(\w+)/,
|
|
346
|
+
/^(?:export\s+)?const\s+(\w+)\s*=/
|
|
347
|
+
]
|
|
180
348
|
};
|
|
181
349
|
const langPatterns = patterns[language] || [];
|
|
182
350
|
lines.forEach((line, index) => {
|
package/dist/server/index.js
CHANGED
|
@@ -228,9 +228,10 @@ export class ArchiCoreServer {
|
|
|
228
228
|
credentials: true,
|
|
229
229
|
maxAge: 86400, // Cache preflight for 24 hours
|
|
230
230
|
}));
|
|
231
|
-
// JSON парсинг
|
|
232
|
-
|
|
233
|
-
this.app.use(express.
|
|
231
|
+
// JSON парсинг - лимит должен покрывать максимальный тариф (admin = 1GB)
|
|
232
|
+
// Проверка по тарифу пользователя происходит в бизнес-логике после парсинга
|
|
233
|
+
this.app.use(express.json({ limit: '1gb' }));
|
|
234
|
+
this.app.use(express.urlencoded({ extended: true, limit: '1gb' }));
|
|
234
235
|
// Request ID для трейсинга
|
|
235
236
|
this.app.use((req, res, next) => {
|
|
236
237
|
const requestId = req.headers['x-request-id'] ||
|