@zipbul/gildash 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +6 -10
- package/README.md +6 -10
- package/dist/index.js +5 -5
- package/dist/index.js.map +5 -5
- package/dist/src/gildash.d.ts +15 -27
- package/dist/src/parser/parse-source.d.ts +2 -1
- package/dist/src/search/dependency-graph.d.ts +10 -2
- package/package.json +2 -2
package/README.ko.md
CHANGED
|
@@ -17,7 +17,6 @@ gildash는 TypeScript 코드베이스를 로컬 SQLite 데이터베이스에 인
|
|
|
17
17
|
| "이 모듈을 바꾸면 어디가 깨지지?" | 방향 import 그래프 + 전이적(transitive) 영향도 분석 |
|
|
18
18
|
| "순환 의존성이 있나?" | 전체 import 그래프에서 순환 감지 |
|
|
19
19
|
| "이 심볼이 실제로 어디서 정의된 거지?" | re-export 체인을 따라가 원본 소스까지 추적 |
|
|
20
|
-
| "사용되지 않는 export는?" | 프로젝트 전체에서 미사용 export 탐지 |
|
|
21
20
|
| "모든 `console.log(...)` 호출을 찾아줘" | [ast-grep](https://ast-grep.github.io/) 기반 AST 레벨 구조적 패턴 검색 |
|
|
22
21
|
|
|
23
22
|
<br>
|
|
@@ -137,19 +136,17 @@ const transitive = await ledger.getTransitiveDependencies('src/app.ts');
|
|
|
137
136
|
|
|
138
137
|
// 순환 의존성 감지
|
|
139
138
|
const hasCycles = await ledger.hasCycle();
|
|
140
|
-
const cyclePaths = await ledger.getCyclePaths();
|
|
139
|
+
const cyclePaths = await ledger.getCyclePaths(); // 모든 elementary circuit
|
|
140
|
+
const limited = await ledger.getCyclePaths(undefined, { maxCycles: 100 }); // undefined = 기본 프로젝트 사용
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
|
145
145
|
### 코드 품질 분석
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
모듈 인터페이스 조회, 결합도 측정을 수행합니다.
|
|
148
148
|
|
|
149
149
|
```ts
|
|
150
|
-
// 미사용 export — 어디에서도 import되지 않은 exported 심볼
|
|
151
|
-
const dead = ledger.getDeadExports();
|
|
152
|
-
|
|
153
150
|
// 파일 통계 — 라인 수, 심볼 수, 파일 크기
|
|
154
151
|
const stats = ledger.getFileStats('src/app.ts');
|
|
155
152
|
|
|
@@ -257,7 +254,7 @@ if (isErr(result)) {
|
|
|
257
254
|
| `getDependents(filePath)` | `Result<string[]>` | `filePath`를 import하는 파일 목록 |
|
|
258
255
|
| `getAffected(changedFiles)` | `Promise<Result<string[]>>` | 전이적 영향 범위 |
|
|
259
256
|
| `hasCycle(project?)` | `Promise<Result<boolean>>` | 순환 의존성 감지 |
|
|
260
|
-
| `getCyclePaths(project?)` | `Promise<Result<string[][]>>` | 모든 순환 경로 |
|
|
257
|
+
| `getCyclePaths(project?, opts?)` | `Promise<Result<string[][]>>` | 모든 순환 경로 (Tarjan SCC + Johnson's). `opts.maxCycles`로 개수 제한 가능. |
|
|
261
258
|
| `getImportGraph(project?)` | `Promise<Result<Map>>` | 전체 인접 리스트 |
|
|
262
259
|
| `getTransitiveDependencies(filePath)` | `Promise<Result<string[]>>` | 전방 전이적 BFS |
|
|
263
260
|
|
|
@@ -265,7 +262,6 @@ if (isErr(result)) {
|
|
|
265
262
|
|
|
266
263
|
| 메서드 | 반환 타입 | 설명 |
|
|
267
264
|
|--------|-----------|------|
|
|
268
|
-
| `getDeadExports(project?, opts?)` | `Result<Array>` | 미사용 exported 심볼 |
|
|
269
265
|
| `getFullSymbol(name, filePath)` | `Result<FullSymbol>` | 멤버, jsDoc, 데코레이터, 타입 정보 |
|
|
270
266
|
| `getFileStats(filePath)` | `Result<FileStats>` | 라인 수, 심볼 수, 파일 크기 |
|
|
271
267
|
| `getFanMetrics(filePath)` | `Promise<Result<FanMetrics>>` | fan-in/fan-out 결합도 |
|
|
@@ -281,7 +277,7 @@ if (isErr(result)) {
|
|
|
281
277
|
| `resolveSymbol(name, filePath)` | `Result<ResolvedSymbol>` | re-export 체인을 따라 원본 추적 |
|
|
282
278
|
| `getHeritageChain(name, filePath)` | `Promise<Result<HeritageNode>>` | extends/implements 트리 |
|
|
283
279
|
| `indexExternalPackages(packages)` | `Promise<Result<IndexResult[]>>` | `node_modules`의 `.d.ts` 인덱싱 |
|
|
284
|
-
| `batchParse(filePaths)` | `Promise<Result<Map>>` | 다중 파일 동시
|
|
280
|
+
| `batchParse(filePaths, opts?)` | `Promise<Result<Map>>` | 다중 파일 동시 파싱. `opts`: oxc-parser `ParserOptions`. |
|
|
285
281
|
|
|
286
282
|
### 라이프사이클 & 저수준
|
|
287
283
|
|
|
@@ -289,7 +285,7 @@ if (isErr(result)) {
|
|
|
289
285
|
|--------|-----------|------|
|
|
290
286
|
| `reindex()` | `Promise<Result<IndexResult>>` | 강제 전체 재인덱싱 (owner만 가능) |
|
|
291
287
|
| `onIndexed(callback)` | `() => void` | 인덱싱 완료 이벤트 구독 |
|
|
292
|
-
| `parseSource(filePath, src)` | `Result<ParsedFile>` | 단일 파일 파싱 &
|
|
288
|
+
| `parseSource(filePath, src, opts?)` | `Result<ParsedFile>` | 단일 파일 파싱 & 캐시. `opts`: oxc-parser `ParserOptions`. |
|
|
293
289
|
| `extractSymbols(parsed)` | `Result<ExtractedSymbol[]>` | 파싱된 AST에서 심볼 추출 |
|
|
294
290
|
| `extractRelations(parsed)` | `Result<CodeRelation[]>` | 파싱된 AST에서 관계 추출 |
|
|
295
291
|
| `getParsedAst(filePath)` | `ParsedFile \| undefined` | 캐시된 AST 조회 (읽기 전용) |
|
package/README.md
CHANGED
|
@@ -17,7 +17,6 @@ gildash indexes your TypeScript codebase into a local SQLite database, then lets
|
|
|
17
17
|
| "Which files break if I change this module?" | Directed import graph with transitive impact analysis |
|
|
18
18
|
| "Are there any circular dependencies?" | Cycle detection across the full import graph |
|
|
19
19
|
| "Where is this symbol actually defined?" | Re-export chain resolution to the original source |
|
|
20
|
-
| "Which exports are never imported?" | Dead-export detection across projects |
|
|
21
20
|
| "Find every `console.log(...)` call" | AST-level structural pattern search via [ast-grep](https://ast-grep.github.io/) |
|
|
22
21
|
|
|
23
22
|
<br>
|
|
@@ -137,19 +136,17 @@ const transitive = await ledger.getTransitiveDependencies('src/app.ts');
|
|
|
137
136
|
|
|
138
137
|
// Circular dependency detection
|
|
139
138
|
const hasCycles = await ledger.hasCycle();
|
|
140
|
-
const cyclePaths = await ledger.getCyclePaths();
|
|
139
|
+
const cyclePaths = await ledger.getCyclePaths(); // all elementary circuits
|
|
140
|
+
const limited = await ledger.getCyclePaths(undefined, { maxCycles: 100 }); // undefined = use default project
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
|
145
145
|
### Code Quality Analysis
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
Inspect module interfaces and measure coupling.
|
|
148
148
|
|
|
149
149
|
```ts
|
|
150
|
-
// Dead exports — exported symbols never imported anywhere
|
|
151
|
-
const dead = ledger.getDeadExports();
|
|
152
|
-
|
|
153
150
|
// File statistics — line count, symbol count, size
|
|
154
151
|
const stats = ledger.getFileStats('src/app.ts');
|
|
155
152
|
|
|
@@ -257,7 +254,7 @@ Returns `Promise<Gildash>` (wrapped in `Result`).
|
|
|
257
254
|
| `getDependents(filePath)` | `Result<string[]>` | Files that import `filePath` |
|
|
258
255
|
| `getAffected(changedFiles)` | `Promise<Result<string[]>>` | Transitive impact set |
|
|
259
256
|
| `hasCycle(project?)` | `Promise<Result<boolean>>` | Circular dependency check |
|
|
260
|
-
| `getCyclePaths(project?)` | `Promise<Result<string[][]>>` | All cycle paths |
|
|
257
|
+
| `getCyclePaths(project?, opts?)` | `Promise<Result<string[][]>>` | All cycle paths (Tarjan SCC + Johnson's). `opts.maxCycles` limits results. |
|
|
261
258
|
| `getImportGraph(project?)` | `Promise<Result<Map>>` | Full adjacency list |
|
|
262
259
|
| `getTransitiveDependencies(filePath)` | `Promise<Result<string[]>>` | Forward transitive BFS |
|
|
263
260
|
|
|
@@ -265,7 +262,6 @@ Returns `Promise<Gildash>` (wrapped in `Result`).
|
|
|
265
262
|
|
|
266
263
|
| Method | Returns | Description |
|
|
267
264
|
|--------|---------|-------------|
|
|
268
|
-
| `getDeadExports(project?, opts?)` | `Result<Array>` | Unused exported symbols |
|
|
269
265
|
| `getFullSymbol(name, filePath)` | `Result<FullSymbol>` | Members, jsDoc, decorators, type info |
|
|
270
266
|
| `getFileStats(filePath)` | `Result<FileStats>` | Line count, symbol count, size |
|
|
271
267
|
| `getFanMetrics(filePath)` | `Promise<Result<FanMetrics>>` | Fan-in / fan-out coupling |
|
|
@@ -281,7 +277,7 @@ Returns `Promise<Gildash>` (wrapped in `Result`).
|
|
|
281
277
|
| `resolveSymbol(name, filePath)` | `Result<ResolvedSymbol>` | Follow re-export chain to original |
|
|
282
278
|
| `getHeritageChain(name, filePath)` | `Promise<Result<HeritageNode>>` | extends / implements tree |
|
|
283
279
|
| `indexExternalPackages(packages)` | `Promise<Result<IndexResult[]>>` | Index `.d.ts` from `node_modules` |
|
|
284
|
-
| `batchParse(filePaths)` | `Promise<Result<Map>>` | Concurrent multi-file parsing |
|
|
280
|
+
| `batchParse(filePaths, opts?)` | `Promise<Result<Map>>` | Concurrent multi-file parsing. `opts`: oxc-parser `ParserOptions`. |
|
|
285
281
|
|
|
286
282
|
### Lifecycle & Low-level
|
|
287
283
|
|
|
@@ -289,7 +285,7 @@ Returns `Promise<Gildash>` (wrapped in `Result`).
|
|
|
289
285
|
|--------|---------|-------------|
|
|
290
286
|
| `reindex()` | `Promise<Result<IndexResult>>` | Force full re-index (owner only) |
|
|
291
287
|
| `onIndexed(callback)` | `() => void` | Subscribe to index-complete events |
|
|
292
|
-
| `parseSource(filePath, src)` | `Result<ParsedFile>` | Parse & cache a single file |
|
|
288
|
+
| `parseSource(filePath, src, opts?)` | `Result<ParsedFile>` | Parse & cache a single file. `opts`: oxc-parser `ParserOptions`. |
|
|
293
289
|
| `extractSymbols(parsed)` | `Result<ExtractedSymbol[]>` | Extract symbols from parsed AST |
|
|
294
290
|
| `extractRelations(parsed)` | `Result<CodeRelation[]>` | Extract relations from parsed AST |
|
|
295
291
|
| `getParsedAst(filePath)` | `ParsedFile \| undefined` | Cached AST lookup (read-only) |
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
`)t.push(e+1);return t}function An(n,t){let e=0,i=n.length-1;while(e<i){let r=e+i+1>>1;if(n[r]<=t)e=r;else i=r-1}return{line:e+1,column:t-n[e]}}import{err as wt}from"@zipbul/result";import{parse as St}from"comment-parser";function Qn(n){try{let t=n.trim();if(t.startsWith("/**"))t=t.slice(3);if(t.endsWith("*/"))t=t.slice(0,-2);let i=St(`/** ${t} */`)[0]??{description:"",tags:[]};return{description:(i.description??"").trim(),tags:(i.tags??[]).map((r)=>({tag:r.tag??"",name:r.name??"",type:r.type??"",description:r.description??"",optional:r.optional??!1,...r.default!==void 0?{default:r.default}:{}}))}}catch(t){return wt(d("parse","Failed to parse JSDoc comment",t))}}import{isErr as Ot}from"@zipbul/result";function ln(n){let{program:t,sourceText:e,comments:i}=n,r=Un(e);function s(l,g){return{start:An(r,l),end:An(r,g)}}function u(l){let g=null;for(let o of i){if(o.type!=="Block")continue;if(o.end>l)continue;if(!o.value.startsWith("*"))continue;if(!g||o.end>g.end)g={value:`/*${o.value}*/`,end:o.end}}if(!g)return;for(let o of t.body){let c=o.start??0;if(c===l)continue;if(c>g.end&&c<l)return}return g.value}function m(l){if(!l)return;let g=l.typeAnnotation??l;return e.slice(g.start,g.end)}function a(l){if(!l||l.length===0)return[];return l.map((g)=>{let o=g.expression;if(!o)return{name:"unknown"};if(o.type==="CallExpression"){let c=o.callee?.name??o.callee?.property?.name??"unknown",f=(o.arguments??[]).map((O)=>e.slice(O.start,O.end));return{name:c,arguments:f.length>0?f:void 0}}if(o.type==="Identifier")return{name:o.name??"unknown"};return{name:e.slice(o.start,o.end)}})}function x(l){let g=l.type==="TSParameterProperty"?l.parameter:l;if(g?.type==="RestElement"){let k=`...${g.argument?.name??"unknown"}`,J=g.typeAnnotation,K=J?m(J):void 0,I={name:k,isOptional:!1};if(K)I.type=K;return I}if(g?.type==="AssignmentPattern"){let{left:h,right:k}=g,J=h?.name??"unknown",K=h?.typeAnnotation,I=K?m(K):void 0,$=e.slice(k.start,k.end),rn=a(h?.decorators??[]),Z={name:J,isOptional:!0,defaultValue:$};if(I)Z.type=I;if(rn.length>0)Z.decorators=rn;return Z}let o=g?.name??g?.pattern?.name??"unknown",c=!!g?.optional,f=g?.typeAnnotation,O=f?m(f):void 0,A=a(g?.decorators??[]),C={name:o,isOptional:c};if(O)C.type=O;if(A.length>0)C.decorators=A;return C}function p(l,g){let o=[];if(g?.async)o.push("async");if(l.static)o.push("static");if(l.abstract)o.push("abstract");if(l.readonly)o.push("readonly");if(l.override)o.push("override");if(l.declare)o.push("declare");if(l.const)o.push("const");let c=l.accessibility;if(c==="private")o.push("private");else if(c==="protected")o.push("protected");else if(c==="public")o.push("public");return o}function y(l){let g=[];if(l.superClass){let c=e.slice(l.superClass.start,l.superClass.end);g.push({kind:"extends",name:c})}let o=l.implements??[];for(let c of o){let f=c.expression??c,O=e.slice(f.start,f.end);g.push({kind:"implements",name:O})}return g}function w(l){let g=[];for(let o of l.extends??[]){let c=o.expression??o,f=e.slice(c.start,c.end);g.push({kind:"extends",name:f})}return g}function N(l){let g=[];for(let o of l)if(o.type==="MethodDefinition"){let c=o.key?.name??"unknown",f=o.value,O=o.kind??"method",A=O==="constructor"?"constructor":O==="get"?"getter":O==="set"?"setter":"method",C=p(o,f),h=(f?.params??[]).map(x),k=m(f?.returnType),J={kind:"method",name:c,span:s(o.start,o.end),isExported:!1,methodKind:A,modifiers:C,parameters:h.length>0?h:void 0,returnType:k};g.push(J)}else if(o.type==="PropertyDefinition"){let c=o.key?.name??"unknown",f=p(o),O={kind:"property",name:c,span:s(o.start,o.end),isExported:!1,modifiers:f};g.push(O)}return g}function _(l){let g=[];for(let o of l)if(o.type==="TSMethodSignature"){let c=o.key?.name??"unknown",f=(o.params??[]).map(x),O=m(o.returnType);g.push({kind:"method",name:c,span:s(o.start,o.end),isExported:!1,modifiers:[],methodKind:"method",parameters:f.length>0?f:void 0,returnType:O})}else if(o.type==="TSPropertySignature"){let c=o.key?.name??"unknown",f=m(o.typeAnnotation),O={kind:"property",name:c,span:s(o.start,o.end),isExported:!1,modifiers:o.readonly?["readonly"]:[],returnType:f};g.push(O)}return g}function D(l,g){let o=l.type??"";if(o==="FunctionDeclaration"){let c=l.id?.name??"default",f=(l.params??[]).map(x),O=m(l.returnType),A=p(l,l),C=a(l.decorators??[]),h=l.typeParameters?.params?.map((J)=>J.name?.name).filter(Boolean)||void 0,k={kind:"function",name:c,span:s(l.start,l.end),isExported:g,modifiers:A,parameters:f.length>0?f:void 0,returnType:O,decorators:C.length>0?C:void 0};if(h&&h.length>0)k.typeParameters=h;return k}if(o==="ClassDeclaration"||o==="ClassExpression"){let c=l.id?.name??"default",f=y(l),O=N(l.body?.body??[]),A=a(l.decorators??[]),C=p(l,l),h=l.typeParameters?.params?.map((J)=>J.name?.name).filter(Boolean)||void 0,k={kind:"class",name:c,span:s(l.start,l.end),isExported:g,modifiers:C,heritage:f.length>0?f:void 0,members:O.length>0?O:void 0,decorators:A.length>0?A:void 0};if(h&&h.length>0)k.typeParameters=h;return k}if(o==="VariableDeclaration"){let c=[];for(let f of l.declarations??[]){let{id:O,init:A}=f;if(O?.type==="ObjectPattern"){for(let I of O.properties??[]){let $=I.value?.name??I.key?.name??"unknown";c.push({kind:"variable",name:$,span:s(I.start??f.start,I.end??f.end),isExported:g,modifiers:[]})}continue}if(O?.type==="ArrayPattern"){for(let I of O.elements??[]){if(!I||I.type!=="Identifier")continue;let $=I.name??"unknown";c.push({kind:"variable",name:$,span:s(I.start??f.start,I.end??f.end),isExported:g,modifiers:[]})}continue}let C=O?.name??"unknown",h="variable",k,J;if(A?.type==="FunctionExpression"||A?.type==="ArrowFunctionExpression")h="function",k=(A.params??[]).map(x),J=m(A.returnType);let K=[];c.push({kind:h,name:C,span:s(f.start,f.end),isExported:g,modifiers:K,parameters:k,returnType:J})}if(c.length===0)return null;if(c.length===1)return c[0];return c}if(o==="TSTypeAliasDeclaration")return{kind:"type",name:l.id?.name??"unknown",span:s(l.start,l.end),isExported:g,modifiers:[]};if(o==="TSInterfaceDeclaration"){let c=l.id?.name??"unknown",f=w(l),O=_(l.body?.body??[]),A=l.typeParameters?.params?.map((h)=>h.name?.name).filter(Boolean)||void 0,C={kind:"interface",name:c,span:s(l.start,l.end),isExported:g,modifiers:[],heritage:f.length>0?f:void 0,members:O.length>0?O:void 0};if(A&&A.length>0)C.typeParameters=A;return C}if(o==="TSEnumDeclaration"){let c=l.id?.name??"unknown",f=p(l),A=(l.body?.members??[]).map((C)=>({kind:"property",name:C.id?.name??C.id?.value??"unknown",span:s(C.start,C.end),isExported:!1,modifiers:[]}));return{kind:"enum",name:c,span:s(l.start,l.end),isExported:g,modifiers:f,members:A.length>0?A:void 0}}return null}let M=[];for(let l of t.body){let g=null,o=l,c=typeof o.type==="string"?o.type:"";if(c==="ExportNamedDeclaration"){let O=l;if(O.declaration){if(g=D(O.declaration,!0),g&&!Array.isArray(g))g.span=s(O.start,O.end);else if(Array.isArray(g))for(let A of g)A.span=s(O.start,O.end)}}else if(c==="ExportDefaultDeclaration"){let O=l,A=O.declaration;if(A){if(g=D(A,!0),g&&!Array.isArray(g))g.name=A.id?.name??"default",g.isExported=!0,g.span=s(O.start,O.end)}}else g=D(l,!1);let f=Array.isArray(g)?g:g?[g]:[];for(let O of f){let A=l.start??0,C=u(A);if(C){let h=Qn(C);if(!Ot(h))O.jsDoc=h}M.push(O)}}return M}import{resolve as Dn,dirname as Nt,extname as kt}from"path";function hn(n,t,e){let i=(r)=>{let s=kt(r);if(s==="")return[r+".ts",r+"/index.ts",r+".mts",r+"/index.mts",r+".cts",r+"/index.cts"];if(s===".js")return[r.slice(0,-3)+".ts"];if(s===".mjs")return[r.slice(0,-4)+".mts"];if(s===".cjs")return[r.slice(0,-4)+".cts"];return[r]};if(t.startsWith(".")){let r=Dn(Nt(n),t);return i(r)}if(e)for(let[r,s]of e.paths){if(s.length===0)continue;let u=r.indexOf("*");if(u===-1){if(t===r){let m=[];for(let a of s)m.push(...i(Dn(e.baseUrl,a)));return m}}else{let m=r.slice(0,u),a=r.slice(u+1);if(t.startsWith(m)&&(a===""||t.endsWith(a))){let x=t.slice(m.length,a===""?void 0:t.length-a.length),p=[];for(let y of s)p.push(...i(Dn(e.baseUrl,y.replace("*",x))));return p}}}return[]}function Vn(n,t,e,i=hn){let r=new Map,s=n.body??[];for(let u of s){if(u.type!=="ImportDeclaration")continue;let m=u.source?.value??"",a=i(t,m,e);if(a.length===0)continue;let x=a[0],p=u.specifiers??[];for(let y of p)switch(y.type){case"ImportSpecifier":r.set(y.local.name,{path:x,importedName:y.imported.name});break;case"ImportDefaultSpecifier":r.set(y.local.name,{path:x,importedName:"default"});break;case"ImportNamespaceSpecifier":r.set(y.local.name,{path:x,importedName:"*"});break}}return r}var At=new Set(["loc","start","end","scope"]);function sn(n,t){if(!n||typeof n!=="object")return;if(Array.isArray(n)){for(let i of n)sn(i,t);return}let e=n;t(e);for(let i of Object.keys(e)){if(At.has(i))continue;let r=e[i];if(r&&typeof r==="object")sn(r,t)}}function Yn(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n;if((t.type==="StringLiteral"||t.type==="Literal")&&typeof t.value==="string")return t.value;return null}function q(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n;if(t.type==="Identifier"){let e=t.name;return{root:e,parts:[],full:e}}if(t.type==="ThisExpression")return{root:"this",parts:[],full:"this"};if(t.type==="Super")return{root:"super",parts:[],full:"super"};if(t.type==="MemberExpression"){let e=[],i=t;while(i.type==="MemberExpression"){let u=i.property;if(!u||typeof u.name!=="string")return null;e.unshift(u.name),i=i.object}let r;if(i.type==="Identifier")r=i.name;else if(i.type==="ThisExpression")r="this";else if(i.type==="Super")r="super";else return null;let s=[r,...e].join(".");return{root:r,parts:e,full:s}}return null}function Zn(n,t,e,i=hn){let r=[],s=n.body??[];for(let u of s){if(u.type==="ImportDeclaration"){let m=u.source?.value??"",a=i(t,m,e);if(a.length===0)continue;let x=a[0],p=u.importKind==="type",y=u.specifiers??[];if(y.length===0){let w={};if(p)w.isType=!0;r.push({type:p?"type-references":"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:x,dstSymbolName:null,...Object.keys(w).length>0?{metaJson:JSON.stringify(w)}:{}})}else for(let w of y){let N=w.type,_=p||w.importKind==="type",D={};if(_)D.isType=!0;let M,l;if(N==="ImportDefaultSpecifier")M="default",l=w.local.name;else if(N==="ImportNamespaceSpecifier")M="*",l=w.local.name,D.importKind="namespace";else M=w.imported.name,l=w.local.name;r.push({type:_?"type-references":"imports",srcFilePath:t,srcSymbolName:l,dstFilePath:x,dstSymbolName:M,...Object.keys(D).length>0?{metaJson:JSON.stringify(D)}:{}})}continue}if(u.type==="ExportAllDeclaration"&&u.source){let m=u.source?.value??"",a=i(t,m,e);if(a.length===0)continue;let x=a[0],p=u.exportKind==="type",y={isReExport:!0};if(p)y.isType=!0;r.push({type:p?"type-references":"re-exports",srcFilePath:t,srcSymbolName:null,dstFilePath:x,dstSymbolName:null,metaJson:JSON.stringify(y)});continue}if(u.type==="ExportNamedDeclaration"&&u.source){let m=u.source?.value??"",a=i(t,m,e);if(a.length===0)continue;let x=a[0],p=u.exportKind==="type",N={isReExport:!0,specifiers:(u.specifiers??[]).map((_)=>({local:_.local.name,exported:_.exported.name}))};if(p)N.isType=!0;r.push({type:p?"type-references":"re-exports",srcFilePath:t,srcSymbolName:null,dstFilePath:x,dstSymbolName:null,metaJson:JSON.stringify(N)})}}return sn(n,(u)=>{if(u.type!=="ImportExpression")return;let m=Yn(u.source);if(!m)return;let a=i(t,m,e);if(a.length===0)return;let x=a[0];r.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:x,dstSymbolName:null,metaJson:JSON.stringify({isDynamic:!0})})}),r}function vn(n,t,e){let i=[],r=[],s=[];function u(){if(r.length>0)return r[r.length-1]??null;return null}function m(x){if(!x)return null;let p=e.get(x.root);if(x.parts.length===0){if(p)return{dstFilePath:p.path,dstSymbolName:p.importedName,resolution:"import"};return{dstFilePath:t,dstSymbolName:x.root,resolution:"local"}}else{if(p&&p.importedName==="*"){let y=x.parts[x.parts.length-1];return{dstFilePath:p.path,dstSymbolName:y,resolution:"namespace"}}return{dstFilePath:t,dstSymbolName:x.full,resolution:"local-member"}}}function a(x){if(!x||typeof x!=="object")return;if(Array.isArray(x)){for(let w of x)a(w);return}let p=x,y=typeof p.type==="string"?p.type:"";if(y==="ClassDeclaration"||y==="ClassExpression"){let w=p,N=w.id?.name??"AnonymousClass";s.push(N),a(w.body),s.pop();return}if(y==="FunctionDeclaration"){let w=p,N=w.id?.name??"anonymous";r.push(N),a(w.body),r.pop();return}if(y==="VariableDeclarator"&&p.init&&(p.init?.type==="FunctionExpression"||p.init?.type==="ArrowFunctionExpression")){let w=p,N=w.id?.name??"anonymous";r.push(N),a(w.init?.body??w.init),r.pop();return}if(y==="MethodDefinition"&&p.value){let w=p,N=s[s.length-1]??"",_=w.key?.name??"anonymous",D=N?`${N}.${_}`:_;r.push(D),a(w.value?.body),r.pop();return}if(y==="FunctionExpression"||y==="ArrowFunctionExpression"){let w=u(),N=w?`${w}.<anonymous>`:"<anonymous>";r.push(N),a(p.body),r.pop();return}if(y==="CallExpression"){let w=p,N=q(w.callee),_=m(N);if(_){let D=u(),M={};if(D===null)M.scope="module";i.push({type:"calls",srcFilePath:t,srcSymbolName:D,dstFilePath:_.dstFilePath,dstSymbolName:_.dstSymbolName,...Object.keys(M).length>0?{metaJson:JSON.stringify(M)}:{}})}a(w.callee);for(let D of w.arguments??[])a(D);return}if(y==="NewExpression"){let w=p,N=q(w.callee),_=m(N);if(_){let D=u(),M={isNew:!0};if(D===null)M.scope="module";i.push({type:"calls",srcFilePath:t,srcSymbolName:D,dstFilePath:_.dstFilePath,dstSymbolName:_.dstSymbolName,metaJson:JSON.stringify(M)})}for(let D of w.arguments??[])a(D);return}for(let w of Object.keys(p)){if(w==="loc"||w==="start"||w==="end"||w==="scope")continue;let N=p[w];if(N&&typeof N==="object")a(N)}}return a(n),i}function Xn(n,t,e){let i=[];return sn(n,(r)=>{if(r.type==="TSInterfaceDeclaration"){let m=r.id?.name??"AnonymousInterface",a=r.extends??[];for(let x of a){let p=x.expression??x,y=q(p);if(!y)continue;let w=Fn(y,t,e);i.push({type:"extends",srcFilePath:t,srcSymbolName:m,...w})}return}if(r.type!=="ClassDeclaration"&&r.type!=="ClassExpression")return;let s=r.id?.name??"AnonymousClass";if(r.superClass){let m=q(r.superClass);if(m){let a=Fn(m,t,e);i.push({type:"extends",srcFilePath:t,srcSymbolName:s,...a})}}let u=r.implements??[];for(let m of u){let a=m.expression??m,x=q(a);if(!x)continue;let p=Fn(x,t,e);i.push({type:"implements",srcFilePath:t,srcSymbolName:s,...p})}}),i}function Fn(n,t,e){let i=e.get(n.root);if(i){if(i.importedName==="*"){let r=n.parts[n.parts.length-1]??n.root;return{dstFilePath:i.path,dstSymbolName:r,metaJson:JSON.stringify({isNamespaceImport:!0})}}return{dstFilePath:i.path,dstSymbolName:n.parts.length>0?n.full:i.importedName}}return{dstFilePath:t,dstSymbolName:n.full,metaJson:JSON.stringify({isLocal:!0})}}function pn(n,t,e){let i=Vn(n,t,e),r=Zn(n,t,e),s=vn(n,t,i),u=Xn(n,t,i);return[...r,...s,...u]}import{err as Pn,isErr as Mt}from"@zipbul/result";import{Database as Jt}from"bun:sqlite";import{mkdirSync as Kt,unlinkSync as En,existsSync as jn}from"fs";import{dirname as It,join as qn}from"path";import{drizzle as Rt}from"drizzle-orm/bun-sqlite";import{migrate as zt}from"drizzle-orm/bun-sqlite/migrator";var Cn={};xt(Cn,{watcherOwner:()=>Ct,symbols:()=>F,relations:()=>b,files:()=>L});import{sql as Dt}from"drizzle-orm";import{sqliteTable as fn,text as T,integer as H,real as ht,index as nn,primaryKey as Ft,foreignKey as _n,check as _t}from"drizzle-orm/sqlite-core";var L=fn("files",{project:T("project").notNull(),filePath:T("file_path").notNull(),mtimeMs:ht("mtime_ms").notNull(),size:H("size").notNull(),contentHash:T("content_hash").notNull(),updatedAt:T("updated_at").notNull(),lineCount:H("line_count")},(n)=>[Ft({columns:[n.project,n.filePath]})]),F=fn("symbols",{id:H("id").primaryKey({autoIncrement:!0}),project:T("project").notNull(),filePath:T("file_path").notNull(),kind:T("kind").notNull(),name:T("name").notNull(),startLine:H("start_line").notNull(),startColumn:H("start_column").notNull(),endLine:H("end_line").notNull(),endColumn:H("end_column").notNull(),isExported:H("is_exported").notNull().default(0),signature:T("signature"),fingerprint:T("fingerprint"),detailJson:T("detail_json"),contentHash:T("content_hash").notNull(),indexedAt:T("indexed_at").notNull()},(n)=>[nn("idx_symbols_project_file").on(n.project,n.filePath),nn("idx_symbols_project_kind").on(n.project,n.kind),nn("idx_symbols_project_name").on(n.project,n.name),nn("idx_symbols_fingerprint").on(n.project,n.fingerprint),_n({columns:[n.project,n.filePath],foreignColumns:[L.project,L.filePath]}).onDelete("cascade")]),b=fn("relations",{id:H("id").primaryKey({autoIncrement:!0}),project:T("project").notNull(),type:T("type").notNull(),srcFilePath:T("src_file_path").notNull(),srcSymbolName:T("src_symbol_name"),dstFilePath:T("dst_file_path").notNull(),dstSymbolName:T("dst_symbol_name"),metaJson:T("meta_json")},(n)=>[nn("idx_relations_src").on(n.project,n.srcFilePath),nn("idx_relations_dst").on(n.project,n.dstFilePath),nn("idx_relations_type").on(n.project,n.type),_n({columns:[n.project,n.srcFilePath],foreignColumns:[L.project,L.filePath]}).onDelete("cascade"),_n({columns:[n.project,n.dstFilePath],foreignColumns:[L.project,L.filePath]}).onDelete("cascade")]),Ct=fn("watcher_owner",{id:H("id").primaryKey(),pid:H("pid").notNull(),startedAt:T("started_at").notNull(),heartbeatAt:T("heartbeat_at").notNull()},(n)=>[_t("watcher_owner_singleton",Dt`${n.id} = 1`)]);class Mn{client=null;drizzle=null;dbPath;txDepth=0;constructor(n){this.dbPath=qn(n.projectRoot,".zipbul","gildash.db")}get drizzleDb(){if(!this.drizzle)throw Error("Database is not open. Call open() first.");return this.drizzle}open(){try{Kt(It(this.dbPath),{recursive:!0}),this.client=new Jt(this.dbPath),this.client.run("PRAGMA journal_mode = WAL"),this.client.run("PRAGMA foreign_keys = ON"),this.client.run("PRAGMA busy_timeout = 5000"),this.drizzle=Rt(this.client,{schema:Cn}),zt(this.drizzle,{migrationsFolder:qn(import.meta.dirname,"migrations")});let n=this.client;if(typeof n.function==="function")n.function.call(this.client,"regexp",(t,e)=>{try{return new RegExp(t).test(e)?1:0}catch{return 0}})}catch(n){if(this.isCorruptionError(n)&&jn(this.dbPath)){this.closeClient(),En(this.dbPath);for(let e of["-wal","-shm"]){let i=this.dbPath+e;if(jn(i))En(i)}let t=this.open();if(Mt(t))return Pn(d("store",`Failed to recover database at ${this.dbPath}`,t.data));return t}return Pn(d("store",`Failed to open database at ${this.dbPath}`,n))}}close(){this.closeClient(),this.drizzle=null}transaction(n){let t=this.requireClient();if(this.txDepth===0){this.txDepth++;try{return t.transaction(()=>n(this))()}finally{this.txDepth--}}let e=`sp_${this.txDepth++}`;t.run(`SAVEPOINT "${e}"`);try{let i=n(this);return t.run(`RELEASE SAVEPOINT "${e}"`),i}catch(i){throw t.run(`ROLLBACK TO SAVEPOINT "${e}"`),t.run(`RELEASE SAVEPOINT "${e}"`),i}finally{this.txDepth--}}immediateTransaction(n){let t=this.requireClient();this.txDepth++,t.run("BEGIN IMMEDIATE");try{let e=n();return t.run("COMMIT"),e}catch(e){throw t.run("ROLLBACK"),e}finally{this.txDepth--}}query(n){let t=this.requireClient().prepare(n).get();if(!t)return null;return Object.values(t)[0]}getTableNames(){return this.requireClient().query("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((t)=>t.name)}selectOwner(){return this.requireClient().prepare("SELECT pid, heartbeat_at FROM watcher_owner WHERE id = 1").get()??void 0}insertOwner(n){let t=new Date().toISOString();this.requireClient().prepare("INSERT INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(n,t,t)}replaceOwner(n){let t=new Date().toISOString();this.requireClient().prepare("INSERT OR REPLACE INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(n,t,t)}touchOwner(n){let t=new Date().toISOString();this.requireClient().prepare("UPDATE watcher_owner SET heartbeat_at = ? WHERE id = 1 AND pid = ?").run(t,n)}deleteOwner(n){this.requireClient().prepare("DELETE FROM watcher_owner WHERE id = 1 AND pid = ?").run(n)}requireClient(){if(!this.client)throw Error("Database is not open. Call open() first.");return this.client}closeClient(){if(this.client)this.client.close(),this.client=null}isCorruptionError(n){if(!(n instanceof Error))return!1;let t=n.message.toLowerCase();return t.includes("malformed")||t.includes("corrupt")||t.includes("not a database")||t.includes("disk i/o error")||t.includes("sqlite_corrupt")}}import{eq as un,and as nt}from"drizzle-orm";class Jn{db;constructor(n){this.db=n}getFile(n,t){return this.db.drizzleDb.select().from(L).where(nt(un(L.project,n),un(L.filePath,t))).get()??null}upsertFile(n){this.db.drizzleDb.insert(L).values({project:n.project,filePath:n.filePath,mtimeMs:n.mtimeMs,size:n.size,contentHash:n.contentHash,updatedAt:n.updatedAt,lineCount:n.lineCount??null}).onConflictDoUpdate({target:[L.project,L.filePath],set:{mtimeMs:n.mtimeMs,size:n.size,contentHash:n.contentHash,updatedAt:n.updatedAt,lineCount:n.lineCount??null}}).run()}getAllFiles(n){return this.db.drizzleDb.select().from(L).where(un(L.project,n)).all()}getFilesMap(n){let t=this.getAllFiles(n),e=new Map;for(let i of t)e.set(i.filePath,i);return e}deleteFile(n,t){this.db.drizzleDb.delete(L).where(nt(un(L.project,n),un(L.filePath,t))).run()}}import{eq as B,and as tn,sql as dn,count as Tt}from"drizzle-orm";function gn(n){return n.trim().split(/\s+/).map((t)=>t.trim()).filter((t)=>t.length>0).map((t)=>`"${t.replaceAll('"','""')}"*`).join(" ")}class Kn{db;constructor(n){this.db=n}replaceFileSymbols(n,t,e,i){if(this.db.drizzleDb.delete(F).where(tn(B(F.project,n),B(F.filePath,t))).run(),!i.length)return;let r=new Date().toISOString();for(let s of i)this.db.drizzleDb.insert(F).values({project:n,filePath:t,kind:s.kind??"unknown",name:s.name??"",startLine:s.startLine??0,startColumn:s.startColumn??0,endLine:s.endLine??0,endColumn:s.endColumn??0,isExported:s.isExported??0,signature:s.signature??null,fingerprint:s.fingerprint??null,detailJson:s.detailJson??null,contentHash:e,indexedAt:s.indexedAt??r}).run()}getFileSymbols(n,t){return this.db.drizzleDb.select().from(F).where(tn(B(F.project,n),B(F.filePath,t))).all()}searchByName(n,t,e={}){let i=e.limit??50,r=gn(t);if(!r)return[];return this.db.drizzleDb.select().from(F).where(tn(dn`${F.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${r})`,B(F.project,n),e.kind?B(F.kind,e.kind):void 0)).orderBy(F.name).limit(i).all()}searchByKind(n,t){return this.db.drizzleDb.select().from(F).where(tn(B(F.project,n),B(F.kind,t))).orderBy(F.name).all()}getStats(n){let t=this.db.drizzleDb.select({symbolCount:Tt(),fileCount:dn`COUNT(DISTINCT ${F.filePath})`}).from(F).where(B(F.project,n)).get();return{symbolCount:t?.symbolCount??0,fileCount:t?.fileCount??0}}getByFingerprint(n,t){return this.db.drizzleDb.select().from(F).where(tn(B(F.project,n),B(F.fingerprint,t))).all()}deleteFileSymbols(n,t){this.db.drizzleDb.delete(F).where(tn(B(F.project,n),B(F.filePath,t))).run()}searchByQuery(n){let t=this.db.drizzleDb.select().from(F).where(tn(n.ftsQuery?dn`${F.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${n.ftsQuery})`:void 0,n.exactName?B(F.name,n.exactName):void 0,n.project!==void 0?B(F.project,n.project):void 0,n.kind?B(F.kind,n.kind):void 0,n.filePath!==void 0?B(F.filePath,n.filePath):void 0,n.isExported!==void 0?B(F.isExported,n.isExported?1:0):void 0,n.decorator?dn`${F.id} IN (SELECT s.id FROM symbols s, json_each(s.detail_json, '$.decorators') je WHERE json_extract(je.value, '$.name') = ${n.decorator})`:void 0)).orderBy(F.name).limit(n.regex?Math.max(n.limit*50,5000):n.limit).all();if(!n.regex)return t;try{let e=new RegExp(n.regex);return t.filter((i)=>e.test(i.name)).slice(0,n.limit)}catch{return[]}}}import{eq as z,and as V,isNull as tt,or as Lt}from"drizzle-orm";class In{db;constructor(n){this.db=n}replaceFileRelations(n,t,e){if(this.db.drizzleDb.delete(b).where(V(z(b.project,n),z(b.srcFilePath,t))).run(),!e.length)return;for(let i of e)this.db.drizzleDb.insert(b).values({project:n,type:i.type??"unknown",srcFilePath:i.srcFilePath??t,srcSymbolName:i.srcSymbolName??null,dstFilePath:i.dstFilePath??"",dstSymbolName:i.dstSymbolName??null,metaJson:i.metaJson??null}).run()}getOutgoing(n,t,e){if(e!==void 0)return this.db.drizzleDb.select({project:b.project,type:b.type,srcFilePath:b.srcFilePath,srcSymbolName:b.srcSymbolName,dstFilePath:b.dstFilePath,dstSymbolName:b.dstSymbolName,metaJson:b.metaJson}).from(b).where(V(z(b.project,n),z(b.srcFilePath,t),Lt(z(b.srcSymbolName,e),tt(b.srcSymbolName)))).all();return this.db.drizzleDb.select({project:b.project,type:b.type,srcFilePath:b.srcFilePath,srcSymbolName:b.srcSymbolName,dstFilePath:b.dstFilePath,dstSymbolName:b.dstSymbolName,metaJson:b.metaJson}).from(b).where(V(z(b.project,n),z(b.srcFilePath,t))).all()}getIncoming(n,t){return this.db.drizzleDb.select({project:b.project,type:b.type,srcFilePath:b.srcFilePath,srcSymbolName:b.srcSymbolName,dstFilePath:b.dstFilePath,dstSymbolName:b.dstSymbolName,metaJson:b.metaJson}).from(b).where(V(z(b.project,n),z(b.dstFilePath,t))).all()}getByType(n,t){return this.db.drizzleDb.select({project:b.project,type:b.type,srcFilePath:b.srcFilePath,srcSymbolName:b.srcSymbolName,dstFilePath:b.dstFilePath,dstSymbolName:b.dstSymbolName,metaJson:b.metaJson}).from(b).where(V(z(b.project,n),z(b.type,t))).all()}deleteFileRelations(n,t){this.db.drizzleDb.delete(b).where(V(z(b.project,n),z(b.srcFilePath,t))).run()}searchRelations(n){return this.db.drizzleDb.select({project:b.project,type:b.type,srcFilePath:b.srcFilePath,srcSymbolName:b.srcSymbolName,dstFilePath:b.dstFilePath,dstSymbolName:b.dstSymbolName,metaJson:b.metaJson}).from(b).where(V(n.project!==void 0?z(b.project,n.project):void 0,n.srcFilePath!==void 0?z(b.srcFilePath,n.srcFilePath):void 0,n.srcSymbolName!==void 0?z(b.srcSymbolName,n.srcSymbolName):void 0,n.dstFilePath!==void 0?z(b.dstFilePath,n.dstFilePath):void 0,n.dstSymbolName!==void 0?z(b.dstSymbolName,n.dstSymbolName):void 0,n.type!==void 0?z(b.type,n.type):void 0)).limit(n.limit).all()}retargetRelations(n,t,e,i,r){let s=e===null?V(z(b.project,n),z(b.dstFilePath,t),tt(b.dstSymbolName)):V(z(b.project,n),z(b.dstFilePath,t),z(b.dstSymbolName,e));this.db.drizzleDb.update(b).set({dstFilePath:i,dstSymbolName:r}).where(s).run()}}import{err as et}from"@zipbul/result";import{subscribe as $t}from"@parcel/watcher";import Rn from"path";var Bt=["**/.git/**","**/.zipbul/**","**/dist/**","**/node_modules/**"],Gt=new Set(["package.json","tsconfig.json"]);function Wt(n){return n.replaceAll("\\","/")}function Ht(n){if(n==="update")return"change";if(n==="create")return"create";return"delete"}class xn{#t;#n;#i;#r;#s;#e;constructor(n,t=$t,e=console){this.#n=n.projectRoot,this.#i=[...Bt,...n.ignorePatterns??[]],this.#r=new Set((n.extensions??[".ts",".mts",".cts"]).map((i)=>i.toLowerCase())),this.#s=t,this.#e=e}async start(n){try{this.#t=await this.#s(this.#n,(t,e)=>{if(t){this.#e.error(d("watcher","Callback error",t));return}try{for(let i of e){let r=Wt(Rn.relative(this.#n,i.path));if(r.startsWith(".."))continue;let s=Rn.basename(r),u=Rn.extname(r).toLowerCase();if(!Gt.has(s)&&!this.#r.has(u))continue;if(r.endsWith(".d.ts"))continue;n({eventType:Ht(i.type),filePath:r})}}catch(i){this.#e.error(d("watcher","Callback error",i))}},{ignore:this.#i})}catch(t){return et(d("watcher","Failed to subscribe watcher",t))}}async close(){if(!this.#t)return;try{await this.#t.unsubscribe(),this.#t=void 0}catch(n){return et(d("watcher","Failed to close watcher",n))}}}import zn from"path";import{promises as Ut}from"fs";var Qt=["**/node_modules/**","**/.git/**","**/.zipbul/**","**/dist/**"];async function yn(n){let t=[];for await(let e of Ut.glob("**/package.json",{cwd:n,exclude:Qt})){let i=zn.dirname(e).replaceAll("\\","/"),r=zn.join(n,e),s=await Bun.file(r).json(),u=typeof s?.name==="string"&&s.name.length>0?s.name:zn.basename(i==="."?n:i);t.push({dir:i,project:u})}return t.sort((e,i)=>i.dir.length-e.dir.length),t}function Y(n,t,e="default"){let i=n.replaceAll("\\","/");for(let r of t){if(r.dir===".")return r.project;if(i===r.dir||i.startsWith(`${r.dir}/`))return r.project}return e}import it from"path";var X=new Map;async function Vt(n){let t=Bun.file(n);if(!await t.exists())return null;let e=await t.json();return typeof e==="object"&&e!==null?e:null}async function mn(n){if(X.has(n))return X.get(n)??null;let t=it.join(n,"tsconfig.json"),e=await Vt(t);if(!e)return X.set(n,null),null;let i=typeof e.compilerOptions==="object"&&e.compilerOptions!==null?e.compilerOptions:null;if(!i)return X.set(n,null),null;let r=typeof i.baseUrl==="string"?i.baseUrl:null,s=typeof i.paths==="object"&&i.paths!==null?i.paths:null;if(!r&&!s)return X.set(n,null),null;let u=r?it.resolve(n,r):n,m=new Map;if(s)for(let[x,p]of Object.entries(s)){if(!Array.isArray(p))continue;let y=p.filter((w)=>typeof w==="string");m.set(x,y)}let a={baseUrl:u,paths:m};return X.set(n,a),a}function bn(n){if(n){X.delete(n);return}X.clear()}import rt from"path";function Tn(n,t){return rt.relative(n,t).replaceAll("\\","/")}function on(n,t){return rt.resolve(n,t)}function P(n){let t=Bun.hash.xxHash64(n);return BigInt.asUintN(64,BigInt(t)).toString(16).padStart(16,"0")}import{isErr as at}from"@zipbul/result";import{promises as Yt}from"fs";import{join as Zt}from"path";async function st(n){let{projectRoot:t,extensions:e,ignorePatterns:i,fileRepo:r}=n,s=r.getFilesMap(),u=new Set,m=[],a=[],x=i.map((y)=>new Bun.Glob(y));for await(let y of Yt.glob("**/*",{cwd:t})){if(!e.some((o)=>y.endsWith(o)))continue;if(x.some((o)=>o.match(y)))continue;u.add(y);let w=Zt(t,y),N=Bun.file(w),{size:_,lastModified:D}=N,M=s.get(y);if(!M){let o=await N.text(),c=P(o);m.push({filePath:y,contentHash:c,mtimeMs:D,size:_});continue}if(M.mtimeMs===D&&M.size===_){a.push({filePath:y,contentHash:M.contentHash,mtimeMs:D,size:_});continue}let l=await N.text(),g=P(l);if(g===M.contentHash)a.push({filePath:y,contentHash:g,mtimeMs:D,size:_});else m.push({filePath:y,contentHash:g,mtimeMs:D,size:_})}let p=[];for(let y of s.keys())if(!u.has(y))p.push(y);return{changed:m,unchanged:a,deleted:p}}function vt(n){if(n.kind==="function"||n.kind==="method"){let t=n.parameters?.length??0,e=n.modifiers.includes("async")?1:0;return`params:${t}|async:${e}`}return null}function Xt(n){let t={};if(n.jsDoc)t.jsDoc=n.jsDoc;if(n.kind==="function"||n.kind==="method"){if(n.parameters!==void 0)t.parameters=n.parameters;if(n.returnType!==void 0)t.returnType=n.returnType}if(n.heritage?.length)t.heritage=n.heritage;if(n.decorators?.length)t.decorators=n.decorators;if(n.typeParameters?.length)t.typeParameters=n.typeParameters;if(n.modifiers?.length)t.modifiers=n.modifiers;if(n.members?.length)t.members=n.members.map((e)=>{let i=e.modifiers.find((r)=>r==="private"||r==="protected"||r==="public");return{name:e.name,kind:e.methodKind??e.kind,type:e.returnType,visibility:i,isStatic:e.modifiers.includes("static")||void 0,isReadonly:e.modifiers.includes("readonly")||void 0}});return Object.keys(t).length>0?JSON.stringify(t):null}function ot(n,t,e,i,r){let s=vt(n),u=P(`${t}|${n.kind}|${s??""}`);return{project:e,filePath:i,kind:n.kind,name:t,startLine:n.span.start.line,startColumn:n.span.start.column,endLine:n.span.end.line,endColumn:n.span.end.column,isExported:n.isExported?1:0,signature:s,fingerprint:u,detailJson:Xt(n),contentHash:r,indexedAt:new Date().toISOString()}}function Ln(n){let{parsed:t,project:e,filePath:i,contentHash:r,symbolRepo:s}=n,u=ln(t),m=[];for(let a of u){m.push(ot(a,a.name,e,i,r));for(let x of a.members??[])m.push(ot(x,`${a.name}.${x.name}`,e,i,r))}s.replaceFileSymbols(e,i,r,m)}function $n(n){let{ast:t,project:e,filePath:i,relationRepo:r,projectRoot:s,tsconfigPaths:u}=n,m=on(s,i),a=pn(t,m,u),x=[];for(let p of a){let y=Tn(s,p.dstFilePath);if(y.startsWith(".."))continue;let w=Tn(s,p.srcFilePath);x.push({project:e,type:p.type,srcFilePath:w,srcSymbolName:p.srcSymbolName??null,dstFilePath:y,dstSymbolName:p.dstSymbolName??null,metaJson:p.metaJson??null})}return r.replaceFileRelations(e,i,x),x.length}var Pt=100;class cn{opts;logger;callbacks=new Set;indexingLock=!1;pendingEvents=[];debounceTimer=null;currentIndexing=null;pendingFullIndex=!1;pendingFullIndexWaiters=[];tsconfigPathsRaw;boundariesRefresh=null;constructor(n){this.opts=n,this.logger=n.logger??console,this.tsconfigPathsRaw=mn(n.projectRoot)}get tsconfigPaths(){return this.tsconfigPathsRaw}fullIndex(){return this.startIndex(void 0,!0)}incrementalIndex(n){return this.startIndex(n,!1)}onIndexed(n){return this.callbacks.add(n),()=>this.callbacks.delete(n)}handleWatcherEvent(n){if(n.filePath.endsWith("tsconfig.json")){bn(this.opts.projectRoot),this.tsconfigPathsRaw=mn(this.opts.projectRoot),this.fullIndex().catch((t)=>{this.logger.error("[IndexCoordinator] fullIndex failed after tsconfig change:",t)});return}if(n.filePath.endsWith("package.json")){let t=this.opts.discoverProjectsFn??yn;this.boundariesRefresh=t(this.opts.projectRoot).then((e)=>{this.opts.boundaries=e})}if(this.pendingEvents.push(n),this.debounceTimer===null)this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.flushPending()},Pt)}async shutdown(){if(this.debounceTimer!==null)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.currentIndexing)await this.currentIndexing}startIndex(n,t){if(this.indexingLock){if(t)return this.pendingFullIndex=!0,new Promise((i,r)=>{this.pendingFullIndexWaiters.push({resolve:i,reject:r})});return this.currentIndexing}this.indexingLock=!0;let e=this.doIndex(n,t).then((i)=>{return this.fireCallbacks(i),i}).finally(()=>{if(this.indexingLock=!1,this.currentIndexing=null,this.pendingFullIndex){this.pendingFullIndex=!1;let i=this.pendingFullIndexWaiters.splice(0);this.startIndex(void 0,!0).then((r)=>{for(let s of i)s.resolve(r)}).catch((r)=>{for(let s of i)s.reject(r)})}else if(this.pendingEvents.length>0){let i=this.pendingEvents.splice(0);this.startIndex(i,!1).catch((r)=>this.logger.error("[IndexCoordinator] incremental drain error",r))}});return this.currentIndexing=e,e}async doIndex(n,t){let e=Date.now(),{fileRepo:i,symbolRepo:r,relationRepo:s,dbConnection:u}=this.opts;if(this.boundariesRefresh)await this.boundariesRefresh,this.boundariesRefresh=null;let m,a;if(n!==void 0)m=n.filter((o)=>o.eventType==="create"||o.eventType==="change").map((o)=>({filePath:o.filePath,contentHash:"",mtimeMs:0,size:0})),a=n.filter((o)=>o.eventType==="delete").map((o)=>o.filePath);else{let o=new Map;for(let f of this.opts.boundaries)for(let[O,A]of i.getFilesMap(f.project))o.set(O,A);let c=await st({projectRoot:this.opts.projectRoot,extensions:this.opts.extensions,ignorePatterns:this.opts.ignorePatterns,fileRepo:{getFilesMap:()=>o}});m=c.changed,a=c.deleted}let x=await this.tsconfigPathsRaw??void 0,p=new Map;for(let o of a){let c=Y(o,this.opts.boundaries),f=r.getFileSymbols(c,o);p.set(o,f)}let y=new Map,w=new Map;if(t)for(let o of this.opts.boundaries)for(let c of i.getAllFiles(o.project))for(let f of r.getFileSymbols(o.project,c.filePath))y.set(`${f.filePath}::${f.name}`,{name:f.name,filePath:f.filePath,kind:f.kind,fingerprint:f.fingerprint});else{for(let o of m){let c=Y(o.filePath,this.opts.boundaries);for(let f of r.getFileSymbols(c,o.filePath))y.set(`${f.filePath}::${f.name}`,{name:f.name,filePath:f.filePath,kind:f.kind,fingerprint:f.fingerprint})}for(let[,o]of p)for(let c of o)y.set(`${c.filePath}::${c.name}`,{name:c.name,filePath:c.filePath,kind:c.kind,fingerprint:c.fingerprint})}let N=()=>{for(let o of a){let c=Y(o,this.opts.boundaries);r.deleteFileSymbols(c,o),s.deleteFileRelations(c,o),i.deleteFile(c,o)}},_=async()=>{let o=0,c=0,f=[];for(let O of m)try{let A=await this.processFile(O.filePath,O.contentHash||void 0,x);o+=A.symbolCount,c+=A.relCount}catch(A){this.logger.error(`[IndexCoordinator] Failed to index ${O.filePath}:`,A),f.push(O.filePath)}return{symbols:o,relations:c,failedFiles:f}},D=0,M=0,l=[];if(t){let{projectRoot:o,boundaries:c}=this.opts,{parseCache:f}=this.opts,O=await Promise.allSettled(m.map(async(h)=>{let k=on(o,h.filePath),J=Bun.file(k),K=await J.text(),I=h.contentHash||P(K);return{filePath:h.filePath,text:K,contentHash:I,mtimeMs:J.lastModified,size:J.size}})),A=O.filter((h)=>h.status==="fulfilled").map((h)=>h.value);for(let h of O)if(h.status==="rejected")this.logger.error("[IndexCoordinator] Failed to pre-read file:",h.reason);let C=[];u.transaction(()=>{for(let k of c){let J=i.getAllFiles(k.project);for(let K of J)i.deleteFile(K.project,K.filePath)}for(let k of A){let J=Y(k.filePath,c);i.upsertFile({project:J,filePath:k.filePath,mtimeMs:k.mtimeMs,size:k.size,contentHash:k.contentHash,updatedAt:new Date().toISOString(),lineCount:k.text.split(`
|
|
4
|
-
`).length})}let
|
|
5
|
-
`).length}),Ln({parsed:M,project:N,filePath:n,contentHash:w,symbolRepo:u});let l=$n({ast:M.program,project:N,filePath:n,relationRepo:m,projectRoot:i,tsconfigPaths:e});return{symbolCount:u.getFileSymbols(N,n).length,relCount:l}}fireCallbacks(n){for(let t of this.callbacks)try{t(n)}catch(e){this.logger.error("[IndexCoordinator] onIndexed callback threw:",e)}}flushPending(){if(this.indexingLock)return;if(this.pendingEvents.length>0){let n=this.pendingEvents.splice(0);this.startIndex(n,!1).catch((t)=>this.logger.error("[IndexCoordinator] flushPending startIndex error:",t))}}}function Et(n){try{return process.kill(n,0),!0}catch(t){if(typeof t==="object"&&t&&"code"in t)return t.code!=="ESRCH";return!0}}function jt(n){let t=new Date(n).getTime();return Number.isNaN(t)?0:t}function ut(n,t,e={}){let i=e.now??Date.now,r=e.isAlive??Et,s=e.staleAfterSeconds??90;return n.immediateTransaction(()=>{let u=n.selectOwner();if(!u)return n.insertOwner(t),"owner";let m=Math.floor((i()-jt(u.heartbeat_at))/1000);if(r(u.pid)&&m<s)return"reader";return n.replaceOwner(t),"owner"})}function mt(n,t){n.deleteOwner(t)}function ct(n,t){n.touchOwner(t)}function Bn(n){let{symbolRepo:t,project:e,query:i}=n,r=i.project??e,s=i.limit??100,u={kind:i.kind,filePath:i.filePath,isExported:i.isExported,project:r,limit:s};if(i.text)if(i.exact)u.exactName=i.text;else{let a=gn(i.text);if(a)u.ftsQuery=a}if(i.decorator)u.decorator=i.decorator;if(i.regex)u.regex=i.regex;return t.searchByQuery(u).map((a)=>({id:a.id,filePath:a.filePath,kind:a.kind,name:a.name,span:{start:{line:a.startLine,column:a.startColumn},end:{line:a.endLine,column:a.endColumn}},isExported:a.isExported===1,signature:a.signature,fingerprint:a.fingerprint,detail:a.detailJson?(()=>{try{return JSON.parse(a.detailJson)}catch{return{}}})():{}}))}function Gn(n){let{relationRepo:t,project:e,query:i}=n,r=i.project??e,s=i.limit??500;return t.searchRelations({srcFilePath:i.srcFilePath,srcSymbolName:i.srcSymbolName,dstFilePath:i.dstFilePath,dstSymbolName:i.dstSymbolName,type:i.type,project:r,limit:s}).map((m)=>{let a;if(m.metaJson)try{a=JSON.parse(m.metaJson)}catch{console.error("[relationSearch] malformed metaJson:",m.metaJson)}return{type:m.type,srcFilePath:m.srcFilePath,srcSymbolName:m.srcSymbolName,dstFilePath:m.dstFilePath,dstSymbolName:m.dstSymbolName,metaJson:m.metaJson??void 0,meta:a}})}class wn{options;adjacencyList=new Map;reverseAdjacencyList=new Map;constructor(n){this.options=n}build(){this.adjacencyList=new Map,this.reverseAdjacencyList=new Map;let n=[...this.options.relationRepo.getByType(this.options.project,"imports"),...this.options.relationRepo.getByType(this.options.project,"type-references"),...this.options.relationRepo.getByType(this.options.project,"re-exports")];for(let t of n){let{srcFilePath:e,dstFilePath:i}=t;if(!this.adjacencyList.has(e))this.adjacencyList.set(e,new Set);if(this.adjacencyList.get(e).add(i),!this.adjacencyList.has(i))this.adjacencyList.set(i,new Set);if(!this.reverseAdjacencyList.has(i))this.reverseAdjacencyList.set(i,new Set);this.reverseAdjacencyList.get(i).add(e)}}getDependencies(n){return Array.from(this.adjacencyList.get(n)??[])}getDependents(n){return Array.from(this.reverseAdjacencyList.get(n)??[])}getTransitiveDependents(n){let t=new Set,e=[n];while(e.length>0){let i=e.shift();for(let r of this.reverseAdjacencyList.get(i)??[])if(!t.has(r))t.add(r),e.push(r)}return Array.from(t)}hasCycle(){let n=new Set,t=new Set;for(let e of this.adjacencyList.keys()){if(n.has(e))continue;let i=[{node:e,entered:!1}];while(i.length>0){let r=i.pop();if(r.entered){t.delete(r.node);continue}if(t.has(r.node))return!0;if(n.has(r.node))continue;n.add(r.node),t.add(r.node),i.push({node:r.node,entered:!0});for(let s of this.adjacencyList.get(r.node)??[]){if(t.has(s))return!0;if(!n.has(s))i.push({node:s,entered:!1})}}}return!1}getAffectedByChange(n){let t=new Set;for(let e of n)for(let i of this.getTransitiveDependents(e))t.add(i);return Array.from(t)}getAdjacencyList(){let n=new Map;for(let[t,e]of this.adjacencyList)n.set(t,Array.from(e));return n}getTransitiveDependencies(n){let t=new Set,e=[n];while(e.length>0){let i=e.shift();for(let r of this.adjacencyList.get(i)??[])if(!t.has(r))t.add(r),e.push(r)}return Array.from(t)}getCyclePaths(){let n=new Set,t=[],e=new Set,i=new Map,r=[],s=(u)=>{if(e.has(u))return;if(i.has(u)){let m=i.get(u),a=r.slice(m),x=a.reduce((N,_)=>N<=_?N:_),p=a.indexOf(x),y=[...a.slice(p),...a.slice(0,p)],w=y.join("\x00");if(!n.has(w))n.add(w),t.push(y);return}i.set(u,r.length),r.push(u);for(let m of this.adjacencyList.get(u)??[])s(m);r.pop(),i.delete(u),e.add(u)};for(let u of this.adjacencyList.keys())s(u);return t}}import{findInFiles as qt,Lang as ne}from"@ast-grep/napi";async function Wn(n){if(n.filePaths.length===0)return[];let t=[];return await qt(ne.TypeScript,{paths:n.filePaths,matcher:{rule:{pattern:n.pattern}}},(e,i)=>{if(e)return;for(let r of i){let s=r.range();t.push({filePath:r.getRoot().filename(),startLine:s.start.line+1,endLine:s.end.line+1,matchedText:r.text()})}}),t}var lt=30000,pt=60000,ee=10;class Hn{projectRoot;db;symbolRepo;relationRepo;fileRepo;parseCache;coordinator;watcher;releaseWatcherRoleFn;parseSourceFn;extractSymbolsFn;extractRelationsFn;symbolSearchFn;relationSearchFn;patternSearchFn;readFileFn;unlinkFn;existsSyncFn;makeExternalCoordinatorFn;logger;defaultProject;role;timer=null;signalHandlers=[];closed=!1;tsconfigPaths=null;boundaries=[];onIndexedCallbacks=new Set;graphCache=null;graphCacheKey=null;constructor(n){this.projectRoot=n.projectRoot,this.db=n.db,this.symbolRepo=n.symbolRepo,this.relationRepo=n.relationRepo,this.fileRepo=n.fileRepo,this.parseCache=n.parseCache,this.coordinator=n.coordinator,this.watcher=n.watcher,this.releaseWatcherRoleFn=n.releaseWatcherRoleFn,this.parseSourceFn=n.parseSourceFn,this.extractSymbolsFn=n.extractSymbolsFn,this.extractRelationsFn=n.extractRelationsFn,this.symbolSearchFn=n.symbolSearchFn,this.relationSearchFn=n.relationSearchFn,this.patternSearchFn=n.patternSearchFn,this.readFileFn=n.readFileFn,this.unlinkFn=n.unlinkFn,this.existsSyncFn=n.existsSyncFn,this.makeExternalCoordinatorFn=n.makeExternalCoordinatorFn,this.logger=n.logger,this.defaultProject=n.defaultProject,this.role=n.role}static async open(n){let{projectRoot:t,extensions:e=[".ts",".mts",".cts"],ignorePatterns:i=[],parseCacheCapacity:r=500,logger:s=console,existsSyncFn:u=te,dbConnectionFactory:m,watcherFactory:a,coordinatorFactory:x,repositoryFactory:p,acquireWatcherRoleFn:y=ut,releaseWatcherRoleFn:w=mt,updateHeartbeatFn:N=ct,discoverProjectsFn:_=yn,parseSourceFn:D=an,extractSymbolsFn:M=ln,extractRelationsFn:l=pn,symbolSearchFn:g=Bn,relationSearchFn:o=Gn,patternSearchFn:c=Wn,loadTsconfigPathsFn:f=mn,makeExternalCoordinatorFn:O,readFileFn:A=async(K)=>Bun.file(K).text(),unlinkFn:C=async(K)=>{await Bun.file(K).unlink()},watchMode:h}=n;if(!Sn.isAbsolute(t))return S(d("validation",`Gildash: projectRoot must be an absolute path, got: "${t}"`));if(!u(t))return S(d("validation",`Gildash: projectRoot does not exist: "${t}"`));let k=m?m():new Mn({projectRoot:t}),J=k.open();if(en(J))return J;try{let K=await _(t),I=K[0]?.project??Sn.basename(t),$=p?p():(()=>{let G=k;return{fileRepo:new Jn(G),symbolRepo:new Kn(G),relationRepo:new In(G),parseCache:new kn(r)}})(),rn=h??!0,Z;if(rn)Z=await Promise.resolve(y(k,process.pid,{}));else Z="owner";let ft=null,gt=null,R=new Hn({projectRoot:t,db:k,symbolRepo:$.symbolRepo,relationRepo:$.relationRepo,fileRepo:$.fileRepo,parseCache:$.parseCache,coordinator:ft,watcher:gt,releaseWatcherRoleFn:w,parseSourceFn:D,extractSymbolsFn:M,extractRelationsFn:l,symbolSearchFn:g,relationSearchFn:o,patternSearchFn:c,readFileFn:A,unlinkFn:C,existsSyncFn:u,makeExternalCoordinatorFn:O,logger:s,defaultProject:I,role:Z});if(bn(t),R.tsconfigPaths=await f(t),R.boundaries=K,Z==="owner"){let G=x?x():new cn({projectRoot:t,boundaries:K,extensions:e,ignorePatterns:i,dbConnection:k,parseCache:$.parseCache,fileRepo:$.fileRepo,symbolRepo:$.symbolRepo,relationRepo:$.relationRepo,logger:s});if(R.coordinator=G,G.onIndexed(()=>R.invalidateGraphCache()),rn){let U=a?a():new xn({projectRoot:t,ignorePatterns:i,extensions:e},void 0,s);R.watcher=U,await U.start((Q)=>G.handleWatcherEvent?.(Q)).then((Q)=>{if(en(Q))throw Q.data});let E=setInterval(()=>{N(k,process.pid)},lt);R.timer=E}await G.fullIndex()}else{let G=0,U=async()=>{try{let Q=await Promise.resolve(y(k,process.pid,{}));if(G=0,Q==="owner"){clearInterval(R.timer),R.timer=null;let j=null,v=null;try{j=a?a():new xn({projectRoot:t,ignorePatterns:i,extensions:e},void 0,s),v=x?x():new cn({projectRoot:t,boundaries:K,extensions:e,ignorePatterns:i,dbConnection:k,parseCache:$.parseCache,fileRepo:$.fileRepo,symbolRepo:$.symbolRepo,relationRepo:$.relationRepo,logger:s});for(let W of R.onIndexedCallbacks)v.onIndexed(W);v.onIndexed(()=>R.invalidateGraphCache()),await j.start((W)=>v?.handleWatcherEvent?.(W)).then((W)=>{if(en(W))throw W.data});let On=setInterval(()=>{N(k,process.pid)},lt);R.timer=On,R.coordinator=v,R.watcher=j,await v.fullIndex()}catch(On){if(s.error("[Gildash] owner promotion failed, reverting to reader",On),j){let W=await j.close();if(en(W))s.error("[Gildash] watcher close error during promotion rollback",W.data);R.watcher=null}if(v)await v.shutdown().catch((W)=>s.error("[Gildash] coordinator shutdown error during promotion rollback",W)),R.coordinator=null;if(R.timer===null)R.timer=setInterval(U,pt)}}}catch(Q){if(G++,s.error("[Gildash] healthcheck error",Q),G>=ee)s.error("[Gildash] healthcheck failed too many times, shutting down"),clearInterval(R.timer),R.timer=null,R.close().catch((j)=>s.error("[Gildash] close error during healthcheck shutdown",j))}},E=setInterval(U,pt);R.timer=E}if(rn){let G=["SIGTERM","SIGINT","beforeExit"];for(let U of G){let E=()=>{R.close().catch((Q)=>s.error("[Gildash] close error during signal",U,Q))};if(U==="beforeExit")process.on("beforeExit",E);else process.on(U,E);R.signalHandlers.push([U,E])}}return R}catch(K){return k.close(),S(d("store","Gildash: initialization failed",K))}}async close(n){if(this.closed)return;this.closed=!0;let t=[];for(let[e,i]of this.signalHandlers)if(e==="beforeExit")process.off("beforeExit",i);else process.off(e,i);if(this.signalHandlers=[],this.coordinator)try{await this.coordinator.shutdown()}catch(e){t.push(e instanceof Error?e:Error(String(e)))}if(this.watcher){let e=await this.watcher.close();if(en(e))t.push(e.data)}if(this.timer!==null)clearInterval(this.timer),this.timer=null;try{this.releaseWatcherRoleFn(this.db,process.pid)}catch(e){t.push(e instanceof Error?e:Error(String(e)))}try{this.db.close()}catch(e){t.push(e instanceof Error?e:Error(String(e)))}if(n?.cleanup)for(let e of["","-wal","-shm"])try{await this.unlinkFn(Sn.join(this.projectRoot,".zipbul","gildash.db"+e))}catch{}if(t.length>0)return S(d("close","Gildash: one or more errors occurred during close()",t))}onIndexed(n){if(this.onIndexedCallbacks.add(n),!this.coordinator)return()=>{this.onIndexedCallbacks.delete(n)};let t=this.coordinator.onIndexed(n);return()=>{this.onIndexedCallbacks.delete(n),t()}}parseSource(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));let e=this.parseSourceFn(n,t);if(en(e))return e;return this.parseCache.set(n,e),e}extractSymbols(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));return this.extractSymbolsFn(n)}extractRelations(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));return this.extractRelationsFn(n.program,n.filePath,this.tsconfigPaths??void 0)}invalidateGraphCache(){this.graphCache=null,this.graphCacheKey=null}getOrBuildGraph(n){let t=n??"__cross__";if(this.graphCache&&this.graphCacheKey===t)return this.graphCache;let e=new wn({relationRepo:this.relationRepo,project:n??this.defaultProject});return e.build(),this.graphCache=e,this.graphCacheKey=t,e}async reindex(){if(this.closed)return S(d("closed","Gildash: instance is closed"));if(!this.coordinator)return S(d("closed","Gildash: reindex() is not available for readers"));try{let n=await this.coordinator.fullIndex();return this.invalidateGraphCache(),n}catch(n){return S(d("index","Gildash: reindex failed",n))}}get projects(){return[...this.boundaries]}getStats(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.symbolRepo.getStats(n??this.defaultProject)}catch(t){return S(d("store","Gildash: getStats failed",t))}}searchSymbols(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:this.defaultProject,query:n})}catch(t){return S(d("search","Gildash: searchSymbols failed",t))}}searchRelations(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:this.defaultProject,query:n})}catch(t){return S(d("search","Gildash: searchRelations failed",t))}}searchAllSymbols(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:void 0,query:n})}catch(t){return S(d("search","Gildash: searchAllSymbols failed",t))}}searchAllRelations(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:void 0,query:n})}catch(t){return S(d("search","Gildash: searchAllRelations failed",t))}}listIndexedFiles(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.fileRepo.getAllFiles(n??this.defaultProject)}catch(t){return S(d("store","Gildash: listIndexedFiles failed",t))}}getInternalRelations(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{srcFilePath:n,dstFilePath:n,limit:1e4}})}catch(e){return S(d("search","Gildash: getInternalRelations failed",e))}}diffSymbols(n,t){let e=new Map(n.map((m)=>[`${m.name}::${m.filePath}`,m])),i=new Map(t.map((m)=>[`${m.name}::${m.filePath}`,m])),r=[],s=[],u=[];for(let[m,a]of i){let x=e.get(m);if(!x)r.push(a);else if(x.fingerprint!==a.fingerprint)u.push({before:x,after:a})}for(let[m,a]of e)if(!i.has(m))s.push(a);return{added:r,removed:s,modified:u}}getDependencies(n,t,e=1e4){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{srcFilePath:n,type:"imports",project:t??this.defaultProject,limit:e}}).map((i)=>i.dstFilePath)}catch(i){return S(d("search","Gildash: getDependencies failed",i))}}getDependents(n,t,e=1e4){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{dstFilePath:n,type:"imports",project:t??this.defaultProject,limit:e}}).map((i)=>i.srcFilePath)}catch(i){return S(d("search","Gildash: getDependents failed",i))}}async getAffected(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(t).getAffectedByChange(n)}catch(e){return S(d("search","Gildash: getAffected failed",e))}}async hasCycle(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(n).hasCycle()}catch(t){return S(d("search","Gildash: hasCycle failed",t))}}async getImportGraph(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(n).getAdjacencyList()}catch(t){return S(d("search","Gildash: getImportGraph failed",t))}}async getTransitiveDependencies(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(t).getTransitiveDependencies(n)}catch(e){return S(d("search","Gildash: getTransitiveDependencies failed",e))}}async getCyclePaths(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(n).getCyclePaths()}catch(t){return S(d("search","Gildash: getCyclePaths failed",t))}}getDeadExports(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let e=n??this.defaultProject,i=this.symbolRepo.searchByQuery({project:e,isExported:!0,limit:1e5}),r=new Set;for(let a of["imports","re-exports"]){let x=this.relationRepo.getByType(e,a);for(let p of x)if(p.dstSymbolName!=null)r.add(`${p.dstFilePath}::${p.dstSymbolName}`)}let s=t?.entryPoints,u=["index.ts","index.mts","main.ts"];return i.filter((a)=>{if(r.has(`${a.filePath}::${a.name}`))return!1;if(s!==void 0)return!s.includes(a.filePath);let x=a.filePath.split("/").pop()??a.filePath;return!u.includes(x)}).map((a)=>({symbolName:a.name,filePath:a.filePath}))}catch(e){return S(d("store","Gildash: getDeadExports failed",e))}}getFullSymbol(n,t,e){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let i=e??this.defaultProject,r=this.symbolSearchFn({symbolRepo:this.symbolRepo,project:i,query:{text:n,exact:!0,filePath:t,limit:1}});if(r.length===0)return S(d("search",`Gildash: symbol '${n}' not found in '${t}'`));let s=r[0],u=s.detail;return{...s,members:Array.isArray(u.members)?u.members:void 0,jsDoc:typeof u.jsDoc==="string"?u.jsDoc:void 0,parameters:typeof u.parameters==="string"?u.parameters:void 0,returnType:typeof u.returnType==="string"?u.returnType:void 0,heritage:Array.isArray(u.heritage)?u.heritage:void 0,decorators:Array.isArray(u.decorators)?u.decorators:void 0,typeParameters:typeof u.typeParameters==="string"?u.typeParameters:void 0}}catch(i){return S(d("search","Gildash: getFullSymbol failed",i))}}getFileStats(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let e=t??this.defaultProject,i=this.fileRepo.getFile(e,n);if(!i)return S(d("search",`Gildash: file '${n}' is not in the index`));let r=this.symbolRepo.getFileSymbols(e,n),s=this.relationRepo.getOutgoing(e,n);return{filePath:i.filePath,lineCount:i.lineCount??0,size:i.size,symbolCount:r.length,exportedSymbolCount:r.filter((u)=>u.isExported).length,relationCount:s.length}}catch(e){return S(d("store","Gildash: getFileStats failed",e))}}async getFanMetrics(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let e=this.getOrBuildGraph(t);return{filePath:n,fanIn:e.getDependents(n).length,fanOut:e.getDependencies(n).length}}catch(e){return S(d("search","Gildash: getFanMetrics failed",e))}}resolveSymbol(n,t,e){if(this.closed)return S(d("closed","Gildash: instance is closed"));let i=e??this.defaultProject,r=new Set,s=[],u=n,m=t;for(;;){let a=`${m}::${u}`;if(r.has(a))return S(d("search","Gildash: resolveSymbol detected circular re-export chain"));r.add(a);let x=this.relationSearchFn({relationRepo:this.relationRepo,project:i,query:{type:"re-exports",srcFilePath:m,limit:500}}),p,y;for(let w of x){let N;if(w.metaJson)try{let D=JSON.parse(w.metaJson);if(Array.isArray(D.specifiers))N=D.specifiers}catch{}if(!N)continue;let _=N.find((D)=>D.exported===u);if(!_)continue;p=w.dstFilePath,y=_.local;break}if(!p||!y)return{originalName:u,originalFilePath:m,reExportChain:s};s.push({filePath:m,exportedAs:u}),m=p,u=y}}async findPattern(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let e=t?.project??this.defaultProject,i=t?.filePaths?t.filePaths:this.fileRepo.getAllFiles(e).map((r)=>r.filePath);return await this.patternSearchFn({pattern:n,filePaths:i})}catch(e){return S(d("search","Gildash: findPattern failed",e))}}async indexExternalPackages(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));if(this.role!=="owner")return S(d("closed","Gildash: indexExternalPackages() is not available for readers"));try{let e=[];for(let i of n){let r=Sn.resolve(this.projectRoot,"node_modules",i);if(!this.existsSyncFn(r))return S(d("validation",`Gildash: package not found in node_modules: ${i}`));let s=`@external/${i}`,m=await(this.makeExternalCoordinatorFn?this.makeExternalCoordinatorFn(r,s):new cn({projectRoot:r,boundaries:[{dir:".",project:s}],extensions:[".d.ts"],ignorePatterns:[],dbConnection:this.db,parseCache:this.parseCache,fileRepo:this.fileRepo,symbolRepo:this.symbolRepo,relationRepo:this.relationRepo,logger:this.logger})).fullIndex();e.push(m)}return e}catch(e){return S(d("store","Gildash: indexExternalPackages failed",e))}}async batchParse(n){if(this.closed)return S(d("closed","Gildash: instance is closed"));let t=new Map;return await Promise.all(n.map(async(e)=>{try{let i=await this.readFileFn(e),r=this.parseSourceFn(e,i);if(!en(r))t.set(e,r)}catch{}})),t}getModuleInterface(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let i=this.symbolSearchFn({symbolRepo:this.symbolRepo,project:t??this.defaultProject,query:{filePath:n,isExported:!0}}).map((r)=>({name:r.name,kind:r.kind,parameters:r.detail.parameters??void 0,returnType:r.detail.returnType??void 0,jsDoc:r.detail.jsDoc??void 0}));return{filePath:n,exports:i}}catch(e){return S(d("search","Gildash: getModuleInterface failed",e))}}async getHeritageChain(n,t,e){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{let i=e??this.defaultProject,r=new Set,s=(u,m,a)=>{let x=`${u}::${m}`;if(r.has(x))return{symbolName:u,filePath:m,kind:a,children:[]};r.add(x);let w=this.relationSearchFn({relationRepo:this.relationRepo,project:i,query:{srcFilePath:m,srcSymbolName:u,limit:1000}}).filter((N)=>N.type==="extends"||N.type==="implements").filter((N)=>N.dstSymbolName!=null).map((N)=>s(N.dstSymbolName,N.dstFilePath,N.type));return{symbolName:u,filePath:m,kind:a,children:w}};return s(n,t)}catch(i){return S(d("search","Gildash: getHeritageChain failed",i))}}getParsedAst(n){if(this.closed)return;return this.parseCache.get(n)}getFileInfo(n,t){if(this.closed)return S(d("closed","Gildash: instance is closed"));try{return this.fileRepo.getFile(t??this.defaultProject,n)}catch(e){return S(d("store","Gildash: getFileInfo failed",e))}}getSymbolsByFile(n,t){return this.searchSymbols({filePath:n,project:t??void 0,limit:1e4})}}export{Bn as symbolSearch,Gn as relationSearch,Wn as patternSearch,d as gildashError,Hn as Gildash,wn as DependencyGraph};
|
|
2
|
+
var xt=Object.defineProperty;var yt=(n,t)=>{for(var i in t)xt(n,i,{get:t[i],enumerable:!0,configurable:!0,set:(e)=>t[i]=()=>e})};import{err as O,isErr as en}from"@zipbul/result";import bn from"path";import{existsSync as oi}from"fs";import{err as wt}from"@zipbul/result";import{parseSync as St}from"oxc-parser";function y(n,t,i){return i!==void 0?{type:n,message:t,cause:i}:{type:n,message:t}}function on(n,t,i,e=St){try{let{program:r,errors:s,comments:m}=e(n,t,i);return{filePath:n,program:r,errors:s,comments:m,sourceText:t}}catch(r){return wt(y("parse",`Failed to parse file: ${n}`,r))}}class Nn{#t;#n=new Map;constructor(n){this.#t=Math.max(1,n)}get size(){return this.#n.size}has(n){return this.#n.has(n)}get(n){if(!this.#n.has(n))return;let t=this.#n.get(n);return this.#n.delete(n),this.#n.set(n,t),t}set(n,t){if(this.#n.has(n))this.#n.delete(n);if(this.#n.set(n,t),this.#n.size>this.#t){let i=this.#n.keys().next().value;if(i!==void 0)this.#n.delete(i)}}delete(n){return this.#n.delete(n)}clear(){this.#n.clear()}}class An{lru;constructor(n=500){this.lru=new Nn(n)}get(n){return this.lru.get(n)}set(n,t){this.lru.set(n,t)}invalidate(n){this.lru.delete(n)}invalidateAll(){this.lru.clear()}size(){return this.lru.size}}function Vn(n){let t=[0];for(let i=0;i<n.length;i++)if(n[i]===`
|
|
3
|
+
`)t.push(i+1);return t}function hn(n,t){let i=0,e=n.length-1;while(i<e){let r=i+e+1>>1;if(n[r]<=t)i=r;else e=r-1}return{line:i+1,column:t-n[i]}}import{err as bt}from"@zipbul/result";import{parse as Ot}from"comment-parser";function Pn(n){try{let t=n.trim();if(t.startsWith("/**"))t=t.slice(3);if(t.endsWith("*/"))t=t.slice(0,-2);let e=Ot(`/** ${t} */`)[0]??{description:"",tags:[]};return{description:(e.description??"").trim(),tags:(e.tags??[]).map((r)=>({tag:r.tag??"",name:r.name??"",type:r.type??"",description:r.description??"",optional:r.optional??!1,...r.default!==void 0?{default:r.default}:{}}))}}catch(t){return bt(y("parse","Failed to parse JSDoc comment",t))}}import{isErr as Nt}from"@zipbul/result";function ln(n){let{program:t,sourceText:i,comments:e}=n,r=Vn(i);function s(c,g){return{start:hn(r,c),end:hn(r,g)}}function m(c){let g=null;for(let o of e){if(o.type!=="Block")continue;if(o.end>c)continue;if(!o.value.startsWith("*"))continue;if(!g||o.end>g.end)g={value:`/*${o.value}*/`,end:o.end}}if(!g)return;for(let o of t.body){let l=o.start??0;if(l===c)continue;if(l>g.end&&l<c)return}return g.value}function u(c){if(!c)return;let g=c.typeAnnotation??c;return i.slice(g.start,g.end)}function a(c){if(!c||c.length===0)return[];return c.map((g)=>{let o=g.expression;if(!o)return{name:"unknown"};if(o.type==="CallExpression"){let l=o.callee?.name??o.callee?.property?.name??"unknown",d=(o.arguments??[]).map((b)=>i.slice(b.start,b.end));return{name:l,arguments:d.length>0?d:void 0}}if(o.type==="Identifier")return{name:o.name??"unknown"};return{name:i.slice(o.start,o.end)}})}function p(c){let g=c.type==="TSParameterProperty"?c.parameter:c;if(g?.type==="RestElement"){let h=`...${g.argument?.name??"unknown"}`,I=g.typeAnnotation,R=I?u(I):void 0,T={name:h,isOptional:!1};if(R)T.type=R;return T}if(g?.type==="AssignmentPattern"){let{left:k,right:h}=g,I=k?.name??"unknown",R=k?.typeAnnotation,T=R?u(R):void 0,z=i.slice(h.start,h.end),rn=a(k?.decorators??[]),Y={name:I,isOptional:!0,defaultValue:z};if(T)Y.type=T;if(rn.length>0)Y.decorators=rn;return Y}let o=g?.name??g?.pattern?.name??"unknown",l=!!g?.optional,d=g?.typeAnnotation,b=d?u(d):void 0,D=a(g?.decorators??[]),M={name:o,isOptional:l};if(b)M.type=b;if(D.length>0)M.decorators=D;return M}function f(c,g){let o=[];if(g?.async)o.push("async");if(c.static)o.push("static");if(c.abstract)o.push("abstract");if(c.readonly)o.push("readonly");if(c.override)o.push("override");if(c.declare)o.push("declare");if(c.const)o.push("const");let l=c.accessibility;if(l==="private")o.push("private");else if(l==="protected")o.push("protected");else if(l==="public")o.push("public");return o}function x(c){let g=[];if(c.superClass){let l=i.slice(c.superClass.start,c.superClass.end);g.push({kind:"extends",name:l})}let o=c.implements??[];for(let l of o){let d=l.expression??l,b=i.slice(d.start,d.end);g.push({kind:"implements",name:b})}return g}function S(c){let g=[];for(let o of c.extends??[]){let l=o.expression??o,d=i.slice(l.start,l.end);g.push({kind:"extends",name:d})}return g}function N(c){let g=[];for(let o of c)if(o.type==="MethodDefinition"){let l=o.key?.name??"unknown",d=o.value,b=o.kind??"method",D=b==="constructor"?"constructor":b==="get"?"getter":b==="set"?"setter":"method",M=f(o,d),k=(d?.params??[]).map(p),h=u(d?.returnType),I={kind:"method",name:l,span:s(o.start,o.end),isExported:!1,methodKind:D,modifiers:M,parameters:k.length>0?k:void 0,returnType:h};g.push(I)}else if(o.type==="PropertyDefinition"){let l=o.key?.name??"unknown",d=f(o),b={kind:"property",name:l,span:s(o.start,o.end),isExported:!1,modifiers:d};g.push(b)}return g}function J(c){let g=[];for(let o of c)if(o.type==="TSMethodSignature"){let l=o.key?.name??"unknown",d=(o.params??[]).map(p),b=u(o.returnType);g.push({kind:"method",name:l,span:s(o.start,o.end),isExported:!1,modifiers:[],methodKind:"method",parameters:d.length>0?d:void 0,returnType:b})}else if(o.type==="TSPropertySignature"){let l=o.key?.name??"unknown",d=u(o.typeAnnotation),b={kind:"property",name:l,span:s(o.start,o.end),isExported:!1,modifiers:o.readonly?["readonly"]:[],returnType:d};g.push(b)}return g}function A(c,g){let o=c.type??"";if(o==="FunctionDeclaration"){let l=c.id?.name??"default",d=(c.params??[]).map(p),b=u(c.returnType),D=f(c,c),M=a(c.decorators??[]),k=c.typeParameters?.params?.map((I)=>I.name?.name).filter(Boolean)||void 0,h={kind:"function",name:l,span:s(c.start,c.end),isExported:g,modifiers:D,parameters:d.length>0?d:void 0,returnType:b,decorators:M.length>0?M:void 0};if(k&&k.length>0)h.typeParameters=k;return h}if(o==="ClassDeclaration"||o==="ClassExpression"){let l=c.id?.name??"default",d=x(c),b=N(c.body?.body??[]),D=a(c.decorators??[]),M=f(c,c),k=c.typeParameters?.params?.map((I)=>I.name?.name).filter(Boolean)||void 0,h={kind:"class",name:l,span:s(c.start,c.end),isExported:g,modifiers:M,heritage:d.length>0?d:void 0,members:b.length>0?b:void 0,decorators:D.length>0?D:void 0};if(k&&k.length>0)h.typeParameters=k;return h}if(o==="VariableDeclaration"){let l=[];for(let d of c.declarations??[]){let{id:b,init:D}=d;if(b?.type==="ObjectPattern"){for(let T of b.properties??[]){let z=T.value?.name??T.key?.name??"unknown";l.push({kind:"variable",name:z,span:s(T.start??d.start,T.end??d.end),isExported:g,modifiers:[]})}continue}if(b?.type==="ArrayPattern"){for(let T of b.elements??[]){if(!T||T.type!=="Identifier")continue;let z=T.name??"unknown";l.push({kind:"variable",name:z,span:s(T.start??d.start,T.end??d.end),isExported:g,modifiers:[]})}continue}let M=b?.name??"unknown",k="variable",h,I;if(D?.type==="FunctionExpression"||D?.type==="ArrowFunctionExpression")k="function",h=(D.params??[]).map(p),I=u(D.returnType);let R=[];l.push({kind:k,name:M,span:s(d.start,d.end),isExported:g,modifiers:R,parameters:h,returnType:I})}if(l.length===0)return null;if(l.length===1)return l[0];return l}if(o==="TSTypeAliasDeclaration")return{kind:"type",name:c.id?.name??"unknown",span:s(c.start,c.end),isExported:g,modifiers:[]};if(o==="TSInterfaceDeclaration"){let l=c.id?.name??"unknown",d=S(c),b=J(c.body?.body??[]),D=c.typeParameters?.params?.map((k)=>k.name?.name).filter(Boolean)||void 0,M={kind:"interface",name:l,span:s(c.start,c.end),isExported:g,modifiers:[],heritage:d.length>0?d:void 0,members:b.length>0?b:void 0};if(D&&D.length>0)M.typeParameters=D;return M}if(o==="TSEnumDeclaration"){let l=c.id?.name??"unknown",d=f(c),D=(c.body?.members??[]).map((M)=>({kind:"property",name:M.id?.name??M.id?.value??"unknown",span:s(M.start,M.end),isExported:!1,modifiers:[]}));return{kind:"enum",name:l,span:s(c.start,c.end),isExported:g,modifiers:d,members:D.length>0?D:void 0}}return null}let F=[];for(let c of t.body){let g=null,o=c,l=typeof o.type==="string"?o.type:"";if(l==="ExportNamedDeclaration"){let b=c;if(b.declaration){if(g=A(b.declaration,!0),g&&!Array.isArray(g))g.span=s(b.start,b.end);else if(Array.isArray(g))for(let D of g)D.span=s(b.start,b.end)}}else if(l==="ExportDefaultDeclaration"){let b=c,D=b.declaration;if(D){if(g=A(D,!0),g&&!Array.isArray(g))g.name=D.id?.name??"default",g.isExported=!0,g.span=s(b.start,b.end)}}else g=A(c,!1);let d=Array.isArray(g)?g:g?[g]:[];for(let b of d){let D=c.start??0,M=m(D);if(M){let k=Pn(M);if(!Nt(k))b.jsDoc=k}F.push(b)}}return F}import{resolve as Dn,dirname as At,extname as ht}from"path";function kn(n,t,i){let e=(r)=>{let s=ht(r);if(s==="")return[r+".ts",r+"/index.ts",r+".mts",r+"/index.mts",r+".cts",r+"/index.cts"];if(s===".js")return[r.slice(0,-3)+".ts"];if(s===".mjs")return[r.slice(0,-4)+".mts"];if(s===".cjs")return[r.slice(0,-4)+".cts"];return[r]};if(t.startsWith(".")){let r=Dn(At(n),t);return e(r)}if(i)for(let[r,s]of i.paths){if(s.length===0)continue;let m=r.indexOf("*");if(m===-1){if(t===r){let u=[];for(let a of s)u.push(...e(Dn(i.baseUrl,a)));return u}}else{let u=r.slice(0,m),a=r.slice(m+1);if(t.startsWith(u)&&(a===""||t.endsWith(a))){let p=t.slice(u.length,a===""?void 0:t.length-a.length),f=[];for(let x of s)f.push(...e(Dn(i.baseUrl,x.replace("*",p))));return f}}}return[]}function Qn(n,t,i,e=kn){let r=new Map,s=n.body??[];for(let m of s){if(m.type!=="ImportDeclaration")continue;let u=m.source?.value??"",a=e(t,u,i);if(a.length===0)continue;let p=a[0],f=m.specifiers??[];for(let x of f)switch(x.type){case"ImportSpecifier":r.set(x.local.name,{path:p,importedName:x.imported.name});break;case"ImportDefaultSpecifier":r.set(x.local.name,{path:p,importedName:"default"});break;case"ImportNamespaceSpecifier":r.set(x.local.name,{path:p,importedName:"*"});break}}return r}var Dt=new Set(["loc","start","end","scope"]);function sn(n,t){if(!n||typeof n!=="object")return;if(Array.isArray(n)){for(let e of n)sn(e,t);return}let i=n;t(i);for(let e of Object.keys(i)){if(Dt.has(e))continue;let r=i[e];if(r&&typeof r==="object")sn(r,t)}}function Yn(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n;if((t.type==="StringLiteral"||t.type==="Literal")&&typeof t.value==="string")return t.value;return null}function q(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n;if(t.type==="Identifier"){let i=t.name;return{root:i,parts:[],full:i}}if(t.type==="ThisExpression")return{root:"this",parts:[],full:"this"};if(t.type==="Super")return{root:"super",parts:[],full:"super"};if(t.type==="MemberExpression"){let i=[],e=t;while(e.type==="MemberExpression"){let m=e.property;if(!m||typeof m.name!=="string")return null;i.unshift(m.name),e=e.object}let r;if(e.type==="Identifier")r=e.name;else if(e.type==="ThisExpression")r="this";else if(e.type==="Super")r="super";else return null;let s=[r,...i].join(".");return{root:r,parts:i,full:s}}return null}function Zn(n,t,i,e=kn){let r=[],s=n.body??[];for(let m of s){if(m.type==="ImportDeclaration"){let u=m.source?.value??"",a=e(t,u,i);if(a.length===0)continue;let p=a[0],f=m.importKind==="type",x=m.specifiers??[];if(x.length===0){let S={};if(f)S.isType=!0;r.push({type:f?"type-references":"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:p,dstSymbolName:null,...Object.keys(S).length>0?{metaJson:JSON.stringify(S)}:{}})}else for(let S of x){let N=S.type,J=f||S.importKind==="type",A={};if(J)A.isType=!0;let F,c;if(N==="ImportDefaultSpecifier")F="default",c=S.local.name;else if(N==="ImportNamespaceSpecifier")F="*",c=S.local.name,A.importKind="namespace";else F=S.imported.name,c=S.local.name;r.push({type:J?"type-references":"imports",srcFilePath:t,srcSymbolName:c,dstFilePath:p,dstSymbolName:F,...Object.keys(A).length>0?{metaJson:JSON.stringify(A)}:{}})}continue}if(m.type==="ExportAllDeclaration"&&m.source){let u=m.source?.value??"",a=e(t,u,i);if(a.length===0)continue;let p=a[0],f=m.exportKind==="type",x={isReExport:!0};if(f)x.isType=!0;r.push({type:f?"type-references":"re-exports",srcFilePath:t,srcSymbolName:null,dstFilePath:p,dstSymbolName:null,metaJson:JSON.stringify(x)});continue}if(m.type==="ExportNamedDeclaration"&&m.source){let u=m.source?.value??"",a=e(t,u,i);if(a.length===0)continue;let p=a[0],f=m.exportKind==="type",N={isReExport:!0,specifiers:(m.specifiers??[]).map((J)=>({local:J.local.name,exported:J.exported.name}))};if(f)N.isType=!0;r.push({type:f?"type-references":"re-exports",srcFilePath:t,srcSymbolName:null,dstFilePath:p,dstSymbolName:null,metaJson:JSON.stringify(N)})}}return sn(n,(m)=>{if(m.type!=="ImportExpression")return;let u=Yn(m.source);if(!u)return;let a=e(t,u,i);if(a.length===0)return;let p=a[0];r.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:p,dstSymbolName:null,metaJson:JSON.stringify({isDynamic:!0})})}),r}function vn(n,t,i){let e=[],r=[],s=[];function m(){if(r.length>0)return r[r.length-1]??null;return null}function u(p){if(!p)return null;let f=i.get(p.root);if(p.parts.length===0){if(f)return{dstFilePath:f.path,dstSymbolName:f.importedName,resolution:"import"};return{dstFilePath:t,dstSymbolName:p.root,resolution:"local"}}else{if(f&&f.importedName==="*"){let x=p.parts[p.parts.length-1];return{dstFilePath:f.path,dstSymbolName:x,resolution:"namespace"}}return{dstFilePath:t,dstSymbolName:p.full,resolution:"local-member"}}}function a(p){if(!p||typeof p!=="object")return;if(Array.isArray(p)){for(let S of p)a(S);return}let f=p,x=typeof f.type==="string"?f.type:"";if(x==="ClassDeclaration"||x==="ClassExpression"){let S=f,N=S.id?.name??"AnonymousClass";s.push(N),a(S.body),s.pop();return}if(x==="FunctionDeclaration"){let S=f,N=S.id?.name??"anonymous";r.push(N),a(S.body),r.pop();return}if(x==="VariableDeclarator"&&f.init&&(f.init?.type==="FunctionExpression"||f.init?.type==="ArrowFunctionExpression")){let S=f,N=S.id?.name??"anonymous";r.push(N),a(S.init?.body??S.init),r.pop();return}if(x==="MethodDefinition"&&f.value){let S=f,N=s[s.length-1]??"",J=S.key?.name??"anonymous",A=N?`${N}.${J}`:J;r.push(A),a(S.value?.body),r.pop();return}if(x==="FunctionExpression"||x==="ArrowFunctionExpression"){let S=m(),N=S?`${S}.<anonymous>`:"<anonymous>";r.push(N),a(f.body),r.pop();return}if(x==="CallExpression"){let S=f,N=q(S.callee),J=u(N);if(J){let A=m(),F={};if(A===null)F.scope="module";e.push({type:"calls",srcFilePath:t,srcSymbolName:A,dstFilePath:J.dstFilePath,dstSymbolName:J.dstSymbolName,...Object.keys(F).length>0?{metaJson:JSON.stringify(F)}:{}})}a(S.callee);for(let A of S.arguments??[])a(A);return}if(x==="NewExpression"){let S=f,N=q(S.callee),J=u(N);if(J){let A=m(),F={isNew:!0};if(A===null)F.scope="module";e.push({type:"calls",srcFilePath:t,srcSymbolName:A,dstFilePath:J.dstFilePath,dstSymbolName:J.dstSymbolName,metaJson:JSON.stringify(F)})}for(let A of S.arguments??[])a(A);return}for(let S of Object.keys(f)){if(S==="loc"||S==="start"||S==="end"||S==="scope")continue;let N=f[S];if(N&&typeof N==="object")a(N)}}return a(n),e}function Xn(n,t,i){let e=[];return sn(n,(r)=>{if(r.type==="TSInterfaceDeclaration"){let u=r.id?.name??"AnonymousInterface",a=r.extends??[];for(let p of a){let f=p.expression??p,x=q(f);if(!x)continue;let S=Fn(x,t,i);e.push({type:"extends",srcFilePath:t,srcSymbolName:u,...S})}return}if(r.type!=="ClassDeclaration"&&r.type!=="ClassExpression")return;let s=r.id?.name??"AnonymousClass";if(r.superClass){let u=q(r.superClass);if(u){let a=Fn(u,t,i);e.push({type:"extends",srcFilePath:t,srcSymbolName:s,...a})}}let m=r.implements??[];for(let u of m){let a=u.expression??u,p=q(a);if(!p)continue;let f=Fn(p,t,i);e.push({type:"implements",srcFilePath:t,srcSymbolName:s,...f})}}),e}function Fn(n,t,i){let e=i.get(n.root);if(e){if(e.importedName==="*"){let r=n.parts[n.parts.length-1]??n.root;return{dstFilePath:e.path,dstSymbolName:r,metaJson:JSON.stringify({isNamespaceImport:!0})}}return{dstFilePath:e.path,dstSymbolName:n.parts.length>0?n.full:e.importedName}}return{dstFilePath:t,dstSymbolName:n.full,metaJson:JSON.stringify({isLocal:!0})}}function fn(n,t,i){let e=Qn(n,t,i),r=Zn(n,t,i),s=vn(n,t,e),m=Xn(n,t,e);return[...r,...s,...m]}import{err as En,isErr as It}from"@zipbul/result";import{Database as Rt}from"bun:sqlite";import{mkdirSync as Tt,unlinkSync as jn,existsSync as qn}from"fs";import{dirname as Lt,join as nt}from"path";import{drizzle as $t}from"drizzle-orm/bun-sqlite";import{migrate as Ct}from"drizzle-orm/bun-sqlite/migrator";var Jn={};yt(Jn,{watcherOwner:()=>Mt,symbols:()=>_,relations:()=>w,files:()=>K});import{sql as kt}from"drizzle-orm";import{sqliteTable as pn,text as C,integer as H,real as Ft,index as nn,primaryKey as _t,foreignKey as _n,check as Jt}from"drizzle-orm/sqlite-core";var K=pn("files",{project:C("project").notNull(),filePath:C("file_path").notNull(),mtimeMs:Ft("mtime_ms").notNull(),size:H("size").notNull(),contentHash:C("content_hash").notNull(),updatedAt:C("updated_at").notNull(),lineCount:H("line_count")},(n)=>[_t({columns:[n.project,n.filePath]})]),_=pn("symbols",{id:H("id").primaryKey({autoIncrement:!0}),project:C("project").notNull(),filePath:C("file_path").notNull(),kind:C("kind").notNull(),name:C("name").notNull(),startLine:H("start_line").notNull(),startColumn:H("start_column").notNull(),endLine:H("end_line").notNull(),endColumn:H("end_column").notNull(),isExported:H("is_exported").notNull().default(0),signature:C("signature"),fingerprint:C("fingerprint"),detailJson:C("detail_json"),contentHash:C("content_hash").notNull(),indexedAt:C("indexed_at").notNull()},(n)=>[nn("idx_symbols_project_file").on(n.project,n.filePath),nn("idx_symbols_project_kind").on(n.project,n.kind),nn("idx_symbols_project_name").on(n.project,n.name),nn("idx_symbols_fingerprint").on(n.project,n.fingerprint),_n({columns:[n.project,n.filePath],foreignColumns:[K.project,K.filePath]}).onDelete("cascade")]),w=pn("relations",{id:H("id").primaryKey({autoIncrement:!0}),project:C("project").notNull(),type:C("type").notNull(),srcFilePath:C("src_file_path").notNull(),srcSymbolName:C("src_symbol_name"),dstFilePath:C("dst_file_path").notNull(),dstSymbolName:C("dst_symbol_name"),metaJson:C("meta_json")},(n)=>[nn("idx_relations_src").on(n.project,n.srcFilePath),nn("idx_relations_dst").on(n.project,n.dstFilePath),nn("idx_relations_type").on(n.project,n.type),_n({columns:[n.project,n.srcFilePath],foreignColumns:[K.project,K.filePath]}).onDelete("cascade"),_n({columns:[n.project,n.dstFilePath],foreignColumns:[K.project,K.filePath]}).onDelete("cascade")]),Mt=pn("watcher_owner",{id:H("id").primaryKey(),pid:H("pid").notNull(),startedAt:C("started_at").notNull(),heartbeatAt:C("heartbeat_at").notNull()},(n)=>[Jt("watcher_owner_singleton",kt`${n.id} = 1`)]);class Mn{client=null;drizzle=null;dbPath;txDepth=0;constructor(n){this.dbPath=nt(n.projectRoot,".zipbul","gildash.db")}get drizzleDb(){if(!this.drizzle)throw Error("Database is not open. Call open() first.");return this.drizzle}open(){try{Tt(Lt(this.dbPath),{recursive:!0}),this.client=new Rt(this.dbPath),this.client.run("PRAGMA journal_mode = WAL"),this.client.run("PRAGMA foreign_keys = ON"),this.client.run("PRAGMA busy_timeout = 5000"),this.drizzle=$t(this.client,{schema:Jn}),Ct(this.drizzle,{migrationsFolder:nt(import.meta.dirname,"migrations")});let n=this.client;if(typeof n.function==="function")n.function.call(this.client,"regexp",(t,i)=>{try{return new RegExp(t).test(i)?1:0}catch{return 0}})}catch(n){if(this.isCorruptionError(n)&&qn(this.dbPath)){this.closeClient(),jn(this.dbPath);for(let i of["-wal","-shm"]){let e=this.dbPath+i;if(qn(e))jn(e)}let t=this.open();if(It(t))return En(y("store",`Failed to recover database at ${this.dbPath}`,t.data));return t}return En(y("store",`Failed to open database at ${this.dbPath}`,n))}}close(){this.closeClient(),this.drizzle=null}transaction(n){let t=this.requireClient();if(this.txDepth===0){this.txDepth++;try{return t.transaction(()=>n(this))()}finally{this.txDepth--}}let i=`sp_${this.txDepth++}`;t.run(`SAVEPOINT "${i}"`);try{let e=n(this);return t.run(`RELEASE SAVEPOINT "${i}"`),e}catch(e){throw t.run(`ROLLBACK TO SAVEPOINT "${i}"`),t.run(`RELEASE SAVEPOINT "${i}"`),e}finally{this.txDepth--}}immediateTransaction(n){let t=this.requireClient();this.txDepth++,t.run("BEGIN IMMEDIATE");try{let i=n();return t.run("COMMIT"),i}catch(i){throw t.run("ROLLBACK"),i}finally{this.txDepth--}}query(n){let t=this.requireClient().prepare(n).get();if(!t)return null;return Object.values(t)[0]}getTableNames(){return this.requireClient().query("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((t)=>t.name)}selectOwner(){return this.requireClient().prepare("SELECT pid, heartbeat_at FROM watcher_owner WHERE id = 1").get()??void 0}insertOwner(n){let t=new Date().toISOString();this.requireClient().prepare("INSERT INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(n,t,t)}replaceOwner(n){let t=new Date().toISOString();this.requireClient().prepare("INSERT OR REPLACE INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(n,t,t)}touchOwner(n){let t=new Date().toISOString();this.requireClient().prepare("UPDATE watcher_owner SET heartbeat_at = ? WHERE id = 1 AND pid = ?").run(t,n)}deleteOwner(n){this.requireClient().prepare("DELETE FROM watcher_owner WHERE id = 1 AND pid = ?").run(n)}requireClient(){if(!this.client)throw Error("Database is not open. Call open() first.");return this.client}closeClient(){if(this.client)this.client.close(),this.client=null}isCorruptionError(n){if(!(n instanceof Error))return!1;let t=n.message.toLowerCase();return t.includes("malformed")||t.includes("corrupt")||t.includes("not a database")||t.includes("disk i/o error")||t.includes("sqlite_corrupt")}}import{eq as un,and as tt}from"drizzle-orm";class In{db;constructor(n){this.db=n}getFile(n,t){return this.db.drizzleDb.select().from(K).where(tt(un(K.project,n),un(K.filePath,t))).get()??null}upsertFile(n){this.db.drizzleDb.insert(K).values({project:n.project,filePath:n.filePath,mtimeMs:n.mtimeMs,size:n.size,contentHash:n.contentHash,updatedAt:n.updatedAt,lineCount:n.lineCount??null}).onConflictDoUpdate({target:[K.project,K.filePath],set:{mtimeMs:n.mtimeMs,size:n.size,contentHash:n.contentHash,updatedAt:n.updatedAt,lineCount:n.lineCount??null}}).run()}getAllFiles(n){return this.db.drizzleDb.select().from(K).where(un(K.project,n)).all()}getFilesMap(n){let t=this.getAllFiles(n),i=new Map;for(let e of t)i.set(e.filePath,e);return i}deleteFile(n,t){this.db.drizzleDb.delete(K).where(tt(un(K.project,n),un(K.filePath,t))).run()}}import{eq as G,and as tn,sql as dn,count as Kt}from"drizzle-orm";function gn(n){return n.trim().split(/\s+/).map((t)=>t.trim()).filter((t)=>t.length>0).map((t)=>`"${t.replaceAll('"','""')}"*`).join(" ")}class Rn{db;constructor(n){this.db=n}replaceFileSymbols(n,t,i,e){if(this.db.drizzleDb.delete(_).where(tn(G(_.project,n),G(_.filePath,t))).run(),!e.length)return;let r=new Date().toISOString();for(let s of e)this.db.drizzleDb.insert(_).values({project:n,filePath:t,kind:s.kind??"unknown",name:s.name??"",startLine:s.startLine??0,startColumn:s.startColumn??0,endLine:s.endLine??0,endColumn:s.endColumn??0,isExported:s.isExported??0,signature:s.signature??null,fingerprint:s.fingerprint??null,detailJson:s.detailJson??null,contentHash:i,indexedAt:s.indexedAt??r}).run()}getFileSymbols(n,t){return this.db.drizzleDb.select().from(_).where(tn(G(_.project,n),G(_.filePath,t))).all()}searchByName(n,t,i={}){let e=i.limit??50,r=gn(t);if(!r)return[];return this.db.drizzleDb.select().from(_).where(tn(dn`${_.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${r})`,G(_.project,n),i.kind?G(_.kind,i.kind):void 0)).orderBy(_.name).limit(e).all()}searchByKind(n,t){return this.db.drizzleDb.select().from(_).where(tn(G(_.project,n),G(_.kind,t))).orderBy(_.name).all()}getStats(n){let t=this.db.drizzleDb.select({symbolCount:Kt(),fileCount:dn`COUNT(DISTINCT ${_.filePath})`}).from(_).where(G(_.project,n)).get();return{symbolCount:t?.symbolCount??0,fileCount:t?.fileCount??0}}getByFingerprint(n,t){return this.db.drizzleDb.select().from(_).where(tn(G(_.project,n),G(_.fingerprint,t))).all()}deleteFileSymbols(n,t){this.db.drizzleDb.delete(_).where(tn(G(_.project,n),G(_.filePath,t))).run()}searchByQuery(n){let t=this.db.drizzleDb.select().from(_).where(tn(n.ftsQuery?dn`${_.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${n.ftsQuery})`:void 0,n.exactName?G(_.name,n.exactName):void 0,n.project!==void 0?G(_.project,n.project):void 0,n.kind?G(_.kind,n.kind):void 0,n.filePath!==void 0?G(_.filePath,n.filePath):void 0,n.isExported!==void 0?G(_.isExported,n.isExported?1:0):void 0,n.decorator?dn`${_.id} IN (SELECT s.id FROM symbols s, json_each(s.detail_json, '$.decorators') je WHERE json_extract(je.value, '$.name') = ${n.decorator})`:void 0)).orderBy(_.name).limit(n.regex?Math.max(n.limit*50,5000):n.limit).all();if(!n.regex)return t;try{let i=new RegExp(n.regex);return t.filter((e)=>i.test(e.name)).slice(0,n.limit)}catch{return[]}}}import{eq as $,and as P,isNull as it,or as zt}from"drizzle-orm";class Tn{db;constructor(n){this.db=n}replaceFileRelations(n,t,i){if(this.db.drizzleDb.delete(w).where(P($(w.project,n),$(w.srcFilePath,t))).run(),!i.length)return;for(let e of i)this.db.drizzleDb.insert(w).values({project:n,type:e.type??"unknown",srcFilePath:e.srcFilePath??t,srcSymbolName:e.srcSymbolName??null,dstFilePath:e.dstFilePath??"",dstSymbolName:e.dstSymbolName??null,metaJson:e.metaJson??null}).run()}getOutgoing(n,t,i){if(i!==void 0)return this.db.drizzleDb.select({project:w.project,type:w.type,srcFilePath:w.srcFilePath,srcSymbolName:w.srcSymbolName,dstFilePath:w.dstFilePath,dstSymbolName:w.dstSymbolName,metaJson:w.metaJson}).from(w).where(P($(w.project,n),$(w.srcFilePath,t),zt($(w.srcSymbolName,i),it(w.srcSymbolName)))).all();return this.db.drizzleDb.select({project:w.project,type:w.type,srcFilePath:w.srcFilePath,srcSymbolName:w.srcSymbolName,dstFilePath:w.dstFilePath,dstSymbolName:w.dstSymbolName,metaJson:w.metaJson}).from(w).where(P($(w.project,n),$(w.srcFilePath,t))).all()}getIncoming(n,t){return this.db.drizzleDb.select({project:w.project,type:w.type,srcFilePath:w.srcFilePath,srcSymbolName:w.srcSymbolName,dstFilePath:w.dstFilePath,dstSymbolName:w.dstSymbolName,metaJson:w.metaJson}).from(w).where(P($(w.project,n),$(w.dstFilePath,t))).all()}getByType(n,t){return this.db.drizzleDb.select({project:w.project,type:w.type,srcFilePath:w.srcFilePath,srcSymbolName:w.srcSymbolName,dstFilePath:w.dstFilePath,dstSymbolName:w.dstSymbolName,metaJson:w.metaJson}).from(w).where(P($(w.project,n),$(w.type,t))).all()}deleteFileRelations(n,t){this.db.drizzleDb.delete(w).where(P($(w.project,n),$(w.srcFilePath,t))).run()}searchRelations(n){return this.db.drizzleDb.select({project:w.project,type:w.type,srcFilePath:w.srcFilePath,srcSymbolName:w.srcSymbolName,dstFilePath:w.dstFilePath,dstSymbolName:w.dstSymbolName,metaJson:w.metaJson}).from(w).where(P(n.project!==void 0?$(w.project,n.project):void 0,n.srcFilePath!==void 0?$(w.srcFilePath,n.srcFilePath):void 0,n.srcSymbolName!==void 0?$(w.srcSymbolName,n.srcSymbolName):void 0,n.dstFilePath!==void 0?$(w.dstFilePath,n.dstFilePath):void 0,n.dstSymbolName!==void 0?$(w.dstSymbolName,n.dstSymbolName):void 0,n.type!==void 0?$(w.type,n.type):void 0)).limit(n.limit).all()}retargetRelations(n,t,i,e,r){let s=i===null?P($(w.project,n),$(w.dstFilePath,t),it(w.dstSymbolName)):P($(w.project,n),$(w.dstFilePath,t),$(w.dstSymbolName,i));this.db.drizzleDb.update(w).set({dstFilePath:e,dstSymbolName:r}).where(s).run()}}import{err as et}from"@zipbul/result";import{subscribe as Gt}from"@parcel/watcher";import Ln from"path";var Bt=["**/.git/**","**/.zipbul/**","**/dist/**","**/node_modules/**"],Wt=new Set(["package.json","tsconfig.json"]);function Ht(n){return n.replaceAll("\\","/")}function Ut(n){if(n==="update")return"change";if(n==="create")return"create";return"delete"}class xn{#t;#n;#e;#r;#s;#i;constructor(n,t=Gt,i=console){this.#n=n.projectRoot,this.#e=[...Bt,...n.ignorePatterns??[]],this.#r=new Set((n.extensions??[".ts",".mts",".cts"]).map((e)=>e.toLowerCase())),this.#s=t,this.#i=i}async start(n){try{this.#t=await this.#s(this.#n,(t,i)=>{if(t){this.#i.error(y("watcher","Callback error",t));return}try{for(let e of i){let r=Ht(Ln.relative(this.#n,e.path));if(r.startsWith(".."))continue;let s=Ln.basename(r),m=Ln.extname(r).toLowerCase();if(!Wt.has(s)&&!this.#r.has(m))continue;if(r.endsWith(".d.ts"))continue;n({eventType:Ut(e.type),filePath:r})}}catch(e){this.#i.error(y("watcher","Callback error",e))}},{ignore:this.#e})}catch(t){return et(y("watcher","Failed to subscribe watcher",t))}}async close(){if(!this.#t)return;try{await this.#t.unsubscribe(),this.#t=void 0}catch(n){return et(y("watcher","Failed to close watcher",n))}}}import $n from"path";import{promises as Vt}from"fs";var Pt=["**/node_modules/**","**/.git/**","**/.zipbul/**","**/dist/**"];async function yn(n){let t=[];for await(let i of Vt.glob("**/package.json",{cwd:n,exclude:Pt})){let e=$n.dirname(i).replaceAll("\\","/"),r=$n.join(n,i),s=await Bun.file(r).json(),m=typeof s?.name==="string"&&s.name.length>0?s.name:$n.basename(e==="."?n:e);t.push({dir:e,project:m})}return t.sort((i,e)=>e.dir.length-i.dir.length),t}function Q(n,t,i="default"){let e=n.replaceAll("\\","/");for(let r of t){if(r.dir===".")return r.project;if(e===r.dir||e.startsWith(`${r.dir}/`))return r.project}return i}import rt from"path";var v=new Map;async function Qt(n){let t=Bun.file(n);if(!await t.exists())return null;let i=await t.json();return typeof i==="object"&&i!==null?i:null}async function mn(n){if(v.has(n))return v.get(n)??null;let t=rt.join(n,"tsconfig.json"),i=await Qt(t);if(!i)return v.set(n,null),null;let e=typeof i.compilerOptions==="object"&&i.compilerOptions!==null?i.compilerOptions:null;if(!e)return v.set(n,null),null;let r=typeof e.baseUrl==="string"?e.baseUrl:null,s=typeof e.paths==="object"&&e.paths!==null?e.paths:null;if(!r&&!s)return v.set(n,null),null;let m=r?rt.resolve(n,r):n,u=new Map;if(s)for(let[p,f]of Object.entries(s)){if(!Array.isArray(f))continue;let x=f.filter((S)=>typeof S==="string");u.set(p,x)}let a={baseUrl:m,paths:u};return v.set(n,a),a}function wn(n){if(n){v.delete(n);return}v.clear()}import st from"path";function Cn(n,t){return st.relative(n,t).replaceAll("\\","/")}function an(n,t){return st.resolve(n,t)}function X(n){let t=Bun.hash.xxHash64(n);return BigInt.asUintN(64,BigInt(t)).toString(16).padStart(16,"0")}import{isErr as ut}from"@zipbul/result";import{promises as Yt}from"fs";import{join as Zt}from"path";async function at(n){let{projectRoot:t,extensions:i,ignorePatterns:e,fileRepo:r}=n,s=r.getFilesMap(),m=new Set,u=[],a=[],p=e.map((x)=>new Bun.Glob(x));for await(let x of Yt.glob("**/*",{cwd:t})){if(!i.some((o)=>x.endsWith(o)))continue;if(p.some((o)=>o.match(x)))continue;m.add(x);let S=Zt(t,x),N=Bun.file(S),{size:J,lastModified:A}=N,F=s.get(x);if(!F){let o=await N.text(),l=X(o);u.push({filePath:x,contentHash:l,mtimeMs:A,size:J});continue}if(F.mtimeMs===A&&F.size===J){a.push({filePath:x,contentHash:F.contentHash,mtimeMs:A,size:J});continue}let c=await N.text(),g=X(c);if(g===F.contentHash)a.push({filePath:x,contentHash:g,mtimeMs:A,size:J});else u.push({filePath:x,contentHash:g,mtimeMs:A,size:J})}let f=[];for(let x of s.keys())if(!m.has(x))f.push(x);return{changed:u,unchanged:a,deleted:f}}function vt(n){if(n.kind==="function"||n.kind==="method"){let t=n.parameters?.length??0,i=n.modifiers.includes("async")?1:0;return`params:${t}|async:${i}`}return null}function Xt(n){let t={};if(n.jsDoc)t.jsDoc=n.jsDoc;if(n.kind==="function"||n.kind==="method"){if(n.parameters!==void 0)t.parameters=n.parameters;if(n.returnType!==void 0)t.returnType=n.returnType}if(n.heritage?.length)t.heritage=n.heritage;if(n.decorators?.length)t.decorators=n.decorators;if(n.typeParameters?.length)t.typeParameters=n.typeParameters;if(n.modifiers?.length)t.modifiers=n.modifiers;if(n.members?.length)t.members=n.members.map((i)=>{let e=i.modifiers.find((r)=>r==="private"||r==="protected"||r==="public");return{name:i.name,kind:i.methodKind??i.kind,type:i.returnType,visibility:e,isStatic:i.modifiers.includes("static")||void 0,isReadonly:i.modifiers.includes("readonly")||void 0}});return Object.keys(t).length>0?JSON.stringify(t):null}function ot(n,t,i,e,r){let s=vt(n),m=X(`${t}|${n.kind}|${s??""}`);return{project:i,filePath:e,kind:n.kind,name:t,startLine:n.span.start.line,startColumn:n.span.start.column,endLine:n.span.end.line,endColumn:n.span.end.column,isExported:n.isExported?1:0,signature:s,fingerprint:m,detailJson:Xt(n),contentHash:r,indexedAt:new Date().toISOString()}}function Kn(n){let{parsed:t,project:i,filePath:e,contentHash:r,symbolRepo:s}=n,m=ln(t),u=[];for(let a of m){u.push(ot(a,a.name,i,e,r));for(let p of a.members??[])u.push(ot(p,`${a.name}.${p.name}`,i,e,r))}s.replaceFileSymbols(i,e,r,u)}function zn(n){let{ast:t,project:i,filePath:e,relationRepo:r,projectRoot:s,tsconfigPaths:m}=n,u=an(s,e),a=fn(t,u,m),p=[];for(let f of a){let x=Cn(s,f.dstFilePath);if(x.startsWith(".."))continue;let S=Cn(s,f.srcFilePath);p.push({project:i,type:f.type,srcFilePath:S,srcSymbolName:f.srcSymbolName??null,dstFilePath:x,dstSymbolName:f.dstSymbolName??null,metaJson:f.metaJson??null})}return r.replaceFileRelations(i,e,p),p.length}var Et=100;class cn{opts;logger;callbacks=new Set;indexingLock=!1;pendingEvents=[];debounceTimer=null;currentIndexing=null;pendingFullIndex=!1;pendingFullIndexWaiters=[];tsconfigPathsRaw;boundariesRefresh=null;constructor(n){this.opts=n,this.logger=n.logger??console,this.tsconfigPathsRaw=mn(n.projectRoot)}get tsconfigPaths(){return this.tsconfigPathsRaw}fullIndex(){return this.startIndex(void 0,!0)}incrementalIndex(n){return this.startIndex(n,!1)}onIndexed(n){return this.callbacks.add(n),()=>this.callbacks.delete(n)}handleWatcherEvent(n){if(n.filePath.endsWith("tsconfig.json")){wn(this.opts.projectRoot),this.tsconfigPathsRaw=mn(this.opts.projectRoot),this.fullIndex().catch((t)=>{this.logger.error("[IndexCoordinator] fullIndex failed after tsconfig change:",t)});return}if(n.filePath.endsWith("package.json")){let t=this.opts.discoverProjectsFn??yn;this.boundariesRefresh=t(this.opts.projectRoot).then((i)=>{this.opts.boundaries=i})}if(this.pendingEvents.push(n),this.debounceTimer===null)this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.flushPending()},Et)}async shutdown(){if(this.debounceTimer!==null)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.currentIndexing)await this.currentIndexing}startIndex(n,t){if(this.indexingLock){if(t)return this.pendingFullIndex=!0,new Promise((e,r)=>{this.pendingFullIndexWaiters.push({resolve:e,reject:r})});return this.currentIndexing}this.indexingLock=!0;let i=this.doIndex(n,t).then((e)=>{return this.fireCallbacks(e),e}).finally(()=>{if(this.indexingLock=!1,this.currentIndexing=null,this.pendingFullIndex){this.pendingFullIndex=!1;let e=this.pendingFullIndexWaiters.splice(0);this.startIndex(void 0,!0).then((r)=>{for(let s of e)s.resolve(r)}).catch((r)=>{for(let s of e)s.reject(r)})}else if(this.pendingEvents.length>0){let e=this.pendingEvents.splice(0);this.startIndex(e,!1).catch((r)=>this.logger.error("[IndexCoordinator] incremental drain error",r))}});return this.currentIndexing=i,i}async doIndex(n,t){let i=Date.now(),{fileRepo:e,symbolRepo:r,relationRepo:s,dbConnection:m}=this.opts;if(this.boundariesRefresh)await this.boundariesRefresh,this.boundariesRefresh=null;let u,a;if(n!==void 0)u=n.filter((o)=>o.eventType==="create"||o.eventType==="change").map((o)=>({filePath:o.filePath,contentHash:"",mtimeMs:0,size:0})),a=n.filter((o)=>o.eventType==="delete").map((o)=>o.filePath);else{let o=new Map;for(let d of this.opts.boundaries)for(let[b,D]of e.getFilesMap(d.project))o.set(b,D);let l=await at({projectRoot:this.opts.projectRoot,extensions:this.opts.extensions,ignorePatterns:this.opts.ignorePatterns,fileRepo:{getFilesMap:()=>o}});u=l.changed,a=l.deleted}let p=await this.tsconfigPathsRaw??void 0,f=new Map;for(let o of a){let l=Q(o,this.opts.boundaries),d=r.getFileSymbols(l,o);f.set(o,d)}let x=new Map,S=new Map;if(t)for(let o of this.opts.boundaries)for(let l of e.getAllFiles(o.project))for(let d of r.getFileSymbols(o.project,l.filePath))x.set(`${d.filePath}::${d.name}`,{name:d.name,filePath:d.filePath,kind:d.kind,fingerprint:d.fingerprint});else{for(let o of u){let l=Q(o.filePath,this.opts.boundaries);for(let d of r.getFileSymbols(l,o.filePath))x.set(`${d.filePath}::${d.name}`,{name:d.name,filePath:d.filePath,kind:d.kind,fingerprint:d.fingerprint})}for(let[,o]of f)for(let l of o)x.set(`${l.filePath}::${l.name}`,{name:l.name,filePath:l.filePath,kind:l.kind,fingerprint:l.fingerprint})}let N=()=>{for(let o of a){let l=Q(o,this.opts.boundaries);r.deleteFileSymbols(l,o),s.deleteFileRelations(l,o),e.deleteFile(l,o)}},J=async()=>{let o=0,l=0,d=[];for(let b of u)try{let D=await this.processFile(b.filePath,b.contentHash||void 0,p);o+=D.symbolCount,l+=D.relCount}catch(D){this.logger.error(`[IndexCoordinator] Failed to index ${b.filePath}:`,D),d.push(b.filePath)}return{symbols:o,relations:l,failedFiles:d}},A=0,F=0,c=[];if(t){let{projectRoot:o,boundaries:l}=this.opts,{parseCache:d}=this.opts,b=await Promise.allSettled(u.map(async(k)=>{let h=an(o,k.filePath),I=Bun.file(h),R=await I.text(),T=k.contentHash||X(R);return{filePath:k.filePath,text:R,contentHash:T,mtimeMs:I.lastModified,size:I.size}})),D=b.filter((k)=>k.status==="fulfilled").map((k)=>k.value);for(let k of b)if(k.status==="rejected")this.logger.error("[IndexCoordinator] Failed to pre-read file:",k.reason);let M=[];m.transaction(()=>{for(let h of l){let I=e.getAllFiles(h.project);for(let R of I)e.deleteFile(R.project,R.filePath)}for(let h of D){let I=Q(h.filePath,l);e.upsertFile({project:I,filePath:h.filePath,mtimeMs:h.mtimeMs,size:h.size,contentHash:h.contentHash,updatedAt:new Date().toISOString(),lineCount:h.text.split(`
|
|
4
|
+
`).length})}let k=this.opts.parseSourceFn??on;for(let h of D){let I=Q(h.filePath,l),R=k(an(o,h.filePath),h.text);if(ut(R))throw R.data;let T=R;M.push({filePath:h.filePath,parsed:T}),Kn({parsed:T,project:I,filePath:h.filePath,contentHash:h.contentHash,symbolRepo:r}),F+=zn({ast:T.program,project:I,filePath:h.filePath,relationRepo:s,projectRoot:o,tsconfigPaths:p}),A+=r.getFileSymbols(I,h.filePath).length}});for(let k of M)d.set(k.filePath,k.parsed)}else{N();let o=await J();A=o.symbols,F=o.relations,c=o.failedFiles}for(let o of u){let l=Q(o.filePath,this.opts.boundaries);for(let d of r.getFileSymbols(l,o.filePath))S.set(`${d.filePath}::${d.name}`,{name:d.name,filePath:d.filePath,kind:d.kind,fingerprint:d.fingerprint})}let g={added:[],modified:[],removed:[]};for(let[o,l]of S){let d=x.get(o);if(!d)g.added.push({name:l.name,filePath:l.filePath,kind:l.kind});else if(d.fingerprint!==l.fingerprint)g.modified.push({name:l.name,filePath:l.filePath,kind:l.kind})}for(let[o,l]of x)if(!S.has(o))g.removed.push({name:l.name,filePath:l.filePath,kind:l.kind});if(!t)for(let[o,l]of f)for(let d of l){if(!d.fingerprint)continue;let b=Q(o,this.opts.boundaries),D=r.getByFingerprint(b,d.fingerprint);if(D.length===1){let M=D[0];s.retargetRelations(b,o,d.name,M.filePath,M.name)}}return{indexedFiles:u.length,removedFiles:a.length,totalSymbols:A,totalRelations:F,durationMs:Date.now()-i,changedFiles:u.map((o)=>o.filePath),deletedFiles:[...a],failedFiles:c,changedSymbols:g}}async processFile(n,t,i){let{projectRoot:e,boundaries:r}=this.opts,{fileRepo:s,symbolRepo:m,relationRepo:u,parseCache:a}=this.opts,p=an(e,n),f=Bun.file(p),x=await f.text(),S=t||X(x),N=Q(n,r),A=(this.opts.parseSourceFn??on)(p,x);if(ut(A))throw A.data;let F=A;a.set(n,F),s.upsertFile({project:N,filePath:n,mtimeMs:f.lastModified,size:f.size,contentHash:S,updatedAt:new Date().toISOString(),lineCount:x.split(`
|
|
5
|
+
`).length}),Kn({parsed:F,project:N,filePath:n,contentHash:S,symbolRepo:m});let c=zn({ast:F.program,project:N,filePath:n,relationRepo:u,projectRoot:e,tsconfigPaths:i});return{symbolCount:m.getFileSymbols(N,n).length,relCount:c}}fireCallbacks(n){for(let t of this.callbacks)try{t(n)}catch(i){this.logger.error("[IndexCoordinator] onIndexed callback threw:",i)}}flushPending(){if(this.indexingLock)return;if(this.pendingEvents.length>0){let n=this.pendingEvents.splice(0);this.startIndex(n,!1).catch((t)=>this.logger.error("[IndexCoordinator] flushPending startIndex error:",t))}}}function jt(n){try{return process.kill(n,0),!0}catch(t){if(typeof t==="object"&&t&&"code"in t)return t.code!=="ESRCH";return!0}}function qt(n){let t=new Date(n).getTime();return Number.isNaN(t)?0:t}function mt(n,t,i={}){let e=i.now??Date.now,r=i.isAlive??jt,s=i.staleAfterSeconds??90;return n.immediateTransaction(()=>{let m=n.selectOwner();if(!m)return n.insertOwner(t),"owner";let u=Math.floor((e()-qt(m.heartbeat_at))/1000);if(r(m.pid)&&u<s)return"reader";return n.replaceOwner(t),"owner"})}function ct(n,t){n.deleteOwner(t)}function lt(n,t){n.touchOwner(t)}function Gn(n){let{symbolRepo:t,project:i,query:e}=n,r=e.project??i,s=e.limit??100,m={kind:e.kind,filePath:e.filePath,isExported:e.isExported,project:r,limit:s};if(e.text)if(e.exact)m.exactName=e.text;else{let a=gn(e.text);if(a)m.ftsQuery=a}if(e.decorator)m.decorator=e.decorator;if(e.regex)m.regex=e.regex;return t.searchByQuery(m).map((a)=>({id:a.id,filePath:a.filePath,kind:a.kind,name:a.name,span:{start:{line:a.startLine,column:a.startColumn},end:{line:a.endLine,column:a.endColumn}},isExported:a.isExported===1,signature:a.signature,fingerprint:a.fingerprint,detail:a.detailJson?(()=>{try{return JSON.parse(a.detailJson)}catch{return{}}})():{}}))}function Bn(n){let{relationRepo:t,project:i,query:e}=n,r=e.project??i,s=e.limit??500;return t.searchRelations({srcFilePath:e.srcFilePath,srcSymbolName:e.srcSymbolName,dstFilePath:e.dstFilePath,dstSymbolName:e.dstSymbolName,type:e.type,project:r,limit:s}).map((u)=>{let a;if(u.metaJson)try{a=JSON.parse(u.metaJson)}catch{console.error("[relationSearch] malformed metaJson:",u.metaJson)}return{type:u.type,srcFilePath:u.srcFilePath,srcSymbolName:u.srcSymbolName,dstFilePath:u.dstFilePath,dstSymbolName:u.dstSymbolName,metaJson:u.metaJson??void 0,meta:a}})}class Sn{options;adjacencyList=new Map;reverseAdjacencyList=new Map;constructor(n){this.options=n}build(){this.adjacencyList=new Map,this.reverseAdjacencyList=new Map;let n=[...this.options.relationRepo.getByType(this.options.project,"imports"),...this.options.relationRepo.getByType(this.options.project,"type-references"),...this.options.relationRepo.getByType(this.options.project,"re-exports")];for(let t of n){let{srcFilePath:i,dstFilePath:e}=t;if(!this.adjacencyList.has(i))this.adjacencyList.set(i,new Set);if(this.adjacencyList.get(i).add(e),!this.adjacencyList.has(e))this.adjacencyList.set(e,new Set);if(!this.reverseAdjacencyList.has(e))this.reverseAdjacencyList.set(e,new Set);this.reverseAdjacencyList.get(e).add(i)}}getDependencies(n){return Array.from(this.adjacencyList.get(n)??[])}getDependents(n){return Array.from(this.reverseAdjacencyList.get(n)??[])}getTransitiveDependents(n){let t=new Set,i=[n];while(i.length>0){let e=i.shift();for(let r of this.reverseAdjacencyList.get(e)??[])if(!t.has(r))t.add(r),i.push(r)}return Array.from(t)}hasCycle(){let n=new Set,t=new Set;for(let i of this.adjacencyList.keys()){if(n.has(i))continue;let e=[{node:i,entered:!1}];while(e.length>0){let r=e.pop();if(r.entered){t.delete(r.node);continue}if(t.has(r.node))return!0;if(n.has(r.node))continue;n.add(r.node),t.add(r.node),e.push({node:r.node,entered:!0});for(let s of this.adjacencyList.get(r.node)??[]){if(t.has(s))return!0;if(!n.has(s))e.push({node:s,entered:!1})}}}return!1}getAffectedByChange(n){let t=new Set;for(let i of n)for(let e of this.getTransitiveDependents(i))t.add(e);return Array.from(t)}getAdjacencyList(){let n=new Map;for(let[t,i]of this.adjacencyList)n.set(t,Array.from(i));return n}getTransitiveDependencies(n){let t=new Set,i=[n];while(i.length>0){let e=i.shift();for(let r of this.adjacencyList.get(e)??[])if(!t.has(r))t.add(r),i.push(r)}return Array.from(t)}getCyclePaths(n){let t=n?.maxCycles??1/0;if(t<=0)return[];let i=new Map;for(let[e,r]of this.adjacencyList)i.set(e,Array.from(r));return ri(i,t)}}var ni=(n,t)=>n.localeCompare(t);function ti(n){let t=n.length>1&&n[0]===n[n.length-1]?n.slice(0,-1):[...n];if(t.length===0)return[];let i=t;for(let e=1;e<t.length;e++){let r=t.slice(e).concat(t.slice(0,e));if(r.join("::")<i.join("::"))i=r}return[...i]}function Wn(n,t,i){let e=ti(i);if(e.length===0)return!1;let r=e.join("->");if(n.has(r))return!1;return n.add(r),t.push(e),!0}function ii(n){let t=0,i=[],e=new Set,r=new Map,s=new Map,m=[],u=(a)=>{r.set(a,t),s.set(a,t),t+=1,i.push(a),e.add(a);for(let p of n.get(a)??[])if(!r.has(p))u(p),s.set(a,Math.min(s.get(a)??0,s.get(p)??0));else if(e.has(p))s.set(a,Math.min(s.get(a)??0,r.get(p)??0));if(s.get(a)===r.get(a)){let p=[],f="";do f=i.pop()??"",e.delete(f),p.push(f);while(f!==a&&i.length>0);m.push(p)}};for(let a of n.keys())if(!r.has(a))u(a);return{components:m}}function ei(n,t,i){let e=[],r=new Set,s=[...n].sort(ni),m=(u,a,p)=>{a.delete(u);let f=p.get(u);if(!f)return;for(let x of f)if(a.has(x))m(x,a,p);f.clear()};for(let u=0;u<s.length&&e.length<i;u++){let a=s[u]??"",p=new Set(s.slice(u)),f=new Set,x=new Map,S=[],N=(A)=>(t.get(A)??[]).filter((F)=>p.has(F)),J=(A)=>{if(e.length>=i)return!0;let F=!1;S.push(A),f.add(A);for(let c of N(A)){if(e.length>=i)break;if(c===a)Wn(r,e,S.concat(a)),F=!0;else if(!f.has(c)){if(J(c))F=!0}}if(F)m(A,f,x);else for(let c of N(A)){let g=x.get(c)??new Set;g.add(A),x.set(c,g)}return S.pop(),F};J(a)}return e}function ri(n,t){let{components:i}=ii(n),e=[],r=new Set;for(let s of i){if(e.length>=t)break;if(s.length===0)continue;if(s.length===1){let a=s[0]??"";if((n.get(a)??[]).includes(a))Wn(r,e,[a,a]);continue}let m=t-e.length,u=ei(s,n,m);for(let a of u){if(e.length>=t)break;Wn(r,e,a)}}return e}import{findInFiles as si,Lang as ai}from"@ast-grep/napi";async function Hn(n){if(n.filePaths.length===0)return[];let t=[];return await si(ai.TypeScript,{paths:n.filePaths,matcher:{rule:{pattern:n.pattern}}},(i,e)=>{if(i)return;for(let r of e){let s=r.range();t.push({filePath:r.getRoot().filename(),startLine:s.start.line+1,endLine:s.end.line+1,matchedText:r.text()})}}),t}var ft=30000,pt=60000,ui=10;class Un{projectRoot;db;symbolRepo;relationRepo;fileRepo;parseCache;coordinator;watcher;releaseWatcherRoleFn;parseSourceFn;extractSymbolsFn;extractRelationsFn;symbolSearchFn;relationSearchFn;patternSearchFn;readFileFn;unlinkFn;existsSyncFn;makeExternalCoordinatorFn;logger;defaultProject;role;timer=null;signalHandlers=[];closed=!1;tsconfigPaths=null;boundaries=[];onIndexedCallbacks=new Set;graphCache=null;graphCacheKey=null;constructor(n){this.projectRoot=n.projectRoot,this.db=n.db,this.symbolRepo=n.symbolRepo,this.relationRepo=n.relationRepo,this.fileRepo=n.fileRepo,this.parseCache=n.parseCache,this.coordinator=n.coordinator,this.watcher=n.watcher,this.releaseWatcherRoleFn=n.releaseWatcherRoleFn,this.parseSourceFn=n.parseSourceFn,this.extractSymbolsFn=n.extractSymbolsFn,this.extractRelationsFn=n.extractRelationsFn,this.symbolSearchFn=n.symbolSearchFn,this.relationSearchFn=n.relationSearchFn,this.patternSearchFn=n.patternSearchFn,this.readFileFn=n.readFileFn,this.unlinkFn=n.unlinkFn,this.existsSyncFn=n.existsSyncFn,this.makeExternalCoordinatorFn=n.makeExternalCoordinatorFn,this.logger=n.logger,this.defaultProject=n.defaultProject,this.role=n.role}static async open(n){let{projectRoot:t,extensions:i=[".ts",".mts",".cts"],ignorePatterns:e=[],parseCacheCapacity:r=500,logger:s=console,existsSyncFn:m=oi,dbConnectionFactory:u,watcherFactory:a,coordinatorFactory:p,repositoryFactory:f,acquireWatcherRoleFn:x=mt,releaseWatcherRoleFn:S=ct,updateHeartbeatFn:N=lt,discoverProjectsFn:J=yn,parseSourceFn:A=on,extractSymbolsFn:F=ln,extractRelationsFn:c=fn,symbolSearchFn:g=Gn,relationSearchFn:o=Bn,patternSearchFn:l=Hn,loadTsconfigPathsFn:d=mn,makeExternalCoordinatorFn:b,readFileFn:D=async(R)=>Bun.file(R).text(),unlinkFn:M=async(R)=>{await Bun.file(R).unlink()},watchMode:k}=n;if(!bn.isAbsolute(t))return O(y("validation",`Gildash: projectRoot must be an absolute path, got: "${t}"`));if(!m(t))return O(y("validation",`Gildash: projectRoot does not exist: "${t}"`));let h=u?u():new Mn({projectRoot:t}),I=h.open();if(en(I))return I;try{let R=await J(t),T=R[0]?.project??bn.basename(t),z=f?f():(()=>{let B=h;return{fileRepo:new In(B),symbolRepo:new Rn(B),relationRepo:new Tn(B),parseCache:new An(r)}})(),rn=k??!0,Y;if(rn)Y=await Promise.resolve(x(h,process.pid,{}));else Y="owner";let gt=null,dt=null,L=new Un({projectRoot:t,db:h,symbolRepo:z.symbolRepo,relationRepo:z.relationRepo,fileRepo:z.fileRepo,parseCache:z.parseCache,coordinator:gt,watcher:dt,releaseWatcherRoleFn:S,parseSourceFn:A,extractSymbolsFn:F,extractRelationsFn:c,symbolSearchFn:g,relationSearchFn:o,patternSearchFn:l,readFileFn:D,unlinkFn:M,existsSyncFn:m,makeExternalCoordinatorFn:b,logger:s,defaultProject:T,role:Y});if(wn(t),L.tsconfigPaths=await d(t),L.boundaries=R,Y==="owner"){let B=p?p():new cn({projectRoot:t,boundaries:R,extensions:i,ignorePatterns:e,dbConnection:h,parseCache:z.parseCache,fileRepo:z.fileRepo,symbolRepo:z.symbolRepo,relationRepo:z.relationRepo,logger:s});if(L.coordinator=B,B.onIndexed(()=>L.invalidateGraphCache()),rn){let U=a?a():new xn({projectRoot:t,ignorePatterns:e,extensions:i},void 0,s);L.watcher=U,await U.start((V)=>B.handleWatcherEvent?.(V)).then((V)=>{if(en(V))throw V.data});let E=setInterval(()=>{N(h,process.pid)},ft);L.timer=E}await B.fullIndex()}else{let B=0,U=async()=>{try{let V=await Promise.resolve(x(h,process.pid,{}));if(B=0,V==="owner"){clearInterval(L.timer),L.timer=null;let j=null,Z=null;try{j=a?a():new xn({projectRoot:t,ignorePatterns:e,extensions:i},void 0,s),Z=p?p():new cn({projectRoot:t,boundaries:R,extensions:i,ignorePatterns:e,dbConnection:h,parseCache:z.parseCache,fileRepo:z.fileRepo,symbolRepo:z.symbolRepo,relationRepo:z.relationRepo,logger:s});for(let W of L.onIndexedCallbacks)Z.onIndexed(W);Z.onIndexed(()=>L.invalidateGraphCache()),await j.start((W)=>Z?.handleWatcherEvent?.(W)).then((W)=>{if(en(W))throw W.data});let On=setInterval(()=>{N(h,process.pid)},ft);L.timer=On,L.coordinator=Z,L.watcher=j,await Z.fullIndex()}catch(On){if(s.error("[Gildash] owner promotion failed, reverting to reader",On),j){let W=await j.close();if(en(W))s.error("[Gildash] watcher close error during promotion rollback",W.data);L.watcher=null}if(Z)await Z.shutdown().catch((W)=>s.error("[Gildash] coordinator shutdown error during promotion rollback",W)),L.coordinator=null;if(L.timer===null)L.timer=setInterval(U,pt)}}}catch(V){if(B++,s.error("[Gildash] healthcheck error",V),B>=ui)s.error("[Gildash] healthcheck failed too many times, shutting down"),clearInterval(L.timer),L.timer=null,L.close().catch((j)=>s.error("[Gildash] close error during healthcheck shutdown",j))}},E=setInterval(U,pt);L.timer=E}if(rn){let B=["SIGTERM","SIGINT","beforeExit"];for(let U of B){let E=()=>{L.close().catch((V)=>s.error("[Gildash] close error during signal",U,V))};if(U==="beforeExit")process.on("beforeExit",E);else process.on(U,E);L.signalHandlers.push([U,E])}}return L}catch(R){return h.close(),O(y("store","Gildash: initialization failed",R))}}async close(n){if(this.closed)return;this.closed=!0;let t=[];for(let[i,e]of this.signalHandlers)if(i==="beforeExit")process.off("beforeExit",e);else process.off(i,e);if(this.signalHandlers=[],this.coordinator)try{await this.coordinator.shutdown()}catch(i){t.push(i instanceof Error?i:Error(String(i)))}if(this.watcher){let i=await this.watcher.close();if(en(i))t.push(i.data)}if(this.timer!==null)clearInterval(this.timer),this.timer=null;try{this.releaseWatcherRoleFn(this.db,process.pid)}catch(i){t.push(i instanceof Error?i:Error(String(i)))}try{this.db.close()}catch(i){t.push(i instanceof Error?i:Error(String(i)))}if(n?.cleanup)for(let i of["","-wal","-shm"])try{await this.unlinkFn(bn.join(this.projectRoot,".zipbul","gildash.db"+i))}catch{}if(t.length>0)return O(y("close","Gildash: one or more errors occurred during close()",t))}onIndexed(n){if(this.onIndexedCallbacks.add(n),!this.coordinator)return()=>{this.onIndexedCallbacks.delete(n)};let t=this.coordinator.onIndexed(n);return()=>{this.onIndexedCallbacks.delete(n),t()}}parseSource(n,t,i){if(this.closed)return O(y("closed","Gildash: instance is closed"));let e=this.parseSourceFn(n,t,i);if(en(e))return e;return this.parseCache.set(n,e),e}extractSymbols(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));return this.extractSymbolsFn(n)}extractRelations(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));return this.extractRelationsFn(n.program,n.filePath,this.tsconfigPaths??void 0)}invalidateGraphCache(){this.graphCache=null,this.graphCacheKey=null}getOrBuildGraph(n){let t=n??"__cross__";if(this.graphCache&&this.graphCacheKey===t)return this.graphCache;let i=new Sn({relationRepo:this.relationRepo,project:n??this.defaultProject});return i.build(),this.graphCache=i,this.graphCacheKey=t,i}async reindex(){if(this.closed)return O(y("closed","Gildash: instance is closed"));if(!this.coordinator)return O(y("closed","Gildash: reindex() is not available for readers"));try{let n=await this.coordinator.fullIndex();return this.invalidateGraphCache(),n}catch(n){return O(y("index","Gildash: reindex failed",n))}}get projects(){return[...this.boundaries]}getStats(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.symbolRepo.getStats(n??this.defaultProject)}catch(t){return O(y("store","Gildash: getStats failed",t))}}searchSymbols(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:this.defaultProject,query:n})}catch(t){return O(y("search","Gildash: searchSymbols failed",t))}}searchRelations(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:this.defaultProject,query:n})}catch(t){return O(y("search","Gildash: searchRelations failed",t))}}searchAllSymbols(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:void 0,query:n})}catch(t){return O(y("search","Gildash: searchAllSymbols failed",t))}}searchAllRelations(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:void 0,query:n})}catch(t){return O(y("search","Gildash: searchAllRelations failed",t))}}listIndexedFiles(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.fileRepo.getAllFiles(n??this.defaultProject)}catch(t){return O(y("store","Gildash: listIndexedFiles failed",t))}}getInternalRelations(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{srcFilePath:n,dstFilePath:n,limit:1e4}})}catch(i){return O(y("search","Gildash: getInternalRelations failed",i))}}diffSymbols(n,t){let i=new Map(n.map((u)=>[`${u.name}::${u.filePath}`,u])),e=new Map(t.map((u)=>[`${u.name}::${u.filePath}`,u])),r=[],s=[],m=[];for(let[u,a]of e){let p=i.get(u);if(!p)r.push(a);else if(p.fingerprint!==a.fingerprint)m.push({before:p,after:a})}for(let[u,a]of i)if(!e.has(u))s.push(a);return{added:r,removed:s,modified:m}}getDependencies(n,t,i=1e4){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{srcFilePath:n,type:"imports",project:t??this.defaultProject,limit:i}}).map((e)=>e.dstFilePath)}catch(e){return O(y("search","Gildash: getDependencies failed",e))}}getDependents(n,t,i=1e4){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{dstFilePath:n,type:"imports",project:t??this.defaultProject,limit:i}}).map((e)=>e.srcFilePath)}catch(e){return O(y("search","Gildash: getDependents failed",e))}}async getAffected(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(t).getAffectedByChange(n)}catch(i){return O(y("search","Gildash: getAffected failed",i))}}async hasCycle(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(n).hasCycle()}catch(t){return O(y("search","Gildash: hasCycle failed",t))}}async getImportGraph(n){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(n).getAdjacencyList()}catch(t){return O(y("search","Gildash: getImportGraph failed",t))}}async getTransitiveDependencies(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(t).getTransitiveDependencies(n)}catch(i){return O(y("search","Gildash: getTransitiveDependencies failed",i))}}async getCyclePaths(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.getOrBuildGraph(n).getCyclePaths(t)}catch(i){return O(y("search","Gildash: getCyclePaths failed",i))}}getFullSymbol(n,t,i){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{let e=i??this.defaultProject,r=this.symbolSearchFn({symbolRepo:this.symbolRepo,project:e,query:{text:n,exact:!0,filePath:t,limit:1}});if(r.length===0)return O(y("search",`Gildash: symbol '${n}' not found in '${t}'`));let s=r[0],m=s.detail;return{...s,members:Array.isArray(m.members)?m.members:void 0,jsDoc:typeof m.jsDoc==="string"?m.jsDoc:void 0,parameters:typeof m.parameters==="string"?m.parameters:void 0,returnType:typeof m.returnType==="string"?m.returnType:void 0,heritage:Array.isArray(m.heritage)?m.heritage:void 0,decorators:Array.isArray(m.decorators)?m.decorators:void 0,typeParameters:typeof m.typeParameters==="string"?m.typeParameters:void 0}}catch(e){return O(y("search","Gildash: getFullSymbol failed",e))}}getFileStats(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{let i=t??this.defaultProject,e=this.fileRepo.getFile(i,n);if(!e)return O(y("search",`Gildash: file '${n}' is not in the index`));let r=this.symbolRepo.getFileSymbols(i,n),s=this.relationRepo.getOutgoing(i,n);return{filePath:e.filePath,lineCount:e.lineCount??0,size:e.size,symbolCount:r.length,exportedSymbolCount:r.filter((m)=>m.isExported).length,relationCount:s.length}}catch(i){return O(y("store","Gildash: getFileStats failed",i))}}async getFanMetrics(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{let i=this.getOrBuildGraph(t);return{filePath:n,fanIn:i.getDependents(n).length,fanOut:i.getDependencies(n).length}}catch(i){return O(y("search","Gildash: getFanMetrics failed",i))}}resolveSymbol(n,t,i){if(this.closed)return O(y("closed","Gildash: instance is closed"));let e=i??this.defaultProject,r=new Set,s=[],m=n,u=t;for(;;){let a=`${u}::${m}`;if(r.has(a))return O(y("search","Gildash: resolveSymbol detected circular re-export chain"));r.add(a);let p=this.relationSearchFn({relationRepo:this.relationRepo,project:e,query:{type:"re-exports",srcFilePath:u,limit:500}}),f,x;for(let S of p){let N;if(S.metaJson)try{let A=JSON.parse(S.metaJson);if(Array.isArray(A.specifiers))N=A.specifiers}catch{}if(!N)continue;let J=N.find((A)=>A.exported===m);if(!J)continue;f=S.dstFilePath,x=J.local;break}if(!f||!x)return{originalName:m,originalFilePath:u,reExportChain:s};s.push({filePath:u,exportedAs:m}),u=f,m=x}}async findPattern(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{let i=t?.project??this.defaultProject,e=t?.filePaths?t.filePaths:this.fileRepo.getAllFiles(i).map((r)=>r.filePath);return await this.patternSearchFn({pattern:n,filePaths:e})}catch(i){return O(y("search","Gildash: findPattern failed",i))}}async indexExternalPackages(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));if(this.role!=="owner")return O(y("closed","Gildash: indexExternalPackages() is not available for readers"));try{let i=[];for(let e of n){let r=bn.resolve(this.projectRoot,"node_modules",e);if(!this.existsSyncFn(r))return O(y("validation",`Gildash: package not found in node_modules: ${e}`));let s=`@external/${e}`,u=await(this.makeExternalCoordinatorFn?this.makeExternalCoordinatorFn(r,s):new cn({projectRoot:r,boundaries:[{dir:".",project:s}],extensions:[".d.ts"],ignorePatterns:[],dbConnection:this.db,parseCache:this.parseCache,fileRepo:this.fileRepo,symbolRepo:this.symbolRepo,relationRepo:this.relationRepo,logger:this.logger})).fullIndex();i.push(u)}return i}catch(i){return O(y("store","Gildash: indexExternalPackages failed",i))}}async batchParse(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));let i=new Map;return await Promise.all(n.map(async(e)=>{try{let r=await this.readFileFn(e),s=this.parseSourceFn(e,r,t);if(!en(s))i.set(e,s)}catch{}})),i}getModuleInterface(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{let e=this.symbolSearchFn({symbolRepo:this.symbolRepo,project:t??this.defaultProject,query:{filePath:n,isExported:!0}}).map((r)=>({name:r.name,kind:r.kind,parameters:r.detail.parameters??void 0,returnType:r.detail.returnType??void 0,jsDoc:r.detail.jsDoc??void 0}));return{filePath:n,exports:e}}catch(i){return O(y("search","Gildash: getModuleInterface failed",i))}}async getHeritageChain(n,t,i){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{let e=i??this.defaultProject,r=new Set,s=(m,u,a)=>{let p=`${m}::${u}`;if(r.has(p))return{symbolName:m,filePath:u,kind:a,children:[]};r.add(p);let S=this.relationSearchFn({relationRepo:this.relationRepo,project:e,query:{srcFilePath:u,srcSymbolName:m,limit:1000}}).filter((N)=>N.type==="extends"||N.type==="implements").filter((N)=>N.dstSymbolName!=null).map((N)=>s(N.dstSymbolName,N.dstFilePath,N.type));return{symbolName:m,filePath:u,kind:a,children:S}};return s(n,t)}catch(e){return O(y("search","Gildash: getHeritageChain failed",e))}}getParsedAst(n){if(this.closed)return;return this.parseCache.get(n)}getFileInfo(n,t){if(this.closed)return O(y("closed","Gildash: instance is closed"));try{return this.fileRepo.getFile(t??this.defaultProject,n)}catch(i){return O(y("store","Gildash: getFileInfo failed",i))}}getSymbolsByFile(n,t){return this.searchSymbols({filePath:n,project:t??void 0,limit:1e4})}}export{Gn as symbolSearch,Bn as relationSearch,Hn as patternSearch,y as gildashError,Un as Gildash,Sn as DependencyGraph};
|
|
6
6
|
|
|
7
|
-
//# debugId=
|
|
7
|
+
//# debugId=F837B101196A860D64756E2164756E21
|
|
8
8
|
//# sourceMappingURL=index.js.map
|