raggrep 0.1.5 → 0.1.7
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/README.md +23 -9
- package/dist/app/indexer/index.d.ts +2 -2
- package/dist/cli/main.js +1964 -918
- package/dist/cli/main.js.map +21 -14
- package/dist/domain/entities/conventions.d.ts +63 -0
- package/dist/domain/entities/index.d.ts +2 -0
- package/dist/domain/services/conventions/configFiles.d.ts +10 -0
- package/dist/domain/services/conventions/conventions.test.d.ts +4 -0
- package/dist/domain/services/conventions/entryPoints.d.ts +10 -0
- package/dist/domain/services/conventions/frameworks/convex.d.ts +11 -0
- package/dist/domain/services/conventions/frameworks/index.d.ts +22 -0
- package/dist/domain/services/conventions/frameworks/nextjs.d.ts +10 -0
- package/dist/domain/services/conventions/index.d.ts +39 -0
- package/dist/domain/services/introspection.d.ts +31 -0
- package/dist/index.js +1452 -416
- package/dist/index.js.map +20 -14
- package/dist/infrastructure/config/configLoader.d.ts +22 -3
- package/dist/infrastructure/config/index.d.ts +1 -1
- package/dist/{introspection/index.d.ts → infrastructure/introspection/IntrospectionIndex.d.ts} +3 -14
- package/dist/infrastructure/introspection/index.d.ts +9 -0
- package/dist/{introspection → infrastructure/introspection}/projectDetector.d.ts +3 -12
- package/dist/tests/integration.test.d.ts +9 -0
- package/dist/types.d.ts +4 -4
- package/package.json +1 -1
- package/dist/introspection/fileIntrospector.d.ts +0 -14
- /package/dist/{introspection/types.d.ts → domain/entities/introspection.d.ts} +0 -0
- /package/dist/{introspection → domain/services}/introspection.test.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -76,7 +76,8 @@ var init_config = __esm(() => {
|
|
|
76
76
|
".go",
|
|
77
77
|
".rs",
|
|
78
78
|
".java",
|
|
79
|
-
".md"
|
|
79
|
+
".md",
|
|
80
|
+
".txt"
|
|
80
81
|
];
|
|
81
82
|
});
|
|
82
83
|
|
|
@@ -89,20 +90,40 @@ var init_entities = __esm(() => {
|
|
|
89
90
|
// src/infrastructure/config/configLoader.ts
|
|
90
91
|
import * as path from "path";
|
|
91
92
|
import * as fs from "fs/promises";
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
import * as os from "os";
|
|
94
|
+
import * as crypto from "crypto";
|
|
95
|
+
function hashPath(inputPath) {
|
|
96
|
+
return crypto.createHash("sha256").update(inputPath).digest("hex").slice(0, 12);
|
|
97
|
+
}
|
|
98
|
+
function getRaggrepDir(rootDir, _config = DEFAULT_CONFIG) {
|
|
99
|
+
const absoluteRoot = path.resolve(rootDir);
|
|
100
|
+
const projectHash = hashPath(absoluteRoot);
|
|
101
|
+
return path.join(RAGGREP_TEMP_BASE, projectHash);
|
|
102
|
+
}
|
|
103
|
+
function getIndexLocation(rootDir) {
|
|
104
|
+
const absoluteRoot = path.resolve(rootDir);
|
|
105
|
+
const projectHash = hashPath(absoluteRoot);
|
|
106
|
+
return {
|
|
107
|
+
indexDir: path.join(RAGGREP_TEMP_BASE, projectHash),
|
|
108
|
+
projectRoot: absoluteRoot,
|
|
109
|
+
projectHash
|
|
110
|
+
};
|
|
94
111
|
}
|
|
95
112
|
function getModuleIndexPath(rootDir, moduleId, config = DEFAULT_CONFIG) {
|
|
96
|
-
|
|
113
|
+
const indexDir = getRaggrepDir(rootDir, config);
|
|
114
|
+
return path.join(indexDir, "index", moduleId);
|
|
97
115
|
}
|
|
98
116
|
function getModuleManifestPath(rootDir, moduleId, config = DEFAULT_CONFIG) {
|
|
99
|
-
|
|
117
|
+
const indexDir = getRaggrepDir(rootDir, config);
|
|
118
|
+
return path.join(indexDir, "index", moduleId, "manifest.json");
|
|
100
119
|
}
|
|
101
120
|
function getGlobalManifestPath(rootDir, config = DEFAULT_CONFIG) {
|
|
102
|
-
|
|
121
|
+
const indexDir = getRaggrepDir(rootDir, config);
|
|
122
|
+
return path.join(indexDir, "manifest.json");
|
|
103
123
|
}
|
|
104
124
|
function getConfigPath(rootDir, config = DEFAULT_CONFIG) {
|
|
105
|
-
|
|
125
|
+
const indexDir = getRaggrepDir(rootDir, config);
|
|
126
|
+
return path.join(indexDir, "config.json");
|
|
106
127
|
}
|
|
107
128
|
async function loadConfig(rootDir) {
|
|
108
129
|
const configPath = getConfigPath(rootDir, DEFAULT_CONFIG);
|
|
@@ -129,10 +150,11 @@ function getEmbeddingConfigFromModule(moduleConfig) {
|
|
|
129
150
|
showProgress: options.showProgress !== false
|
|
130
151
|
};
|
|
131
152
|
}
|
|
132
|
-
var DEFAULT_CONFIG, EMBEDDING_MODELS;
|
|
153
|
+
var DEFAULT_CONFIG, RAGGREP_TEMP_BASE, EMBEDDING_MODELS;
|
|
133
154
|
var init_configLoader = __esm(() => {
|
|
134
155
|
init_entities();
|
|
135
156
|
DEFAULT_CONFIG = createDefaultConfig();
|
|
157
|
+
RAGGREP_TEMP_BASE = path.join(os.tmpdir(), "raggrep-indexes");
|
|
136
158
|
EMBEDDING_MODELS = {
|
|
137
159
|
"all-MiniLM-L6-v2": "Xenova/all-MiniLM-L6-v2",
|
|
138
160
|
"all-MiniLM-L12-v2": "Xenova/all-MiniLM-L12-v2",
|
|
@@ -232,21 +254,1323 @@ class BM25Index {
|
|
|
232
254
|
totalDocs: this.totalDocs
|
|
233
255
|
};
|
|
234
256
|
}
|
|
235
|
-
static deserialize(data) {
|
|
236
|
-
const index = new BM25Index;
|
|
237
|
-
index.avgDocLength = data.avgDocLength;
|
|
238
|
-
index.totalDocs = data.totalDocs;
|
|
239
|
-
index.documentFrequencies = new Map(Object.entries(data.documentFrequencies));
|
|
240
|
-
for (const [id, tokens] of Object.entries(data.documents)) {
|
|
241
|
-
index.documents.set(id, { content: "", tokens });
|
|
257
|
+
static deserialize(data) {
|
|
258
|
+
const index = new BM25Index;
|
|
259
|
+
index.avgDocLength = data.avgDocLength;
|
|
260
|
+
index.totalDocs = data.totalDocs;
|
|
261
|
+
index.documentFrequencies = new Map(Object.entries(data.documentFrequencies));
|
|
262
|
+
for (const [id, tokens] of Object.entries(data.documents)) {
|
|
263
|
+
index.documents.set(id, { content: "", tokens });
|
|
264
|
+
}
|
|
265
|
+
return index;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function normalizeScore(score, midpoint = 5) {
|
|
269
|
+
return 1 / (1 + Math.exp(-score / midpoint + 1));
|
|
270
|
+
}
|
|
271
|
+
var BM25_K1 = 1.5, BM25_B = 0.75;
|
|
272
|
+
|
|
273
|
+
// src/domain/services/conventions/entryPoints.ts
|
|
274
|
+
import * as path2 from "path";
|
|
275
|
+
function getParentFolder(filepath) {
|
|
276
|
+
const dir = path2.dirname(filepath);
|
|
277
|
+
return path2.basename(dir);
|
|
278
|
+
}
|
|
279
|
+
var entryPointConventions;
|
|
280
|
+
var init_entryPoints = __esm(() => {
|
|
281
|
+
entryPointConventions = [
|
|
282
|
+
{
|
|
283
|
+
id: "index-file",
|
|
284
|
+
name: "Index/Barrel File",
|
|
285
|
+
description: "Module entry point that typically re-exports from other files",
|
|
286
|
+
category: "entry-point",
|
|
287
|
+
match: (filepath, filename) => {
|
|
288
|
+
return /^index\.(ts|tsx|js|jsx|mjs|cjs)$/.test(filename);
|
|
289
|
+
},
|
|
290
|
+
keywords: ["entry", "barrel", "exports", "module"],
|
|
291
|
+
dynamicKeywords: (filepath) => {
|
|
292
|
+
const parent = getParentFolder(filepath);
|
|
293
|
+
if (["src", "lib", "dist", "build", ".", ""].includes(parent)) {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
return [parent.toLowerCase()];
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: "main-file",
|
|
301
|
+
name: "Main Entry Point",
|
|
302
|
+
description: "Application main entry point",
|
|
303
|
+
category: "entry-point",
|
|
304
|
+
match: (filepath, filename) => {
|
|
305
|
+
return /^main\.(ts|tsx|js|jsx|mjs|cjs)$/.test(filename);
|
|
306
|
+
},
|
|
307
|
+
keywords: ["entry", "main", "entrypoint", "bootstrap", "startup"]
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: "app-component",
|
|
311
|
+
name: "Root App Component",
|
|
312
|
+
description: "Root application component (React, Vue, etc.)",
|
|
313
|
+
category: "entry-point",
|
|
314
|
+
match: (filepath, filename) => {
|
|
315
|
+
return /^App\.(tsx|jsx|vue|svelte)$/.test(filename);
|
|
316
|
+
},
|
|
317
|
+
keywords: ["root", "app", "application", "component", "main"]
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
id: "deno-mod",
|
|
321
|
+
name: "Deno Module Entry",
|
|
322
|
+
description: "Deno module entry point",
|
|
323
|
+
category: "entry-point",
|
|
324
|
+
match: (filepath, filename) => {
|
|
325
|
+
return filename === "mod.ts";
|
|
326
|
+
},
|
|
327
|
+
keywords: ["entry", "module", "deno", "exports"],
|
|
328
|
+
dynamicKeywords: (filepath) => {
|
|
329
|
+
const parent = getParentFolder(filepath);
|
|
330
|
+
if (["src", "lib", ".", ""].includes(parent)) {
|
|
331
|
+
return [];
|
|
332
|
+
}
|
|
333
|
+
return [parent.toLowerCase()];
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
id: "python-init",
|
|
338
|
+
name: "Python Package Init",
|
|
339
|
+
description: "Python package initialization file",
|
|
340
|
+
category: "entry-point",
|
|
341
|
+
match: (filepath, filename) => {
|
|
342
|
+
return filename === "__init__.py";
|
|
343
|
+
},
|
|
344
|
+
keywords: ["entry", "package", "init", "python", "module"],
|
|
345
|
+
dynamicKeywords: (filepath) => {
|
|
346
|
+
const parent = getParentFolder(filepath);
|
|
347
|
+
if (["src", "lib", ".", ""].includes(parent)) {
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
return [parent.toLowerCase()];
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
id: "rust-lib",
|
|
355
|
+
name: "Rust Library Entry",
|
|
356
|
+
description: "Rust library crate entry point",
|
|
357
|
+
category: "entry-point",
|
|
358
|
+
match: (filepath, filename) => {
|
|
359
|
+
return filename === "lib.rs" || filename === "main.rs";
|
|
360
|
+
},
|
|
361
|
+
keywords: ["entry", "crate", "rust", "module"]
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
id: "go-main",
|
|
365
|
+
name: "Go Main Entry",
|
|
366
|
+
description: "Go application main entry point",
|
|
367
|
+
category: "entry-point",
|
|
368
|
+
match: (filepath, filename) => {
|
|
369
|
+
return filename === "main.go";
|
|
370
|
+
},
|
|
371
|
+
keywords: ["entry", "main", "go", "golang", "entrypoint"],
|
|
372
|
+
dynamicKeywords: (filepath) => {
|
|
373
|
+
const parent = getParentFolder(filepath);
|
|
374
|
+
if (parent && !["cmd", "src", ".", ""].includes(parent)) {
|
|
375
|
+
return [parent.toLowerCase()];
|
|
376
|
+
}
|
|
377
|
+
return [];
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
id: "python-main",
|
|
382
|
+
name: "Python Main Module",
|
|
383
|
+
description: "Python package main entry point",
|
|
384
|
+
category: "entry-point",
|
|
385
|
+
match: (filepath, filename) => {
|
|
386
|
+
return filename === "__main__.py";
|
|
387
|
+
},
|
|
388
|
+
keywords: ["entry", "main", "python", "entrypoint", "cli"],
|
|
389
|
+
dynamicKeywords: (filepath) => {
|
|
390
|
+
const parent = getParentFolder(filepath);
|
|
391
|
+
if (["src", "lib", ".", ""].includes(parent)) {
|
|
392
|
+
return [];
|
|
393
|
+
}
|
|
394
|
+
return [parent.toLowerCase()];
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
id: "python-app",
|
|
399
|
+
name: "Python App Entry",
|
|
400
|
+
description: "Common Python application entry points",
|
|
401
|
+
category: "entry-point",
|
|
402
|
+
match: (filepath, filename) => {
|
|
403
|
+
return filename === "app.py" || filename === "main.py" || filename === "run.py";
|
|
404
|
+
},
|
|
405
|
+
keywords: ["entry", "main", "python", "app", "entrypoint"]
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
id: "python-manage",
|
|
409
|
+
name: "Django Manage",
|
|
410
|
+
description: "Django management script",
|
|
411
|
+
category: "entry-point",
|
|
412
|
+
match: (filepath, filename) => {
|
|
413
|
+
return filename === "manage.py";
|
|
414
|
+
},
|
|
415
|
+
keywords: ["entry", "django", "python", "manage", "cli", "admin"]
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
id: "python-wsgi",
|
|
419
|
+
name: "Python WSGI Entry",
|
|
420
|
+
description: "Python WSGI application entry point",
|
|
421
|
+
category: "entry-point",
|
|
422
|
+
match: (filepath, filename) => {
|
|
423
|
+
return filename === "wsgi.py" || filename === "asgi.py";
|
|
424
|
+
},
|
|
425
|
+
keywords: ["entry", "wsgi", "asgi", "python", "server", "web"]
|
|
426
|
+
}
|
|
427
|
+
];
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// src/domain/services/conventions/configFiles.ts
|
|
431
|
+
var configFileConventions;
|
|
432
|
+
var init_configFiles = __esm(() => {
|
|
433
|
+
configFileConventions = [
|
|
434
|
+
{
|
|
435
|
+
id: "package-json",
|
|
436
|
+
name: "Package.json",
|
|
437
|
+
description: "Node.js package manifest",
|
|
438
|
+
category: "configuration",
|
|
439
|
+
match: (filepath, filename) => filename === "package.json",
|
|
440
|
+
keywords: ["package", "dependencies", "npm", "scripts", "manifest", "node"]
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
id: "pnpm-workspace",
|
|
444
|
+
name: "PNPM Workspace",
|
|
445
|
+
description: "PNPM monorepo workspace configuration",
|
|
446
|
+
category: "configuration",
|
|
447
|
+
match: (filepath, filename) => filename === "pnpm-workspace.yaml" || filename === "pnpm-workspace.yml",
|
|
448
|
+
keywords: ["workspace", "monorepo", "pnpm", "packages"]
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: "yarn-lock",
|
|
452
|
+
name: "Yarn Lock",
|
|
453
|
+
description: "Yarn dependency lock file",
|
|
454
|
+
category: "configuration",
|
|
455
|
+
match: (filepath, filename) => filename === "yarn.lock",
|
|
456
|
+
keywords: ["dependencies", "lock", "yarn", "versions"]
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
id: "package-lock",
|
|
460
|
+
name: "Package Lock",
|
|
461
|
+
description: "NPM dependency lock file",
|
|
462
|
+
category: "configuration",
|
|
463
|
+
match: (filepath, filename) => filename === "package-lock.json",
|
|
464
|
+
keywords: ["dependencies", "lock", "npm", "versions"]
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
id: "bun-lockb",
|
|
468
|
+
name: "Bun Lock",
|
|
469
|
+
description: "Bun dependency lock file",
|
|
470
|
+
category: "configuration",
|
|
471
|
+
match: (filepath, filename) => filename === "bun.lockb" || filename === "bun.lock",
|
|
472
|
+
keywords: ["dependencies", "lock", "bun", "versions"]
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
id: "go-mod",
|
|
476
|
+
name: "Go Module",
|
|
477
|
+
description: "Go module definition file",
|
|
478
|
+
category: "configuration",
|
|
479
|
+
match: (filepath, filename) => filename === "go.mod",
|
|
480
|
+
keywords: [
|
|
481
|
+
"go",
|
|
482
|
+
"golang",
|
|
483
|
+
"module",
|
|
484
|
+
"dependencies",
|
|
485
|
+
"package",
|
|
486
|
+
"workspace"
|
|
487
|
+
]
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
id: "go-sum",
|
|
491
|
+
name: "Go Sum",
|
|
492
|
+
description: "Go module checksum file",
|
|
493
|
+
category: "configuration",
|
|
494
|
+
match: (filepath, filename) => filename === "go.sum",
|
|
495
|
+
keywords: ["go", "golang", "dependencies", "checksum", "lock", "versions"]
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
id: "go-work",
|
|
499
|
+
name: "Go Workspace",
|
|
500
|
+
description: "Go workspace configuration for multi-module development",
|
|
501
|
+
category: "configuration",
|
|
502
|
+
match: (filepath, filename) => filename === "go.work" || filename === "go.work.sum",
|
|
503
|
+
keywords: ["go", "golang", "workspace", "monorepo", "modules"]
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
id: "makefile",
|
|
507
|
+
name: "Makefile",
|
|
508
|
+
description: "Make build automation file",
|
|
509
|
+
category: "build",
|
|
510
|
+
match: (filepath, filename) => filename === "Makefile" || filename === "makefile" || filename === "GNUmakefile",
|
|
511
|
+
keywords: ["make", "build", "automation", "tasks", "compile"]
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
id: "requirements-txt",
|
|
515
|
+
name: "Python Requirements",
|
|
516
|
+
description: "Python pip requirements file",
|
|
517
|
+
category: "configuration",
|
|
518
|
+
match: (filepath, filename) => filename === "requirements.txt" || filename.startsWith("requirements-") || filename.startsWith("requirements_"),
|
|
519
|
+
keywords: ["python", "pip", "dependencies", "packages", "requirements"]
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
id: "pyproject-toml",
|
|
523
|
+
name: "Python Project",
|
|
524
|
+
description: "Python project configuration (PEP 518/621)",
|
|
525
|
+
category: "configuration",
|
|
526
|
+
match: (filepath, filename) => filename === "pyproject.toml",
|
|
527
|
+
keywords: [
|
|
528
|
+
"python",
|
|
529
|
+
"project",
|
|
530
|
+
"config",
|
|
531
|
+
"poetry",
|
|
532
|
+
"build",
|
|
533
|
+
"dependencies",
|
|
534
|
+
"package"
|
|
535
|
+
]
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
id: "setup-py",
|
|
539
|
+
name: "Python Setup",
|
|
540
|
+
description: "Python package setup script",
|
|
541
|
+
category: "configuration",
|
|
542
|
+
match: (filepath, filename) => filename === "setup.py",
|
|
543
|
+
keywords: ["python", "setup", "package", "install", "distribution"]
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
id: "setup-cfg",
|
|
547
|
+
name: "Python Setup Config",
|
|
548
|
+
description: "Python setup configuration file",
|
|
549
|
+
category: "configuration",
|
|
550
|
+
match: (filepath, filename) => filename === "setup.cfg",
|
|
551
|
+
keywords: ["python", "setup", "config", "package", "metadata"]
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
id: "pipfile",
|
|
555
|
+
name: "Pipfile",
|
|
556
|
+
description: "Pipenv dependency file",
|
|
557
|
+
category: "configuration",
|
|
558
|
+
match: (filepath, filename) => filename === "Pipfile" || filename === "Pipfile.lock",
|
|
559
|
+
keywords: ["python", "pipenv", "dependencies", "packages", "virtualenv"]
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
id: "poetry-lock",
|
|
563
|
+
name: "Poetry Lock",
|
|
564
|
+
description: "Poetry dependency lock file",
|
|
565
|
+
category: "configuration",
|
|
566
|
+
match: (filepath, filename) => filename === "poetry.lock",
|
|
567
|
+
keywords: ["python", "poetry", "dependencies", "lock", "versions"]
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: "tox-ini",
|
|
571
|
+
name: "Tox Config",
|
|
572
|
+
description: "Tox testing automation configuration",
|
|
573
|
+
category: "test",
|
|
574
|
+
match: (filepath, filename) => filename === "tox.ini",
|
|
575
|
+
keywords: ["python", "tox", "testing", "automation", "environments"]
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
id: "pytest-ini",
|
|
579
|
+
name: "Pytest Config",
|
|
580
|
+
description: "Pytest configuration file",
|
|
581
|
+
category: "test",
|
|
582
|
+
match: (filepath, filename) => filename === "pytest.ini" || filename === "conftest.py",
|
|
583
|
+
keywords: ["python", "pytest", "testing", "test", "fixtures"]
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
id: "mypy-ini",
|
|
587
|
+
name: "Mypy Config",
|
|
588
|
+
description: "Mypy type checker configuration",
|
|
589
|
+
category: "configuration",
|
|
590
|
+
match: (filepath, filename) => filename === "mypy.ini" || filename === ".mypy.ini",
|
|
591
|
+
keywords: ["python", "mypy", "types", "type checking", "static analysis"]
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
id: "flake8",
|
|
595
|
+
name: "Flake8 Config",
|
|
596
|
+
description: "Flake8 linter configuration",
|
|
597
|
+
category: "configuration",
|
|
598
|
+
match: (filepath, filename) => filename === ".flake8",
|
|
599
|
+
keywords: ["python", "flake8", "linting", "lint", "style"]
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
id: "pylintrc",
|
|
603
|
+
name: "Pylint Config",
|
|
604
|
+
description: "Pylint linter configuration",
|
|
605
|
+
category: "configuration",
|
|
606
|
+
match: (filepath, filename) => filename === ".pylintrc" || filename === "pylintrc" || filename === "pylint.toml",
|
|
607
|
+
keywords: ["python", "pylint", "linting", "lint", "code quality"]
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
id: "ruff-toml",
|
|
611
|
+
name: "Ruff Config",
|
|
612
|
+
description: "Ruff linter/formatter configuration",
|
|
613
|
+
category: "configuration",
|
|
614
|
+
match: (filepath, filename) => filename === "ruff.toml" || filename === ".ruff.toml",
|
|
615
|
+
keywords: ["python", "ruff", "linting", "formatting", "fast"]
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
id: "black-toml",
|
|
619
|
+
name: "Black Config",
|
|
620
|
+
description: "Black formatter configuration",
|
|
621
|
+
category: "configuration",
|
|
622
|
+
match: (filepath, filename) => filename === ".black.toml",
|
|
623
|
+
keywords: ["python", "black", "formatting", "format", "style"]
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
id: "tsconfig",
|
|
627
|
+
name: "TypeScript Config",
|
|
628
|
+
description: "TypeScript compiler configuration",
|
|
629
|
+
category: "configuration",
|
|
630
|
+
match: (filepath, filename) => filename === "tsconfig.json" || filename.startsWith("tsconfig.") && filename.endsWith(".json"),
|
|
631
|
+
keywords: [
|
|
632
|
+
"typescript",
|
|
633
|
+
"config",
|
|
634
|
+
"compiler",
|
|
635
|
+
"ts",
|
|
636
|
+
"settings",
|
|
637
|
+
"paths",
|
|
638
|
+
"types"
|
|
639
|
+
]
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
id: "jsconfig",
|
|
643
|
+
name: "JavaScript Config",
|
|
644
|
+
description: "JavaScript project configuration",
|
|
645
|
+
category: "configuration",
|
|
646
|
+
match: (filepath, filename) => filename === "jsconfig.json",
|
|
647
|
+
keywords: ["javascript", "config", "compiler", "js", "settings", "paths"]
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
id: "eslint-config",
|
|
651
|
+
name: "ESLint Config",
|
|
652
|
+
description: "ESLint linting configuration",
|
|
653
|
+
category: "configuration",
|
|
654
|
+
match: (filepath, filename) => filename === ".eslintrc" || filename === ".eslintrc.js" || filename === ".eslintrc.cjs" || filename === ".eslintrc.json" || filename === ".eslintrc.yml" || filename === ".eslintrc.yaml" || filename === "eslint.config.js" || filename === "eslint.config.mjs" || filename === "eslint.config.cjs",
|
|
655
|
+
keywords: ["eslint", "linting", "lint", "rules", "code quality"]
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
id: "prettier-config",
|
|
659
|
+
name: "Prettier Config",
|
|
660
|
+
description: "Prettier code formatting configuration",
|
|
661
|
+
category: "configuration",
|
|
662
|
+
match: (filepath, filename) => filename === ".prettierrc" || filename === ".prettierrc.js" || filename === ".prettierrc.cjs" || filename === ".prettierrc.json" || filename === ".prettierrc.yml" || filename === ".prettierrc.yaml" || filename === "prettier.config.js" || filename === "prettier.config.cjs" || filename === "prettier.config.mjs",
|
|
663
|
+
keywords: ["prettier", "formatting", "format", "code style", "style"]
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
id: "biome-config",
|
|
667
|
+
name: "Biome Config",
|
|
668
|
+
description: "Biome linting and formatting configuration",
|
|
669
|
+
category: "configuration",
|
|
670
|
+
match: (filepath, filename) => filename === "biome.json" || filename === "biome.jsonc",
|
|
671
|
+
keywords: ["biome", "linting", "formatting", "lint", "format"]
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
id: "vite-config",
|
|
675
|
+
name: "Vite Config",
|
|
676
|
+
description: "Vite build tool configuration",
|
|
677
|
+
category: "build",
|
|
678
|
+
match: (filepath, filename) => filename === "vite.config.ts" || filename === "vite.config.js" || filename === "vite.config.mjs",
|
|
679
|
+
keywords: ["vite", "bundler", "build", "dev server", "hmr"]
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
id: "webpack-config",
|
|
683
|
+
name: "Webpack Config",
|
|
684
|
+
description: "Webpack bundler configuration",
|
|
685
|
+
category: "build",
|
|
686
|
+
match: (filepath, filename) => filename === "webpack.config.js" || filename === "webpack.config.ts" || filename.startsWith("webpack.") && (filename.endsWith(".js") || filename.endsWith(".ts")),
|
|
687
|
+
keywords: ["webpack", "bundler", "build", "loaders", "plugins"]
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
id: "rollup-config",
|
|
691
|
+
name: "Rollup Config",
|
|
692
|
+
description: "Rollup bundler configuration",
|
|
693
|
+
category: "build",
|
|
694
|
+
match: (filepath, filename) => filename === "rollup.config.js" || filename === "rollup.config.ts" || filename === "rollup.config.mjs",
|
|
695
|
+
keywords: ["rollup", "bundler", "build", "esm", "bundle"]
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
id: "esbuild-config",
|
|
699
|
+
name: "esbuild Config",
|
|
700
|
+
description: "esbuild bundler configuration",
|
|
701
|
+
category: "build",
|
|
702
|
+
match: (filepath, filename) => filename === "esbuild.config.js" || filename === "esbuild.config.ts" || filename === "esbuild.config.mjs",
|
|
703
|
+
keywords: ["esbuild", "bundler", "build", "fast"]
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
id: "jest-config",
|
|
707
|
+
name: "Jest Config",
|
|
708
|
+
description: "Jest testing framework configuration",
|
|
709
|
+
category: "test",
|
|
710
|
+
match: (filepath, filename) => filename === "jest.config.js" || filename === "jest.config.ts" || filename === "jest.config.mjs" || filename === "jest.config.cjs" || filename === "jest.config.json",
|
|
711
|
+
keywords: ["jest", "testing", "test", "unit test", "config"]
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
id: "vitest-config",
|
|
715
|
+
name: "Vitest Config",
|
|
716
|
+
description: "Vitest testing framework configuration",
|
|
717
|
+
category: "test",
|
|
718
|
+
match: (filepath, filename) => filename === "vitest.config.ts" || filename === "vitest.config.js" || filename === "vitest.config.mts",
|
|
719
|
+
keywords: ["vitest", "testing", "test", "unit test", "config"]
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
id: "playwright-config",
|
|
723
|
+
name: "Playwright Config",
|
|
724
|
+
description: "Playwright E2E testing configuration",
|
|
725
|
+
category: "test",
|
|
726
|
+
match: (filepath, filename) => filename === "playwright.config.ts" || filename === "playwright.config.js",
|
|
727
|
+
keywords: ["playwright", "testing", "e2e", "end-to-end", "browser test"]
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
id: "cypress-config",
|
|
731
|
+
name: "Cypress Config",
|
|
732
|
+
description: "Cypress E2E testing configuration",
|
|
733
|
+
category: "test",
|
|
734
|
+
match: (filepath, filename) => filename === "cypress.config.ts" || filename === "cypress.config.js" || filename === "cypress.json",
|
|
735
|
+
keywords: ["cypress", "testing", "e2e", "end-to-end", "browser test"]
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
id: "tailwind-config",
|
|
739
|
+
name: "Tailwind Config",
|
|
740
|
+
description: "Tailwind CSS configuration",
|
|
741
|
+
category: "configuration",
|
|
742
|
+
match: (filepath, filename) => filename === "tailwind.config.js" || filename === "tailwind.config.ts" || filename === "tailwind.config.cjs" || filename === "tailwind.config.mjs",
|
|
743
|
+
keywords: ["tailwind", "css", "styling", "utility", "design"]
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
id: "postcss-config",
|
|
747
|
+
name: "PostCSS Config",
|
|
748
|
+
description: "PostCSS configuration",
|
|
749
|
+
category: "configuration",
|
|
750
|
+
match: (filepath, filename) => filename === "postcss.config.js" || filename === "postcss.config.cjs" || filename === "postcss.config.mjs" || filename === ".postcssrc" || filename === ".postcssrc.json",
|
|
751
|
+
keywords: ["postcss", "css", "styling", "transforms"]
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
id: "env-file",
|
|
755
|
+
name: "Environment File",
|
|
756
|
+
description: "Environment variables file",
|
|
757
|
+
category: "configuration",
|
|
758
|
+
match: (filepath, filename) => filename === ".env" || filename === ".env.local" || filename === ".env.development" || filename === ".env.production" || filename === ".env.test" || filename.startsWith(".env."),
|
|
759
|
+
keywords: ["environment", "env", "variables", "secrets", "config"]
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
id: "env-example",
|
|
763
|
+
name: "Environment Example",
|
|
764
|
+
description: "Example environment variables file",
|
|
765
|
+
category: "documentation",
|
|
766
|
+
match: (filepath, filename) => filename === ".env.example" || filename === ".env.sample" || filename === ".env.template",
|
|
767
|
+
keywords: ["environment", "env", "example", "template", "setup"]
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
id: "dockerfile",
|
|
771
|
+
name: "Dockerfile",
|
|
772
|
+
description: "Docker container image definition",
|
|
773
|
+
category: "deployment",
|
|
774
|
+
match: (filepath, filename) => filename === "Dockerfile" || filename.startsWith("Dockerfile."),
|
|
775
|
+
keywords: ["docker", "container", "image", "deployment", "build"]
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
id: "docker-compose",
|
|
779
|
+
name: "Docker Compose",
|
|
780
|
+
description: "Docker Compose multi-container configuration",
|
|
781
|
+
category: "deployment",
|
|
782
|
+
match: (filepath, filename) => filename === "docker-compose.yml" || filename === "docker-compose.yaml" || filename === "compose.yml" || filename === "compose.yaml" || filename.startsWith("docker-compose."),
|
|
783
|
+
keywords: ["docker", "compose", "containers", "services", "deployment"]
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
id: "github-actions",
|
|
787
|
+
name: "GitHub Actions Workflow",
|
|
788
|
+
description: "GitHub Actions CI/CD workflow",
|
|
789
|
+
category: "deployment",
|
|
790
|
+
match: (filepath) => filepath.includes(".github/workflows/") && filepath.endsWith(".yml"),
|
|
791
|
+
keywords: ["github", "actions", "ci", "cd", "workflow", "automation"]
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
id: "vercel-config",
|
|
795
|
+
name: "Vercel Config",
|
|
796
|
+
description: "Vercel deployment configuration",
|
|
797
|
+
category: "deployment",
|
|
798
|
+
match: (filepath, filename) => filename === "vercel.json",
|
|
799
|
+
keywords: ["vercel", "deployment", "hosting", "serverless"]
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
id: "netlify-config",
|
|
803
|
+
name: "Netlify Config",
|
|
804
|
+
description: "Netlify deployment configuration",
|
|
805
|
+
category: "deployment",
|
|
806
|
+
match: (filepath, filename) => filename === "netlify.toml",
|
|
807
|
+
keywords: ["netlify", "deployment", "hosting", "functions"]
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
id: "gitignore",
|
|
811
|
+
name: "Git Ignore",
|
|
812
|
+
description: "Git ignored files configuration",
|
|
813
|
+
category: "configuration",
|
|
814
|
+
match: (filepath, filename) => filename === ".gitignore",
|
|
815
|
+
keywords: ["git", "ignore", "version control", "excluded"]
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
id: "gitattributes",
|
|
819
|
+
name: "Git Attributes",
|
|
820
|
+
description: "Git file attributes configuration",
|
|
821
|
+
category: "configuration",
|
|
822
|
+
match: (filepath, filename) => filename === ".gitattributes",
|
|
823
|
+
keywords: ["git", "attributes", "version control", "line endings"]
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
id: "readme",
|
|
827
|
+
name: "README",
|
|
828
|
+
description: "Project documentation",
|
|
829
|
+
category: "documentation",
|
|
830
|
+
match: (filepath, filename) => filename.toLowerCase() === "readme.md" || filename.toLowerCase() === "readme",
|
|
831
|
+
keywords: [
|
|
832
|
+
"readme",
|
|
833
|
+
"documentation",
|
|
834
|
+
"docs",
|
|
835
|
+
"overview",
|
|
836
|
+
"getting started"
|
|
837
|
+
]
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
id: "changelog",
|
|
841
|
+
name: "Changelog",
|
|
842
|
+
description: "Project changelog",
|
|
843
|
+
category: "documentation",
|
|
844
|
+
match: (filepath, filename) => filename.toLowerCase() === "changelog.md" || filename.toLowerCase() === "changelog",
|
|
845
|
+
keywords: ["changelog", "changes", "releases", "history", "versions"]
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
id: "contributing",
|
|
849
|
+
name: "Contributing Guide",
|
|
850
|
+
description: "Contribution guidelines",
|
|
851
|
+
category: "documentation",
|
|
852
|
+
match: (filepath, filename) => filename.toLowerCase() === "contributing.md" || filename.toLowerCase() === "contributing",
|
|
853
|
+
keywords: ["contributing", "contribution", "guidelines", "development"]
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
id: "license",
|
|
857
|
+
name: "License",
|
|
858
|
+
description: "Project license",
|
|
859
|
+
category: "documentation",
|
|
860
|
+
match: (filepath, filename) => filename.toLowerCase() === "license" || filename.toLowerCase() === "license.md" || filename.toLowerCase() === "license.txt",
|
|
861
|
+
keywords: ["license", "legal", "copyright", "terms"]
|
|
862
|
+
}
|
|
863
|
+
];
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
// src/domain/services/conventions/frameworks/nextjs.ts
|
|
867
|
+
var nextjsConventions, nextjsFramework;
|
|
868
|
+
var init_nextjs = __esm(() => {
|
|
869
|
+
nextjsConventions = [
|
|
870
|
+
{
|
|
871
|
+
id: "next-config",
|
|
872
|
+
name: "Next.js Config",
|
|
873
|
+
description: "Next.js framework configuration",
|
|
874
|
+
category: "configuration",
|
|
875
|
+
match: (filepath, filename) => filename === "next.config.js" || filename === "next.config.mjs" || filename === "next.config.ts",
|
|
876
|
+
keywords: ["nextjs", "next", "config", "framework", "settings"]
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
id: "next-env",
|
|
880
|
+
name: "Next.js Environment Types",
|
|
881
|
+
description: "Next.js TypeScript environment declarations",
|
|
882
|
+
category: "types",
|
|
883
|
+
match: (filepath, filename) => filename === "next-env.d.ts",
|
|
884
|
+
keywords: ["nextjs", "types", "typescript", "declarations"]
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
id: "next-layout",
|
|
888
|
+
name: "Next.js Layout",
|
|
889
|
+
description: "Next.js layout component (App Router)",
|
|
890
|
+
category: "framework",
|
|
891
|
+
match: (filepath, filename) => (filename === "layout.tsx" || filename === "layout.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
892
|
+
keywords: ["nextjs", "layout", "wrapper", "template", "app router"],
|
|
893
|
+
dynamicKeywords: (filepath) => {
|
|
894
|
+
const match = filepath.match(/app\/(.+?)\/layout\./);
|
|
895
|
+
if (match) {
|
|
896
|
+
const segments = match[1].split("/").filter((s) => !s.startsWith("(") && !s.startsWith("["));
|
|
897
|
+
return segments.map((s) => s.toLowerCase());
|
|
898
|
+
}
|
|
899
|
+
if (filepath === "app/layout.tsx" || filepath === "app/layout.js") {
|
|
900
|
+
return ["root", "main"];
|
|
901
|
+
}
|
|
902
|
+
return [];
|
|
903
|
+
}
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
id: "next-page",
|
|
907
|
+
name: "Next.js Page",
|
|
908
|
+
description: "Next.js page component (App Router)",
|
|
909
|
+
category: "framework",
|
|
910
|
+
match: (filepath, filename) => (filename === "page.tsx" || filename === "page.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
911
|
+
keywords: ["nextjs", "page", "route", "view", "app router"],
|
|
912
|
+
dynamicKeywords: (filepath) => {
|
|
913
|
+
const match = filepath.match(/app\/(.+?)\/page\./);
|
|
914
|
+
if (match) {
|
|
915
|
+
const segments = match[1].split("/").filter((s) => !s.startsWith("(")).map((s) => s.replace(/^\[(.+?)\]$/, "$1"));
|
|
916
|
+
return segments.map((s) => s.toLowerCase());
|
|
917
|
+
}
|
|
918
|
+
if (filepath === "app/page.tsx" || filepath === "app/page.js") {
|
|
919
|
+
return ["home", "index", "root"];
|
|
920
|
+
}
|
|
921
|
+
return [];
|
|
922
|
+
}
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
id: "next-loading",
|
|
926
|
+
name: "Next.js Loading",
|
|
927
|
+
description: "Next.js loading UI component",
|
|
928
|
+
category: "framework",
|
|
929
|
+
match: (filepath, filename) => (filename === "loading.tsx" || filename === "loading.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
930
|
+
keywords: ["nextjs", "loading", "suspense", "skeleton", "spinner"]
|
|
931
|
+
},
|
|
932
|
+
{
|
|
933
|
+
id: "next-error",
|
|
934
|
+
name: "Next.js Error",
|
|
935
|
+
description: "Next.js error boundary component",
|
|
936
|
+
category: "framework",
|
|
937
|
+
match: (filepath, filename) => (filename === "error.tsx" || filename === "error.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
938
|
+
keywords: ["nextjs", "error", "boundary", "fallback", "catch"]
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
id: "next-not-found",
|
|
942
|
+
name: "Next.js Not Found",
|
|
943
|
+
description: "Next.js 404 page component",
|
|
944
|
+
category: "framework",
|
|
945
|
+
match: (filepath, filename) => (filename === "not-found.tsx" || filename === "not-found.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
946
|
+
keywords: ["nextjs", "404", "not found", "missing", "error"]
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
id: "next-template",
|
|
950
|
+
name: "Next.js Template",
|
|
951
|
+
description: "Next.js template component",
|
|
952
|
+
category: "framework",
|
|
953
|
+
match: (filepath, filename) => (filename === "template.tsx" || filename === "template.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
954
|
+
keywords: ["nextjs", "template", "wrapper", "app router"]
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
id: "next-route-handler",
|
|
958
|
+
name: "Next.js Route Handler",
|
|
959
|
+
description: "Next.js API route handler (App Router)",
|
|
960
|
+
category: "framework",
|
|
961
|
+
match: (filepath, filename) => (filename === "route.ts" || filename === "route.js") && (filepath.includes("/app/") || filepath.startsWith("app/")),
|
|
962
|
+
keywords: ["nextjs", "api", "route", "handler", "endpoint", "rest"],
|
|
963
|
+
dynamicKeywords: (filepath) => {
|
|
964
|
+
const match = filepath.match(/app\/api\/(.+?)\/route\./);
|
|
965
|
+
if (match) {
|
|
966
|
+
const segments = match[1].split("/").filter((s) => !s.startsWith("(")).map((s) => s.replace(/^\[(.+?)\]$/, "$1"));
|
|
967
|
+
return ["api", ...segments.map((s) => s.toLowerCase())];
|
|
968
|
+
}
|
|
969
|
+
return ["api"];
|
|
970
|
+
}
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
id: "next-middleware",
|
|
974
|
+
name: "Next.js Middleware",
|
|
975
|
+
description: "Next.js edge middleware",
|
|
976
|
+
category: "framework",
|
|
977
|
+
match: (filepath, filename) => filename === "middleware.ts" || filename === "middleware.js",
|
|
978
|
+
keywords: ["nextjs", "middleware", "edge", "request", "interceptor"]
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
id: "next-global-error",
|
|
982
|
+
name: "Next.js Global Error",
|
|
983
|
+
description: "Next.js global error handler",
|
|
984
|
+
category: "framework",
|
|
985
|
+
match: (filepath, filename) => filename === "global-error.tsx" || filename === "global-error.js",
|
|
986
|
+
keywords: ["nextjs", "error", "global", "boundary", "catch"]
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
id: "next-pages-api",
|
|
990
|
+
name: "Next.js API Route (Pages)",
|
|
991
|
+
description: "Next.js API route (Pages Router)",
|
|
992
|
+
category: "framework",
|
|
993
|
+
match: (filepath) => filepath.includes("/pages/api/") || filepath.startsWith("pages/api/"),
|
|
994
|
+
keywords: ["nextjs", "api", "route", "handler", "endpoint", "pages router"],
|
|
995
|
+
dynamicKeywords: (filepath) => {
|
|
996
|
+
const match = filepath.match(/pages\/api\/(.+?)\.(ts|js)/);
|
|
997
|
+
if (match) {
|
|
998
|
+
const segments = match[1].split("/").map((s) => s.replace(/^\[(.+?)\]$/, "$1"));
|
|
999
|
+
return ["api", ...segments.map((s) => s.toLowerCase())];
|
|
1000
|
+
}
|
|
1001
|
+
return ["api"];
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
id: "next-pages-document",
|
|
1006
|
+
name: "Next.js Document",
|
|
1007
|
+
description: "Next.js custom document (Pages Router)",
|
|
1008
|
+
category: "framework",
|
|
1009
|
+
match: (filepath, filename) => (filename === "_document.tsx" || filename === "_document.js") && (filepath.includes("/pages/") || filepath.startsWith("pages/")),
|
|
1010
|
+
keywords: ["nextjs", "document", "html", "head", "body", "pages router"]
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
id: "next-pages-app",
|
|
1014
|
+
name: "Next.js App (Pages)",
|
|
1015
|
+
description: "Next.js custom app (Pages Router)",
|
|
1016
|
+
category: "framework",
|
|
1017
|
+
match: (filepath, filename) => (filename === "_app.tsx" || filename === "_app.js") && (filepath.includes("/pages/") || filepath.startsWith("pages/")),
|
|
1018
|
+
keywords: ["nextjs", "app", "wrapper", "provider", "pages router"]
|
|
1019
|
+
}
|
|
1020
|
+
];
|
|
1021
|
+
nextjsFramework = {
|
|
1022
|
+
id: "nextjs",
|
|
1023
|
+
name: "Next.js",
|
|
1024
|
+
detect: (filepath) => {
|
|
1025
|
+
return filepath === "next.config.js" || filepath === "next.config.mjs" || filepath === "next.config.ts" || filepath.includes("/app/page.") || filepath.includes("/pages/_app.");
|
|
1026
|
+
},
|
|
1027
|
+
conventions: nextjsConventions
|
|
1028
|
+
};
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
// src/domain/services/conventions/frameworks/convex.ts
|
|
1032
|
+
var convexConventions, convexFramework;
|
|
1033
|
+
var init_convex = __esm(() => {
|
|
1034
|
+
convexConventions = [
|
|
1035
|
+
{
|
|
1036
|
+
id: "convex-config",
|
|
1037
|
+
name: "Convex Config",
|
|
1038
|
+
description: "Convex project configuration",
|
|
1039
|
+
category: "configuration",
|
|
1040
|
+
match: (filepath, filename) => filename === "convex.json",
|
|
1041
|
+
keywords: ["convex", "config", "backend", "settings"]
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
id: "convex-schema",
|
|
1045
|
+
name: "Convex Schema",
|
|
1046
|
+
description: "Convex database schema definition",
|
|
1047
|
+
category: "framework",
|
|
1048
|
+
match: (filepath, filename) => filename === "schema.ts" && (filepath.includes("/convex/") || filepath.startsWith("convex/")),
|
|
1049
|
+
keywords: ["convex", "schema", "database", "tables", "types", "model"]
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
id: "convex-function",
|
|
1053
|
+
name: "Convex Function File",
|
|
1054
|
+
description: "Convex backend function file",
|
|
1055
|
+
category: "framework",
|
|
1056
|
+
match: (filepath, filename, extension) => (extension === ".ts" || extension === ".js") && (filepath.includes("/convex/") || filepath.startsWith("convex/")) && !filepath.includes("/_generated/") && filename !== "schema.ts" && !filename.startsWith("_"),
|
|
1057
|
+
keywords: ["convex", "function", "backend", "query", "mutation", "action"],
|
|
1058
|
+
dynamicKeywords: (filepath) => {
|
|
1059
|
+
const match = filepath.match(/convex\/(.+?)\.(ts|js)/);
|
|
1060
|
+
if (match) {
|
|
1061
|
+
const name = match[1].replace(/\//g, " ").split(" ").pop() || "";
|
|
1062
|
+
if (name && !["schema", "http", "crons"].includes(name)) {
|
|
1063
|
+
return [name.toLowerCase()];
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return [];
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
id: "convex-http",
|
|
1071
|
+
name: "Convex HTTP Routes",
|
|
1072
|
+
description: "Convex HTTP endpoint definitions",
|
|
1073
|
+
category: "framework",
|
|
1074
|
+
match: (filepath, filename) => filename === "http.ts" && (filepath.includes("/convex/") || filepath.startsWith("convex/")),
|
|
1075
|
+
keywords: ["convex", "http", "routes", "api", "endpoints", "rest"]
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
id: "convex-crons",
|
|
1079
|
+
name: "Convex Cron Jobs",
|
|
1080
|
+
description: "Convex scheduled function definitions",
|
|
1081
|
+
category: "framework",
|
|
1082
|
+
match: (filepath, filename) => filename === "crons.ts" && (filepath.includes("/convex/") || filepath.startsWith("convex/")),
|
|
1083
|
+
keywords: [
|
|
1084
|
+
"convex",
|
|
1085
|
+
"crons",
|
|
1086
|
+
"scheduled",
|
|
1087
|
+
"jobs",
|
|
1088
|
+
"background",
|
|
1089
|
+
"recurring"
|
|
1090
|
+
]
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
id: "convex-generated",
|
|
1094
|
+
name: "Convex Generated",
|
|
1095
|
+
description: "Convex auto-generated files",
|
|
1096
|
+
category: "framework",
|
|
1097
|
+
match: (filepath) => filepath.includes("/convex/_generated/") || filepath.startsWith("convex/_generated/"),
|
|
1098
|
+
keywords: ["convex", "generated", "types", "api"]
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
id: "convex-auth",
|
|
1102
|
+
name: "Convex Auth",
|
|
1103
|
+
description: "Convex authentication configuration",
|
|
1104
|
+
category: "framework",
|
|
1105
|
+
match: (filepath, filename) => filename === "auth.ts" && (filepath.includes("/convex/") || filepath.startsWith("convex/")),
|
|
1106
|
+
keywords: ["convex", "auth", "authentication", "login", "users"]
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
id: "convex-auth-config",
|
|
1110
|
+
name: "Convex Auth Config",
|
|
1111
|
+
description: "Convex auth configuration file",
|
|
1112
|
+
category: "configuration",
|
|
1113
|
+
match: (filepath, filename) => filename === "auth.config.ts",
|
|
1114
|
+
keywords: ["convex", "auth", "config", "providers", "oauth"]
|
|
1115
|
+
}
|
|
1116
|
+
];
|
|
1117
|
+
convexFramework = {
|
|
1118
|
+
id: "convex",
|
|
1119
|
+
name: "Convex",
|
|
1120
|
+
detect: (filepath) => {
|
|
1121
|
+
return filepath === "convex.json" || filepath.startsWith("convex/") || filepath.includes("/convex/");
|
|
1122
|
+
},
|
|
1123
|
+
conventions: convexConventions
|
|
1124
|
+
};
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
// src/domain/services/conventions/frameworks/index.ts
|
|
1128
|
+
function getAllFrameworkConventions() {
|
|
1129
|
+
return frameworkProviders.flatMap((f) => f.conventions);
|
|
1130
|
+
}
|
|
1131
|
+
var frameworkProviders;
|
|
1132
|
+
var init_frameworks = __esm(() => {
|
|
1133
|
+
init_nextjs();
|
|
1134
|
+
init_convex();
|
|
1135
|
+
init_nextjs();
|
|
1136
|
+
init_convex();
|
|
1137
|
+
frameworkProviders = [
|
|
1138
|
+
nextjsFramework,
|
|
1139
|
+
convexFramework
|
|
1140
|
+
];
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1143
|
+
// src/domain/services/conventions/index.ts
|
|
1144
|
+
import * as path3 from "path";
|
|
1145
|
+
function getConventions() {
|
|
1146
|
+
return [
|
|
1147
|
+
...entryPointConventions,
|
|
1148
|
+
...configFileConventions,
|
|
1149
|
+
...getAllFrameworkConventions(),
|
|
1150
|
+
...typeDefinitionConventions,
|
|
1151
|
+
...testFileConventions
|
|
1152
|
+
];
|
|
1153
|
+
}
|
|
1154
|
+
function getConventionKeywords(filepath) {
|
|
1155
|
+
const conventions = getConventions();
|
|
1156
|
+
const filename = path3.basename(filepath);
|
|
1157
|
+
const extension = path3.extname(filepath);
|
|
1158
|
+
const keywords = new Set;
|
|
1159
|
+
for (const convention of conventions) {
|
|
1160
|
+
try {
|
|
1161
|
+
if (convention.match(filepath, filename, extension)) {
|
|
1162
|
+
for (const keyword of convention.keywords) {
|
|
1163
|
+
keywords.add(keyword.toLowerCase());
|
|
1164
|
+
}
|
|
1165
|
+
if (convention.dynamicKeywords) {
|
|
1166
|
+
const dynamicKws = convention.dynamicKeywords(filepath);
|
|
1167
|
+
for (const kw of dynamicKws) {
|
|
1168
|
+
if (kw && kw.length > 1) {
|
|
1169
|
+
keywords.add(kw.toLowerCase());
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
} catch {}
|
|
1175
|
+
}
|
|
1176
|
+
return Array.from(keywords);
|
|
1177
|
+
}
|
|
1178
|
+
var typeDefinitionConventions, testFileConventions;
|
|
1179
|
+
var init_conventions = __esm(() => {
|
|
1180
|
+
init_entryPoints();
|
|
1181
|
+
init_configFiles();
|
|
1182
|
+
init_frameworks();
|
|
1183
|
+
init_entryPoints();
|
|
1184
|
+
init_configFiles();
|
|
1185
|
+
init_frameworks();
|
|
1186
|
+
typeDefinitionConventions = [
|
|
1187
|
+
{
|
|
1188
|
+
id: "dts-file",
|
|
1189
|
+
name: "TypeScript Declaration",
|
|
1190
|
+
description: "TypeScript type declaration file",
|
|
1191
|
+
category: "types",
|
|
1192
|
+
match: (filepath, filename) => filename.endsWith(".d.ts"),
|
|
1193
|
+
keywords: ["types", "declarations", "typescript", "definitions"]
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
id: "types-file",
|
|
1197
|
+
name: "Types File",
|
|
1198
|
+
description: "TypeScript types file",
|
|
1199
|
+
category: "types",
|
|
1200
|
+
match: (filepath, filename) => filename.endsWith(".types.ts") || filename === "types.ts",
|
|
1201
|
+
keywords: ["types", "definitions", "typescript", "interfaces"],
|
|
1202
|
+
dynamicKeywords: (filepath) => {
|
|
1203
|
+
const match = filepath.match(/([^/]+)\.types\.ts$/);
|
|
1204
|
+
if (match)
|
|
1205
|
+
return [match[1].toLowerCase()];
|
|
1206
|
+
return [];
|
|
1207
|
+
}
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
id: "types-folder",
|
|
1211
|
+
name: "Types Folder File",
|
|
1212
|
+
description: "File in a types folder",
|
|
1213
|
+
category: "types",
|
|
1214
|
+
match: (filepath) => filepath.includes("/types/") || filepath.startsWith("types/"),
|
|
1215
|
+
keywords: ["types", "definitions"]
|
|
1216
|
+
}
|
|
1217
|
+
];
|
|
1218
|
+
testFileConventions = [
|
|
1219
|
+
{
|
|
1220
|
+
id: "test-file",
|
|
1221
|
+
name: "Test File",
|
|
1222
|
+
description: "Unit/integration test file",
|
|
1223
|
+
category: "test",
|
|
1224
|
+
match: (filepath, filename) => filename.includes(".test.") || filename.includes(".spec.") || filename.includes("_test."),
|
|
1225
|
+
keywords: ["test", "spec", "unit test"],
|
|
1226
|
+
dynamicKeywords: (filepath) => {
|
|
1227
|
+
const match = filepath.match(/([^/]+)\.(test|spec)\./);
|
|
1228
|
+
if (match)
|
|
1229
|
+
return [match[1].toLowerCase()];
|
|
1230
|
+
return [];
|
|
1231
|
+
}
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
id: "test-folder",
|
|
1235
|
+
name: "Test Folder File",
|
|
1236
|
+
description: "File in a test folder",
|
|
1237
|
+
category: "test",
|
|
1238
|
+
match: (filepath) => filepath.includes("/__tests__/") || filepath.includes("/test/") || filepath.includes("/tests/") || filepath.startsWith("__tests__/") || filepath.startsWith("test/") || filepath.startsWith("tests/"),
|
|
1239
|
+
keywords: ["test", "testing"]
|
|
1240
|
+
}
|
|
1241
|
+
];
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
// src/domain/services/introspection.ts
|
|
1245
|
+
import * as path4 from "path";
|
|
1246
|
+
function introspectFile(filepath, structure, fileContent) {
|
|
1247
|
+
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
1248
|
+
const segments = normalizedPath.split("/").filter((s) => s.length > 0);
|
|
1249
|
+
const filename = segments[segments.length - 1] || "";
|
|
1250
|
+
const ext = path4.extname(filename);
|
|
1251
|
+
const project = findProjectForFile(normalizedPath, structure);
|
|
1252
|
+
const language = EXTENSION_TO_LANGUAGE[ext] || "unknown";
|
|
1253
|
+
const layer = detectLayer(segments, filename);
|
|
1254
|
+
const domain = detectDomain(segments);
|
|
1255
|
+
const scope = detectScope(segments, project, layer);
|
|
1256
|
+
const framework = fileContent ? detectFramework(fileContent) : undefined;
|
|
1257
|
+
return {
|
|
1258
|
+
filepath: normalizedPath,
|
|
1259
|
+
project,
|
|
1260
|
+
scope,
|
|
1261
|
+
layer,
|
|
1262
|
+
domain,
|
|
1263
|
+
language,
|
|
1264
|
+
framework,
|
|
1265
|
+
depth: segments.length - 1,
|
|
1266
|
+
pathSegments: segments.slice(0, -1)
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
function introspectionToKeywords(intro) {
|
|
1270
|
+
const keywords = [];
|
|
1271
|
+
const filename = path4.basename(intro.filepath);
|
|
1272
|
+
const filenameWithoutExt = filename.replace(/\.[^.]+$/, "");
|
|
1273
|
+
const filenameParts = filenameWithoutExt.split(/[-_.]/).flatMap((part) => part.split(/(?=[A-Z])/)).map((part) => part.toLowerCase()).filter((part) => part.length > 1);
|
|
1274
|
+
keywords.push(...filenameParts);
|
|
1275
|
+
keywords.push(filenameWithoutExt.toLowerCase());
|
|
1276
|
+
if (intro.project.name && intro.project.name !== "root") {
|
|
1277
|
+
keywords.push(intro.project.name.toLowerCase());
|
|
1278
|
+
}
|
|
1279
|
+
if (intro.scope !== "unknown")
|
|
1280
|
+
keywords.push(intro.scope);
|
|
1281
|
+
if (intro.layer)
|
|
1282
|
+
keywords.push(intro.layer);
|
|
1283
|
+
if (intro.domain)
|
|
1284
|
+
keywords.push(intro.domain);
|
|
1285
|
+
if (intro.language !== "unknown")
|
|
1286
|
+
keywords.push(intro.language);
|
|
1287
|
+
if (intro.framework)
|
|
1288
|
+
keywords.push(intro.framework);
|
|
1289
|
+
const skipSegments = new Set(["src", "lib", "index"]);
|
|
1290
|
+
for (const segment of intro.pathSegments) {
|
|
1291
|
+
if (!skipSegments.has(segment.toLowerCase()) && segment.length > 2) {
|
|
1292
|
+
keywords.push(segment.toLowerCase());
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
const conventionKeywords = getConventionKeywords(intro.filepath);
|
|
1296
|
+
keywords.push(...conventionKeywords);
|
|
1297
|
+
return [...new Set(keywords)];
|
|
1298
|
+
}
|
|
1299
|
+
function detectScopeFromName(name) {
|
|
1300
|
+
const nameLower = name.toLowerCase();
|
|
1301
|
+
for (const [scope, keywords] of Object.entries(SCOPE_KEYWORDS)) {
|
|
1302
|
+
if (scope === "unknown")
|
|
1303
|
+
continue;
|
|
1304
|
+
for (const keyword of keywords) {
|
|
1305
|
+
if (nameLower.includes(keyword)) {
|
|
1306
|
+
return scope;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
return "unknown";
|
|
1311
|
+
}
|
|
1312
|
+
function findProjectForFile(filepath, structure) {
|
|
1313
|
+
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
1314
|
+
const matches = [];
|
|
1315
|
+
for (const project of structure.projects) {
|
|
1316
|
+
if (normalizedPath === project.root || normalizedPath.startsWith(project.root + "/")) {
|
|
1317
|
+
matches.push(project);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
if (matches.length > 0) {
|
|
1321
|
+
return matches.reduce((best, current) => current.root.length > best.root.length ? current : best);
|
|
1322
|
+
}
|
|
1323
|
+
for (const { pattern, type } of PROJECT_PATTERNS) {
|
|
1324
|
+
const match = normalizedPath.match(pattern);
|
|
1325
|
+
if (match) {
|
|
1326
|
+
return { name: match[1], root: match[0], type };
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
return { name: "root", root: "", type: structure.rootType ?? "unknown" };
|
|
1330
|
+
}
|
|
1331
|
+
function detectLayer(segments, filename) {
|
|
1332
|
+
const filenameLower = filename.toLowerCase();
|
|
1333
|
+
for (const [layer, patterns] of Object.entries(LAYER_PATTERNS)) {
|
|
1334
|
+
for (const pattern of patterns) {
|
|
1335
|
+
if (filenameLower.includes(pattern))
|
|
1336
|
+
return layer;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
for (let i = segments.length - 2;i >= 0; i--) {
|
|
1340
|
+
const segment = segments[i].toLowerCase();
|
|
1341
|
+
for (const [layer, patterns] of Object.entries(LAYER_PATTERNS)) {
|
|
1342
|
+
if (patterns.includes(segment))
|
|
1343
|
+
return layer;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
function detectDomain(segments) {
|
|
1349
|
+
const skipSegments = new Set([
|
|
1350
|
+
"src",
|
|
1351
|
+
"lib",
|
|
1352
|
+
"app",
|
|
1353
|
+
"apps",
|
|
1354
|
+
"packages",
|
|
1355
|
+
"services",
|
|
1356
|
+
"modules",
|
|
1357
|
+
"features",
|
|
1358
|
+
...Object.values(LAYER_PATTERNS).flat()
|
|
1359
|
+
]);
|
|
1360
|
+
for (const segment of segments) {
|
|
1361
|
+
const segmentLower = segment.toLowerCase();
|
|
1362
|
+
if (skipSegments.has(segmentLower))
|
|
1363
|
+
continue;
|
|
1364
|
+
if (DOMAIN_PATTERNS.includes(segmentLower))
|
|
1365
|
+
return segmentLower;
|
|
1366
|
+
for (const domain of DOMAIN_PATTERNS) {
|
|
1367
|
+
if (segmentLower.startsWith(domain) || segmentLower.endsWith(domain)) {
|
|
1368
|
+
return domain;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
function detectScope(segments, project, layer) {
|
|
1375
|
+
const projectScope = detectScopeFromName(project.name);
|
|
1376
|
+
if (projectScope !== "unknown")
|
|
1377
|
+
return projectScope;
|
|
1378
|
+
if (layer) {
|
|
1379
|
+
switch (layer) {
|
|
1380
|
+
case "controller":
|
|
1381
|
+
case "repository":
|
|
1382
|
+
case "middleware":
|
|
1383
|
+
return "backend";
|
|
1384
|
+
case "presentation":
|
|
1385
|
+
return "frontend";
|
|
1386
|
+
case "util":
|
|
1387
|
+
case "model":
|
|
1388
|
+
return "shared";
|
|
1389
|
+
case "test":
|
|
1390
|
+
return "tooling";
|
|
242
1391
|
}
|
|
243
|
-
return index;
|
|
244
1392
|
}
|
|
1393
|
+
for (const segment of segments) {
|
|
1394
|
+
const segmentLower = segment.toLowerCase();
|
|
1395
|
+
if (["server", "api", "backend"].includes(segmentLower))
|
|
1396
|
+
return "backend";
|
|
1397
|
+
if (["client", "web", "frontend", "ui"].includes(segmentLower))
|
|
1398
|
+
return "frontend";
|
|
1399
|
+
if (["shared", "common", "lib", "libs"].includes(segmentLower))
|
|
1400
|
+
return "shared";
|
|
1401
|
+
}
|
|
1402
|
+
return "unknown";
|
|
245
1403
|
}
|
|
246
|
-
function
|
|
247
|
-
|
|
1404
|
+
function detectFramework(content) {
|
|
1405
|
+
for (const [framework, indicators] of Object.entries(FRAMEWORK_INDICATORS)) {
|
|
1406
|
+
for (const indicator of indicators) {
|
|
1407
|
+
if (content.includes(`from '${indicator}`) || content.includes(`from "${indicator}`) || content.includes(`require('${indicator}`) || content.includes(`require("${indicator}`)) {
|
|
1408
|
+
return framework;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
return;
|
|
248
1413
|
}
|
|
249
|
-
var
|
|
1414
|
+
var LAYER_PATTERNS, DOMAIN_PATTERNS, FRAMEWORK_INDICATORS, EXTENSION_TO_LANGUAGE, SCOPE_KEYWORDS, PROJECT_PATTERNS;
|
|
1415
|
+
var init_introspection = __esm(() => {
|
|
1416
|
+
init_conventions();
|
|
1417
|
+
LAYER_PATTERNS = {
|
|
1418
|
+
controller: ["controller", "api", "routes", "route", "handler"],
|
|
1419
|
+
service: ["service", "logic", "usecase", "usecases", "handler"],
|
|
1420
|
+
repository: ["repository", "repo", "dao", "store", "persistence"],
|
|
1421
|
+
model: [
|
|
1422
|
+
"model",
|
|
1423
|
+
"models",
|
|
1424
|
+
"entity",
|
|
1425
|
+
"entities",
|
|
1426
|
+
"schema",
|
|
1427
|
+
"schemas",
|
|
1428
|
+
"types",
|
|
1429
|
+
"type"
|
|
1430
|
+
],
|
|
1431
|
+
util: ["util", "utils", "helper", "helpers", "common", "lib"],
|
|
1432
|
+
config: ["config", "configuration", "settings"],
|
|
1433
|
+
middleware: ["middleware", "middlewares"],
|
|
1434
|
+
domain: ["domain"],
|
|
1435
|
+
infrastructure: ["infrastructure", "infra"],
|
|
1436
|
+
application: ["application", "app"],
|
|
1437
|
+
presentation: [
|
|
1438
|
+
"presentation",
|
|
1439
|
+
"ui",
|
|
1440
|
+
"views",
|
|
1441
|
+
"view",
|
|
1442
|
+
"component",
|
|
1443
|
+
"components"
|
|
1444
|
+
],
|
|
1445
|
+
test: ["test", "tests", "spec", "specs", "__tests__", "e2e"]
|
|
1446
|
+
};
|
|
1447
|
+
DOMAIN_PATTERNS = [
|
|
1448
|
+
"auth",
|
|
1449
|
+
"authentication",
|
|
1450
|
+
"user",
|
|
1451
|
+
"users",
|
|
1452
|
+
"account",
|
|
1453
|
+
"accounts",
|
|
1454
|
+
"profile",
|
|
1455
|
+
"profiles",
|
|
1456
|
+
"product",
|
|
1457
|
+
"products",
|
|
1458
|
+
"item",
|
|
1459
|
+
"items",
|
|
1460
|
+
"catalog",
|
|
1461
|
+
"order",
|
|
1462
|
+
"orders",
|
|
1463
|
+
"cart",
|
|
1464
|
+
"checkout",
|
|
1465
|
+
"payment",
|
|
1466
|
+
"payments",
|
|
1467
|
+
"billing",
|
|
1468
|
+
"subscription",
|
|
1469
|
+
"subscriptions",
|
|
1470
|
+
"notification",
|
|
1471
|
+
"notifications",
|
|
1472
|
+
"email",
|
|
1473
|
+
"sms",
|
|
1474
|
+
"report",
|
|
1475
|
+
"reports",
|
|
1476
|
+
"analytics",
|
|
1477
|
+
"metrics",
|
|
1478
|
+
"dashboard",
|
|
1479
|
+
"admin",
|
|
1480
|
+
"settings",
|
|
1481
|
+
"search",
|
|
1482
|
+
"chat",
|
|
1483
|
+
"message",
|
|
1484
|
+
"messages",
|
|
1485
|
+
"feed",
|
|
1486
|
+
"post",
|
|
1487
|
+
"posts",
|
|
1488
|
+
"comment",
|
|
1489
|
+
"comments",
|
|
1490
|
+
"media",
|
|
1491
|
+
"upload",
|
|
1492
|
+
"file",
|
|
1493
|
+
"files",
|
|
1494
|
+
"storage",
|
|
1495
|
+
"cache",
|
|
1496
|
+
"session",
|
|
1497
|
+
"log",
|
|
1498
|
+
"logs",
|
|
1499
|
+
"audit"
|
|
1500
|
+
];
|
|
1501
|
+
FRAMEWORK_INDICATORS = {
|
|
1502
|
+
nextjs: ["next", "next/"],
|
|
1503
|
+
express: ["express"],
|
|
1504
|
+
fastify: ["fastify"],
|
|
1505
|
+
react: ["react"],
|
|
1506
|
+
vue: ["vue"],
|
|
1507
|
+
angular: ["@angular/"],
|
|
1508
|
+
nestjs: ["@nestjs/"],
|
|
1509
|
+
koa: ["koa"]
|
|
1510
|
+
};
|
|
1511
|
+
EXTENSION_TO_LANGUAGE = {
|
|
1512
|
+
".ts": "typescript",
|
|
1513
|
+
".tsx": "typescript",
|
|
1514
|
+
".js": "javascript",
|
|
1515
|
+
".jsx": "javascript",
|
|
1516
|
+
".mjs": "javascript",
|
|
1517
|
+
".cjs": "javascript",
|
|
1518
|
+
".py": "python",
|
|
1519
|
+
".go": "go",
|
|
1520
|
+
".rs": "rust",
|
|
1521
|
+
".java": "java",
|
|
1522
|
+
".kt": "kotlin",
|
|
1523
|
+
".swift": "swift",
|
|
1524
|
+
".rb": "ruby",
|
|
1525
|
+
".php": "php",
|
|
1526
|
+
".cs": "csharp",
|
|
1527
|
+
".cpp": "cpp",
|
|
1528
|
+
".c": "c",
|
|
1529
|
+
".h": "c",
|
|
1530
|
+
".hpp": "cpp",
|
|
1531
|
+
".md": "markdown",
|
|
1532
|
+
".json": "json",
|
|
1533
|
+
".yaml": "yaml",
|
|
1534
|
+
".yml": "yaml",
|
|
1535
|
+
".txt": "text"
|
|
1536
|
+
};
|
|
1537
|
+
SCOPE_KEYWORDS = {
|
|
1538
|
+
frontend: [
|
|
1539
|
+
"web",
|
|
1540
|
+
"webapp",
|
|
1541
|
+
"frontend",
|
|
1542
|
+
"client",
|
|
1543
|
+
"ui",
|
|
1544
|
+
"app",
|
|
1545
|
+
"mobile",
|
|
1546
|
+
"react",
|
|
1547
|
+
"vue",
|
|
1548
|
+
"angular",
|
|
1549
|
+
"next",
|
|
1550
|
+
"nuxt"
|
|
1551
|
+
],
|
|
1552
|
+
backend: [
|
|
1553
|
+
"api",
|
|
1554
|
+
"server",
|
|
1555
|
+
"backend",
|
|
1556
|
+
"service",
|
|
1557
|
+
"worker",
|
|
1558
|
+
"lambda",
|
|
1559
|
+
"functions"
|
|
1560
|
+
],
|
|
1561
|
+
shared: ["shared", "common", "utils", "lib", "core", "types", "models"],
|
|
1562
|
+
tooling: ["scripts", "tools", "cli", "devtools", "build", "config", "infra"],
|
|
1563
|
+
unknown: []
|
|
1564
|
+
};
|
|
1565
|
+
PROJECT_PATTERNS = [
|
|
1566
|
+
{ pattern: /^apps\/([^/]+)/, type: "app", defaultScope: "unknown" },
|
|
1567
|
+
{ pattern: /^packages\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
1568
|
+
{ pattern: /^libs\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
1569
|
+
{ pattern: /^services\/([^/]+)/, type: "service", defaultScope: "backend" },
|
|
1570
|
+
{ pattern: /^scripts\/([^/]+)/, type: "script", defaultScope: "tooling" },
|
|
1571
|
+
{ pattern: /^tools\/([^/]+)/, type: "script", defaultScope: "tooling" }
|
|
1572
|
+
];
|
|
1573
|
+
});
|
|
250
1574
|
|
|
251
1575
|
// src/modules/core/symbols.ts
|
|
252
1576
|
function extractSymbols(content) {
|
|
@@ -415,7 +1739,7 @@ var exports_core = {};
|
|
|
415
1739
|
__export(exports_core, {
|
|
416
1740
|
CoreModule: () => CoreModule
|
|
417
1741
|
});
|
|
418
|
-
import * as
|
|
1742
|
+
import * as path5 from "path";
|
|
419
1743
|
import * as fs2 from "fs/promises";
|
|
420
1744
|
|
|
421
1745
|
class CoreModule {
|
|
@@ -432,7 +1756,11 @@ class CoreModule {
|
|
|
432
1756
|
const symbols = extractSymbols(content);
|
|
433
1757
|
const symbolKeywords = symbolsToKeywords(symbols);
|
|
434
1758
|
const contentTokens = tokenize(content);
|
|
435
|
-
const
|
|
1759
|
+
const intro = ctx.getIntrospection?.(filepath);
|
|
1760
|
+
const introKeywords = intro ? introspectionToKeywords(intro) : [];
|
|
1761
|
+
const allTokens = [
|
|
1762
|
+
...new Set([...contentTokens, ...symbolKeywords, ...introKeywords])
|
|
1763
|
+
];
|
|
436
1764
|
const chunks = this.createChunks(filepath, content, symbols);
|
|
437
1765
|
const stats = await ctx.getFileStats(filepath);
|
|
438
1766
|
this.symbolIndex.set(filepath, {
|
|
@@ -506,7 +1834,7 @@ class CoreModule {
|
|
|
506
1834
|
}
|
|
507
1835
|
async finalize(ctx) {
|
|
508
1836
|
const config = ctx.config;
|
|
509
|
-
const coreDir =
|
|
1837
|
+
const coreDir = path5.join(getRaggrepDir(ctx.rootDir, config), "index", "core");
|
|
510
1838
|
await fs2.mkdir(coreDir, { recursive: true });
|
|
511
1839
|
this.bm25Index = new BM25Index;
|
|
512
1840
|
for (const [filepath, entry] of this.symbolIndex) {
|
|
@@ -518,7 +1846,7 @@ class CoreModule {
|
|
|
518
1846
|
files: Object.fromEntries(this.symbolIndex),
|
|
519
1847
|
bm25Data: this.bm25Index.serialize()
|
|
520
1848
|
};
|
|
521
|
-
await fs2.writeFile(
|
|
1849
|
+
await fs2.writeFile(path5.join(coreDir, "symbols.json"), JSON.stringify(symbolIndexData, null, 2));
|
|
522
1850
|
console.log(` [Core] Symbol index built with ${this.symbolIndex.size} files`);
|
|
523
1851
|
}
|
|
524
1852
|
async search(query, ctx, options) {
|
|
@@ -615,8 +1943,8 @@ class CoreModule {
|
|
|
615
1943
|
return bestChunk;
|
|
616
1944
|
}
|
|
617
1945
|
async loadSymbolIndex(rootDir, config) {
|
|
618
|
-
const coreDir =
|
|
619
|
-
const symbolsPath =
|
|
1946
|
+
const coreDir = path5.join(getRaggrepDir(rootDir, config), "index", "core");
|
|
1947
|
+
const symbolsPath = path5.join(coreDir, "symbols.json");
|
|
620
1948
|
try {
|
|
621
1949
|
const content = await fs2.readFile(symbolsPath, "utf-8");
|
|
622
1950
|
const data = JSON.parse(content);
|
|
@@ -637,13 +1965,14 @@ class CoreModule {
|
|
|
637
1965
|
var DEFAULT_MIN_SCORE = 0.1, DEFAULT_TOP_K = 20, LINES_PER_CHUNK = 50, CHUNK_OVERLAP = 10;
|
|
638
1966
|
var init_core = __esm(() => {
|
|
639
1967
|
init_config2();
|
|
1968
|
+
init_introspection();
|
|
640
1969
|
init_symbols();
|
|
641
1970
|
});
|
|
642
1971
|
|
|
643
1972
|
// src/infrastructure/embeddings/transformersEmbedding.ts
|
|
644
1973
|
import { pipeline, env } from "@xenova/transformers";
|
|
645
|
-
import * as
|
|
646
|
-
import * as
|
|
1974
|
+
import * as path6 from "path";
|
|
1975
|
+
import * as os2 from "os";
|
|
647
1976
|
|
|
648
1977
|
class TransformersEmbeddingProvider {
|
|
649
1978
|
pipeline = null;
|
|
@@ -775,7 +2104,7 @@ async function getEmbeddings(texts) {
|
|
|
775
2104
|
}
|
|
776
2105
|
var CACHE_DIR, EMBEDDING_MODELS2, EMBEDDING_DIMENSION = 384, BATCH_SIZE = 32, globalProvider = null, globalConfig;
|
|
777
2106
|
var init_transformersEmbedding = __esm(() => {
|
|
778
|
-
CACHE_DIR =
|
|
2107
|
+
CACHE_DIR = path6.join(os2.homedir(), ".cache", "raggrep", "models");
|
|
779
2108
|
env.cacheDir = CACHE_DIR;
|
|
780
2109
|
env.allowLocalModels = true;
|
|
781
2110
|
EMBEDDING_MODELS2 = {
|
|
@@ -1060,7 +2389,7 @@ function parsePathContext(filepath) {
|
|
|
1060
2389
|
let layer;
|
|
1061
2390
|
const allLower = [...dirSegments, filename].map((s) => s.toLowerCase()).join(" ");
|
|
1062
2391
|
const filenameLower = filename.toLowerCase();
|
|
1063
|
-
for (const [layerName, patterns] of Object.entries(
|
|
2392
|
+
for (const [layerName, patterns] of Object.entries(LAYER_PATTERNS2)) {
|
|
1064
2393
|
for (const pattern of patterns) {
|
|
1065
2394
|
if (filenameLower.includes(pattern)) {
|
|
1066
2395
|
layer = layerName;
|
|
@@ -1075,7 +2404,7 @@ function parsePathContext(filepath) {
|
|
|
1075
2404
|
break;
|
|
1076
2405
|
}
|
|
1077
2406
|
let domain;
|
|
1078
|
-
const layerPatternSet = new Set(Object.values(
|
|
2407
|
+
const layerPatternSet = new Set(Object.values(LAYER_PATTERNS2).flat());
|
|
1079
2408
|
const reversedSegments = [...dirSegments].reverse();
|
|
1080
2409
|
for (const segment of reversedSegments) {
|
|
1081
2410
|
const lower = segment.toLowerCase();
|
|
@@ -1113,7 +2442,7 @@ function formatPathContextForEmbedding(pathContext) {
|
|
|
1113
2442
|
const unique = [...new Set(parts)];
|
|
1114
2443
|
return `[${unique.join(" ")}]`;
|
|
1115
2444
|
}
|
|
1116
|
-
var COMMON_KEYWORDS,
|
|
2445
|
+
var COMMON_KEYWORDS, LAYER_PATTERNS2;
|
|
1117
2446
|
var init_keywords = __esm(() => {
|
|
1118
2447
|
COMMON_KEYWORDS = new Set([
|
|
1119
2448
|
"const",
|
|
@@ -1183,7 +2512,7 @@ var init_keywords = __esm(() => {
|
|
|
1183
2512
|
"has",
|
|
1184
2513
|
"have"
|
|
1185
2514
|
]);
|
|
1186
|
-
|
|
2515
|
+
LAYER_PATTERNS2 = {
|
|
1187
2516
|
controller: ["controller", "controllers", "handler", "handlers", "route", "routes", "api"],
|
|
1188
2517
|
service: ["service", "services", "usecase", "usecases", "application"],
|
|
1189
2518
|
repository: ["repository", "repositories", "repo", "repos", "dao", "store", "storage"],
|
|
@@ -1200,7 +2529,7 @@ var init_keywords = __esm(() => {
|
|
|
1200
2529
|
|
|
1201
2530
|
// src/infrastructure/storage/symbolicIndex.ts
|
|
1202
2531
|
import * as fs3 from "fs/promises";
|
|
1203
|
-
import * as
|
|
2532
|
+
import * as path7 from "path";
|
|
1204
2533
|
|
|
1205
2534
|
class SymbolicIndex {
|
|
1206
2535
|
meta = null;
|
|
@@ -1209,7 +2538,7 @@ class SymbolicIndex {
|
|
|
1209
2538
|
symbolicPath;
|
|
1210
2539
|
moduleId;
|
|
1211
2540
|
constructor(indexDir, moduleId) {
|
|
1212
|
-
this.symbolicPath =
|
|
2541
|
+
this.symbolicPath = path7.join(indexDir, "index", moduleId, "symbolic");
|
|
1213
2542
|
this.moduleId = moduleId;
|
|
1214
2543
|
}
|
|
1215
2544
|
async initialize() {
|
|
@@ -1270,16 +2599,16 @@ class SymbolicIndex {
|
|
|
1270
2599
|
this.meta.lastUpdated = new Date().toISOString();
|
|
1271
2600
|
this.meta.fileCount = this.fileSummaries.size;
|
|
1272
2601
|
await fs3.mkdir(this.symbolicPath, { recursive: true });
|
|
1273
|
-
const metaPath =
|
|
2602
|
+
const metaPath = path7.join(this.symbolicPath, "_meta.json");
|
|
1274
2603
|
await fs3.writeFile(metaPath, JSON.stringify(this.meta, null, 2));
|
|
1275
2604
|
for (const [filepath, summary] of this.fileSummaries) {
|
|
1276
2605
|
const summaryPath = this.getFileSummaryPath(filepath);
|
|
1277
|
-
await fs3.mkdir(
|
|
2606
|
+
await fs3.mkdir(path7.dirname(summaryPath), { recursive: true });
|
|
1278
2607
|
await fs3.writeFile(summaryPath, JSON.stringify(summary, null, 2));
|
|
1279
2608
|
}
|
|
1280
2609
|
}
|
|
1281
2610
|
async load() {
|
|
1282
|
-
const metaPath =
|
|
2611
|
+
const metaPath = path7.join(this.symbolicPath, "_meta.json");
|
|
1283
2612
|
const metaContent = await fs3.readFile(metaPath, "utf-8");
|
|
1284
2613
|
this.meta = JSON.parse(metaContent);
|
|
1285
2614
|
this.fileSummaries.clear();
|
|
@@ -1290,7 +2619,7 @@ class SymbolicIndex {
|
|
|
1290
2619
|
try {
|
|
1291
2620
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
1292
2621
|
for (const entry of entries) {
|
|
1293
|
-
const fullPath =
|
|
2622
|
+
const fullPath = path7.join(dir, entry.name);
|
|
1294
2623
|
if (entry.isDirectory()) {
|
|
1295
2624
|
await this.loadFileSummariesRecursive(fullPath);
|
|
1296
2625
|
} else if (entry.name.endsWith(".json") && entry.name !== "_meta.json") {
|
|
@@ -1307,7 +2636,7 @@ class SymbolicIndex {
|
|
|
1307
2636
|
}
|
|
1308
2637
|
getFileSummaryPath(filepath) {
|
|
1309
2638
|
const jsonPath = filepath.replace(/\.[^.]+$/, ".json");
|
|
1310
|
-
return
|
|
2639
|
+
return path7.join(this.symbolicPath, jsonPath);
|
|
1311
2640
|
}
|
|
1312
2641
|
async deleteFileSummary(filepath) {
|
|
1313
2642
|
try {
|
|
@@ -1317,7 +2646,7 @@ class SymbolicIndex {
|
|
|
1317
2646
|
}
|
|
1318
2647
|
async exists() {
|
|
1319
2648
|
try {
|
|
1320
|
-
const metaPath =
|
|
2649
|
+
const metaPath = path7.join(this.symbolicPath, "_meta.json");
|
|
1321
2650
|
await fs3.access(metaPath);
|
|
1322
2651
|
return true;
|
|
1323
2652
|
} catch {
|
|
@@ -1357,7 +2686,7 @@ __export(exports_typescript, {
|
|
|
1357
2686
|
DEFAULT_TOP_K: () => DEFAULT_TOP_K2,
|
|
1358
2687
|
DEFAULT_MIN_SCORE: () => DEFAULT_MIN_SCORE2
|
|
1359
2688
|
});
|
|
1360
|
-
import * as
|
|
2689
|
+
import * as path8 from "path";
|
|
1361
2690
|
|
|
1362
2691
|
class TypeScriptModule {
|
|
1363
2692
|
id = "language/typescript";
|
|
@@ -1551,16 +2880,16 @@ class TypeScriptModule {
|
|
|
1551
2880
|
while ((match = importRegex.exec(content)) !== null) {
|
|
1552
2881
|
const importPath = match[1];
|
|
1553
2882
|
if (importPath.startsWith(".")) {
|
|
1554
|
-
const dir =
|
|
1555
|
-
const resolved =
|
|
2883
|
+
const dir = path8.dirname(filepath);
|
|
2884
|
+
const resolved = path8.normalize(path8.join(dir, importPath));
|
|
1556
2885
|
references.push(resolved);
|
|
1557
2886
|
}
|
|
1558
2887
|
}
|
|
1559
2888
|
while ((match = requireRegex.exec(content)) !== null) {
|
|
1560
2889
|
const importPath = match[1];
|
|
1561
2890
|
if (importPath.startsWith(".")) {
|
|
1562
|
-
const dir =
|
|
1563
|
-
const resolved =
|
|
2891
|
+
const dir = path8.dirname(filepath);
|
|
2892
|
+
const resolved = path8.normalize(path8.join(dir, importPath));
|
|
1564
2893
|
references.push(resolved);
|
|
1565
2894
|
}
|
|
1566
2895
|
}
|
|
@@ -1581,7 +2910,7 @@ var init_typescript = __esm(() => {
|
|
|
1581
2910
|
init_config2();
|
|
1582
2911
|
import { glob } from "glob";
|
|
1583
2912
|
import * as fs6 from "fs/promises";
|
|
1584
|
-
import * as
|
|
2913
|
+
import * as path11 from "path";
|
|
1585
2914
|
|
|
1586
2915
|
// src/modules/registry.ts
|
|
1587
2916
|
class ModuleRegistryImpl {
|
|
@@ -1611,12 +2940,12 @@ async function registerBuiltInModules() {
|
|
|
1611
2940
|
registry.register(new TypeScriptModule2);
|
|
1612
2941
|
}
|
|
1613
2942
|
|
|
1614
|
-
// src/introspection/
|
|
1615
|
-
import * as
|
|
2943
|
+
// src/infrastructure/introspection/IntrospectionIndex.ts
|
|
2944
|
+
import * as path10 from "path";
|
|
1616
2945
|
import * as fs5 from "fs/promises";
|
|
1617
2946
|
|
|
1618
|
-
// src/introspection/projectDetector.ts
|
|
1619
|
-
import * as
|
|
2947
|
+
// src/infrastructure/introspection/projectDetector.ts
|
|
2948
|
+
import * as path9 from "path";
|
|
1620
2949
|
import * as fs4 from "fs/promises";
|
|
1621
2950
|
var MAX_SCAN_DEPTH = 4;
|
|
1622
2951
|
var SKIP_DIRS = new Set([
|
|
@@ -1629,76 +2958,18 @@ var SKIP_DIRS = new Set([
|
|
|
1629
2958
|
"coverage",
|
|
1630
2959
|
".raggrep"
|
|
1631
2960
|
]);
|
|
1632
|
-
var PROJECT_PATTERNS = [
|
|
1633
|
-
{ pattern: /^apps\/([^/]+)/, type: "app", defaultScope: "unknown" },
|
|
1634
|
-
{ pattern: /^packages\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
1635
|
-
{ pattern: /^libs\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
1636
|
-
{ pattern: /^services\/([^/]+)/, type: "service", defaultScope: "backend" },
|
|
1637
|
-
{ pattern: /^scripts\/([^/]+)/, type: "script", defaultScope: "tooling" },
|
|
1638
|
-
{ pattern: /^tools\/([^/]+)/, type: "script", defaultScope: "tooling" }
|
|
1639
|
-
];
|
|
1640
|
-
var SCOPE_KEYWORDS = {
|
|
1641
|
-
frontend: [
|
|
1642
|
-
"web",
|
|
1643
|
-
"webapp",
|
|
1644
|
-
"frontend",
|
|
1645
|
-
"client",
|
|
1646
|
-
"ui",
|
|
1647
|
-
"app",
|
|
1648
|
-
"mobile",
|
|
1649
|
-
"react",
|
|
1650
|
-
"vue",
|
|
1651
|
-
"angular",
|
|
1652
|
-
"next",
|
|
1653
|
-
"nuxt"
|
|
1654
|
-
],
|
|
1655
|
-
backend: [
|
|
1656
|
-
"api",
|
|
1657
|
-
"server",
|
|
1658
|
-
"backend",
|
|
1659
|
-
"service",
|
|
1660
|
-
"worker",
|
|
1661
|
-
"lambda",
|
|
1662
|
-
"functions"
|
|
1663
|
-
],
|
|
1664
|
-
shared: ["shared", "common", "utils", "lib", "core", "types", "models"],
|
|
1665
|
-
tooling: [
|
|
1666
|
-
"scripts",
|
|
1667
|
-
"tools",
|
|
1668
|
-
"cli",
|
|
1669
|
-
"devtools",
|
|
1670
|
-
"build",
|
|
1671
|
-
"config",
|
|
1672
|
-
"infra"
|
|
1673
|
-
],
|
|
1674
|
-
unknown: []
|
|
1675
|
-
};
|
|
1676
|
-
function detectScopeFromName(name) {
|
|
1677
|
-
const nameLower = name.toLowerCase();
|
|
1678
|
-
for (const [scope, keywords] of Object.entries(SCOPE_KEYWORDS)) {
|
|
1679
|
-
if (scope === "unknown")
|
|
1680
|
-
continue;
|
|
1681
|
-
for (const keyword of keywords) {
|
|
1682
|
-
if (nameLower.includes(keyword)) {
|
|
1683
|
-
return scope;
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
return "unknown";
|
|
1688
|
-
}
|
|
1689
2961
|
async function scanForPackageJsons(rootDir, currentDir = "", depth = 0) {
|
|
1690
2962
|
if (depth > MAX_SCAN_DEPTH)
|
|
1691
2963
|
return [];
|
|
1692
2964
|
const results = [];
|
|
1693
|
-
const fullDir = currentDir ?
|
|
2965
|
+
const fullDir = currentDir ? path9.join(rootDir, currentDir) : rootDir;
|
|
1694
2966
|
try {
|
|
1695
2967
|
const entries = await fs4.readdir(fullDir, { withFileTypes: true });
|
|
1696
2968
|
const hasPackageJson = entries.some((e) => e.isFile() && e.name === "package.json");
|
|
1697
2969
|
if (hasPackageJson && currentDir) {
|
|
1698
2970
|
const info = await parsePackageJson(rootDir, currentDir);
|
|
1699
|
-
if (info)
|
|
2971
|
+
if (info)
|
|
1700
2972
|
results.push(info);
|
|
1701
|
-
}
|
|
1702
2973
|
}
|
|
1703
2974
|
for (const entry of entries) {
|
|
1704
2975
|
if (!entry.isDirectory())
|
|
@@ -1714,10 +2985,10 @@ async function scanForPackageJsons(rootDir, currentDir = "", depth = 0) {
|
|
|
1714
2985
|
}
|
|
1715
2986
|
async function parsePackageJson(rootDir, relativePath) {
|
|
1716
2987
|
try {
|
|
1717
|
-
const packageJsonPath =
|
|
2988
|
+
const packageJsonPath = path9.join(rootDir, relativePath, "package.json");
|
|
1718
2989
|
const content = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1719
2990
|
const pkg = JSON.parse(content);
|
|
1720
|
-
const name = pkg.name ||
|
|
2991
|
+
const name = pkg.name || path9.basename(relativePath);
|
|
1721
2992
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1722
2993
|
let type = "unknown";
|
|
1723
2994
|
if (deps["next"] || deps["react"] || deps["vue"] || deps["svelte"]) {
|
|
@@ -1733,6 +3004,22 @@ async function parsePackageJson(rootDir, relativePath) {
|
|
|
1733
3004
|
return null;
|
|
1734
3005
|
}
|
|
1735
3006
|
}
|
|
3007
|
+
function getProjectType(patternDir) {
|
|
3008
|
+
switch (patternDir) {
|
|
3009
|
+
case "apps":
|
|
3010
|
+
return "app";
|
|
3011
|
+
case "packages":
|
|
3012
|
+
case "libs":
|
|
3013
|
+
return "library";
|
|
3014
|
+
case "services":
|
|
3015
|
+
return "service";
|
|
3016
|
+
case "scripts":
|
|
3017
|
+
case "tools":
|
|
3018
|
+
return "script";
|
|
3019
|
+
default:
|
|
3020
|
+
return "unknown";
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
1736
3023
|
async function detectProjectStructure(rootDir) {
|
|
1737
3024
|
const projectMap = new Map;
|
|
1738
3025
|
let isMonorepo = false;
|
|
@@ -1746,7 +3033,7 @@ async function detectProjectStructure(rootDir) {
|
|
|
1746
3033
|
for (const pattern of monorepoPatterns) {
|
|
1747
3034
|
if (!dirNames.includes(pattern))
|
|
1748
3035
|
continue;
|
|
1749
|
-
const patternDir =
|
|
3036
|
+
const patternDir = path9.join(rootDir, pattern);
|
|
1750
3037
|
try {
|
|
1751
3038
|
const subDirs = await fs4.readdir(patternDir, { withFileTypes: true });
|
|
1752
3039
|
for (const subDir of subDirs) {
|
|
@@ -1765,12 +3052,10 @@ async function detectProjectStructure(rootDir) {
|
|
|
1765
3052
|
}
|
|
1766
3053
|
const packageJsons = await scanForPackageJsons(rootDir);
|
|
1767
3054
|
for (const pkg of packageJsons) {
|
|
1768
|
-
if (pkg.hasWorkspaces)
|
|
3055
|
+
if (pkg.hasWorkspaces)
|
|
1769
3056
|
isMonorepo = true;
|
|
1770
|
-
|
|
1771
|
-
if (packageJsons.length > 1) {
|
|
3057
|
+
if (packageJsons.length > 1)
|
|
1772
3058
|
isMonorepo = true;
|
|
1773
|
-
}
|
|
1774
3059
|
projectMap.set(pkg.relativePath, {
|
|
1775
3060
|
name: pkg.name,
|
|
1776
3061
|
root: pkg.relativePath,
|
|
@@ -1779,11 +3064,10 @@ async function detectProjectStructure(rootDir) {
|
|
|
1779
3064
|
}
|
|
1780
3065
|
let rootType = "unknown";
|
|
1781
3066
|
try {
|
|
1782
|
-
const rootPkgPath =
|
|
3067
|
+
const rootPkgPath = path9.join(rootDir, "package.json");
|
|
1783
3068
|
const rootPkg = JSON.parse(await fs4.readFile(rootPkgPath, "utf-8"));
|
|
1784
|
-
if (rootPkg.workspaces)
|
|
3069
|
+
if (rootPkg.workspaces)
|
|
1785
3070
|
isMonorepo = true;
|
|
1786
|
-
}
|
|
1787
3071
|
const deps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
|
|
1788
3072
|
if (deps["next"] || deps["react"] || deps["vue"]) {
|
|
1789
3073
|
rootType = "app";
|
|
@@ -1805,273 +3089,9 @@ async function detectProjectStructure(rootDir) {
|
|
|
1805
3089
|
};
|
|
1806
3090
|
}
|
|
1807
3091
|
}
|
|
1808
|
-
function getProjectType(patternDir) {
|
|
1809
|
-
switch (patternDir) {
|
|
1810
|
-
case "apps":
|
|
1811
|
-
return "app";
|
|
1812
|
-
case "packages":
|
|
1813
|
-
case "libs":
|
|
1814
|
-
return "library";
|
|
1815
|
-
case "services":
|
|
1816
|
-
return "service";
|
|
1817
|
-
case "scripts":
|
|
1818
|
-
case "tools":
|
|
1819
|
-
return "script";
|
|
1820
|
-
default:
|
|
1821
|
-
return "unknown";
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
|
-
function findProjectForFile(filepath, structure) {
|
|
1825
|
-
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
1826
|
-
const matches = [];
|
|
1827
|
-
for (const project of structure.projects) {
|
|
1828
|
-
if (normalizedPath === project.root || normalizedPath.startsWith(project.root + "/")) {
|
|
1829
|
-
matches.push(project);
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
if (matches.length > 0) {
|
|
1833
|
-
return matches.reduce((best, current) => current.root.length > best.root.length ? current : best);
|
|
1834
|
-
}
|
|
1835
|
-
for (const { pattern, type } of PROJECT_PATTERNS) {
|
|
1836
|
-
const match = normalizedPath.match(pattern);
|
|
1837
|
-
if (match) {
|
|
1838
|
-
return {
|
|
1839
|
-
name: match[1],
|
|
1840
|
-
root: match[0],
|
|
1841
|
-
type
|
|
1842
|
-
};
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
return {
|
|
1846
|
-
name: "root",
|
|
1847
|
-
root: "",
|
|
1848
|
-
type: structure.rootType ?? "unknown"
|
|
1849
|
-
};
|
|
1850
|
-
}
|
|
1851
|
-
|
|
1852
|
-
// src/introspection/fileIntrospector.ts
|
|
1853
|
-
import * as path7 from "path";
|
|
1854
|
-
var LAYER_PATTERNS2 = {
|
|
1855
|
-
controller: ["controller", "api", "routes", "route", "handler"],
|
|
1856
|
-
service: ["service", "logic", "usecase", "usecases", "handler"],
|
|
1857
|
-
repository: ["repository", "repo", "dao", "store", "persistence"],
|
|
1858
|
-
model: ["model", "models", "entity", "entities", "schema", "schemas", "types", "type"],
|
|
1859
|
-
util: ["util", "utils", "helper", "helpers", "common", "lib"],
|
|
1860
|
-
config: ["config", "configuration", "settings"],
|
|
1861
|
-
middleware: ["middleware", "middlewares"],
|
|
1862
|
-
domain: ["domain"],
|
|
1863
|
-
infrastructure: ["infrastructure", "infra"],
|
|
1864
|
-
application: ["application", "app"],
|
|
1865
|
-
presentation: ["presentation", "ui", "views", "view", "component", "components"],
|
|
1866
|
-
test: ["test", "tests", "spec", "specs", "__tests__", "e2e"]
|
|
1867
|
-
};
|
|
1868
|
-
var DOMAIN_PATTERNS = [
|
|
1869
|
-
"auth",
|
|
1870
|
-
"authentication",
|
|
1871
|
-
"user",
|
|
1872
|
-
"users",
|
|
1873
|
-
"account",
|
|
1874
|
-
"accounts",
|
|
1875
|
-
"profile",
|
|
1876
|
-
"profiles",
|
|
1877
|
-
"product",
|
|
1878
|
-
"products",
|
|
1879
|
-
"item",
|
|
1880
|
-
"items",
|
|
1881
|
-
"catalog",
|
|
1882
|
-
"order",
|
|
1883
|
-
"orders",
|
|
1884
|
-
"cart",
|
|
1885
|
-
"checkout",
|
|
1886
|
-
"payment",
|
|
1887
|
-
"payments",
|
|
1888
|
-
"billing",
|
|
1889
|
-
"subscription",
|
|
1890
|
-
"subscriptions",
|
|
1891
|
-
"notification",
|
|
1892
|
-
"notifications",
|
|
1893
|
-
"email",
|
|
1894
|
-
"sms",
|
|
1895
|
-
"report",
|
|
1896
|
-
"reports",
|
|
1897
|
-
"analytics",
|
|
1898
|
-
"metrics",
|
|
1899
|
-
"dashboard",
|
|
1900
|
-
"admin",
|
|
1901
|
-
"settings",
|
|
1902
|
-
"search",
|
|
1903
|
-
"chat",
|
|
1904
|
-
"message",
|
|
1905
|
-
"messages",
|
|
1906
|
-
"feed",
|
|
1907
|
-
"post",
|
|
1908
|
-
"posts",
|
|
1909
|
-
"comment",
|
|
1910
|
-
"comments",
|
|
1911
|
-
"media",
|
|
1912
|
-
"upload",
|
|
1913
|
-
"file",
|
|
1914
|
-
"files",
|
|
1915
|
-
"storage",
|
|
1916
|
-
"cache",
|
|
1917
|
-
"session",
|
|
1918
|
-
"log",
|
|
1919
|
-
"logs",
|
|
1920
|
-
"audit"
|
|
1921
|
-
];
|
|
1922
|
-
var FRAMEWORK_INDICATORS = {
|
|
1923
|
-
nextjs: ["next", "next/"],
|
|
1924
|
-
express: ["express"],
|
|
1925
|
-
fastify: ["fastify"],
|
|
1926
|
-
react: ["react"],
|
|
1927
|
-
vue: ["vue"],
|
|
1928
|
-
angular: ["@angular/"],
|
|
1929
|
-
nestjs: ["@nestjs/"],
|
|
1930
|
-
koa: ["koa"]
|
|
1931
|
-
};
|
|
1932
|
-
var EXTENSION_TO_LANGUAGE = {
|
|
1933
|
-
".ts": "typescript",
|
|
1934
|
-
".tsx": "typescript",
|
|
1935
|
-
".js": "javascript",
|
|
1936
|
-
".jsx": "javascript",
|
|
1937
|
-
".mjs": "javascript",
|
|
1938
|
-
".cjs": "javascript",
|
|
1939
|
-
".py": "python",
|
|
1940
|
-
".go": "go",
|
|
1941
|
-
".rs": "rust",
|
|
1942
|
-
".java": "java",
|
|
1943
|
-
".kt": "kotlin",
|
|
1944
|
-
".swift": "swift",
|
|
1945
|
-
".rb": "ruby",
|
|
1946
|
-
".php": "php",
|
|
1947
|
-
".cs": "csharp",
|
|
1948
|
-
".cpp": "cpp",
|
|
1949
|
-
".c": "c",
|
|
1950
|
-
".h": "c",
|
|
1951
|
-
".hpp": "cpp",
|
|
1952
|
-
".md": "markdown",
|
|
1953
|
-
".json": "json",
|
|
1954
|
-
".yaml": "yaml",
|
|
1955
|
-
".yml": "yaml"
|
|
1956
|
-
};
|
|
1957
|
-
function introspectFile(filepath, structure, fileContent) {
|
|
1958
|
-
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
1959
|
-
const segments = normalizedPath.split("/").filter((s) => s.length > 0);
|
|
1960
|
-
const filename = segments[segments.length - 1] || "";
|
|
1961
|
-
const ext = path7.extname(filename);
|
|
1962
|
-
const project = findProjectForFile(normalizedPath, structure);
|
|
1963
|
-
const language = EXTENSION_TO_LANGUAGE[ext] || "unknown";
|
|
1964
|
-
const layer = detectLayer(segments, filename);
|
|
1965
|
-
const domain = detectDomain(segments);
|
|
1966
|
-
const scope = detectScope(segments, project, layer);
|
|
1967
|
-
let framework;
|
|
1968
|
-
if (fileContent) {
|
|
1969
|
-
framework = detectFramework(fileContent);
|
|
1970
|
-
}
|
|
1971
|
-
return {
|
|
1972
|
-
filepath: normalizedPath,
|
|
1973
|
-
project,
|
|
1974
|
-
scope,
|
|
1975
|
-
layer,
|
|
1976
|
-
domain,
|
|
1977
|
-
language,
|
|
1978
|
-
framework,
|
|
1979
|
-
depth: segments.length - 1,
|
|
1980
|
-
pathSegments: segments.slice(0, -1)
|
|
1981
|
-
};
|
|
1982
|
-
}
|
|
1983
|
-
function detectLayer(segments, filename) {
|
|
1984
|
-
const filenameLower = filename.toLowerCase();
|
|
1985
|
-
for (const [layer, patterns] of Object.entries(LAYER_PATTERNS2)) {
|
|
1986
|
-
for (const pattern of patterns) {
|
|
1987
|
-
if (filenameLower.includes(pattern)) {
|
|
1988
|
-
return layer;
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
for (let i = segments.length - 2;i >= 0; i--) {
|
|
1993
|
-
const segment = segments[i].toLowerCase();
|
|
1994
|
-
for (const [layer, patterns] of Object.entries(LAYER_PATTERNS2)) {
|
|
1995
|
-
if (patterns.includes(segment)) {
|
|
1996
|
-
return layer;
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
return;
|
|
2001
|
-
}
|
|
2002
|
-
function detectDomain(segments) {
|
|
2003
|
-
const skipSegments = new Set([
|
|
2004
|
-
"src",
|
|
2005
|
-
"lib",
|
|
2006
|
-
"app",
|
|
2007
|
-
"apps",
|
|
2008
|
-
"packages",
|
|
2009
|
-
"services",
|
|
2010
|
-
"modules",
|
|
2011
|
-
"features",
|
|
2012
|
-
...Object.values(LAYER_PATTERNS2).flat()
|
|
2013
|
-
]);
|
|
2014
|
-
for (const segment of segments) {
|
|
2015
|
-
const segmentLower = segment.toLowerCase();
|
|
2016
|
-
if (skipSegments.has(segmentLower))
|
|
2017
|
-
continue;
|
|
2018
|
-
if (DOMAIN_PATTERNS.includes(segmentLower)) {
|
|
2019
|
-
return segmentLower;
|
|
2020
|
-
}
|
|
2021
|
-
for (const domain of DOMAIN_PATTERNS) {
|
|
2022
|
-
if (segmentLower.startsWith(domain) || segmentLower.endsWith(domain)) {
|
|
2023
|
-
return domain;
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
return;
|
|
2028
|
-
}
|
|
2029
|
-
function detectScope(segments, project, layer) {
|
|
2030
|
-
const projectScope = detectScopeFromName(project.name);
|
|
2031
|
-
if (projectScope !== "unknown") {
|
|
2032
|
-
return projectScope;
|
|
2033
|
-
}
|
|
2034
|
-
if (layer) {
|
|
2035
|
-
switch (layer) {
|
|
2036
|
-
case "controller":
|
|
2037
|
-
case "repository":
|
|
2038
|
-
case "middleware":
|
|
2039
|
-
return "backend";
|
|
2040
|
-
case "presentation":
|
|
2041
|
-
return "frontend";
|
|
2042
|
-
case "util":
|
|
2043
|
-
case "model":
|
|
2044
|
-
return "shared";
|
|
2045
|
-
case "test":
|
|
2046
|
-
return "tooling";
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
for (const segment of segments) {
|
|
2050
|
-
const segmentLower = segment.toLowerCase();
|
|
2051
|
-
if (["server", "api", "backend"].includes(segmentLower)) {
|
|
2052
|
-
return "backend";
|
|
2053
|
-
}
|
|
2054
|
-
if (["client", "web", "frontend", "ui"].includes(segmentLower)) {
|
|
2055
|
-
return "frontend";
|
|
2056
|
-
}
|
|
2057
|
-
if (["shared", "common", "lib", "libs"].includes(segmentLower)) {
|
|
2058
|
-
return "shared";
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
|
-
return "unknown";
|
|
2062
|
-
}
|
|
2063
|
-
function detectFramework(content) {
|
|
2064
|
-
for (const [framework, indicators] of Object.entries(FRAMEWORK_INDICATORS)) {
|
|
2065
|
-
for (const indicator of indicators) {
|
|
2066
|
-
if (content.includes(`from '${indicator}`) || content.includes(`from "${indicator}`) || content.includes(`require('${indicator}`) || content.includes(`require("${indicator}`)) {
|
|
2067
|
-
return framework;
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
return;
|
|
2072
|
-
}
|
|
2073
3092
|
|
|
2074
|
-
// src/introspection/
|
|
3093
|
+
// src/infrastructure/introspection/IntrospectionIndex.ts
|
|
3094
|
+
init_introspection();
|
|
2075
3095
|
init_config2();
|
|
2076
3096
|
|
|
2077
3097
|
class IntrospectionIndex {
|
|
@@ -2085,7 +3105,7 @@ class IntrospectionIndex {
|
|
|
2085
3105
|
async initialize() {
|
|
2086
3106
|
this.structure = await detectProjectStructure(this.rootDir);
|
|
2087
3107
|
try {
|
|
2088
|
-
const configPath =
|
|
3108
|
+
const configPath = path10.join(this.rootDir, ".raggrep", "config.json");
|
|
2089
3109
|
const configContent = await fs5.readFile(configPath, "utf-8");
|
|
2090
3110
|
const config = JSON.parse(configContent);
|
|
2091
3111
|
this.config = config.introspection || {};
|
|
@@ -2125,29 +3145,29 @@ class IntrospectionIndex {
|
|
|
2125
3145
|
}
|
|
2126
3146
|
}
|
|
2127
3147
|
async save(config) {
|
|
2128
|
-
const introDir =
|
|
3148
|
+
const introDir = path10.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
2129
3149
|
await fs5.mkdir(introDir, { recursive: true });
|
|
2130
|
-
const projectPath =
|
|
3150
|
+
const projectPath = path10.join(introDir, "_project.json");
|
|
2131
3151
|
await fs5.writeFile(projectPath, JSON.stringify({
|
|
2132
3152
|
version: "1.0.0",
|
|
2133
3153
|
lastUpdated: new Date().toISOString(),
|
|
2134
3154
|
structure: this.structure
|
|
2135
3155
|
}, null, 2));
|
|
2136
3156
|
for (const [filepath, intro] of this.files) {
|
|
2137
|
-
const introFilePath =
|
|
2138
|
-
await fs5.mkdir(
|
|
3157
|
+
const introFilePath = path10.join(introDir, "files", filepath.replace(/\.[^.]+$/, ".json"));
|
|
3158
|
+
await fs5.mkdir(path10.dirname(introFilePath), { recursive: true });
|
|
2139
3159
|
await fs5.writeFile(introFilePath, JSON.stringify(intro, null, 2));
|
|
2140
3160
|
}
|
|
2141
3161
|
console.log(` [Introspection] Saved metadata for ${this.files.size} files`);
|
|
2142
3162
|
}
|
|
2143
3163
|
async load(config) {
|
|
2144
|
-
const introDir =
|
|
3164
|
+
const introDir = path10.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
2145
3165
|
try {
|
|
2146
|
-
const projectPath =
|
|
3166
|
+
const projectPath = path10.join(introDir, "_project.json");
|
|
2147
3167
|
const projectContent = await fs5.readFile(projectPath, "utf-8");
|
|
2148
3168
|
const projectData = JSON.parse(projectContent);
|
|
2149
3169
|
this.structure = projectData.structure;
|
|
2150
|
-
await this.loadFilesRecursive(
|
|
3170
|
+
await this.loadFilesRecursive(path10.join(introDir, "files"), "");
|
|
2151
3171
|
} catch {
|
|
2152
3172
|
this.structure = null;
|
|
2153
3173
|
this.files.clear();
|
|
@@ -2157,7 +3177,7 @@ class IntrospectionIndex {
|
|
|
2157
3177
|
try {
|
|
2158
3178
|
const entries = await fs5.readdir(basePath, { withFileTypes: true });
|
|
2159
3179
|
for (const entry of entries) {
|
|
2160
|
-
const entryPath =
|
|
3180
|
+
const entryPath = path10.join(basePath, entry.name);
|
|
2161
3181
|
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
2162
3182
|
if (entry.isDirectory()) {
|
|
2163
3183
|
await this.loadFilesRecursive(entryPath, relativePath);
|
|
@@ -2174,7 +3194,6 @@ class IntrospectionIndex {
|
|
|
2174
3194
|
this.structure = null;
|
|
2175
3195
|
}
|
|
2176
3196
|
}
|
|
2177
|
-
|
|
2178
3197
|
// src/app/indexer/watcher.ts
|
|
2179
3198
|
import { watch } from "chokidar";
|
|
2180
3199
|
init_config2();
|
|
@@ -2182,8 +3201,10 @@ init_config2();
|
|
|
2182
3201
|
// src/app/indexer/index.ts
|
|
2183
3202
|
async function indexDirectory(rootDir, options = {}) {
|
|
2184
3203
|
const verbose = options.verbose ?? false;
|
|
2185
|
-
rootDir =
|
|
3204
|
+
rootDir = path11.resolve(rootDir);
|
|
3205
|
+
const location = getIndexLocation(rootDir);
|
|
2186
3206
|
console.log(`Indexing directory: ${rootDir}`);
|
|
3207
|
+
console.log(`Index location: ${location.indexDir}`);
|
|
2187
3208
|
const config = await loadConfig(rootDir);
|
|
2188
3209
|
const introspection = new IntrospectionIndex(rootDir);
|
|
2189
3210
|
await introspection.initialize();
|
|
@@ -2225,11 +3246,11 @@ async function indexDirectory(rootDir, options = {}) {
|
|
|
2225
3246
|
rootDir,
|
|
2226
3247
|
config,
|
|
2227
3248
|
readFile: async (filepath) => {
|
|
2228
|
-
const fullPath =
|
|
3249
|
+
const fullPath = path11.isAbsolute(filepath) ? filepath : path11.join(rootDir, filepath);
|
|
2229
3250
|
return fs6.readFile(fullPath, "utf-8");
|
|
2230
3251
|
},
|
|
2231
3252
|
getFileStats: async (filepath) => {
|
|
2232
|
-
const fullPath =
|
|
3253
|
+
const fullPath = path11.isAbsolute(filepath) ? filepath : path11.join(rootDir, filepath);
|
|
2233
3254
|
const stats = await fs6.stat(fullPath);
|
|
2234
3255
|
return { lastModified: stats.mtime.toISOString() };
|
|
2235
3256
|
}
|
|
@@ -2254,18 +3275,18 @@ async function indexWithModule(rootDir, files, module, config, verbose, introspe
|
|
|
2254
3275
|
rootDir,
|
|
2255
3276
|
config,
|
|
2256
3277
|
readFile: async (filepath) => {
|
|
2257
|
-
const fullPath =
|
|
3278
|
+
const fullPath = path11.isAbsolute(filepath) ? filepath : path11.join(rootDir, filepath);
|
|
2258
3279
|
return fs6.readFile(fullPath, "utf-8");
|
|
2259
3280
|
},
|
|
2260
3281
|
getFileStats: async (filepath) => {
|
|
2261
|
-
const fullPath =
|
|
3282
|
+
const fullPath = path11.isAbsolute(filepath) ? filepath : path11.join(rootDir, filepath);
|
|
2262
3283
|
const stats = await fs6.stat(fullPath);
|
|
2263
3284
|
return { lastModified: stats.mtime.toISOString() };
|
|
2264
3285
|
},
|
|
2265
3286
|
getIntrospection: (filepath) => introspection.getFile(filepath)
|
|
2266
3287
|
};
|
|
2267
3288
|
for (const filepath of files) {
|
|
2268
|
-
const relativePath =
|
|
3289
|
+
const relativePath = path11.relative(rootDir, filepath);
|
|
2269
3290
|
try {
|
|
2270
3291
|
const stats = await fs6.stat(filepath);
|
|
2271
3292
|
const lastModified = stats.mtime.toISOString();
|
|
@@ -2335,13 +3356,13 @@ async function loadModuleManifest(rootDir, moduleId, config) {
|
|
|
2335
3356
|
}
|
|
2336
3357
|
async function writeModuleManifest(rootDir, moduleId, manifest, config) {
|
|
2337
3358
|
const manifestPath = getModuleManifestPath(rootDir, moduleId, config);
|
|
2338
|
-
await fs6.mkdir(
|
|
3359
|
+
await fs6.mkdir(path11.dirname(manifestPath), { recursive: true });
|
|
2339
3360
|
await fs6.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
2340
3361
|
}
|
|
2341
3362
|
async function writeFileIndex(rootDir, moduleId, filepath, fileIndex, config) {
|
|
2342
3363
|
const indexPath = getModuleIndexPath(rootDir, moduleId, config);
|
|
2343
|
-
const indexFilePath =
|
|
2344
|
-
await fs6.mkdir(
|
|
3364
|
+
const indexFilePath = path11.join(indexPath, filepath.replace(/\.[^.]+$/, ".json"));
|
|
3365
|
+
await fs6.mkdir(path11.dirname(indexFilePath), { recursive: true });
|
|
2345
3366
|
await fs6.writeFile(indexFilePath, JSON.stringify(fileIndex, null, 2));
|
|
2346
3367
|
}
|
|
2347
3368
|
async function updateGlobalManifest(rootDir, modules, config) {
|
|
@@ -2351,12 +3372,12 @@ async function updateGlobalManifest(rootDir, modules, config) {
|
|
|
2351
3372
|
lastUpdated: new Date().toISOString(),
|
|
2352
3373
|
modules: modules.map((m) => m.id)
|
|
2353
3374
|
};
|
|
2354
|
-
await fs6.mkdir(
|
|
3375
|
+
await fs6.mkdir(path11.dirname(manifestPath), { recursive: true });
|
|
2355
3376
|
await fs6.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
2356
3377
|
}
|
|
2357
3378
|
async function cleanupIndex(rootDir, options = {}) {
|
|
2358
3379
|
const verbose = options.verbose ?? false;
|
|
2359
|
-
rootDir =
|
|
3380
|
+
rootDir = path11.resolve(rootDir);
|
|
2360
3381
|
console.log(`Cleaning up index in: ${rootDir}`);
|
|
2361
3382
|
const config = await loadConfig(rootDir);
|
|
2362
3383
|
await registerBuiltInModules();
|
|
@@ -2386,7 +3407,7 @@ async function cleanupModuleIndex(rootDir, moduleId, config, verbose) {
|
|
|
2386
3407
|
const filesToRemove = [];
|
|
2387
3408
|
const updatedFiles = {};
|
|
2388
3409
|
for (const [filepath, entry] of Object.entries(manifest.files)) {
|
|
2389
|
-
const fullPath =
|
|
3410
|
+
const fullPath = path11.join(rootDir, filepath);
|
|
2390
3411
|
try {
|
|
2391
3412
|
await fs6.access(fullPath);
|
|
2392
3413
|
updatedFiles[filepath] = entry;
|
|
@@ -2400,7 +3421,7 @@ async function cleanupModuleIndex(rootDir, moduleId, config, verbose) {
|
|
|
2400
3421
|
}
|
|
2401
3422
|
}
|
|
2402
3423
|
for (const filepath of filesToRemove) {
|
|
2403
|
-
const indexFilePath =
|
|
3424
|
+
const indexFilePath = path11.join(indexPath, filepath.replace(/\.[^.]+$/, ".json"));
|
|
2404
3425
|
try {
|
|
2405
3426
|
await fs6.unlink(indexFilePath);
|
|
2406
3427
|
} catch {}
|
|
@@ -2416,7 +3437,7 @@ async function cleanupEmptyDirectories(dir) {
|
|
|
2416
3437
|
const entries = await fs6.readdir(dir, { withFileTypes: true });
|
|
2417
3438
|
for (const entry of entries) {
|
|
2418
3439
|
if (entry.isDirectory()) {
|
|
2419
|
-
const subDir =
|
|
3440
|
+
const subDir = path11.join(dir, entry.name);
|
|
2420
3441
|
await cleanupEmptyDirectories(subDir);
|
|
2421
3442
|
}
|
|
2422
3443
|
}
|
|
@@ -2434,9 +3455,9 @@ async function cleanupEmptyDirectories(dir) {
|
|
|
2434
3455
|
// src/app/search/index.ts
|
|
2435
3456
|
init_config2();
|
|
2436
3457
|
import * as fs7 from "fs/promises";
|
|
2437
|
-
import * as
|
|
3458
|
+
import * as path12 from "path";
|
|
2438
3459
|
async function search(rootDir, query, options = {}) {
|
|
2439
|
-
rootDir =
|
|
3460
|
+
rootDir = path12.resolve(rootDir);
|
|
2440
3461
|
console.log(`Searching for: "${query}"`);
|
|
2441
3462
|
const config = await loadConfig(rootDir);
|
|
2442
3463
|
await registerBuiltInModules();
|
|
@@ -2477,7 +3498,7 @@ function createSearchContext(rootDir, moduleId, config) {
|
|
|
2477
3498
|
config,
|
|
2478
3499
|
loadFileIndex: async (filepath) => {
|
|
2479
3500
|
const hasExtension = /\.[^./]+$/.test(filepath);
|
|
2480
|
-
const indexFilePath = hasExtension ?
|
|
3501
|
+
const indexFilePath = hasExtension ? path12.join(indexPath, filepath.replace(/\.[^.]+$/, ".json")) : path12.join(indexPath, filepath + ".json");
|
|
2481
3502
|
try {
|
|
2482
3503
|
const content = await fs7.readFile(indexFilePath, "utf-8");
|
|
2483
3504
|
return JSON.parse(content);
|
|
@@ -2489,7 +3510,7 @@ function createSearchContext(rootDir, moduleId, config) {
|
|
|
2489
3510
|
const files = [];
|
|
2490
3511
|
await traverseDirectory(indexPath, files, indexPath);
|
|
2491
3512
|
return files.filter((f) => f.endsWith(".json") && !f.endsWith("manifest.json")).map((f) => {
|
|
2492
|
-
const relative3 =
|
|
3513
|
+
const relative3 = path12.relative(indexPath, f);
|
|
2493
3514
|
return relative3.replace(/\.json$/, "");
|
|
2494
3515
|
});
|
|
2495
3516
|
}
|
|
@@ -2499,7 +3520,7 @@ async function traverseDirectory(dir, files, basePath) {
|
|
|
2499
3520
|
try {
|
|
2500
3521
|
const entries = await fs7.readdir(dir, { withFileTypes: true });
|
|
2501
3522
|
for (const entry of entries) {
|
|
2502
|
-
const fullPath =
|
|
3523
|
+
const fullPath = path12.join(dir, entry.name);
|
|
2503
3524
|
if (entry.isDirectory()) {
|
|
2504
3525
|
await traverseDirectory(fullPath, files, basePath);
|
|
2505
3526
|
} else if (entry.isFile()) {
|
|
@@ -2517,6 +3538,20 @@ async function loadGlobalManifest(rootDir, config) {
|
|
|
2517
3538
|
return null;
|
|
2518
3539
|
}
|
|
2519
3540
|
}
|
|
3541
|
+
function formatModuleName(moduleId) {
|
|
3542
|
+
switch (moduleId) {
|
|
3543
|
+
case "core":
|
|
3544
|
+
return "Core";
|
|
3545
|
+
case "language/typescript":
|
|
3546
|
+
return "TypeScript";
|
|
3547
|
+
default:
|
|
3548
|
+
if (moduleId.startsWith("language/")) {
|
|
3549
|
+
const lang = moduleId.replace("language/", "");
|
|
3550
|
+
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
|
3551
|
+
}
|
|
3552
|
+
return moduleId;
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
2520
3555
|
function formatSearchResults(results) {
|
|
2521
3556
|
if (results.length === 0) {
|
|
2522
3557
|
return "No results found.";
|
|
@@ -2532,6 +3567,7 @@ function formatSearchResults(results) {
|
|
|
2532
3567
|
output += `${i + 1}. ${location}${nameInfo}
|
|
2533
3568
|
`;
|
|
2534
3569
|
output += ` Score: ${(result.score * 100).toFixed(1)}% | Type: ${chunk.type}`;
|
|
3570
|
+
output += ` | via ${formatModuleName(result.moduleId)}`;
|
|
2535
3571
|
if (chunk.isExported) {
|
|
2536
3572
|
output += " | exported";
|
|
2537
3573
|
}
|
|
@@ -2575,4 +3611,4 @@ export {
|
|
|
2575
3611
|
cleanup
|
|
2576
3612
|
};
|
|
2577
3613
|
|
|
2578
|
-
//# debugId=
|
|
3614
|
+
//# debugId=B36BFBBC8240BDFB64756E2164756E21
|