codesearch-mcp 0.0.1-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +129 -0
  2. package/dist/app.d.ts +1 -0
  3. package/dist/app.js +124 -0
  4. package/dist/src/ast.d.ts +2 -0
  5. package/dist/src/ast.js +60 -0
  6. package/dist/src/config.d.ts +26 -0
  7. package/dist/src/config.js +60 -0
  8. package/dist/src/db/data-source.d.ts +2 -0
  9. package/dist/src/db/data-source.js +13 -0
  10. package/dist/src/db/entities/code-chunk.entity.d.ts +9 -0
  11. package/dist/src/db/entities/code-chunk.entity.js +54 -0
  12. package/dist/src/db/entities/code-dependency.entity.d.ts +9 -0
  13. package/dist/src/db/entities/code-dependency.entity.js +54 -0
  14. package/dist/src/db/index.d.ts +4 -0
  15. package/dist/src/db/index.js +12 -0
  16. package/dist/src/db/init.d.ts +2 -0
  17. package/dist/src/db/init.js +50 -0
  18. package/dist/src/env-loader.d.ts +1 -0
  19. package/dist/src/env-loader.js +41 -0
  20. package/dist/src/file-utils.d.ts +12 -0
  21. package/dist/src/file-utils.js +97 -0
  22. package/dist/src/graph.d.ts +4 -0
  23. package/dist/src/graph.js +259 -0
  24. package/dist/src/indexer.d.ts +13 -0
  25. package/dist/src/indexer.js +217 -0
  26. package/dist/src/interrupt.d.ts +3 -0
  27. package/dist/src/interrupt.js +27 -0
  28. package/dist/src/mcp.d.ts +1 -0
  29. package/dist/src/mcp.js +248 -0
  30. package/dist/src/project-selector.d.ts +7 -0
  31. package/dist/src/project-selector.js +116 -0
  32. package/dist/src/searcher.d.ts +50 -0
  33. package/dist/src/searcher.js +205 -0
  34. package/dist/src/setup.d.ts +1 -0
  35. package/dist/src/setup.js +145 -0
  36. package/dist/vitest.config.d.ts +2 -0
  37. package/dist/vitest.config.js +9 -0
  38. package/docker/docker-compose.yml +19 -0
  39. package/package.json +49 -0
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # codesearch-mcp
2
+
3
+ Semantic codebase search for Claude. Indexes your local projects into a PostgreSQL vector database and exposes search via the Model Context Protocol (MCP).
4
+
5
+ Ask Claude things like *"where is the payment retry logic?"* or *"show me how auth tokens are validated"* — across all your projects at once.
6
+
7
+ > **Alpha** — works well locally, API may change before 1.0.
8
+
9
+ ## How it works
10
+
11
+ 1. `rag-index` scans your projects, chunks source files, embeds them with [bge-m3](https://huggingface.co/BAAI/bge-m3) via Ollama, and stores vectors in PostgreSQL
12
+ 2. `rag-mcp` exposes an MCP server — Claude calls it automatically when you ask about code
13
+ 3. Incremental — only changed files are re-indexed on subsequent runs
14
+
15
+ **Stack:** TypeScript · TypeORM · PostgreSQL + pgvector · Ollama (bge-m3) · LangChain text splitters · ts-morph
16
+
17
+ ## Requirements
18
+
19
+ - Node.js 18+
20
+ - Docker (for local DB + Ollama) — or bring your own PostgreSQL with pgvector + Ollama
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install -g codesearch-mcp
26
+ ```
27
+
28
+ ## Setup
29
+
30
+ ```bash
31
+ rag-setup
32
+ ```
33
+
34
+ Walks you through:
35
+ - **Local Docker** — copies `docker-compose.yml`, starts PostgreSQL + Ollama, pulls `bge-m3` automatically
36
+ - **Remote DB** — enter connection details for Supabase, Railway, or self-hosted; connection is verified before saving
37
+
38
+ Config is saved to `~/.config/codesearch-mcp/.env`.
39
+
40
+ ## Index your projects
41
+
42
+ ```bash
43
+ rag-index /home/user/Projects
44
+ ```
45
+
46
+ On first run you will be prompted for each discovered project:
47
+
48
+ ```
49
+ Found 5 new project(s). Select which to index:
50
+ y = yes | n = skip this time | s = always skip
51
+
52
+ myapp [y/n/s]: y
53
+ legacy-app [y/n/s]: s
54
+ → added to .ragskip
55
+ ```
56
+
57
+ Selections are saved in `.ragprojects` / `.ragskip` at the workspace root. Use `--select` to revisit them.
58
+
59
+ ```bash
60
+ rag-index /path --select # re-run project selection
61
+ rag-index /path --reindex # force re-embed all files (use after model change)
62
+ rag-index /path --select --reindex
63
+ ```
64
+
65
+ ## Register with Claude Code
66
+
67
+ ```bash
68
+ claude mcp add codesearch-mcp -s user -- rag-mcp
69
+ ```
70
+
71
+ Then ask Claude anything about your code — it will use `search_codebase`, `list_projects`, `read_file_range`, `get_dependencies`, and `get_dependents` automatically.
72
+
73
+ ## MCP Tools
74
+
75
+ | Tool | Description |
76
+ |------|-------------|
77
+ | `search_codebase` | Semantic search across all indexed projects |
78
+ | `list_projects` | List projects with metadata and chunk counts |
79
+ | `read_file_range` | Read a specific line range from an indexed file |
80
+ | `get_dependencies` | Show what files a given file imports |
81
+ | `get_dependents` | Show which files import a given file |
82
+
83
+ ## Project metadata
84
+
85
+ Add `.ragmeta.json` to a project root to enrich `list_projects` and generate a visual dependency graph:
86
+
87
+ ```json
88
+ {
89
+ "description": "Main API server",
90
+ "stack": "NestJS, GraphQL, PostgreSQL",
91
+ "relations": {
92
+ "consumed_by": ["crm-frontend"],
93
+ "consumes": ["billing-service", "auth-service"]
94
+ }
95
+ }
96
+ ```
97
+
98
+ After each indexing run an interactive `project-graph.html` is written to the workspace root.
99
+
100
+ ## Excluding files
101
+
102
+ Create `.ragignore` in a project root — same syntax as `.gitignore`:
103
+
104
+ ```
105
+ src/gql/graphql.ts
106
+ **/__snapshots__/**
107
+ src/generated/
108
+ ```
109
+
110
+ ## Environment variables
111
+
112
+ All set by `rag-setup`. Override any of them in `~/.config/codesearch-mcp/.env`.
113
+
114
+ | Variable | Default | Description |
115
+ |----------|---------|-------------|
116
+ | `DB_HOST` | — | PostgreSQL host |
117
+ | `DB_PORT` | `5433` | PostgreSQL port |
118
+ | `DB_USER` | — | PostgreSQL user |
119
+ | `DB_PASS` | — | PostgreSQL password |
120
+ | `DB_NAME` | — | Database name |
121
+ | `WORKSPACE_ROOT` | — | Root of your projects directory |
122
+ | `OLLAMA_HOST` | `http://localhost:11434` | Ollama API URL |
123
+ | `OLLAMA_MODEL` | `bge-m3` | Embedding model |
124
+ | `SIMILARITY_THRESHOLD` | `0.6` | Max cosine distance — raise if search returns nothing |
125
+ | `AUTO_TRANSLATE` | `false` | Translate non-English queries to English before embedding |
126
+
127
+ ## License
128
+
129
+ MIT
package/dist/app.d.ts ADDED
@@ -0,0 +1 @@
1
+ import './src/env-loader';
package/dist/app.js ADDED
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ require("./src/env-loader");
38
+ const path = __importStar(require("path"));
39
+ const db_1 = require("./src/db");
40
+ const indexer_1 = require("./src/indexer");
41
+ const interrupt_1 = require("./src/interrupt");
42
+ const project_selector_1 = require("./src/project-selector");
43
+ const mcp_1 = require("./src/mcp");
44
+ const graph_1 = require("./src/graph");
45
+ function printSummary(allStats) {
46
+ const cols = { name: 30, num: 8 };
47
+ const line = '─'.repeat(cols.name + cols.num * 5 + 5);
48
+ console.log('\n=== Indexing Summary ===');
49
+ console.log('Service'.padEnd(cols.name), 'Indexed'.padStart(cols.num), 'Skipped'.padStart(cols.num), 'Failed'.padStart(cols.num), 'Chunks'.padStart(cols.num), 'Time(s)'.padStart(cols.num));
50
+ console.log(line);
51
+ for (const s of allStats) {
52
+ console.log(s.serviceName.padEnd(cols.name), String(s.indexed).padStart(cols.num), String(s.skipped).padStart(cols.num), String(s.failed).padStart(cols.num), String(s.chunks).padStart(cols.num), String(s.elapsedSec).padStart(cols.num));
53
+ }
54
+ console.log(line);
55
+ const total = allStats.reduce((acc, s) => ({
56
+ indexed: acc.indexed + s.indexed,
57
+ skipped: acc.skipped + s.skipped,
58
+ failed: acc.failed + s.failed,
59
+ chunks: acc.chunks + s.chunks,
60
+ elapsedSec: acc.elapsedSec + s.elapsedSec,
61
+ }), { indexed: 0, skipped: 0, failed: 0, chunks: 0, elapsedSec: 0 });
62
+ console.log('TOTAL'.padEnd(cols.name), String(total.indexed).padStart(cols.num), String(total.skipped).padStart(cols.num), String(total.failed).padStart(cols.num), String(total.chunks).padStart(cols.num), String(total.elapsedSec.toFixed(1)).padStart(cols.num));
63
+ }
64
+ async function main() {
65
+ const argv1 = path.basename(process.argv[1] ?? '');
66
+ const isMcp = argv1 === 'rag-mcp' || process.argv[2] === 'mcp';
67
+ const isSetup = argv1 === 'rag-setup' || process.argv[2] === 'setup';
68
+ const mode = isMcp ? 'mcp' : isSetup ? 'setup' : (process.argv[2] ?? '');
69
+ if (mode === 'index') {
70
+ const args = process.argv.slice(argv1 === 'rag-index' ? 2 : 3);
71
+ const workspacePath = args.find(a => !a.startsWith('--'));
72
+ const force = args.includes('--reindex');
73
+ const forceSelect = args.includes('--select');
74
+ if (!workspacePath) {
75
+ console.error('Usage: rag-index <path> [--reindex] [--select]');
76
+ process.exit(1);
77
+ }
78
+ process.env.WORKSPACE_ROOT ??= workspacePath;
79
+ await (0, db_1.initDbWithSchema)();
80
+ (0, interrupt_1.setupInterrupt)();
81
+ const discovered = (0, indexer_1.discoverProjects)(workspacePath);
82
+ const projects = await (0, project_selector_1.selectProjects)(discovered, workspacePath, forceSelect);
83
+ if (projects.length === 0) {
84
+ (0, interrupt_1.teardownInterrupt)();
85
+ process.exit(0);
86
+ }
87
+ const allStats = [];
88
+ if (force)
89
+ console.log('Reindex mode: all files will be re-indexed.');
90
+ for (const proj of projects) {
91
+ if (interrupt_1.signal.aborted)
92
+ break;
93
+ const stats = await (0, indexer_1.scanAndIndex)(proj.path, proj.name, force, interrupt_1.signal);
94
+ allStats.push(stats);
95
+ }
96
+ (0, interrupt_1.teardownInterrupt)();
97
+ if (interrupt_1.signal.aborted)
98
+ console.log('\nIndexing interrupted.');
99
+ printSummary(allStats);
100
+ if (!interrupt_1.signal.aborted)
101
+ (0, graph_1.generateProjectGraph)(projects, workspacePath);
102
+ process.exit(0);
103
+ }
104
+ else if (mode === 'mcp') {
105
+ if (!process.env.WORKSPACE_ROOT) {
106
+ console.error('WORKSPACE_ROOT is required for MCP mode. Set it in ~/.config/codesearch-mcp/.env');
107
+ console.error('Run `rag-setup` to configure.');
108
+ process.exit(1);
109
+ }
110
+ await (0, db_1.initDb)();
111
+ await (0, mcp_1.startMCP)();
112
+ }
113
+ else if (mode === 'setup') {
114
+ const { runSetup } = await Promise.resolve().then(() => __importStar(require('./src/setup')));
115
+ await runSetup();
116
+ }
117
+ else {
118
+ console.log('Usage: rag-index <path> [--reindex] [--select]');
119
+ console.log(' rag-mcp');
120
+ console.log(' rag-setup');
121
+ process.exit(1);
122
+ }
123
+ }
124
+ main().catch(err => { console.error(err); process.exit(1); });
@@ -0,0 +1,2 @@
1
+ import type { CodeDependency } from './db';
2
+ export declare function extractImportEdges(filePath: string, serviceName: string): Promise<Omit<CodeDependency, 'id'>[]>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractImportEdges = extractImportEdges;
4
+ const ts_morph_1 = require("ts-morph");
5
+ // Single ts-morph Project instance for import graph extraction.
6
+ // skipFileDependencyResolution: false is required so getModuleSpecifierSourceFile() resolves relative imports.
7
+ const morphProject = new ts_morph_1.Project({
8
+ skipAddingFilesFromTsConfig: true,
9
+ skipFileDependencyResolution: false,
10
+ compilerOptions: { allowJs: true, noEmit: true },
11
+ });
12
+ // Extract import edges from a TS/JS file using ts-morph.
13
+ // Only resolves relative imports (external packages are skipped).
14
+ // Removes the source file from morphProject after parsing to prevent memory accumulation.
15
+ async function extractImportEdges(filePath, serviceName) {
16
+ // Only process JS/TS files; skip declaration files
17
+ if (!/\.(ts|tsx|js|jsx)$/.test(filePath) || /\.d\.ts$/.test(filePath))
18
+ return [];
19
+ // Remove stale cached version before re-adding
20
+ const existing = morphProject.getSourceFile(filePath);
21
+ if (existing)
22
+ morphProject.removeSourceFile(existing);
23
+ let sourceFile;
24
+ try {
25
+ sourceFile = morphProject.addSourceFileAtPath(filePath);
26
+ }
27
+ catch {
28
+ return []; // file disappeared between stat and parse
29
+ }
30
+ const edges = [];
31
+ for (const decl of sourceFile.getImportDeclarations()) {
32
+ const resolved = decl.getModuleSpecifierSourceFile();
33
+ if (!resolved)
34
+ continue; // external package or unresolvable
35
+ const toFile = resolved.getFilePath();
36
+ if (toFile.includes('/node_modules/'))
37
+ continue; // skip package type declarations
38
+ const namedImports = decl.getNamedImports();
39
+ const defaultImport = decl.getDefaultImport();
40
+ const namespaceImport = decl.getNamespaceImport();
41
+ if (namedImports.length > 0) {
42
+ for (const named of namedImports) {
43
+ edges.push({ project: serviceName, fromFile: filePath, fromSymbol: null, toFile, toSymbol: named.getName(), depType: 'import' });
44
+ }
45
+ }
46
+ else if (defaultImport) {
47
+ edges.push({ project: serviceName, fromFile: filePath, fromSymbol: null, toFile, toSymbol: null, depType: 'import-default' });
48
+ }
49
+ else if (namespaceImport) {
50
+ edges.push({ project: serviceName, fromFile: filePath, fromSymbol: null, toFile, toSymbol: null, depType: 'import-namespace' });
51
+ }
52
+ else {
53
+ // Side-effect import: import './foo'
54
+ edges.push({ project: serviceName, fromFile: filePath, fromSymbol: null, toFile, toSymbol: null, depType: 'import' });
55
+ }
56
+ }
57
+ // Remove from memory — prevents accumulation across large workspaces
58
+ morphProject.removeSourceFile(sourceFile);
59
+ return edges;
60
+ }
@@ -0,0 +1,26 @@
1
+ export declare const config: {
2
+ db: {
3
+ host: string;
4
+ port: number;
5
+ username: string;
6
+ password: string;
7
+ database: string;
8
+ };
9
+ ollama: {
10
+ host: string;
11
+ model: string;
12
+ };
13
+ indexer: {
14
+ chunkSize: number;
15
+ chunkOverlap: number;
16
+ batchSize: number;
17
+ };
18
+ search: {
19
+ similarityThreshold: number;
20
+ defaultLimit: number;
21
+ maxLimit: number;
22
+ autoTranslate: boolean;
23
+ translateModel: string;
24
+ };
25
+ workspaceRoot: string;
26
+ };
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.config = void 0;
4
+ const zod_1 = require("zod");
5
+ const schema = zod_1.z.object({
6
+ // required — no defaults, process exits if missing
7
+ DB_HOST: zod_1.z.string(),
8
+ DB_PORT: zod_1.z.coerce.number().default(5433),
9
+ DB_USER: zod_1.z.string(),
10
+ DB_PASS: zod_1.z.string(),
11
+ DB_NAME: zod_1.z.string(),
12
+ // optional with defaults
13
+ OLLAMA_HOST: zod_1.z.string().url().default('http://localhost:11434'),
14
+ OLLAMA_MODEL: zod_1.z.string().default('bge-m3'),
15
+ CHUNK_SIZE: zod_1.z.coerce.number().default(1500),
16
+ CHUNK_OVERLAP: zod_1.z.coerce.number().default(200),
17
+ EMBED_BATCH_SIZE: zod_1.z.coerce.number().default(5),
18
+ SIMILARITY_THRESHOLD: zod_1.z.coerce.number().default(0.6),
19
+ SEARCH_DEFAULT_LIMIT: zod_1.z.coerce.number().default(5),
20
+ SEARCH_MAX_LIMIT: zod_1.z.coerce.number().default(20),
21
+ // auto-translate non-English queries to English before embedding
22
+ AUTO_TRANSLATE: zod_1.z.string().default('false').transform(v => v === 'true'),
23
+ TRANSLATE_MODEL: zod_1.z.string().default('llama3.2'),
24
+ WORKSPACE_ROOT: zod_1.z.string().optional(),
25
+ });
26
+ const parsed = schema.safeParse(process.env);
27
+ if (!parsed.success) {
28
+ console.error('Invalid or missing config:');
29
+ for (const [key, errors] of Object.entries(parsed.error.flatten().fieldErrors)) {
30
+ console.error(` ${key}: ${errors.join(', ')}`);
31
+ }
32
+ process.exit(1);
33
+ }
34
+ const env = parsed.data;
35
+ exports.config = {
36
+ db: {
37
+ host: env.DB_HOST,
38
+ port: env.DB_PORT,
39
+ username: env.DB_USER,
40
+ password: env.DB_PASS,
41
+ database: env.DB_NAME,
42
+ },
43
+ ollama: {
44
+ host: env.OLLAMA_HOST,
45
+ model: env.OLLAMA_MODEL,
46
+ },
47
+ indexer: {
48
+ chunkSize: env.CHUNK_SIZE,
49
+ chunkOverlap: env.CHUNK_OVERLAP,
50
+ batchSize: env.EMBED_BATCH_SIZE,
51
+ },
52
+ search: {
53
+ similarityThreshold: env.SIMILARITY_THRESHOLD,
54
+ defaultLimit: env.SEARCH_DEFAULT_LIMIT,
55
+ maxLimit: env.SEARCH_MAX_LIMIT,
56
+ autoTranslate: env.AUTO_TRANSLATE,
57
+ translateModel: env.TRANSLATE_MODEL,
58
+ },
59
+ workspaceRoot: env.WORKSPACE_ROOT ?? '',
60
+ };
@@ -0,0 +1,2 @@
1
+ import { DataSource } from 'typeorm';
2
+ export declare const db: DataSource;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.db = void 0;
4
+ const typeorm_1 = require("typeorm");
5
+ const config_1 = require("../config");
6
+ const code_chunk_entity_1 = require("./entities/code-chunk.entity");
7
+ const code_dependency_entity_1 = require("./entities/code-dependency.entity");
8
+ exports.db = new typeorm_1.DataSource({
9
+ type: 'postgres',
10
+ ...config_1.config.db,
11
+ entities: [code_chunk_entity_1.CodeChunk, code_dependency_entity_1.CodeDependency],
12
+ synchronize: false,
13
+ });
@@ -0,0 +1,9 @@
1
+ export declare class CodeChunk {
2
+ id: string;
3
+ serviceName: string;
4
+ filePath: string;
5
+ startLine: number;
6
+ content: string;
7
+ embedding: string;
8
+ lastModified: number;
9
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.CodeChunk = void 0;
13
+ const typeorm_1 = require("typeorm");
14
+ let CodeChunk = class CodeChunk {
15
+ id;
16
+ serviceName;
17
+ filePath;
18
+ startLine;
19
+ content;
20
+ embedding;
21
+ lastModified;
22
+ };
23
+ exports.CodeChunk = CodeChunk;
24
+ __decorate([
25
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
26
+ __metadata("design:type", String)
27
+ ], CodeChunk.prototype, "id", void 0);
28
+ __decorate([
29
+ (0, typeorm_1.Column)(),
30
+ __metadata("design:type", String)
31
+ ], CodeChunk.prototype, "serviceName", void 0);
32
+ __decorate([
33
+ (0, typeorm_1.Column)(),
34
+ __metadata("design:type", String)
35
+ ], CodeChunk.prototype, "filePath", void 0);
36
+ __decorate([
37
+ (0, typeorm_1.Column)({ nullable: true }),
38
+ __metadata("design:type", Number)
39
+ ], CodeChunk.prototype, "startLine", void 0);
40
+ __decorate([
41
+ (0, typeorm_1.Column)('text'),
42
+ __metadata("design:type", String)
43
+ ], CodeChunk.prototype, "content", void 0);
44
+ __decorate([
45
+ (0, typeorm_1.Column)({ type: 'vector', length: 1024 }),
46
+ __metadata("design:type", String)
47
+ ], CodeChunk.prototype, "embedding", void 0);
48
+ __decorate([
49
+ (0, typeorm_1.Column)({ type: 'double precision', nullable: true }),
50
+ __metadata("design:type", Number)
51
+ ], CodeChunk.prototype, "lastModified", void 0);
52
+ exports.CodeChunk = CodeChunk = __decorate([
53
+ (0, typeorm_1.Entity)()
54
+ ], CodeChunk);
@@ -0,0 +1,9 @@
1
+ export declare class CodeDependency {
2
+ id: string;
3
+ project: string;
4
+ fromFile: string;
5
+ fromSymbol: string | null;
6
+ toFile: string;
7
+ toSymbol: string | null;
8
+ depType: string;
9
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.CodeDependency = void 0;
13
+ const typeorm_1 = require("typeorm");
14
+ let CodeDependency = class CodeDependency {
15
+ id;
16
+ project;
17
+ fromFile;
18
+ fromSymbol;
19
+ toFile;
20
+ toSymbol;
21
+ depType; // 'import' | 'import-default' | 'import-namespace'
22
+ };
23
+ exports.CodeDependency = CodeDependency;
24
+ __decorate([
25
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
26
+ __metadata("design:type", String)
27
+ ], CodeDependency.prototype, "id", void 0);
28
+ __decorate([
29
+ (0, typeorm_1.Column)(),
30
+ __metadata("design:type", String)
31
+ ], CodeDependency.prototype, "project", void 0);
32
+ __decorate([
33
+ (0, typeorm_1.Column)(),
34
+ __metadata("design:type", String)
35
+ ], CodeDependency.prototype, "fromFile", void 0);
36
+ __decorate([
37
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
38
+ __metadata("design:type", Object)
39
+ ], CodeDependency.prototype, "fromSymbol", void 0);
40
+ __decorate([
41
+ (0, typeorm_1.Column)(),
42
+ __metadata("design:type", String)
43
+ ], CodeDependency.prototype, "toFile", void 0);
44
+ __decorate([
45
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
46
+ __metadata("design:type", Object)
47
+ ], CodeDependency.prototype, "toSymbol", void 0);
48
+ __decorate([
49
+ (0, typeorm_1.Column)(),
50
+ __metadata("design:type", String)
51
+ ], CodeDependency.prototype, "depType", void 0);
52
+ exports.CodeDependency = CodeDependency = __decorate([
53
+ (0, typeorm_1.Entity)()
54
+ ], CodeDependency);
@@ -0,0 +1,4 @@
1
+ export { CodeChunk } from './entities/code-chunk.entity';
2
+ export { CodeDependency } from './entities/code-dependency.entity';
3
+ export { db } from './data-source';
4
+ export { initDb, initDbWithSchema } from './init';
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initDbWithSchema = exports.initDb = exports.db = exports.CodeDependency = exports.CodeChunk = void 0;
4
+ var code_chunk_entity_1 = require("./entities/code-chunk.entity");
5
+ Object.defineProperty(exports, "CodeChunk", { enumerable: true, get: function () { return code_chunk_entity_1.CodeChunk; } });
6
+ var code_dependency_entity_1 = require("./entities/code-dependency.entity");
7
+ Object.defineProperty(exports, "CodeDependency", { enumerable: true, get: function () { return code_dependency_entity_1.CodeDependency; } });
8
+ var data_source_1 = require("./data-source");
9
+ Object.defineProperty(exports, "db", { enumerable: true, get: function () { return data_source_1.db; } });
10
+ var init_1 = require("./init");
11
+ Object.defineProperty(exports, "initDb", { enumerable: true, get: function () { return init_1.initDb; } });
12
+ Object.defineProperty(exports, "initDbWithSchema", { enumerable: true, get: function () { return init_1.initDbWithSchema; } });
@@ -0,0 +1,2 @@
1
+ export declare function initDb(): Promise<void>;
2
+ export declare function initDbWithSchema(): Promise<void>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initDb = initDb;
4
+ exports.initDbWithSchema = initDbWithSchema;
5
+ const data_source_1 = require("./data-source");
6
+ // For MCP server — just connect, no schema changes
7
+ async function initDb() {
8
+ await data_source_1.db.initialize();
9
+ }
10
+ // For indexer — connect + create schema only if tables don't exist yet
11
+ async function initDbWithSchema() {
12
+ await data_source_1.db.initialize();
13
+ // code_chunk table
14
+ const [{ exists }] = await data_source_1.db.query(`
15
+ SELECT EXISTS (
16
+ SELECT 1 FROM information_schema.tables
17
+ WHERE table_schema = 'public' AND table_name = 'code_chunk'
18
+ )
19
+ `);
20
+ if (!exists) {
21
+ await data_source_1.db.synchronize();
22
+ await data_source_1.db.query(`
23
+ CREATE INDEX idx_code_chunk_embedding
24
+ ON code_chunk USING hnsw (embedding vector_cosine_ops)
25
+ `);
26
+ }
27
+ // code_dependency table
28
+ const [{ existsDep }] = await data_source_1.db.query(`
29
+ SELECT EXISTS (
30
+ SELECT 1 FROM information_schema.tables
31
+ WHERE table_schema = 'public' AND table_name = 'code_dependency'
32
+ ) AS "existsDep"
33
+ `);
34
+ if (!existsDep) {
35
+ await data_source_1.db.query(`
36
+ CREATE TABLE code_dependency (
37
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
38
+ project TEXT NOT NULL,
39
+ "fromFile" TEXT NOT NULL,
40
+ "fromSymbol" TEXT,
41
+ "toFile" TEXT NOT NULL,
42
+ "toSymbol" TEXT,
43
+ "depType" TEXT NOT NULL
44
+ )
45
+ `);
46
+ await data_source_1.db.query(`CREATE INDEX idx_dep_from ON code_dependency ("fromFile")`);
47
+ await data_source_1.db.query(`CREATE INDEX idx_dep_to ON code_dependency ("toFile")`);
48
+ await data_source_1.db.query(`CREATE INDEX idx_dep_project ON code_dependency (project)`);
49
+ }
50
+ }
@@ -0,0 +1 @@
1
+ export {};