raggrep 0.1.6 → 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/dist/app/indexer/index.d.ts +2 -2
- package/dist/cli/main.js +683 -489
- package/dist/cli/main.js.map +17 -16
- package/dist/{introspection/conventions/types.d.ts → domain/entities/conventions.d.ts} +6 -5
- package/dist/domain/entities/index.d.ts +2 -0
- package/dist/{introspection → domain/services}/conventions/configFiles.d.ts +1 -1
- package/dist/{introspection → domain/services}/conventions/entryPoints.d.ts +1 -1
- package/dist/{introspection → domain/services}/conventions/frameworks/convex.d.ts +1 -1
- package/dist/{introspection → domain/services}/conventions/frameworks/index.d.ts +1 -1
- package/dist/{introspection → domain/services}/conventions/frameworks/nextjs.d.ts +1 -1
- package/dist/{introspection → domain/services}/conventions/index.d.ts +5 -5
- package/dist/domain/services/introspection.d.ts +31 -0
- package/dist/index.js +646 -465
- package/dist/index.js.map +16 -16
- 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/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}/conventions/conventions.test.d.ts +0 -0
- /package/dist/{introspection → domain/services}/introspection.test.d.ts +0 -0
package/dist/cli/main.js
CHANGED
|
@@ -429,247 +429,11 @@ function normalizeScore(score, midpoint = 5) {
|
|
|
429
429
|
}
|
|
430
430
|
var BM25_K1 = 1.5, BM25_B = 0.75;
|
|
431
431
|
|
|
432
|
-
// src/
|
|
432
|
+
// src/domain/services/conventions/entryPoints.ts
|
|
433
433
|
import * as path3 from "path";
|
|
434
|
-
import * as fs2 from "fs/promises";
|
|
435
|
-
function detectScopeFromName(name) {
|
|
436
|
-
const nameLower = name.toLowerCase();
|
|
437
|
-
for (const [scope, keywords] of Object.entries(SCOPE_KEYWORDS)) {
|
|
438
|
-
if (scope === "unknown")
|
|
439
|
-
continue;
|
|
440
|
-
for (const keyword of keywords) {
|
|
441
|
-
if (nameLower.includes(keyword)) {
|
|
442
|
-
return scope;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
return "unknown";
|
|
447
|
-
}
|
|
448
|
-
async function scanForPackageJsons(rootDir, currentDir = "", depth = 0) {
|
|
449
|
-
if (depth > MAX_SCAN_DEPTH)
|
|
450
|
-
return [];
|
|
451
|
-
const results = [];
|
|
452
|
-
const fullDir = currentDir ? path3.join(rootDir, currentDir) : rootDir;
|
|
453
|
-
try {
|
|
454
|
-
const entries = await fs2.readdir(fullDir, { withFileTypes: true });
|
|
455
|
-
const hasPackageJson = entries.some((e) => e.isFile() && e.name === "package.json");
|
|
456
|
-
if (hasPackageJson && currentDir) {
|
|
457
|
-
const info = await parsePackageJson(rootDir, currentDir);
|
|
458
|
-
if (info) {
|
|
459
|
-
results.push(info);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
for (const entry of entries) {
|
|
463
|
-
if (!entry.isDirectory())
|
|
464
|
-
continue;
|
|
465
|
-
if (SKIP_DIRS.has(entry.name))
|
|
466
|
-
continue;
|
|
467
|
-
const subPath = currentDir ? `${currentDir}/${entry.name}` : entry.name;
|
|
468
|
-
const subResults = await scanForPackageJsons(rootDir, subPath, depth + 1);
|
|
469
|
-
results.push(...subResults);
|
|
470
|
-
}
|
|
471
|
-
} catch {}
|
|
472
|
-
return results;
|
|
473
|
-
}
|
|
474
|
-
async function parsePackageJson(rootDir, relativePath) {
|
|
475
|
-
try {
|
|
476
|
-
const packageJsonPath = path3.join(rootDir, relativePath, "package.json");
|
|
477
|
-
const content = await fs2.readFile(packageJsonPath, "utf-8");
|
|
478
|
-
const pkg = JSON.parse(content);
|
|
479
|
-
const name = pkg.name || path3.basename(relativePath);
|
|
480
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
481
|
-
let type = "unknown";
|
|
482
|
-
if (deps["next"] || deps["react"] || deps["vue"] || deps["svelte"]) {
|
|
483
|
-
type = "app";
|
|
484
|
-
} else if (deps["express"] || deps["fastify"] || deps["koa"] || deps["hono"]) {
|
|
485
|
-
type = "service";
|
|
486
|
-
} else if (pkg.main || pkg.exports) {
|
|
487
|
-
type = "library";
|
|
488
|
-
}
|
|
489
|
-
const hasWorkspaces = Boolean(pkg.workspaces);
|
|
490
|
-
return { name, relativePath, type, hasWorkspaces };
|
|
491
|
-
} catch {
|
|
492
|
-
return null;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
async function detectProjectStructure(rootDir) {
|
|
496
|
-
const projectMap = new Map;
|
|
497
|
-
let isMonorepo = false;
|
|
498
|
-
try {
|
|
499
|
-
const entries = await fs2.readdir(rootDir, { withFileTypes: true });
|
|
500
|
-
const dirNames = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
501
|
-
const monorepoPatterns = ["apps", "packages", "libs", "services"];
|
|
502
|
-
const hasMonorepoStructure = monorepoPatterns.some((p) => dirNames.includes(p));
|
|
503
|
-
if (hasMonorepoStructure) {
|
|
504
|
-
isMonorepo = true;
|
|
505
|
-
for (const pattern of monorepoPatterns) {
|
|
506
|
-
if (!dirNames.includes(pattern))
|
|
507
|
-
continue;
|
|
508
|
-
const patternDir = path3.join(rootDir, pattern);
|
|
509
|
-
try {
|
|
510
|
-
const subDirs = await fs2.readdir(patternDir, { withFileTypes: true });
|
|
511
|
-
for (const subDir of subDirs) {
|
|
512
|
-
if (!subDir.isDirectory())
|
|
513
|
-
continue;
|
|
514
|
-
const projectRoot = `${pattern}/${subDir.name}`;
|
|
515
|
-
const type = getProjectType(pattern);
|
|
516
|
-
projectMap.set(projectRoot, {
|
|
517
|
-
name: subDir.name,
|
|
518
|
-
root: projectRoot,
|
|
519
|
-
type
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
} catch {}
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
const packageJsons = await scanForPackageJsons(rootDir);
|
|
526
|
-
for (const pkg of packageJsons) {
|
|
527
|
-
if (pkg.hasWorkspaces) {
|
|
528
|
-
isMonorepo = true;
|
|
529
|
-
}
|
|
530
|
-
if (packageJsons.length > 1) {
|
|
531
|
-
isMonorepo = true;
|
|
532
|
-
}
|
|
533
|
-
projectMap.set(pkg.relativePath, {
|
|
534
|
-
name: pkg.name,
|
|
535
|
-
root: pkg.relativePath,
|
|
536
|
-
type: pkg.type
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
let rootType = "unknown";
|
|
540
|
-
try {
|
|
541
|
-
const rootPkgPath = path3.join(rootDir, "package.json");
|
|
542
|
-
const rootPkg = JSON.parse(await fs2.readFile(rootPkgPath, "utf-8"));
|
|
543
|
-
if (rootPkg.workspaces) {
|
|
544
|
-
isMonorepo = true;
|
|
545
|
-
}
|
|
546
|
-
const deps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
|
|
547
|
-
if (deps["next"] || deps["react"] || deps["vue"]) {
|
|
548
|
-
rootType = "app";
|
|
549
|
-
} else if (deps["express"] || deps["fastify"] || deps["koa"]) {
|
|
550
|
-
rootType = "service";
|
|
551
|
-
}
|
|
552
|
-
} catch {}
|
|
553
|
-
const projects = Array.from(projectMap.values()).sort((a, b) => a.root.length - b.root.length);
|
|
554
|
-
return {
|
|
555
|
-
projects,
|
|
556
|
-
isMonorepo,
|
|
557
|
-
rootType: isMonorepo ? undefined : rootType
|
|
558
|
-
};
|
|
559
|
-
} catch {
|
|
560
|
-
return {
|
|
561
|
-
projects: [],
|
|
562
|
-
isMonorepo: false,
|
|
563
|
-
rootType: "unknown"
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
function getProjectType(patternDir) {
|
|
568
|
-
switch (patternDir) {
|
|
569
|
-
case "apps":
|
|
570
|
-
return "app";
|
|
571
|
-
case "packages":
|
|
572
|
-
case "libs":
|
|
573
|
-
return "library";
|
|
574
|
-
case "services":
|
|
575
|
-
return "service";
|
|
576
|
-
case "scripts":
|
|
577
|
-
case "tools":
|
|
578
|
-
return "script";
|
|
579
|
-
default:
|
|
580
|
-
return "unknown";
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
function findProjectForFile(filepath, structure) {
|
|
584
|
-
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
585
|
-
const matches = [];
|
|
586
|
-
for (const project of structure.projects) {
|
|
587
|
-
if (normalizedPath === project.root || normalizedPath.startsWith(project.root + "/")) {
|
|
588
|
-
matches.push(project);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
if (matches.length > 0) {
|
|
592
|
-
return matches.reduce((best, current) => current.root.length > best.root.length ? current : best);
|
|
593
|
-
}
|
|
594
|
-
for (const { pattern, type } of PROJECT_PATTERNS) {
|
|
595
|
-
const match = normalizedPath.match(pattern);
|
|
596
|
-
if (match) {
|
|
597
|
-
return {
|
|
598
|
-
name: match[1],
|
|
599
|
-
root: match[0],
|
|
600
|
-
type
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
return {
|
|
605
|
-
name: "root",
|
|
606
|
-
root: "",
|
|
607
|
-
type: structure.rootType ?? "unknown"
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
var MAX_SCAN_DEPTH = 4, SKIP_DIRS, PROJECT_PATTERNS, SCOPE_KEYWORDS;
|
|
611
|
-
var init_projectDetector = __esm(() => {
|
|
612
|
-
SKIP_DIRS = new Set([
|
|
613
|
-
"node_modules",
|
|
614
|
-
".git",
|
|
615
|
-
"dist",
|
|
616
|
-
"build",
|
|
617
|
-
".next",
|
|
618
|
-
".nuxt",
|
|
619
|
-
"coverage",
|
|
620
|
-
".raggrep"
|
|
621
|
-
]);
|
|
622
|
-
PROJECT_PATTERNS = [
|
|
623
|
-
{ pattern: /^apps\/([^/]+)/, type: "app", defaultScope: "unknown" },
|
|
624
|
-
{ pattern: /^packages\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
625
|
-
{ pattern: /^libs\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
626
|
-
{ pattern: /^services\/([^/]+)/, type: "service", defaultScope: "backend" },
|
|
627
|
-
{ pattern: /^scripts\/([^/]+)/, type: "script", defaultScope: "tooling" },
|
|
628
|
-
{ pattern: /^tools\/([^/]+)/, type: "script", defaultScope: "tooling" }
|
|
629
|
-
];
|
|
630
|
-
SCOPE_KEYWORDS = {
|
|
631
|
-
frontend: [
|
|
632
|
-
"web",
|
|
633
|
-
"webapp",
|
|
634
|
-
"frontend",
|
|
635
|
-
"client",
|
|
636
|
-
"ui",
|
|
637
|
-
"app",
|
|
638
|
-
"mobile",
|
|
639
|
-
"react",
|
|
640
|
-
"vue",
|
|
641
|
-
"angular",
|
|
642
|
-
"next",
|
|
643
|
-
"nuxt"
|
|
644
|
-
],
|
|
645
|
-
backend: [
|
|
646
|
-
"api",
|
|
647
|
-
"server",
|
|
648
|
-
"backend",
|
|
649
|
-
"service",
|
|
650
|
-
"worker",
|
|
651
|
-
"lambda",
|
|
652
|
-
"functions"
|
|
653
|
-
],
|
|
654
|
-
shared: ["shared", "common", "utils", "lib", "core", "types", "models"],
|
|
655
|
-
tooling: [
|
|
656
|
-
"scripts",
|
|
657
|
-
"tools",
|
|
658
|
-
"cli",
|
|
659
|
-
"devtools",
|
|
660
|
-
"build",
|
|
661
|
-
"config",
|
|
662
|
-
"infra"
|
|
663
|
-
],
|
|
664
|
-
unknown: []
|
|
665
|
-
};
|
|
666
|
-
});
|
|
667
|
-
|
|
668
|
-
// src/introspection/conventions/entryPoints.ts
|
|
669
|
-
import * as path4 from "path";
|
|
670
434
|
function getParentFolder(filepath) {
|
|
671
|
-
const dir =
|
|
672
|
-
return
|
|
435
|
+
const dir = path3.dirname(filepath);
|
|
436
|
+
return path3.basename(dir);
|
|
673
437
|
}
|
|
674
438
|
var entryPointConventions;
|
|
675
439
|
var init_entryPoints = __esm(() => {
|
|
@@ -754,53 +518,268 @@ var init_entryPoints = __esm(() => {
|
|
|
754
518
|
return filename === "lib.rs" || filename === "main.rs";
|
|
755
519
|
},
|
|
756
520
|
keywords: ["entry", "crate", "rust", "module"]
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
id: "go-main",
|
|
524
|
+
name: "Go Main Entry",
|
|
525
|
+
description: "Go application main entry point",
|
|
526
|
+
category: "entry-point",
|
|
527
|
+
match: (filepath, filename) => {
|
|
528
|
+
return filename === "main.go";
|
|
529
|
+
},
|
|
530
|
+
keywords: ["entry", "main", "go", "golang", "entrypoint"],
|
|
531
|
+
dynamicKeywords: (filepath) => {
|
|
532
|
+
const parent = getParentFolder(filepath);
|
|
533
|
+
if (parent && !["cmd", "src", ".", ""].includes(parent)) {
|
|
534
|
+
return [parent.toLowerCase()];
|
|
535
|
+
}
|
|
536
|
+
return [];
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
id: "python-main",
|
|
541
|
+
name: "Python Main Module",
|
|
542
|
+
description: "Python package main entry point",
|
|
543
|
+
category: "entry-point",
|
|
544
|
+
match: (filepath, filename) => {
|
|
545
|
+
return filename === "__main__.py";
|
|
546
|
+
},
|
|
547
|
+
keywords: ["entry", "main", "python", "entrypoint", "cli"],
|
|
548
|
+
dynamicKeywords: (filepath) => {
|
|
549
|
+
const parent = getParentFolder(filepath);
|
|
550
|
+
if (["src", "lib", ".", ""].includes(parent)) {
|
|
551
|
+
return [];
|
|
552
|
+
}
|
|
553
|
+
return [parent.toLowerCase()];
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: "python-app",
|
|
558
|
+
name: "Python App Entry",
|
|
559
|
+
description: "Common Python application entry points",
|
|
560
|
+
category: "entry-point",
|
|
561
|
+
match: (filepath, filename) => {
|
|
562
|
+
return filename === "app.py" || filename === "main.py" || filename === "run.py";
|
|
563
|
+
},
|
|
564
|
+
keywords: ["entry", "main", "python", "app", "entrypoint"]
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: "python-manage",
|
|
568
|
+
name: "Django Manage",
|
|
569
|
+
description: "Django management script",
|
|
570
|
+
category: "entry-point",
|
|
571
|
+
match: (filepath, filename) => {
|
|
572
|
+
return filename === "manage.py";
|
|
573
|
+
},
|
|
574
|
+
keywords: ["entry", "django", "python", "manage", "cli", "admin"]
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
id: "python-wsgi",
|
|
578
|
+
name: "Python WSGI Entry",
|
|
579
|
+
description: "Python WSGI application entry point",
|
|
580
|
+
category: "entry-point",
|
|
581
|
+
match: (filepath, filename) => {
|
|
582
|
+
return filename === "wsgi.py" || filename === "asgi.py";
|
|
583
|
+
},
|
|
584
|
+
keywords: ["entry", "wsgi", "asgi", "python", "server", "web"]
|
|
757
585
|
}
|
|
758
586
|
];
|
|
759
587
|
});
|
|
760
588
|
|
|
761
|
-
// src/
|
|
589
|
+
// src/domain/services/conventions/configFiles.ts
|
|
762
590
|
var configFileConventions;
|
|
763
591
|
var init_configFiles = __esm(() => {
|
|
764
592
|
configFileConventions = [
|
|
765
593
|
{
|
|
766
|
-
id: "package-json",
|
|
767
|
-
name: "Package.json",
|
|
768
|
-
description: "Node.js package manifest",
|
|
594
|
+
id: "package-json",
|
|
595
|
+
name: "Package.json",
|
|
596
|
+
description: "Node.js package manifest",
|
|
597
|
+
category: "configuration",
|
|
598
|
+
match: (filepath, filename) => filename === "package.json",
|
|
599
|
+
keywords: ["package", "dependencies", "npm", "scripts", "manifest", "node"]
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
id: "pnpm-workspace",
|
|
603
|
+
name: "PNPM Workspace",
|
|
604
|
+
description: "PNPM monorepo workspace configuration",
|
|
605
|
+
category: "configuration",
|
|
606
|
+
match: (filepath, filename) => filename === "pnpm-workspace.yaml" || filename === "pnpm-workspace.yml",
|
|
607
|
+
keywords: ["workspace", "monorepo", "pnpm", "packages"]
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
id: "yarn-lock",
|
|
611
|
+
name: "Yarn Lock",
|
|
612
|
+
description: "Yarn dependency lock file",
|
|
613
|
+
category: "configuration",
|
|
614
|
+
match: (filepath, filename) => filename === "yarn.lock",
|
|
615
|
+
keywords: ["dependencies", "lock", "yarn", "versions"]
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
id: "package-lock",
|
|
619
|
+
name: "Package Lock",
|
|
620
|
+
description: "NPM dependency lock file",
|
|
621
|
+
category: "configuration",
|
|
622
|
+
match: (filepath, filename) => filename === "package-lock.json",
|
|
623
|
+
keywords: ["dependencies", "lock", "npm", "versions"]
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
id: "bun-lockb",
|
|
627
|
+
name: "Bun Lock",
|
|
628
|
+
description: "Bun dependency lock file",
|
|
629
|
+
category: "configuration",
|
|
630
|
+
match: (filepath, filename) => filename === "bun.lockb" || filename === "bun.lock",
|
|
631
|
+
keywords: ["dependencies", "lock", "bun", "versions"]
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
id: "go-mod",
|
|
635
|
+
name: "Go Module",
|
|
636
|
+
description: "Go module definition file",
|
|
637
|
+
category: "configuration",
|
|
638
|
+
match: (filepath, filename) => filename === "go.mod",
|
|
639
|
+
keywords: [
|
|
640
|
+
"go",
|
|
641
|
+
"golang",
|
|
642
|
+
"module",
|
|
643
|
+
"dependencies",
|
|
644
|
+
"package",
|
|
645
|
+
"workspace"
|
|
646
|
+
]
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
id: "go-sum",
|
|
650
|
+
name: "Go Sum",
|
|
651
|
+
description: "Go module checksum file",
|
|
652
|
+
category: "configuration",
|
|
653
|
+
match: (filepath, filename) => filename === "go.sum",
|
|
654
|
+
keywords: ["go", "golang", "dependencies", "checksum", "lock", "versions"]
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
id: "go-work",
|
|
658
|
+
name: "Go Workspace",
|
|
659
|
+
description: "Go workspace configuration for multi-module development",
|
|
660
|
+
category: "configuration",
|
|
661
|
+
match: (filepath, filename) => filename === "go.work" || filename === "go.work.sum",
|
|
662
|
+
keywords: ["go", "golang", "workspace", "monorepo", "modules"]
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
id: "makefile",
|
|
666
|
+
name: "Makefile",
|
|
667
|
+
description: "Make build automation file",
|
|
668
|
+
category: "build",
|
|
669
|
+
match: (filepath, filename) => filename === "Makefile" || filename === "makefile" || filename === "GNUmakefile",
|
|
670
|
+
keywords: ["make", "build", "automation", "tasks", "compile"]
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
id: "requirements-txt",
|
|
674
|
+
name: "Python Requirements",
|
|
675
|
+
description: "Python pip requirements file",
|
|
676
|
+
category: "configuration",
|
|
677
|
+
match: (filepath, filename) => filename === "requirements.txt" || filename.startsWith("requirements-") || filename.startsWith("requirements_"),
|
|
678
|
+
keywords: ["python", "pip", "dependencies", "packages", "requirements"]
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
id: "pyproject-toml",
|
|
682
|
+
name: "Python Project",
|
|
683
|
+
description: "Python project configuration (PEP 518/621)",
|
|
684
|
+
category: "configuration",
|
|
685
|
+
match: (filepath, filename) => filename === "pyproject.toml",
|
|
686
|
+
keywords: [
|
|
687
|
+
"python",
|
|
688
|
+
"project",
|
|
689
|
+
"config",
|
|
690
|
+
"poetry",
|
|
691
|
+
"build",
|
|
692
|
+
"dependencies",
|
|
693
|
+
"package"
|
|
694
|
+
]
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
id: "setup-py",
|
|
698
|
+
name: "Python Setup",
|
|
699
|
+
description: "Python package setup script",
|
|
700
|
+
category: "configuration",
|
|
701
|
+
match: (filepath, filename) => filename === "setup.py",
|
|
702
|
+
keywords: ["python", "setup", "package", "install", "distribution"]
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
id: "setup-cfg",
|
|
706
|
+
name: "Python Setup Config",
|
|
707
|
+
description: "Python setup configuration file",
|
|
708
|
+
category: "configuration",
|
|
709
|
+
match: (filepath, filename) => filename === "setup.cfg",
|
|
710
|
+
keywords: ["python", "setup", "config", "package", "metadata"]
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
id: "pipfile",
|
|
714
|
+
name: "Pipfile",
|
|
715
|
+
description: "Pipenv dependency file",
|
|
716
|
+
category: "configuration",
|
|
717
|
+
match: (filepath, filename) => filename === "Pipfile" || filename === "Pipfile.lock",
|
|
718
|
+
keywords: ["python", "pipenv", "dependencies", "packages", "virtualenv"]
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
id: "poetry-lock",
|
|
722
|
+
name: "Poetry Lock",
|
|
723
|
+
description: "Poetry dependency lock file",
|
|
769
724
|
category: "configuration",
|
|
770
|
-
match: (filepath, filename) => filename === "
|
|
771
|
-
keywords: ["
|
|
725
|
+
match: (filepath, filename) => filename === "poetry.lock",
|
|
726
|
+
keywords: ["python", "poetry", "dependencies", "lock", "versions"]
|
|
772
727
|
},
|
|
773
728
|
{
|
|
774
|
-
id: "
|
|
775
|
-
name: "
|
|
776
|
-
description: "
|
|
729
|
+
id: "tox-ini",
|
|
730
|
+
name: "Tox Config",
|
|
731
|
+
description: "Tox testing automation configuration",
|
|
732
|
+
category: "test",
|
|
733
|
+
match: (filepath, filename) => filename === "tox.ini",
|
|
734
|
+
keywords: ["python", "tox", "testing", "automation", "environments"]
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
id: "pytest-ini",
|
|
738
|
+
name: "Pytest Config",
|
|
739
|
+
description: "Pytest configuration file",
|
|
740
|
+
category: "test",
|
|
741
|
+
match: (filepath, filename) => filename === "pytest.ini" || filename === "conftest.py",
|
|
742
|
+
keywords: ["python", "pytest", "testing", "test", "fixtures"]
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
id: "mypy-ini",
|
|
746
|
+
name: "Mypy Config",
|
|
747
|
+
description: "Mypy type checker configuration",
|
|
777
748
|
category: "configuration",
|
|
778
|
-
match: (filepath, filename) => filename === "
|
|
779
|
-
keywords: ["
|
|
749
|
+
match: (filepath, filename) => filename === "mypy.ini" || filename === ".mypy.ini",
|
|
750
|
+
keywords: ["python", "mypy", "types", "type checking", "static analysis"]
|
|
780
751
|
},
|
|
781
752
|
{
|
|
782
|
-
id: "
|
|
783
|
-
name: "
|
|
784
|
-
description: "
|
|
753
|
+
id: "flake8",
|
|
754
|
+
name: "Flake8 Config",
|
|
755
|
+
description: "Flake8 linter configuration",
|
|
785
756
|
category: "configuration",
|
|
786
|
-
match: (filepath, filename) => filename === "
|
|
787
|
-
keywords: ["
|
|
757
|
+
match: (filepath, filename) => filename === ".flake8",
|
|
758
|
+
keywords: ["python", "flake8", "linting", "lint", "style"]
|
|
788
759
|
},
|
|
789
760
|
{
|
|
790
|
-
id: "
|
|
791
|
-
name: "
|
|
792
|
-
description: "
|
|
761
|
+
id: "pylintrc",
|
|
762
|
+
name: "Pylint Config",
|
|
763
|
+
description: "Pylint linter configuration",
|
|
793
764
|
category: "configuration",
|
|
794
|
-
match: (filepath, filename) => filename === "
|
|
795
|
-
keywords: ["
|
|
765
|
+
match: (filepath, filename) => filename === ".pylintrc" || filename === "pylintrc" || filename === "pylint.toml",
|
|
766
|
+
keywords: ["python", "pylint", "linting", "lint", "code quality"]
|
|
796
767
|
},
|
|
797
768
|
{
|
|
798
|
-
id: "
|
|
799
|
-
name: "
|
|
800
|
-
description: "
|
|
769
|
+
id: "ruff-toml",
|
|
770
|
+
name: "Ruff Config",
|
|
771
|
+
description: "Ruff linter/formatter configuration",
|
|
801
772
|
category: "configuration",
|
|
802
|
-
match: (filepath, filename) => filename === "
|
|
803
|
-
keywords: ["
|
|
773
|
+
match: (filepath, filename) => filename === "ruff.toml" || filename === ".ruff.toml",
|
|
774
|
+
keywords: ["python", "ruff", "linting", "formatting", "fast"]
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
id: "black-toml",
|
|
778
|
+
name: "Black Config",
|
|
779
|
+
description: "Black formatter configuration",
|
|
780
|
+
category: "configuration",
|
|
781
|
+
match: (filepath, filename) => filename === ".black.toml",
|
|
782
|
+
keywords: ["python", "black", "formatting", "format", "style"]
|
|
804
783
|
},
|
|
805
784
|
{
|
|
806
785
|
id: "tsconfig",
|
|
@@ -1043,7 +1022,7 @@ var init_configFiles = __esm(() => {
|
|
|
1043
1022
|
];
|
|
1044
1023
|
});
|
|
1045
1024
|
|
|
1046
|
-
// src/
|
|
1025
|
+
// src/domain/services/conventions/frameworks/nextjs.ts
|
|
1047
1026
|
var nextjsConventions, nextjsFramework;
|
|
1048
1027
|
var init_nextjs = __esm(() => {
|
|
1049
1028
|
nextjsConventions = [
|
|
@@ -1208,7 +1187,7 @@ var init_nextjs = __esm(() => {
|
|
|
1208
1187
|
};
|
|
1209
1188
|
});
|
|
1210
1189
|
|
|
1211
|
-
// src/
|
|
1190
|
+
// src/domain/services/conventions/frameworks/convex.ts
|
|
1212
1191
|
var convexConventions, convexFramework;
|
|
1213
1192
|
var init_convex = __esm(() => {
|
|
1214
1193
|
convexConventions = [
|
|
@@ -1304,7 +1283,7 @@ var init_convex = __esm(() => {
|
|
|
1304
1283
|
};
|
|
1305
1284
|
});
|
|
1306
1285
|
|
|
1307
|
-
// src/
|
|
1286
|
+
// src/domain/services/conventions/frameworks/index.ts
|
|
1308
1287
|
function getAllFrameworkConventions() {
|
|
1309
1288
|
return frameworkProviders.flatMap((f) => f.conventions);
|
|
1310
1289
|
}
|
|
@@ -1320,26 +1299,21 @@ var init_frameworks = __esm(() => {
|
|
|
1320
1299
|
];
|
|
1321
1300
|
});
|
|
1322
1301
|
|
|
1323
|
-
// src/
|
|
1324
|
-
import * as
|
|
1325
|
-
function
|
|
1302
|
+
// src/domain/services/conventions/index.ts
|
|
1303
|
+
import * as path4 from "path";
|
|
1304
|
+
function getConventions() {
|
|
1326
1305
|
return [
|
|
1327
1306
|
...entryPointConventions,
|
|
1328
1307
|
...configFileConventions,
|
|
1329
|
-
...getAllFrameworkConventions()
|
|
1330
|
-
];
|
|
1331
|
-
}
|
|
1332
|
-
function getConventions() {
|
|
1333
|
-
return [
|
|
1334
|
-
...getAllConventions(),
|
|
1308
|
+
...getAllFrameworkConventions(),
|
|
1335
1309
|
...typeDefinitionConventions,
|
|
1336
1310
|
...testFileConventions
|
|
1337
1311
|
];
|
|
1338
1312
|
}
|
|
1339
1313
|
function getConventionKeywords(filepath) {
|
|
1340
1314
|
const conventions = getConventions();
|
|
1341
|
-
const filename =
|
|
1342
|
-
const extension =
|
|
1315
|
+
const filename = path4.basename(filepath);
|
|
1316
|
+
const extension = path4.extname(filepath);
|
|
1343
1317
|
const keywords = new Set;
|
|
1344
1318
|
for (const convention of conventions) {
|
|
1345
1319
|
try {
|
|
@@ -1386,9 +1360,8 @@ var init_conventions = __esm(() => {
|
|
|
1386
1360
|
keywords: ["types", "definitions", "typescript", "interfaces"],
|
|
1387
1361
|
dynamicKeywords: (filepath) => {
|
|
1388
1362
|
const match = filepath.match(/([^/]+)\.types\.ts$/);
|
|
1389
|
-
if (match)
|
|
1363
|
+
if (match)
|
|
1390
1364
|
return [match[1].toLowerCase()];
|
|
1391
|
-
}
|
|
1392
1365
|
return [];
|
|
1393
1366
|
}
|
|
1394
1367
|
},
|
|
@@ -1411,9 +1384,8 @@ var init_conventions = __esm(() => {
|
|
|
1411
1384
|
keywords: ["test", "spec", "unit test"],
|
|
1412
1385
|
dynamicKeywords: (filepath) => {
|
|
1413
1386
|
const match = filepath.match(/([^/]+)\.(test|spec)\./);
|
|
1414
|
-
if (match)
|
|
1387
|
+
if (match)
|
|
1415
1388
|
return [match[1].toLowerCase()];
|
|
1416
|
-
}
|
|
1417
1389
|
return [];
|
|
1418
1390
|
}
|
|
1419
1391
|
},
|
|
@@ -1428,22 +1400,19 @@ var init_conventions = __esm(() => {
|
|
|
1428
1400
|
];
|
|
1429
1401
|
});
|
|
1430
1402
|
|
|
1431
|
-
// src/introspection
|
|
1432
|
-
import * as
|
|
1403
|
+
// src/domain/services/introspection.ts
|
|
1404
|
+
import * as path5 from "path";
|
|
1433
1405
|
function introspectFile(filepath, structure, fileContent) {
|
|
1434
1406
|
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
1435
1407
|
const segments = normalizedPath.split("/").filter((s) => s.length > 0);
|
|
1436
1408
|
const filename = segments[segments.length - 1] || "";
|
|
1437
|
-
const ext =
|
|
1409
|
+
const ext = path5.extname(filename);
|
|
1438
1410
|
const project = findProjectForFile(normalizedPath, structure);
|
|
1439
1411
|
const language = EXTENSION_TO_LANGUAGE[ext] || "unknown";
|
|
1440
1412
|
const layer = detectLayer(segments, filename);
|
|
1441
1413
|
const domain = detectDomain(segments);
|
|
1442
1414
|
const scope = detectScope(segments, project, layer);
|
|
1443
|
-
|
|
1444
|
-
if (fileContent) {
|
|
1445
|
-
framework = detectFramework(fileContent);
|
|
1446
|
-
}
|
|
1415
|
+
const framework = fileContent ? detectFramework(fileContent) : undefined;
|
|
1447
1416
|
return {
|
|
1448
1417
|
filepath: normalizedPath,
|
|
1449
1418
|
project,
|
|
@@ -1456,21 +1425,81 @@ function introspectFile(filepath, structure, fileContent) {
|
|
|
1456
1425
|
pathSegments: segments.slice(0, -1)
|
|
1457
1426
|
};
|
|
1458
1427
|
}
|
|
1428
|
+
function introspectionToKeywords(intro) {
|
|
1429
|
+
const keywords = [];
|
|
1430
|
+
const filename = path5.basename(intro.filepath);
|
|
1431
|
+
const filenameWithoutExt = filename.replace(/\.[^.]+$/, "");
|
|
1432
|
+
const filenameParts = filenameWithoutExt.split(/[-_.]/).flatMap((part) => part.split(/(?=[A-Z])/)).map((part) => part.toLowerCase()).filter((part) => part.length > 1);
|
|
1433
|
+
keywords.push(...filenameParts);
|
|
1434
|
+
keywords.push(filenameWithoutExt.toLowerCase());
|
|
1435
|
+
if (intro.project.name && intro.project.name !== "root") {
|
|
1436
|
+
keywords.push(intro.project.name.toLowerCase());
|
|
1437
|
+
}
|
|
1438
|
+
if (intro.scope !== "unknown")
|
|
1439
|
+
keywords.push(intro.scope);
|
|
1440
|
+
if (intro.layer)
|
|
1441
|
+
keywords.push(intro.layer);
|
|
1442
|
+
if (intro.domain)
|
|
1443
|
+
keywords.push(intro.domain);
|
|
1444
|
+
if (intro.language !== "unknown")
|
|
1445
|
+
keywords.push(intro.language);
|
|
1446
|
+
if (intro.framework)
|
|
1447
|
+
keywords.push(intro.framework);
|
|
1448
|
+
const skipSegments = new Set(["src", "lib", "index"]);
|
|
1449
|
+
for (const segment of intro.pathSegments) {
|
|
1450
|
+
if (!skipSegments.has(segment.toLowerCase()) && segment.length > 2) {
|
|
1451
|
+
keywords.push(segment.toLowerCase());
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
const conventionKeywords = getConventionKeywords(intro.filepath);
|
|
1455
|
+
keywords.push(...conventionKeywords);
|
|
1456
|
+
return [...new Set(keywords)];
|
|
1457
|
+
}
|
|
1458
|
+
function detectScopeFromName(name) {
|
|
1459
|
+
const nameLower = name.toLowerCase();
|
|
1460
|
+
for (const [scope, keywords] of Object.entries(SCOPE_KEYWORDS)) {
|
|
1461
|
+
if (scope === "unknown")
|
|
1462
|
+
continue;
|
|
1463
|
+
for (const keyword of keywords) {
|
|
1464
|
+
if (nameLower.includes(keyword)) {
|
|
1465
|
+
return scope;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return "unknown";
|
|
1470
|
+
}
|
|
1471
|
+
function findProjectForFile(filepath, structure) {
|
|
1472
|
+
const normalizedPath = filepath.replace(/\\/g, "/");
|
|
1473
|
+
const matches = [];
|
|
1474
|
+
for (const project of structure.projects) {
|
|
1475
|
+
if (normalizedPath === project.root || normalizedPath.startsWith(project.root + "/")) {
|
|
1476
|
+
matches.push(project);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
if (matches.length > 0) {
|
|
1480
|
+
return matches.reduce((best, current) => current.root.length > best.root.length ? current : best);
|
|
1481
|
+
}
|
|
1482
|
+
for (const { pattern, type } of PROJECT_PATTERNS) {
|
|
1483
|
+
const match = normalizedPath.match(pattern);
|
|
1484
|
+
if (match) {
|
|
1485
|
+
return { name: match[1], root: match[0], type };
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
return { name: "root", root: "", type: structure.rootType ?? "unknown" };
|
|
1489
|
+
}
|
|
1459
1490
|
function detectLayer(segments, filename) {
|
|
1460
1491
|
const filenameLower = filename.toLowerCase();
|
|
1461
1492
|
for (const [layer, patterns] of Object.entries(LAYER_PATTERNS)) {
|
|
1462
1493
|
for (const pattern of patterns) {
|
|
1463
|
-
if (filenameLower.includes(pattern))
|
|
1494
|
+
if (filenameLower.includes(pattern))
|
|
1464
1495
|
return layer;
|
|
1465
|
-
}
|
|
1466
1496
|
}
|
|
1467
1497
|
}
|
|
1468
1498
|
for (let i = segments.length - 2;i >= 0; i--) {
|
|
1469
1499
|
const segment = segments[i].toLowerCase();
|
|
1470
1500
|
for (const [layer, patterns] of Object.entries(LAYER_PATTERNS)) {
|
|
1471
|
-
if (patterns.includes(segment))
|
|
1501
|
+
if (patterns.includes(segment))
|
|
1472
1502
|
return layer;
|
|
1473
|
-
}
|
|
1474
1503
|
}
|
|
1475
1504
|
}
|
|
1476
1505
|
return;
|
|
@@ -1491,9 +1520,8 @@ function detectDomain(segments) {
|
|
|
1491
1520
|
const segmentLower = segment.toLowerCase();
|
|
1492
1521
|
if (skipSegments.has(segmentLower))
|
|
1493
1522
|
continue;
|
|
1494
|
-
if (DOMAIN_PATTERNS.includes(segmentLower))
|
|
1523
|
+
if (DOMAIN_PATTERNS.includes(segmentLower))
|
|
1495
1524
|
return segmentLower;
|
|
1496
|
-
}
|
|
1497
1525
|
for (const domain of DOMAIN_PATTERNS) {
|
|
1498
1526
|
if (segmentLower.startsWith(domain) || segmentLower.endsWith(domain)) {
|
|
1499
1527
|
return domain;
|
|
@@ -1504,9 +1532,8 @@ function detectDomain(segments) {
|
|
|
1504
1532
|
}
|
|
1505
1533
|
function detectScope(segments, project, layer) {
|
|
1506
1534
|
const projectScope = detectScopeFromName(project.name);
|
|
1507
|
-
if (projectScope !== "unknown")
|
|
1535
|
+
if (projectScope !== "unknown")
|
|
1508
1536
|
return projectScope;
|
|
1509
|
-
}
|
|
1510
1537
|
if (layer) {
|
|
1511
1538
|
switch (layer) {
|
|
1512
1539
|
case "controller":
|
|
@@ -1524,15 +1551,12 @@ function detectScope(segments, project, layer) {
|
|
|
1524
1551
|
}
|
|
1525
1552
|
for (const segment of segments) {
|
|
1526
1553
|
const segmentLower = segment.toLowerCase();
|
|
1527
|
-
if (["server", "api", "backend"].includes(segmentLower))
|
|
1554
|
+
if (["server", "api", "backend"].includes(segmentLower))
|
|
1528
1555
|
return "backend";
|
|
1529
|
-
|
|
1530
|
-
if (["client", "web", "frontend", "ui"].includes(segmentLower)) {
|
|
1556
|
+
if (["client", "web", "frontend", "ui"].includes(segmentLower))
|
|
1531
1557
|
return "frontend";
|
|
1532
|
-
|
|
1533
|
-
if (["shared", "common", "lib", "libs"].includes(segmentLower)) {
|
|
1558
|
+
if (["shared", "common", "lib", "libs"].includes(segmentLower))
|
|
1534
1559
|
return "shared";
|
|
1535
|
-
}
|
|
1536
1560
|
}
|
|
1537
1561
|
return "unknown";
|
|
1538
1562
|
}
|
|
@@ -1546,44 +1570,8 @@ function detectFramework(content) {
|
|
|
1546
1570
|
}
|
|
1547
1571
|
return;
|
|
1548
1572
|
}
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
const filename = path6.basename(intro.filepath);
|
|
1552
|
-
const filenameWithoutExt = filename.replace(/\.[^.]+$/, "");
|
|
1553
|
-
const filenameParts = filenameWithoutExt.split(/[-_.]/).flatMap((part) => part.split(/(?=[A-Z])/)).map((part) => part.toLowerCase()).filter((part) => part.length > 1);
|
|
1554
|
-
keywords.push(...filenameParts);
|
|
1555
|
-
keywords.push(filenameWithoutExt.toLowerCase());
|
|
1556
|
-
if (intro.project.name && intro.project.name !== "root") {
|
|
1557
|
-
keywords.push(intro.project.name.toLowerCase());
|
|
1558
|
-
}
|
|
1559
|
-
if (intro.scope !== "unknown") {
|
|
1560
|
-
keywords.push(intro.scope);
|
|
1561
|
-
}
|
|
1562
|
-
if (intro.layer) {
|
|
1563
|
-
keywords.push(intro.layer);
|
|
1564
|
-
}
|
|
1565
|
-
if (intro.domain) {
|
|
1566
|
-
keywords.push(intro.domain);
|
|
1567
|
-
}
|
|
1568
|
-
if (intro.language !== "unknown") {
|
|
1569
|
-
keywords.push(intro.language);
|
|
1570
|
-
}
|
|
1571
|
-
if (intro.framework) {
|
|
1572
|
-
keywords.push(intro.framework);
|
|
1573
|
-
}
|
|
1574
|
-
const skipSegments = new Set(["src", "lib", "index"]);
|
|
1575
|
-
for (const segment of intro.pathSegments) {
|
|
1576
|
-
if (!skipSegments.has(segment.toLowerCase()) && segment.length > 2) {
|
|
1577
|
-
keywords.push(segment.toLowerCase());
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
const conventionKeywords = getConventionKeywords(intro.filepath);
|
|
1581
|
-
keywords.push(...conventionKeywords);
|
|
1582
|
-
return [...new Set(keywords)];
|
|
1583
|
-
}
|
|
1584
|
-
var LAYER_PATTERNS, DOMAIN_PATTERNS, FRAMEWORK_INDICATORS, EXTENSION_TO_LANGUAGE;
|
|
1585
|
-
var init_fileIntrospector = __esm(() => {
|
|
1586
|
-
init_projectDetector();
|
|
1573
|
+
var LAYER_PATTERNS, DOMAIN_PATTERNS, FRAMEWORK_INDICATORS, EXTENSION_TO_LANGUAGE, SCOPE_KEYWORDS, PROJECT_PATTERNS;
|
|
1574
|
+
var init_introspection = __esm(() => {
|
|
1587
1575
|
init_conventions();
|
|
1588
1576
|
LAYER_PATTERNS = {
|
|
1589
1577
|
controller: ["controller", "api", "routes", "route", "handler"],
|
|
@@ -1702,120 +1690,45 @@ var init_fileIntrospector = __esm(() => {
|
|
|
1702
1690
|
".md": "markdown",
|
|
1703
1691
|
".json": "json",
|
|
1704
1692
|
".yaml": "yaml",
|
|
1705
|
-
".yml": "yaml"
|
|
1693
|
+
".yml": "yaml",
|
|
1694
|
+
".txt": "text"
|
|
1706
1695
|
};
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
return this.files.get(filepath);
|
|
1744
|
-
}
|
|
1745
|
-
getAllFiles() {
|
|
1746
|
-
return Array.from(this.files.values());
|
|
1747
|
-
}
|
|
1748
|
-
applyOverrides(intro) {
|
|
1749
|
-
if (!this.config.projects)
|
|
1750
|
-
return;
|
|
1751
|
-
for (const [projectPath, overrides] of Object.entries(this.config.projects)) {
|
|
1752
|
-
if (intro.filepath.startsWith(projectPath + "/") || intro.project.root === projectPath) {
|
|
1753
|
-
if (overrides.scope) {
|
|
1754
|
-
intro.scope = overrides.scope;
|
|
1755
|
-
}
|
|
1756
|
-
if (overrides.framework) {
|
|
1757
|
-
intro.framework = overrides.framework;
|
|
1758
|
-
}
|
|
1759
|
-
break;
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
async save(config) {
|
|
1764
|
-
const introDir = path7.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
1765
|
-
await fs3.mkdir(introDir, { recursive: true });
|
|
1766
|
-
const projectPath = path7.join(introDir, "_project.json");
|
|
1767
|
-
await fs3.writeFile(projectPath, JSON.stringify({
|
|
1768
|
-
version: "1.0.0",
|
|
1769
|
-
lastUpdated: new Date().toISOString(),
|
|
1770
|
-
structure: this.structure
|
|
1771
|
-
}, null, 2));
|
|
1772
|
-
for (const [filepath, intro] of this.files) {
|
|
1773
|
-
const introFilePath = path7.join(introDir, "files", filepath.replace(/\.[^.]+$/, ".json"));
|
|
1774
|
-
await fs3.mkdir(path7.dirname(introFilePath), { recursive: true });
|
|
1775
|
-
await fs3.writeFile(introFilePath, JSON.stringify(intro, null, 2));
|
|
1776
|
-
}
|
|
1777
|
-
console.log(` [Introspection] Saved metadata for ${this.files.size} files`);
|
|
1778
|
-
}
|
|
1779
|
-
async load(config) {
|
|
1780
|
-
const introDir = path7.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
1781
|
-
try {
|
|
1782
|
-
const projectPath = path7.join(introDir, "_project.json");
|
|
1783
|
-
const projectContent = await fs3.readFile(projectPath, "utf-8");
|
|
1784
|
-
const projectData = JSON.parse(projectContent);
|
|
1785
|
-
this.structure = projectData.structure;
|
|
1786
|
-
await this.loadFilesRecursive(path7.join(introDir, "files"), "");
|
|
1787
|
-
} catch {
|
|
1788
|
-
this.structure = null;
|
|
1789
|
-
this.files.clear();
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
async loadFilesRecursive(basePath, prefix) {
|
|
1793
|
-
try {
|
|
1794
|
-
const entries = await fs3.readdir(basePath, { withFileTypes: true });
|
|
1795
|
-
for (const entry of entries) {
|
|
1796
|
-
const entryPath = path7.join(basePath, entry.name);
|
|
1797
|
-
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
1798
|
-
if (entry.isDirectory()) {
|
|
1799
|
-
await this.loadFilesRecursive(entryPath, relativePath);
|
|
1800
|
-
} else if (entry.name.endsWith(".json")) {
|
|
1801
|
-
const content = await fs3.readFile(entryPath, "utf-8");
|
|
1802
|
-
const intro = JSON.parse(content);
|
|
1803
|
-
this.files.set(intro.filepath, intro);
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
} catch {}
|
|
1807
|
-
}
|
|
1808
|
-
clear() {
|
|
1809
|
-
this.files.clear();
|
|
1810
|
-
this.structure = null;
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
var init_introspection = __esm(() => {
|
|
1814
|
-
init_projectDetector();
|
|
1815
|
-
init_fileIntrospector();
|
|
1816
|
-
init_config2();
|
|
1817
|
-
init_fileIntrospector();
|
|
1818
|
-
init_projectDetector();
|
|
1696
|
+
SCOPE_KEYWORDS = {
|
|
1697
|
+
frontend: [
|
|
1698
|
+
"web",
|
|
1699
|
+
"webapp",
|
|
1700
|
+
"frontend",
|
|
1701
|
+
"client",
|
|
1702
|
+
"ui",
|
|
1703
|
+
"app",
|
|
1704
|
+
"mobile",
|
|
1705
|
+
"react",
|
|
1706
|
+
"vue",
|
|
1707
|
+
"angular",
|
|
1708
|
+
"next",
|
|
1709
|
+
"nuxt"
|
|
1710
|
+
],
|
|
1711
|
+
backend: [
|
|
1712
|
+
"api",
|
|
1713
|
+
"server",
|
|
1714
|
+
"backend",
|
|
1715
|
+
"service",
|
|
1716
|
+
"worker",
|
|
1717
|
+
"lambda",
|
|
1718
|
+
"functions"
|
|
1719
|
+
],
|
|
1720
|
+
shared: ["shared", "common", "utils", "lib", "core", "types", "models"],
|
|
1721
|
+
tooling: ["scripts", "tools", "cli", "devtools", "build", "config", "infra"],
|
|
1722
|
+
unknown: []
|
|
1723
|
+
};
|
|
1724
|
+
PROJECT_PATTERNS = [
|
|
1725
|
+
{ pattern: /^apps\/([^/]+)/, type: "app", defaultScope: "unknown" },
|
|
1726
|
+
{ pattern: /^packages\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
1727
|
+
{ pattern: /^libs\/([^/]+)/, type: "library", defaultScope: "shared" },
|
|
1728
|
+
{ pattern: /^services\/([^/]+)/, type: "service", defaultScope: "backend" },
|
|
1729
|
+
{ pattern: /^scripts\/([^/]+)/, type: "script", defaultScope: "tooling" },
|
|
1730
|
+
{ pattern: /^tools\/([^/]+)/, type: "script", defaultScope: "tooling" }
|
|
1731
|
+
];
|
|
1819
1732
|
});
|
|
1820
1733
|
|
|
1821
1734
|
// src/modules/core/symbols.ts
|
|
@@ -1985,8 +1898,8 @@ var exports_core = {};
|
|
|
1985
1898
|
__export(exports_core, {
|
|
1986
1899
|
CoreModule: () => CoreModule
|
|
1987
1900
|
});
|
|
1988
|
-
import * as
|
|
1989
|
-
import * as
|
|
1901
|
+
import * as path6 from "path";
|
|
1902
|
+
import * as fs2 from "fs/promises";
|
|
1990
1903
|
|
|
1991
1904
|
class CoreModule {
|
|
1992
1905
|
id = "core";
|
|
@@ -2004,7 +1917,9 @@ class CoreModule {
|
|
|
2004
1917
|
const contentTokens = tokenize(content);
|
|
2005
1918
|
const intro = ctx.getIntrospection?.(filepath);
|
|
2006
1919
|
const introKeywords = intro ? introspectionToKeywords(intro) : [];
|
|
2007
|
-
const allTokens = [
|
|
1920
|
+
const allTokens = [
|
|
1921
|
+
...new Set([...contentTokens, ...symbolKeywords, ...introKeywords])
|
|
1922
|
+
];
|
|
2008
1923
|
const chunks = this.createChunks(filepath, content, symbols);
|
|
2009
1924
|
const stats = await ctx.getFileStats(filepath);
|
|
2010
1925
|
this.symbolIndex.set(filepath, {
|
|
@@ -2078,8 +1993,8 @@ class CoreModule {
|
|
|
2078
1993
|
}
|
|
2079
1994
|
async finalize(ctx) {
|
|
2080
1995
|
const config = ctx.config;
|
|
2081
|
-
const coreDir =
|
|
2082
|
-
await
|
|
1996
|
+
const coreDir = path6.join(getRaggrepDir(ctx.rootDir, config), "index", "core");
|
|
1997
|
+
await fs2.mkdir(coreDir, { recursive: true });
|
|
2083
1998
|
this.bm25Index = new BM25Index;
|
|
2084
1999
|
for (const [filepath, entry] of this.symbolIndex) {
|
|
2085
2000
|
this.bm25Index.addDocument(filepath, entry.tokens);
|
|
@@ -2090,7 +2005,7 @@ class CoreModule {
|
|
|
2090
2005
|
files: Object.fromEntries(this.symbolIndex),
|
|
2091
2006
|
bm25Data: this.bm25Index.serialize()
|
|
2092
2007
|
};
|
|
2093
|
-
await
|
|
2008
|
+
await fs2.writeFile(path6.join(coreDir, "symbols.json"), JSON.stringify(symbolIndexData, null, 2));
|
|
2094
2009
|
console.log(` [Core] Symbol index built with ${this.symbolIndex.size} files`);
|
|
2095
2010
|
}
|
|
2096
2011
|
async search(query, ctx, options) {
|
|
@@ -2187,10 +2102,10 @@ class CoreModule {
|
|
|
2187
2102
|
return bestChunk;
|
|
2188
2103
|
}
|
|
2189
2104
|
async loadSymbolIndex(rootDir, config) {
|
|
2190
|
-
const coreDir =
|
|
2191
|
-
const symbolsPath =
|
|
2105
|
+
const coreDir = path6.join(getRaggrepDir(rootDir, config), "index", "core");
|
|
2106
|
+
const symbolsPath = path6.join(coreDir, "symbols.json");
|
|
2192
2107
|
try {
|
|
2193
|
-
const content = await
|
|
2108
|
+
const content = await fs2.readFile(symbolsPath, "utf-8");
|
|
2194
2109
|
const data = JSON.parse(content);
|
|
2195
2110
|
this.symbolIndex = new Map(Object.entries(data.files));
|
|
2196
2111
|
if (data.bm25Data) {
|
|
@@ -2617,8 +2532,8 @@ var init_keywords = __esm(() => {
|
|
|
2617
2532
|
});
|
|
2618
2533
|
|
|
2619
2534
|
// src/infrastructure/storage/symbolicIndex.ts
|
|
2620
|
-
import * as
|
|
2621
|
-
import * as
|
|
2535
|
+
import * as fs3 from "fs/promises";
|
|
2536
|
+
import * as path7 from "path";
|
|
2622
2537
|
|
|
2623
2538
|
class SymbolicIndex {
|
|
2624
2539
|
meta = null;
|
|
@@ -2627,7 +2542,7 @@ class SymbolicIndex {
|
|
|
2627
2542
|
symbolicPath;
|
|
2628
2543
|
moduleId;
|
|
2629
2544
|
constructor(indexDir, moduleId) {
|
|
2630
|
-
this.symbolicPath =
|
|
2545
|
+
this.symbolicPath = path7.join(indexDir, "index", moduleId, "symbolic");
|
|
2631
2546
|
this.moduleId = moduleId;
|
|
2632
2547
|
}
|
|
2633
2548
|
async initialize() {
|
|
@@ -2687,18 +2602,18 @@ class SymbolicIndex {
|
|
|
2687
2602
|
throw new Error("Index not initialized");
|
|
2688
2603
|
this.meta.lastUpdated = new Date().toISOString();
|
|
2689
2604
|
this.meta.fileCount = this.fileSummaries.size;
|
|
2690
|
-
await
|
|
2691
|
-
const metaPath =
|
|
2692
|
-
await
|
|
2605
|
+
await fs3.mkdir(this.symbolicPath, { recursive: true });
|
|
2606
|
+
const metaPath = path7.join(this.symbolicPath, "_meta.json");
|
|
2607
|
+
await fs3.writeFile(metaPath, JSON.stringify(this.meta, null, 2));
|
|
2693
2608
|
for (const [filepath, summary] of this.fileSummaries) {
|
|
2694
2609
|
const summaryPath = this.getFileSummaryPath(filepath);
|
|
2695
|
-
await
|
|
2696
|
-
await
|
|
2610
|
+
await fs3.mkdir(path7.dirname(summaryPath), { recursive: true });
|
|
2611
|
+
await fs3.writeFile(summaryPath, JSON.stringify(summary, null, 2));
|
|
2697
2612
|
}
|
|
2698
2613
|
}
|
|
2699
2614
|
async load() {
|
|
2700
|
-
const metaPath =
|
|
2701
|
-
const metaContent = await
|
|
2615
|
+
const metaPath = path7.join(this.symbolicPath, "_meta.json");
|
|
2616
|
+
const metaContent = await fs3.readFile(metaPath, "utf-8");
|
|
2702
2617
|
this.meta = JSON.parse(metaContent);
|
|
2703
2618
|
this.fileSummaries.clear();
|
|
2704
2619
|
await this.loadFileSummariesRecursive(this.symbolicPath);
|
|
@@ -2706,14 +2621,14 @@ class SymbolicIndex {
|
|
|
2706
2621
|
}
|
|
2707
2622
|
async loadFileSummariesRecursive(dir) {
|
|
2708
2623
|
try {
|
|
2709
|
-
const entries = await
|
|
2624
|
+
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
2710
2625
|
for (const entry of entries) {
|
|
2711
|
-
const fullPath =
|
|
2626
|
+
const fullPath = path7.join(dir, entry.name);
|
|
2712
2627
|
if (entry.isDirectory()) {
|
|
2713
2628
|
await this.loadFileSummariesRecursive(fullPath);
|
|
2714
2629
|
} else if (entry.name.endsWith(".json") && entry.name !== "_meta.json") {
|
|
2715
2630
|
try {
|
|
2716
|
-
const content = await
|
|
2631
|
+
const content = await fs3.readFile(fullPath, "utf-8");
|
|
2717
2632
|
const summary = JSON.parse(content);
|
|
2718
2633
|
if (summary.filepath) {
|
|
2719
2634
|
this.fileSummaries.set(summary.filepath, summary);
|
|
@@ -2725,18 +2640,18 @@ class SymbolicIndex {
|
|
|
2725
2640
|
}
|
|
2726
2641
|
getFileSummaryPath(filepath) {
|
|
2727
2642
|
const jsonPath = filepath.replace(/\.[^.]+$/, ".json");
|
|
2728
|
-
return
|
|
2643
|
+
return path7.join(this.symbolicPath, jsonPath);
|
|
2729
2644
|
}
|
|
2730
2645
|
async deleteFileSummary(filepath) {
|
|
2731
2646
|
try {
|
|
2732
|
-
await
|
|
2647
|
+
await fs3.unlink(this.getFileSummaryPath(filepath));
|
|
2733
2648
|
} catch {}
|
|
2734
2649
|
this.fileSummaries.delete(filepath);
|
|
2735
2650
|
}
|
|
2736
2651
|
async exists() {
|
|
2737
2652
|
try {
|
|
2738
|
-
const metaPath =
|
|
2739
|
-
await
|
|
2653
|
+
const metaPath = path7.join(this.symbolicPath, "_meta.json");
|
|
2654
|
+
await fs3.access(metaPath);
|
|
2740
2655
|
return true;
|
|
2741
2656
|
} catch {
|
|
2742
2657
|
return false;
|
|
@@ -2775,7 +2690,7 @@ __export(exports_typescript, {
|
|
|
2775
2690
|
DEFAULT_TOP_K: () => DEFAULT_TOP_K2,
|
|
2776
2691
|
DEFAULT_MIN_SCORE: () => DEFAULT_MIN_SCORE2
|
|
2777
2692
|
});
|
|
2778
|
-
import * as
|
|
2693
|
+
import * as path8 from "path";
|
|
2779
2694
|
|
|
2780
2695
|
class TypeScriptModule {
|
|
2781
2696
|
id = "language/typescript";
|
|
@@ -2969,16 +2884,16 @@ class TypeScriptModule {
|
|
|
2969
2884
|
while ((match = importRegex.exec(content)) !== null) {
|
|
2970
2885
|
const importPath = match[1];
|
|
2971
2886
|
if (importPath.startsWith(".")) {
|
|
2972
|
-
const dir =
|
|
2973
|
-
const resolved =
|
|
2887
|
+
const dir = path8.dirname(filepath);
|
|
2888
|
+
const resolved = path8.normalize(path8.join(dir, importPath));
|
|
2974
2889
|
references.push(resolved);
|
|
2975
2890
|
}
|
|
2976
2891
|
}
|
|
2977
2892
|
while ((match = requireRegex.exec(content)) !== null) {
|
|
2978
2893
|
const importPath = match[1];
|
|
2979
2894
|
if (importPath.startsWith(".")) {
|
|
2980
|
-
const dir =
|
|
2981
|
-
const resolved =
|
|
2895
|
+
const dir = path8.dirname(filepath);
|
|
2896
|
+
const resolved = path8.normalize(path8.join(dir, importPath));
|
|
2982
2897
|
references.push(resolved);
|
|
2983
2898
|
}
|
|
2984
2899
|
}
|
|
@@ -3026,6 +2941,270 @@ var init_registry = __esm(() => {
|
|
|
3026
2941
|
registry = new ModuleRegistryImpl;
|
|
3027
2942
|
});
|
|
3028
2943
|
|
|
2944
|
+
// src/infrastructure/introspection/projectDetector.ts
|
|
2945
|
+
import * as path9 from "path";
|
|
2946
|
+
import * as fs4 from "fs/promises";
|
|
2947
|
+
async function scanForPackageJsons(rootDir, currentDir = "", depth = 0) {
|
|
2948
|
+
if (depth > MAX_SCAN_DEPTH)
|
|
2949
|
+
return [];
|
|
2950
|
+
const results = [];
|
|
2951
|
+
const fullDir = currentDir ? path9.join(rootDir, currentDir) : rootDir;
|
|
2952
|
+
try {
|
|
2953
|
+
const entries = await fs4.readdir(fullDir, { withFileTypes: true });
|
|
2954
|
+
const hasPackageJson = entries.some((e) => e.isFile() && e.name === "package.json");
|
|
2955
|
+
if (hasPackageJson && currentDir) {
|
|
2956
|
+
const info = await parsePackageJson(rootDir, currentDir);
|
|
2957
|
+
if (info)
|
|
2958
|
+
results.push(info);
|
|
2959
|
+
}
|
|
2960
|
+
for (const entry of entries) {
|
|
2961
|
+
if (!entry.isDirectory())
|
|
2962
|
+
continue;
|
|
2963
|
+
if (SKIP_DIRS.has(entry.name))
|
|
2964
|
+
continue;
|
|
2965
|
+
const subPath = currentDir ? `${currentDir}/${entry.name}` : entry.name;
|
|
2966
|
+
const subResults = await scanForPackageJsons(rootDir, subPath, depth + 1);
|
|
2967
|
+
results.push(...subResults);
|
|
2968
|
+
}
|
|
2969
|
+
} catch {}
|
|
2970
|
+
return results;
|
|
2971
|
+
}
|
|
2972
|
+
async function parsePackageJson(rootDir, relativePath) {
|
|
2973
|
+
try {
|
|
2974
|
+
const packageJsonPath = path9.join(rootDir, relativePath, "package.json");
|
|
2975
|
+
const content = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2976
|
+
const pkg = JSON.parse(content);
|
|
2977
|
+
const name = pkg.name || path9.basename(relativePath);
|
|
2978
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2979
|
+
let type = "unknown";
|
|
2980
|
+
if (deps["next"] || deps["react"] || deps["vue"] || deps["svelte"]) {
|
|
2981
|
+
type = "app";
|
|
2982
|
+
} else if (deps["express"] || deps["fastify"] || deps["koa"] || deps["hono"]) {
|
|
2983
|
+
type = "service";
|
|
2984
|
+
} else if (pkg.main || pkg.exports) {
|
|
2985
|
+
type = "library";
|
|
2986
|
+
}
|
|
2987
|
+
const hasWorkspaces = Boolean(pkg.workspaces);
|
|
2988
|
+
return { name, relativePath, type, hasWorkspaces };
|
|
2989
|
+
} catch {
|
|
2990
|
+
return null;
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
function getProjectType(patternDir) {
|
|
2994
|
+
switch (patternDir) {
|
|
2995
|
+
case "apps":
|
|
2996
|
+
return "app";
|
|
2997
|
+
case "packages":
|
|
2998
|
+
case "libs":
|
|
2999
|
+
return "library";
|
|
3000
|
+
case "services":
|
|
3001
|
+
return "service";
|
|
3002
|
+
case "scripts":
|
|
3003
|
+
case "tools":
|
|
3004
|
+
return "script";
|
|
3005
|
+
default:
|
|
3006
|
+
return "unknown";
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
async function detectProjectStructure(rootDir) {
|
|
3010
|
+
const projectMap = new Map;
|
|
3011
|
+
let isMonorepo = false;
|
|
3012
|
+
try {
|
|
3013
|
+
const entries = await fs4.readdir(rootDir, { withFileTypes: true });
|
|
3014
|
+
const dirNames = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
3015
|
+
const monorepoPatterns = ["apps", "packages", "libs", "services"];
|
|
3016
|
+
const hasMonorepoStructure = monorepoPatterns.some((p) => dirNames.includes(p));
|
|
3017
|
+
if (hasMonorepoStructure) {
|
|
3018
|
+
isMonorepo = true;
|
|
3019
|
+
for (const pattern of monorepoPatterns) {
|
|
3020
|
+
if (!dirNames.includes(pattern))
|
|
3021
|
+
continue;
|
|
3022
|
+
const patternDir = path9.join(rootDir, pattern);
|
|
3023
|
+
try {
|
|
3024
|
+
const subDirs = await fs4.readdir(patternDir, { withFileTypes: true });
|
|
3025
|
+
for (const subDir of subDirs) {
|
|
3026
|
+
if (!subDir.isDirectory())
|
|
3027
|
+
continue;
|
|
3028
|
+
const projectRoot = `${pattern}/${subDir.name}`;
|
|
3029
|
+
const type = getProjectType(pattern);
|
|
3030
|
+
projectMap.set(projectRoot, {
|
|
3031
|
+
name: subDir.name,
|
|
3032
|
+
root: projectRoot,
|
|
3033
|
+
type
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
} catch {}
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
const packageJsons = await scanForPackageJsons(rootDir);
|
|
3040
|
+
for (const pkg of packageJsons) {
|
|
3041
|
+
if (pkg.hasWorkspaces)
|
|
3042
|
+
isMonorepo = true;
|
|
3043
|
+
if (packageJsons.length > 1)
|
|
3044
|
+
isMonorepo = true;
|
|
3045
|
+
projectMap.set(pkg.relativePath, {
|
|
3046
|
+
name: pkg.name,
|
|
3047
|
+
root: pkg.relativePath,
|
|
3048
|
+
type: pkg.type
|
|
3049
|
+
});
|
|
3050
|
+
}
|
|
3051
|
+
let rootType = "unknown";
|
|
3052
|
+
try {
|
|
3053
|
+
const rootPkgPath = path9.join(rootDir, "package.json");
|
|
3054
|
+
const rootPkg = JSON.parse(await fs4.readFile(rootPkgPath, "utf-8"));
|
|
3055
|
+
if (rootPkg.workspaces)
|
|
3056
|
+
isMonorepo = true;
|
|
3057
|
+
const deps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
|
|
3058
|
+
if (deps["next"] || deps["react"] || deps["vue"]) {
|
|
3059
|
+
rootType = "app";
|
|
3060
|
+
} else if (deps["express"] || deps["fastify"] || deps["koa"]) {
|
|
3061
|
+
rootType = "service";
|
|
3062
|
+
}
|
|
3063
|
+
} catch {}
|
|
3064
|
+
const projects = Array.from(projectMap.values()).sort((a, b) => a.root.length - b.root.length);
|
|
3065
|
+
return {
|
|
3066
|
+
projects,
|
|
3067
|
+
isMonorepo,
|
|
3068
|
+
rootType: isMonorepo ? undefined : rootType
|
|
3069
|
+
};
|
|
3070
|
+
} catch {
|
|
3071
|
+
return {
|
|
3072
|
+
projects: [],
|
|
3073
|
+
isMonorepo: false,
|
|
3074
|
+
rootType: "unknown"
|
|
3075
|
+
};
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
var MAX_SCAN_DEPTH = 4, SKIP_DIRS;
|
|
3079
|
+
var init_projectDetector = __esm(() => {
|
|
3080
|
+
SKIP_DIRS = new Set([
|
|
3081
|
+
"node_modules",
|
|
3082
|
+
".git",
|
|
3083
|
+
"dist",
|
|
3084
|
+
"build",
|
|
3085
|
+
".next",
|
|
3086
|
+
".nuxt",
|
|
3087
|
+
"coverage",
|
|
3088
|
+
".raggrep"
|
|
3089
|
+
]);
|
|
3090
|
+
});
|
|
3091
|
+
|
|
3092
|
+
// src/infrastructure/introspection/IntrospectionIndex.ts
|
|
3093
|
+
import * as path10 from "path";
|
|
3094
|
+
import * as fs5 from "fs/promises";
|
|
3095
|
+
|
|
3096
|
+
class IntrospectionIndex {
|
|
3097
|
+
rootDir;
|
|
3098
|
+
structure = null;
|
|
3099
|
+
files = new Map;
|
|
3100
|
+
config = {};
|
|
3101
|
+
constructor(rootDir) {
|
|
3102
|
+
this.rootDir = rootDir;
|
|
3103
|
+
}
|
|
3104
|
+
async initialize() {
|
|
3105
|
+
this.structure = await detectProjectStructure(this.rootDir);
|
|
3106
|
+
try {
|
|
3107
|
+
const configPath = path10.join(this.rootDir, ".raggrep", "config.json");
|
|
3108
|
+
const configContent = await fs5.readFile(configPath, "utf-8");
|
|
3109
|
+
const config = JSON.parse(configContent);
|
|
3110
|
+
this.config = config.introspection || {};
|
|
3111
|
+
} catch {}
|
|
3112
|
+
}
|
|
3113
|
+
getStructure() {
|
|
3114
|
+
return this.structure;
|
|
3115
|
+
}
|
|
3116
|
+
addFile(filepath, content) {
|
|
3117
|
+
if (!this.structure) {
|
|
3118
|
+
throw new Error("IntrospectionIndex not initialized");
|
|
3119
|
+
}
|
|
3120
|
+
const intro = introspectFile(filepath, this.structure, content);
|
|
3121
|
+
this.applyOverrides(intro);
|
|
3122
|
+
this.files.set(filepath, intro);
|
|
3123
|
+
return intro;
|
|
3124
|
+
}
|
|
3125
|
+
getFile(filepath) {
|
|
3126
|
+
return this.files.get(filepath);
|
|
3127
|
+
}
|
|
3128
|
+
getAllFiles() {
|
|
3129
|
+
return Array.from(this.files.values());
|
|
3130
|
+
}
|
|
3131
|
+
applyOverrides(intro) {
|
|
3132
|
+
if (!this.config.projects)
|
|
3133
|
+
return;
|
|
3134
|
+
for (const [projectPath, overrides] of Object.entries(this.config.projects)) {
|
|
3135
|
+
if (intro.filepath.startsWith(projectPath + "/") || intro.project.root === projectPath) {
|
|
3136
|
+
if (overrides.scope) {
|
|
3137
|
+
intro.scope = overrides.scope;
|
|
3138
|
+
}
|
|
3139
|
+
if (overrides.framework) {
|
|
3140
|
+
intro.framework = overrides.framework;
|
|
3141
|
+
}
|
|
3142
|
+
break;
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
async save(config) {
|
|
3147
|
+
const introDir = path10.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
3148
|
+
await fs5.mkdir(introDir, { recursive: true });
|
|
3149
|
+
const projectPath = path10.join(introDir, "_project.json");
|
|
3150
|
+
await fs5.writeFile(projectPath, JSON.stringify({
|
|
3151
|
+
version: "1.0.0",
|
|
3152
|
+
lastUpdated: new Date().toISOString(),
|
|
3153
|
+
structure: this.structure
|
|
3154
|
+
}, null, 2));
|
|
3155
|
+
for (const [filepath, intro] of this.files) {
|
|
3156
|
+
const introFilePath = path10.join(introDir, "files", filepath.replace(/\.[^.]+$/, ".json"));
|
|
3157
|
+
await fs5.mkdir(path10.dirname(introFilePath), { recursive: true });
|
|
3158
|
+
await fs5.writeFile(introFilePath, JSON.stringify(intro, null, 2));
|
|
3159
|
+
}
|
|
3160
|
+
console.log(` [Introspection] Saved metadata for ${this.files.size} files`);
|
|
3161
|
+
}
|
|
3162
|
+
async load(config) {
|
|
3163
|
+
const introDir = path10.join(getRaggrepDir(this.rootDir, config), "introspection");
|
|
3164
|
+
try {
|
|
3165
|
+
const projectPath = path10.join(introDir, "_project.json");
|
|
3166
|
+
const projectContent = await fs5.readFile(projectPath, "utf-8");
|
|
3167
|
+
const projectData = JSON.parse(projectContent);
|
|
3168
|
+
this.structure = projectData.structure;
|
|
3169
|
+
await this.loadFilesRecursive(path10.join(introDir, "files"), "");
|
|
3170
|
+
} catch {
|
|
3171
|
+
this.structure = null;
|
|
3172
|
+
this.files.clear();
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
async loadFilesRecursive(basePath, prefix) {
|
|
3176
|
+
try {
|
|
3177
|
+
const entries = await fs5.readdir(basePath, { withFileTypes: true });
|
|
3178
|
+
for (const entry of entries) {
|
|
3179
|
+
const entryPath = path10.join(basePath, entry.name);
|
|
3180
|
+
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
3181
|
+
if (entry.isDirectory()) {
|
|
3182
|
+
await this.loadFilesRecursive(entryPath, relativePath);
|
|
3183
|
+
} else if (entry.name.endsWith(".json")) {
|
|
3184
|
+
const content = await fs5.readFile(entryPath, "utf-8");
|
|
3185
|
+
const intro = JSON.parse(content);
|
|
3186
|
+
this.files.set(intro.filepath, intro);
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
} catch {}
|
|
3190
|
+
}
|
|
3191
|
+
clear() {
|
|
3192
|
+
this.files.clear();
|
|
3193
|
+
this.structure = null;
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
var init_IntrospectionIndex = __esm(() => {
|
|
3197
|
+
init_projectDetector();
|
|
3198
|
+
init_introspection();
|
|
3199
|
+
init_config2();
|
|
3200
|
+
});
|
|
3201
|
+
|
|
3202
|
+
// src/infrastructure/introspection/index.ts
|
|
3203
|
+
var init_introspection2 = __esm(() => {
|
|
3204
|
+
init_IntrospectionIndex();
|
|
3205
|
+
init_projectDetector();
|
|
3206
|
+
});
|
|
3207
|
+
|
|
3029
3208
|
// src/app/indexer/watcher.ts
|
|
3030
3209
|
import { watch } from "chokidar";
|
|
3031
3210
|
import * as path11 from "path";
|
|
@@ -3521,7 +3700,7 @@ async function getIndexStatus(rootDir) {
|
|
|
3521
3700
|
var init_indexer = __esm(() => {
|
|
3522
3701
|
init_config2();
|
|
3523
3702
|
init_registry();
|
|
3524
|
-
|
|
3703
|
+
init_introspection2();
|
|
3525
3704
|
init_watcher();
|
|
3526
3705
|
});
|
|
3527
3706
|
|
|
@@ -3615,6 +3794,20 @@ async function loadGlobalManifest(rootDir, config) {
|
|
|
3615
3794
|
return null;
|
|
3616
3795
|
}
|
|
3617
3796
|
}
|
|
3797
|
+
function formatModuleName(moduleId) {
|
|
3798
|
+
switch (moduleId) {
|
|
3799
|
+
case "core":
|
|
3800
|
+
return "Core";
|
|
3801
|
+
case "language/typescript":
|
|
3802
|
+
return "TypeScript";
|
|
3803
|
+
default:
|
|
3804
|
+
if (moduleId.startsWith("language/")) {
|
|
3805
|
+
const lang = moduleId.replace("language/", "");
|
|
3806
|
+
return lang.charAt(0).toUpperCase() + lang.slice(1);
|
|
3807
|
+
}
|
|
3808
|
+
return moduleId;
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3618
3811
|
function formatSearchResults(results) {
|
|
3619
3812
|
if (results.length === 0) {
|
|
3620
3813
|
return "No results found.";
|
|
@@ -3630,6 +3823,7 @@ function formatSearchResults(results) {
|
|
|
3630
3823
|
output += `${i + 1}. ${location}${nameInfo}
|
|
3631
3824
|
`;
|
|
3632
3825
|
output += ` Score: ${(result.score * 100).toFixed(1)}% | Type: ${chunk.type}`;
|
|
3826
|
+
output += ` | via ${formatModuleName(result.moduleId)}`;
|
|
3633
3827
|
if (chunk.isExported) {
|
|
3634
3828
|
output += " | exported";
|
|
3635
3829
|
}
|
|
@@ -3657,7 +3851,7 @@ init_embeddings();
|
|
|
3657
3851
|
// package.json
|
|
3658
3852
|
var package_default = {
|
|
3659
3853
|
name: "raggrep",
|
|
3660
|
-
version: "0.1.
|
|
3854
|
+
version: "0.1.7",
|
|
3661
3855
|
description: "Local filesystem-based RAG system for codebases - semantic search using local embeddings",
|
|
3662
3856
|
type: "module",
|
|
3663
3857
|
main: "./dist/index.js",
|
|
@@ -4092,4 +4286,4 @@ Run 'raggrep <command> --help' for more information.
|
|
|
4092
4286
|
}
|
|
4093
4287
|
main();
|
|
4094
4288
|
|
|
4095
|
-
//# debugId=
|
|
4289
|
+
//# debugId=C248CB1C621D0FC764756E2164756E21
|