@zipbul/gildash 0.0.1

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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.ko.md +386 -0
  3. package/README.md +445 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +2736 -0
  6. package/dist/index.js.map +42 -0
  7. package/dist/migrations/0000_soft_revanche.sql +56 -0
  8. package/dist/migrations/meta/0000_snapshot.json +408 -0
  9. package/dist/migrations/meta/_journal.json +13 -0
  10. package/dist/migrations/migrations/0000_soft_revanche.sql +56 -0
  11. package/dist/migrations/migrations/meta/0000_snapshot.json +408 -0
  12. package/dist/migrations/migrations/meta/_journal.json +13 -0
  13. package/dist/src/codeledger.d.ts +103 -0
  14. package/dist/src/common/hasher.d.ts +2 -0
  15. package/dist/src/common/index.d.ts +5 -0
  16. package/dist/src/common/lru-cache.d.ts +10 -0
  17. package/dist/src/common/path-utils.d.ts +2 -0
  18. package/dist/src/common/project-discovery.d.ts +6 -0
  19. package/dist/src/common/tsconfig-resolver.d.ts +6 -0
  20. package/dist/src/errors.d.ts +42 -0
  21. package/dist/src/extractor/calls-extractor.d.ts +3 -0
  22. package/dist/src/extractor/extractor-utils.d.ts +5 -0
  23. package/dist/src/extractor/heritage-extractor.d.ts +3 -0
  24. package/dist/src/extractor/imports-extractor.d.ts +4 -0
  25. package/dist/src/extractor/index.d.ts +7 -0
  26. package/dist/src/extractor/relation-extractor.d.ts +4 -0
  27. package/dist/src/extractor/symbol-extractor.d.ts +3 -0
  28. package/dist/src/extractor/types.d.ts +162 -0
  29. package/dist/src/gildash.d.ts +284 -0
  30. package/dist/src/index.d.ts +8 -0
  31. package/dist/src/indexer/file-indexer.d.ts +27 -0
  32. package/dist/src/indexer/index-coordinator.d.ts +80 -0
  33. package/dist/src/indexer/index.d.ts +8 -0
  34. package/dist/src/indexer/relation-indexer.d.ts +24 -0
  35. package/dist/src/indexer/symbol-indexer.d.ts +29 -0
  36. package/dist/src/parser/ast-utils.d.ts +10 -0
  37. package/dist/src/parser/index.d.ts +6 -0
  38. package/dist/src/parser/jsdoc-parser.d.ts +2 -0
  39. package/dist/src/parser/parse-cache.d.ts +10 -0
  40. package/dist/src/parser/parse-source.d.ts +3 -0
  41. package/dist/src/parser/source-position.d.ts +3 -0
  42. package/dist/src/parser/types.d.ts +16 -0
  43. package/dist/src/search/dependency-graph.d.ts +71 -0
  44. package/dist/src/search/index.d.ts +6 -0
  45. package/dist/src/search/relation-search.d.ts +45 -0
  46. package/dist/src/search/symbol-search.d.ts +76 -0
  47. package/dist/src/store/connection.d.ts +30 -0
  48. package/dist/src/store/index.d.ts +10 -0
  49. package/dist/src/store/repositories/file.repository.d.ts +18 -0
  50. package/dist/src/store/repositories/fts-utils.d.ts +1 -0
  51. package/dist/src/store/repositories/relation.repository.d.ts +29 -0
  52. package/dist/src/store/repositories/symbol.repository.d.ts +46 -0
  53. package/dist/src/store/schema.d.ts +634 -0
  54. package/dist/src/watcher/index.d.ts +3 -0
  55. package/dist/src/watcher/ownership.d.ts +22 -0
  56. package/dist/src/watcher/project-watcher.d.ts +13 -0
  57. package/dist/src/watcher/types.d.ts +11 -0
  58. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,445 @@
1
+ # @zipbul/gildash
2
+
3
+ **English** | [한국어](./README.ko.md)
4
+
5
+ [![npm](https://img.shields.io/npm/v/@zipbul/gildash)](https://www.npmjs.com/package/@zipbul/gildash)
6
+ [![CI](https://github.com/zipbul/gildash/actions/workflows/ci.yml/badge.svg)](https://github.com/zipbul/gildash/actions/workflows/ci.yml)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
8
+
9
+ A **Bun-native** TypeScript code indexer. Extracts symbols, tracks cross-file relationships, and builds a full dependency graph — all stored in a local SQLite database.
10
+
11
+ <br>
12
+
13
+ ## Features
14
+
15
+ - **Symbol extraction** — Functions, classes, variables, types, interfaces, enums, and properties extracted via [oxc-parser](https://oxc.rs) AST
16
+ - **Relation tracking** — `import`, `calls`, `extends`, `implements` relationships across files
17
+ - **Full-text search** — SQLite FTS5-powered symbol name search
18
+ - **Dependency graph** — Directed import graph with cycle detection and transitive impact analysis
19
+ - **Incremental indexing** — `@parcel/watcher`-based file change detection; only re-indexes modified files
20
+ - **Multi-process safe** — Owner/reader role separation guarantees a single writer per database
21
+
22
+ <br>
23
+
24
+ ## Requirements
25
+
26
+ - **Bun** v1.3 or higher
27
+ - TypeScript source files: `.ts`, `.mts`, `.cts`
28
+
29
+ <br>
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ bun add @zipbul/gildash
35
+ ```
36
+
37
+ <br>
38
+
39
+ ## Quick Start
40
+
41
+ ```ts
42
+ import { Gildash } from '@zipbul/gildash';
43
+
44
+ const ledger = await Gildash.open({
45
+ projectRoot: '/absolute/path/to/project',
46
+ });
47
+
48
+ // Search for exported classes by name
49
+ const hits = ledger.searchSymbols({
50
+ text: 'UserService',
51
+ kind: 'class',
52
+ isExported: true,
53
+ });
54
+
55
+ // Find what a file imports
56
+ const deps = ledger.getDependencies('src/app.ts');
57
+
58
+ // Find everything affected by a change
59
+ const affected = await ledger.getAffected(['src/utils.ts']);
60
+
61
+ // Detect circular dependencies
62
+ if (await ledger.hasCycle()) {
63
+ console.warn('Circular dependency detected');
64
+ }
65
+
66
+ // Subscribe to index-complete events
67
+ const unsubscribe = ledger.onIndexed((result) => {
68
+ console.log(`Indexed ${result.indexedFiles} files in ${result.durationMs}ms`);
69
+ });
70
+
71
+ await ledger.close();
72
+ ```
73
+
74
+ ### Error handling
75
+
76
+ All errors extend `GildashError`:
77
+
78
+ ```ts
79
+ import { Gildash, GildashError, ParseError } from '@zipbul/gildash';
80
+
81
+ try {
82
+ const ledger = await Gildash.open({ projectRoot: '/path' });
83
+ } catch (err) {
84
+ if (err instanceof ParseError) {
85
+ // AST parsing failure
86
+ } else if (err instanceof GildashError) {
87
+ // Any gildash error
88
+ }
89
+ }
90
+ ```
91
+
92
+ <br>
93
+
94
+ ## API
95
+
96
+ ### `Gildash.open(options)`
97
+
98
+ Creates and returns a `Gildash` instance. Performs a full index on first run, then watches for file changes.
99
+
100
+ ```ts
101
+ const ledger = await Gildash.open({
102
+ projectRoot: '/absolute/path',
103
+ extensions: ['.ts', '.mts', '.cts'],
104
+ ignorePatterns: ['dist', 'vendor'],
105
+ parseCacheCapacity: 500,
106
+ logger: console,
107
+ });
108
+ ```
109
+
110
+ #### options
111
+
112
+ | Option | Type | Default | Description |
113
+ |--------|------|---------|-------------|
114
+ | `projectRoot` | `string` | — | Absolute path to project root **(required)** |
115
+ | `extensions` | `string[]` | `['.ts', '.mts', '.cts']` | File extensions to index |
116
+ | `ignorePatterns` | `string[]` | `[]` | Glob patterns to exclude |
117
+ | `parseCacheCapacity` | `number` | `500` | LRU parse-cache capacity |
118
+ | `logger` | `Logger` | `console` | Custom logger (`{ error(...args): void }`) |
119
+
120
+ Returns `Promise<Gildash>`
121
+
122
+ ---
123
+
124
+ ### `ledger.searchSymbols(query)`
125
+
126
+ Search symbols by name (FTS5 full-text), kind, file path, and/or export status.
127
+
128
+ ```ts
129
+ // Full-text search
130
+ const results = ledger.searchSymbols({ text: 'handleClick' });
131
+
132
+ // Filter by kind + export status
133
+ const classes = ledger.searchSymbols({
134
+ kind: 'class',
135
+ isExported: true,
136
+ limit: 50,
137
+ });
138
+
139
+ // Scope to a specific file
140
+ const inFile = ledger.searchSymbols({
141
+ filePath: 'src/services/user.ts',
142
+ });
143
+ ```
144
+
145
+ #### SymbolSearchQuery
146
+
147
+ | Field | Type | Description |
148
+ |-------|------|-------------|
149
+ | `text` | `string?` | FTS5 full-text search query |
150
+ | `kind` | `SymbolKind?` | `'function'` \| `'method'` \| `'class'` \| `'variable'` \| `'type'` \| `'interface'` \| `'enum'` \| `'property'` |
151
+ | `filePath` | `string?` | Filter by file path |
152
+ | `isExported` | `boolean?` | Filter by export status |
153
+ | `project` | `string?` | Project name (monorepo) |
154
+ | `limit` | `number?` | Max results (default: `100`) |
155
+
156
+ Returns `SymbolSearchResult[]`
157
+
158
+ ```ts
159
+ interface SymbolSearchResult {
160
+ id: number;
161
+ filePath: string;
162
+ kind: SymbolKind;
163
+ name: string;
164
+ span: {
165
+ start: { line: number; column: number };
166
+ end: { line: number; column: number };
167
+ };
168
+ isExported: boolean;
169
+ signature: string | null;
170
+ fingerprint: string | null;
171
+ detail: Record<string, unknown>;
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ### `ledger.searchRelations(query)`
178
+
179
+ Search cross-file relationships by source/destination file, symbol name, or relation type.
180
+
181
+ ```ts
182
+ // All imports from a file
183
+ const imports = ledger.searchRelations({
184
+ srcFilePath: 'src/app.ts',
185
+ type: 'imports',
186
+ });
187
+
188
+ // Find callers of a specific function
189
+ const callers = ledger.searchRelations({
190
+ dstSymbolName: 'processOrder',
191
+ type: 'calls',
192
+ });
193
+ ```
194
+
195
+ #### RelationSearchQuery
196
+
197
+ | Field | Type | Description |
198
+ |-------|------|-------------|
199
+ | `srcFilePath` | `string?` | Source file path |
200
+ | `srcSymbolName` | `string?` | Source symbol name |
201
+ | `dstFilePath` | `string?` | Destination file path |
202
+ | `dstSymbolName` | `string?` | Destination symbol name |
203
+ | `type` | `'imports'` \| `'calls'` \| `'extends'` \| `'implements'`? | Relation type |
204
+ | `project` | `string?` | Project name |
205
+ | `limit` | `number?` | Max results (default: `500`) |
206
+
207
+ Returns `CodeRelation[]`
208
+
209
+ ```ts
210
+ interface CodeRelation {
211
+ type: 'imports' | 'calls' | 'extends' | 'implements';
212
+ srcFilePath: string;
213
+ srcSymbolName: string | null; // null = module-level
214
+ dstFilePath: string;
215
+ dstSymbolName: string | null;
216
+ metaJson?: string;
217
+ }
218
+ ```
219
+
220
+ ---
221
+
222
+ ### `ledger.getDependencies(filePath, project?)`
223
+
224
+ Returns files that the given file imports.
225
+
226
+ ```ts
227
+ const deps = ledger.getDependencies('src/app.ts');
228
+ // → ['src/utils.ts', 'src/config.ts', ...]
229
+ ```
230
+
231
+ Returns `string[]`
232
+
233
+ ---
234
+
235
+ ### `ledger.getDependents(filePath, project?)`
236
+
237
+ Returns files that import the given file.
238
+
239
+ ```ts
240
+ const dependents = ledger.getDependents('src/utils.ts');
241
+ // → ['src/app.ts', 'src/services/user.ts', ...]
242
+ ```
243
+
244
+ Returns `string[]`
245
+
246
+ ---
247
+
248
+ ### `ledger.getAffected(changedFiles, project?)`
249
+
250
+ Computes the full transitive set of files affected by file changes.
251
+
252
+ ```ts
253
+ const affected = await ledger.getAffected(['src/utils.ts']);
254
+ // → ['src/app.ts', 'src/services/user.ts', 'src/main.ts', ...]
255
+ ```
256
+
257
+ Returns `Promise<string[]>`
258
+
259
+ ---
260
+
261
+ ### `ledger.hasCycle(project?)`
262
+
263
+ Detects circular dependencies in the import graph.
264
+
265
+ ```ts
266
+ if (await ledger.hasCycle()) {
267
+ console.warn('Circular dependency detected');
268
+ }
269
+ ```
270
+
271
+ Returns `Promise<boolean>`
272
+
273
+ ---
274
+
275
+ ### `ledger.reindex()`
276
+
277
+ Forces a full re-index. Only available when the instance holds the owner role.
278
+
279
+ ```ts
280
+ const result = await ledger.reindex();
281
+ console.log(`Indexed ${result.indexedFiles} files in ${result.durationMs}ms`);
282
+ ```
283
+
284
+ Returns `Promise<IndexResult>`
285
+
286
+ ```ts
287
+ interface IndexResult {
288
+ indexedFiles: number;
289
+ removedFiles: number;
290
+ totalSymbols: number;
291
+ totalRelations: number;
292
+ durationMs: number;
293
+ changedFiles: string[];
294
+ deletedFiles: string[];
295
+ failedFiles: string[];
296
+ }
297
+ ```
298
+
299
+ ---
300
+
301
+ ### `ledger.onIndexed(callback)`
302
+
303
+ Subscribes to index-complete events. Returns an unsubscribe function.
304
+
305
+ ```ts
306
+ const unsubscribe = ledger.onIndexed((result) => {
307
+ console.log(`Indexed ${result.indexedFiles} files`);
308
+ });
309
+
310
+ // Later
311
+ unsubscribe();
312
+ ```
313
+
314
+ Returns `() => void`
315
+
316
+ ---
317
+
318
+ ### `ledger.projects`
319
+
320
+ Detected project boundaries. In a monorepo, multiple projects are discovered automatically from `package.json` files.
321
+
322
+ ```ts
323
+ const boundaries = ledger.projects;
324
+ // → [{ dir: '.', project: 'my-app' }, { dir: 'packages/core', project: '@my/core' }]
325
+ ```
326
+
327
+ Type: `ProjectBoundary[]`
328
+
329
+ ```ts
330
+ interface ProjectBoundary {
331
+ dir: string;
332
+ project: string;
333
+ }
334
+ ```
335
+
336
+ ---
337
+
338
+ ### `ledger.getStats(project?)`
339
+
340
+ Returns symbol count statistics.
341
+
342
+ ```ts
343
+ const stats = ledger.getStats();
344
+ // → { symbolCount: 1234, fileCount: 56 }
345
+ ```
346
+
347
+ Returns `SymbolStats`
348
+
349
+ ```ts
350
+ interface SymbolStats {
351
+ symbolCount: number;
352
+ fileCount: number;
353
+ }
354
+ ```
355
+
356
+ ---
357
+
358
+ ### `ledger.parseSource(filePath, sourceText)`
359
+
360
+ Parses a TypeScript file and caches the AST internally.
361
+
362
+ ```ts
363
+ const parsed = ledger.parseSource('src/foo.ts', sourceCode);
364
+ ```
365
+
366
+ Returns `ParsedFile`
367
+
368
+ ---
369
+
370
+ ### `ledger.extractSymbols(parsed)`
371
+
372
+ Extracts symbols from a parsed file.
373
+
374
+ ```ts
375
+ const symbols = ledger.extractSymbols(parsed);
376
+ ```
377
+
378
+ Returns `ExtractedSymbol[]`
379
+
380
+ ---
381
+
382
+ ### `ledger.extractRelations(parsed)`
383
+
384
+ Extracts cross-file relations from a parsed file.
385
+
386
+ ```ts
387
+ const relations = ledger.extractRelations(parsed);
388
+ ```
389
+
390
+ Returns `CodeRelation[]`
391
+
392
+ ---
393
+
394
+ ### `ledger.close()`
395
+
396
+ Graceful shutdown. Stops the watcher, releases the database, and removes signal handlers.
397
+
398
+ ```ts
399
+ await ledger.close();
400
+ ```
401
+
402
+ Returns `Promise<void>`
403
+
404
+ <br>
405
+
406
+ ## Errors
407
+
408
+ All errors extend `GildashError`, which extends `Error`.
409
+
410
+ | Class | When |
411
+ |-------|------|
412
+ | `GildashError` | Base class for all errors |
413
+ | `WatcherError` | File watcher start/stop failure |
414
+ | `ParseError` | AST parsing failure |
415
+ | `ExtractError` | Symbol/relation extraction failure |
416
+ | `IndexError` | Indexing pipeline failure |
417
+ | `StoreError` | Database operation failure |
418
+ | `SearchError` | Search query failure |
419
+
420
+ <br>
421
+
422
+ ## Architecture
423
+
424
+ ```
425
+ Gildash (Facade)
426
+ ├── Parser — oxc-parser-based TypeScript AST parser
427
+ ├── Extractor — Symbol & relation extraction (imports, calls, heritage)
428
+ ├── Store — bun:sqlite + drizzle-orm (files, symbols, relations, FTS5)
429
+ ├── Indexer — Change detection → parse → extract → store pipeline
430
+ ├── Search — Symbol search, relation search, dependency graph
431
+ └── Watcher — @parcel/watcher + owner/reader role management
432
+ ```
433
+
434
+ ### Owner / Reader Pattern
435
+
436
+ When multiple processes share the same SQLite database, a single-writer guarantee is enforced.
437
+
438
+ - **Owner** — Runs the file watcher, performs indexing, sends a heartbeat every 30 s
439
+ - **Reader** — Read-only access; polls owner status every 60 s and self-promotes if the owner goes stale
440
+
441
+ <br>
442
+
443
+ ## License
444
+
445
+ [MIT](./LICENSE) © [zipbul](https://github.com/zipbul)
@@ -0,0 +1 @@
1
+ export * from "./src/index";