@zipbul/gildash 0.1.2 → 0.2.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/dist/index.js +4 -4
- package/dist/index.js.map +6 -6
- package/dist/src/common/project-discovery.d.ts +7 -0
- package/dist/src/gildash.d.ts +2 -1
- package/dist/src/index.d.ts +5 -0
- package/dist/src/indexer/index-coordinator.d.ts +13 -0
- package/dist/src/store/repositories/symbol.repository.d.ts +7 -0
- package/dist/src/watcher/types.d.ts +6 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
`)t.push(n+1);return t}function be(e,t){let n=0,r=e.length-1;while(n<r){let i=n+r+1>>1;if(e[i]<=t)n=i;else r=i-1}return{line:n+1,column:t-e[n]}}import{err as pt}from"@zipbul/result";import{parse as ft}from"comment-parser";function Le(e){try{let t=e.trim();if(t.startsWith("/**"))t=t.slice(3);if(t.endsWith("*/"))t=t.slice(0,-2);let r=ft(`/** ${t} */`)[0]??{description:"",tags:[]};return{description:(r.description??"").trim(),tags:(r.tags??[]).map((i)=>({tag:i.tag??"",name:i.name??"",type:i.type??"",description:i.description??"",optional:i.optional??!1,...i.default!==void 0?{default:i.default}:{}}))}}catch(t){return pt(R("parse","Failed to parse JSDoc comment",t))}}import{isErr as gt}from"@zipbul/result";function ae(e){let{program:t,sourceText:n,comments:r}=e,i=Me(n);function s(o,c){return{start:be(i,o),end:be(i,c)}}function u(o){let c=null;for(let a of r){if(a.type!=="Block")continue;if(a.end>o)continue;if(!a.value.startsWith("*"))continue;if(!c||a.end>c.end)c={value:`/*${a.value}*/`,end:a.end}}if(!c)return;for(let a of t.body){let g=a.start??0;if(g===o)continue;if(g>c.end&&g<o)return}return c.value}function m(o){if(!o)return;let c=o.typeAnnotation??o;return n.slice(c.start,c.end)}function l(o){if(!o||o.length===0)return[];return o.map((c)=>{let a=c.expression;if(!a)return{name:"unknown"};if(a.type==="CallExpression"){let g=a.callee?.name??a.callee?.property?.name??"unknown",y=(a.arguments??[]).map((p)=>n.slice(p.start,p.end));return{name:g,arguments:y.length>0?y:void 0}}if(a.type==="Identifier")return{name:a.name??"unknown"};return{name:n.slice(a.start,a.end)}})}function h(o){let c=o.type==="TSParameterProperty"?o.parameter:o;if(c?.type==="RestElement"){let E=`...${c.argument?.name??"unknown"}`,z=c.typeAnnotation,B=z?m(z):void 0,F={name:E,isOptional:!1};if(B)F.type=B;return F}if(c?.type==="AssignmentPattern"){let{left:w,right:E}=c,z=w?.name??"unknown",B=w?.typeAnnotation,F=B?m(B):void 0,K=n.slice(E.start,E.end),j=l(w?.decorators??[]),M={name:z,isOptional:!0,defaultValue:K};if(F)M.type=F;if(j.length>0)M.decorators=j;return M}let a=c?.name??c?.pattern?.name??"unknown",g=!!c?.optional,y=c?.typeAnnotation,p=y?m(y):void 0,S=l(c?.decorators??[]),k={name:a,isOptional:g};if(p)k.type=p;if(S.length>0)k.decorators=S;return k}function f(o,c){let a=[];if(c?.async)a.push("async");if(o.static)a.push("static");if(o.abstract)a.push("abstract");if(o.readonly)a.push("readonly");if(o.override)a.push("override");if(o.declare)a.push("declare");if(o.const)a.push("const");let g=o.accessibility;if(g==="private")a.push("private");else if(g==="protected")a.push("protected");else if(g==="public")a.push("public");return a}function x(o){let c=[];if(o.superClass){let g=n.slice(o.superClass.start,o.superClass.end);c.push({kind:"extends",name:g})}let a=o.implements??[];for(let g of a){let y=g.expression??g,p=n.slice(y.start,y.end);c.push({kind:"implements",name:p})}return c}function P(o){let c=[];for(let a of o.extends??[]){let g=a.expression??a,y=n.slice(g.start,g.end);c.push({kind:"extends",name:y})}return c}function N(o){let c=[];for(let a of o)if(a.type==="MethodDefinition"){let g=a.key?.name??"unknown",y=a.value,p=a.kind??"method",S=p==="constructor"?"constructor":p==="get"?"getter":p==="set"?"setter":"method",k=f(a,y),w=(y?.params??[]).map(h),E=m(y?.returnType),z={kind:"method",name:g,span:s(a.start,a.end),isExported:!1,methodKind:S,modifiers:k,parameters:w.length>0?w:void 0,returnType:E};c.push(z)}else if(a.type==="PropertyDefinition"){let g=a.key?.name??"unknown",y=f(a),p={kind:"property",name:g,span:s(a.start,a.end),isExported:!1,modifiers:y};c.push(p)}return c}function C(o){let c=[];for(let a of o)if(a.type==="TSMethodSignature"){let g=a.key?.name??"unknown",y=(a.params??[]).map(h),p=m(a.returnType);c.push({kind:"method",name:g,span:s(a.start,a.end),isExported:!1,modifiers:[],methodKind:"method",parameters:y.length>0?y:void 0,returnType:p})}else if(a.type==="TSPropertySignature"){let g=a.key?.name??"unknown",y=m(a.typeAnnotation),p={kind:"property",name:g,span:s(a.start,a.end),isExported:!1,modifiers:a.readonly?["readonly"]:[],returnType:y};c.push(p)}return c}function v(o,c){let a=o.type??"";if(a==="FunctionDeclaration"){let g=o.id?.name??"default",y=(o.params??[]).map(h),p=m(o.returnType),S=f(o,o),k=l(o.decorators??[]),w=o.typeParameters?.params?.map((z)=>z.name?.name).filter(Boolean)||void 0,E={kind:"function",name:g,span:s(o.start,o.end),isExported:c,modifiers:S,parameters:y.length>0?y:void 0,returnType:p,decorators:k.length>0?k:void 0};if(w&&w.length>0)E.typeParameters=w;return E}if(a==="ClassDeclaration"||a==="ClassExpression"){let g=o.id?.name??"default",y=x(o),p=N(o.body?.body??[]),S=l(o.decorators??[]),k=f(o,o),w=o.typeParameters?.params?.map((z)=>z.name?.name).filter(Boolean)||void 0,E={kind:"class",name:g,span:s(o.start,o.end),isExported:c,modifiers:k,heritage:y.length>0?y:void 0,members:p.length>0?p:void 0,decorators:S.length>0?S:void 0};if(w&&w.length>0)E.typeParameters=w;return E}if(a==="VariableDeclaration"){let g=[];for(let y of o.declarations??[]){let{id:p,init:S}=y;if(p?.type==="ObjectPattern"){for(let F of p.properties??[]){let K=F.value?.name??F.key?.name??"unknown";g.push({kind:"variable",name:K,span:s(F.start??y.start,F.end??y.end),isExported:c,modifiers:[]})}continue}if(p?.type==="ArrayPattern"){for(let F of p.elements??[]){if(!F||F.type!=="Identifier")continue;let K=F.name??"unknown";g.push({kind:"variable",name:K,span:s(F.start??y.start,F.end??y.end),isExported:c,modifiers:[]})}continue}let k=p?.name??"unknown",w="variable",E,z;if(S?.type==="FunctionExpression"||S?.type==="ArrowFunctionExpression")w="function",E=(S.params??[]).map(h),z=m(S.returnType);let B=[];g.push({kind:w,name:k,span:s(y.start,y.end),isExported:c,modifiers:B,parameters:E,returnType:z})}if(g.length===0)return null;if(g.length===1)return g[0];return g}if(a==="TSTypeAliasDeclaration")return{kind:"type",name:o.id?.name??"unknown",span:s(o.start,o.end),isExported:c,modifiers:[]};if(a==="TSInterfaceDeclaration"){let g=o.id?.name??"unknown",y=P(o),p=C(o.body?.body??[]),S=o.typeParameters?.params?.map((w)=>w.name?.name).filter(Boolean)||void 0,k={kind:"interface",name:g,span:s(o.start,o.end),isExported:c,modifiers:[],heritage:y.length>0?y:void 0,members:p.length>0?p:void 0};if(S&&S.length>0)k.typeParameters=S;return k}if(a==="TSEnumDeclaration"){let g=o.id?.name??"unknown",y=f(o),S=(o.body?.members??[]).map((k)=>({kind:"property",name:k.id?.name??k.id?.value??"unknown",span:s(k.start,k.end),isExported:!1,modifiers:[]}));return{kind:"enum",name:g,span:s(o.start,o.end),isExported:c,modifiers:y,members:S.length>0?S:void 0}}return null}let b=[];for(let o of t.body){let c=null,a=o,g=typeof a.type==="string"?a.type:"";if(g==="ExportNamedDeclaration"){let p=o;if(p.declaration){if(c=v(p.declaration,!0),c&&!Array.isArray(c))c.span=s(p.start,p.end);else if(Array.isArray(c))for(let S of c)S.span=s(p.start,p.end)}}else if(g==="ExportDefaultDeclaration"){let p=o,S=p.declaration;if(S){if(c=v(S,!0),c&&!Array.isArray(c))c.name=S.id?.name??"default",c.isExported=!0,c.span=s(p.start,p.end)}}else c=v(o,!1);let y=Array.isArray(c)?c:c?[c]:[];for(let p of y){let S=o.start??0,k=u(S);if(k){let w=Le(k);if(!gt(w))p.jsDoc=w}b.push(p)}}return b}import{resolve as xe,dirname as ht,extname as yt}from"path";function Se(e,t,n){let r=(i)=>{let s=yt(i);if(s==="")return[i+".ts",i+"/index.ts",i+".mts",i+"/index.mts",i+".cts",i+"/index.cts"];if(s===".js")return[i.slice(0,-3)+".ts"];if(s===".mjs")return[i.slice(0,-4)+".mts"];if(s===".cjs")return[i.slice(0,-4)+".cts"];return[i]};if(t.startsWith(".")){let i=xe(ht(e),t);return r(i)}if(n)for(let[i,s]of n.paths){if(s.length===0)continue;let u=i.indexOf("*");if(u===-1){if(t===i){let m=[];for(let l of s)m.push(...r(xe(n.baseUrl,l)));return m}}else{let m=i.slice(0,u),l=i.slice(u+1);if(t.startsWith(m)&&(l===""||t.endsWith(l))){let h=t.slice(m.length,l===""?void 0:t.length-l.length),f=[];for(let x of s)f.push(...r(xe(n.baseUrl,x.replace("*",h))));return f}}}return[]}function Je(e,t,n,r=Se){let i=new Map,s=e.body??[];for(let u of s){if(u.type!=="ImportDeclaration")continue;let m=u.source?.value??"",l=r(t,m,n);if(l.length===0)continue;let h=l[0],f=u.specifiers??[];for(let x of f)switch(x.type){case"ImportSpecifier":i.set(x.local.name,{path:h,importedName:x.imported.name});break;case"ImportDefaultSpecifier":i.set(x.local.name,{path:h,importedName:"default"});break;case"ImportNamespaceSpecifier":i.set(x.local.name,{path:h,importedName:"*"});break}}return i}var bt=new Set(["loc","start","end","scope"]);function Z(e,t){if(!e||typeof e!=="object")return;if(Array.isArray(e)){for(let r of e)Z(r,t);return}let n=e;t(n);for(let r of Object.keys(n)){if(bt.has(r))continue;let i=n[r];if(i&&typeof i==="object")Z(i,t)}}function Be(e){if(!e||typeof e!=="object"||Array.isArray(e))return null;let t=e;if((t.type==="StringLiteral"||t.type==="Literal")&&typeof t.value==="string")return t.value;return null}function Q(e){if(!e||typeof e!=="object"||Array.isArray(e))return null;let t=e;if(t.type==="Identifier"){let n=t.name;return{root:n,parts:[],full:n}}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 n=[],r=t;while(r.type==="MemberExpression"){let u=r.property;if(!u||typeof u.name!=="string")return null;n.unshift(u.name),r=r.object}let i;if(r.type==="Identifier")i=r.name;else if(r.type==="ThisExpression")i="this";else if(r.type==="Super")i="super";else return null;let s=[i,...n].join(".");return{root:i,parts:n,full:s}}return null}function He(e,t,n,r=Se){let i=[],s=e.body??[];for(let u of s){if(u.type==="ImportDeclaration"){let m=u.source?.value??"",l=r(t,m,n);if(l.length===0)continue;let h=l[0],f=u.importKind==="type";i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:h,dstSymbolName:null,...f?{metaJson:JSON.stringify({isType:!0})}:{}});continue}if(u.type==="ExportAllDeclaration"&&u.source){let m=u.source?.value??"",l=r(t,m,n);if(l.length===0)continue;let h=l[0],f=u.exportKind==="type",x={isReExport:!0};if(f)x.isType=!0;i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:h,dstSymbolName:null,metaJson:JSON.stringify(x)});continue}if(u.type==="ExportNamedDeclaration"&&u.source){let m=u.source?.value??"",l=r(t,m,n);if(l.length===0)continue;let h=l[0];i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:h,dstSymbolName:null,metaJson:JSON.stringify({isReExport:!0})})}}return Z(e,(u)=>{if(u.type!=="ImportExpression")return;let m=Be(u.source);if(!m)return;let l=r(t,m,n);if(l.length===0)return;let h=l[0];i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:h,dstSymbolName:null,metaJson:JSON.stringify({isDynamic:!0})})}),i}function $e(e,t,n){let r=[],i=[],s=[];function u(){if(i.length>0)return i[i.length-1]??null;return null}function m(h){if(!h)return null;let f=n.get(h.root);if(h.parts.length===0){if(f)return{dstFilePath:f.path,dstSymbolName:f.importedName,resolution:"import"};return{dstFilePath:t,dstSymbolName:h.root,resolution:"local"}}else{if(f&&f.importedName==="*"){let x=h.parts[h.parts.length-1];return{dstFilePath:f.path,dstSymbolName:x,resolution:"namespace"}}return{dstFilePath:t,dstSymbolName:h.full,resolution:"local-member"}}}function l(h){if(!h||typeof h!=="object")return;if(Array.isArray(h)){for(let P of h)l(P);return}let f=h,x=typeof f.type==="string"?f.type:"";if(x==="ClassDeclaration"||x==="ClassExpression"){let P=f,N=P.id?.name??"AnonymousClass";s.push(N),l(P.body),s.pop();return}if(x==="FunctionDeclaration"){let P=f,N=P.id?.name??"anonymous";i.push(N),l(P.body),i.pop();return}if(x==="VariableDeclarator"&&f.init&&(f.init?.type==="FunctionExpression"||f.init?.type==="ArrowFunctionExpression")){let P=f,N=P.id?.name??"anonymous";i.push(N),l(P.init?.body??P.init),i.pop();return}if(x==="MethodDefinition"&&f.value){let P=f,N=s[s.length-1]??"",C=P.key?.name??"anonymous",v=N?`${N}.${C}`:C;i.push(v),l(P.value?.body),i.pop();return}if(x==="FunctionExpression"||x==="ArrowFunctionExpression"){let P=u(),N=P?`${P}.<anonymous>`:"<anonymous>";i.push(N),l(f.body),i.pop();return}if(x==="CallExpression"){let P=f,N=Q(P.callee),C=m(N);if(C){let v=u(),b={};if(v===null)b.scope="module";r.push({type:"calls",srcFilePath:t,srcSymbolName:v,dstFilePath:C.dstFilePath,dstSymbolName:C.dstSymbolName,...Object.keys(b).length>0?{metaJson:JSON.stringify(b)}:{}})}l(P.callee);for(let v of P.arguments??[])l(v);return}if(x==="NewExpression"){let P=f,N=Q(P.callee),C=m(N);if(C){let v=u(),b={isNew:!0};if(v===null)b.scope="module";r.push({type:"calls",srcFilePath:t,srcSymbolName:v,dstFilePath:C.dstFilePath,dstSymbolName:C.dstSymbolName,metaJson:JSON.stringify(b)})}for(let v of P.arguments??[])l(v);return}for(let P of Object.keys(f)){if(P==="loc"||P==="start"||P==="end"||P==="scope")continue;let N=f[P];if(N&&typeof N==="object")l(N)}}return l(e),r}function Ge(e,t,n){let r=[];return Z(e,(i)=>{if(i.type==="TSInterfaceDeclaration"){let m=i.id?.name??"AnonymousInterface",l=i.extends??[];for(let h of l){let f=h.expression??h,x=Q(f);if(!x)continue;let P=Pe(x,t,n);r.push({type:"extends",srcFilePath:t,srcSymbolName:m,...P})}return}if(i.type!=="ClassDeclaration"&&i.type!=="ClassExpression")return;let s=i.id?.name??"AnonymousClass";if(i.superClass){let m=Q(i.superClass);if(m){let l=Pe(m,t,n);r.push({type:"extends",srcFilePath:t,srcSymbolName:s,...l})}}let u=i.implements??[];for(let m of u){let l=m.expression??m,h=Q(l);if(!h)continue;let f=Pe(h,t,n);r.push({type:"implements",srcFilePath:t,srcSymbolName:s,...f})}}),r}function Pe(e,t,n){let r=n.get(e.root);if(r){if(r.importedName==="*"){let i=e.parts[e.parts.length-1]??e.root;return{dstFilePath:r.path,dstSymbolName:i,metaJson:JSON.stringify({isNamespaceImport:!0})}}return{dstFilePath:r.path,dstSymbolName:e.parts.length>0?e.full:r.importedName}}return{dstFilePath:t,dstSymbolName:e.full,metaJson:JSON.stringify({isLocal:!0})}}function le(e,t,n){let r=Je(e,t,n),i=He(e,t,n),s=$e(e,t,r),u=Ge(e,t,r);return[...i,...s,...u]}import{err as We,isErr as Rt}from"@zipbul/result";import{Database as Nt}from"bun:sqlite";import{mkdirSync as kt,unlinkSync as Ke,existsSync as Ue}from"fs";import{dirname as Ot,join as Ve}from"path";import{drizzle as vt}from"drizzle-orm/bun-sqlite";import{migrate as Ct}from"drizzle-orm/bun-sqlite/migrator";var Re={};mt(Re,{watcherOwner:()=>Ft,symbols:()=>O,relations:()=>d,files:()=>I,FTS_SETUP_SQL:()=>Fe});import{sql as xt}from"drizzle-orm";import{sqliteTable as ce,text as D,integer as J,real as St,index as X,primaryKey as Pt,foreignKey as we,check as wt}from"drizzle-orm/sqlite-core";var I=ce("files",{project:D("project").notNull(),filePath:D("file_path").notNull(),mtimeMs:St("mtime_ms").notNull(),size:J("size").notNull(),contentHash:D("content_hash").notNull(),updatedAt:D("updated_at").notNull()},(e)=>[Pt({columns:[e.project,e.filePath]})]),O=ce("symbols",{id:J("id").primaryKey({autoIncrement:!0}),project:D("project").notNull(),filePath:D("file_path").notNull(),kind:D("kind").notNull(),name:D("name").notNull(),startLine:J("start_line").notNull(),startColumn:J("start_column").notNull(),endLine:J("end_line").notNull(),endColumn:J("end_column").notNull(),isExported:J("is_exported").notNull().default(0),signature:D("signature"),fingerprint:D("fingerprint"),detailJson:D("detail_json"),contentHash:D("content_hash").notNull(),indexedAt:D("indexed_at").notNull()},(e)=>[X("idx_symbols_project_file").on(e.project,e.filePath),X("idx_symbols_project_kind").on(e.project,e.kind),X("idx_symbols_project_name").on(e.project,e.name),X("idx_symbols_fingerprint").on(e.project,e.fingerprint),we({columns:[e.project,e.filePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade")]),d=ce("relations",{id:J("id").primaryKey({autoIncrement:!0}),project:D("project").notNull(),type:D("type").notNull(),srcFilePath:D("src_file_path").notNull(),srcSymbolName:D("src_symbol_name"),dstFilePath:D("dst_file_path").notNull(),dstSymbolName:D("dst_symbol_name"),metaJson:D("meta_json")},(e)=>[X("idx_relations_src").on(e.project,e.srcFilePath),X("idx_relations_dst").on(e.project,e.dstFilePath),X("idx_relations_type").on(e.project,e.type),we({columns:[e.project,e.srcFilePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade"),we({columns:[e.project,e.dstFilePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade")]),Ft=ce("watcher_owner",{id:J("id").primaryKey(),pid:J("pid").notNull(),startedAt:D("started_at").notNull(),heartbeatAt:D("heartbeat_at").notNull()},(e)=>[wt("watcher_owner_singleton",xt`${e.id} = 1`)]),Fe=[`CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(
|
|
2
|
+
var mn=Object.defineProperty;var un=(t,n)=>{for(var e in n)mn(t,e,{get:n[e],enumerable:!0,configurable:!0,set:(r)=>n[e]=()=>r})};import{err as _,isErr as nt}from"@zipbul/result";import an from"path";import{existsSync as Qn}from"fs";import{err as pn}from"@zipbul/result";import{parseSync as dn}from"oxc-parser";function k(t,n,e){return e!==void 0?{type:t,message:n,cause:e}:{type:t,message:n}}function rt(t,n,e=dn){try{let{program:r,errors:i,comments:s}=e(t,n);return{filePath:t,program:r,errors:i,comments:s,sourceText:n}}catch(r){return pn(k("parse",`Failed to parse file: ${t}`,r))}}class yt{#n;#t=new Map;constructor(t){this.#n=Math.max(1,t)}get size(){return this.#t.size}has(t){return this.#t.has(t)}get(t){if(!this.#t.has(t))return;let n=this.#t.get(t);return this.#t.delete(t),this.#t.set(t,n),n}set(t,n){if(this.#t.has(t))this.#t.delete(t);if(this.#t.set(t,n),this.#t.size>this.#n){let e=this.#t.keys().next().value;if(e!==void 0)this.#t.delete(e)}}delete(t){return this.#t.delete(t)}clear(){this.#t.clear()}}class ht{lru;constructor(t=500){this.lru=new yt(t)}get(t){return this.lru.get(t)}set(t,n){this.lru.set(t,n)}invalidate(t){this.lru.delete(t)}invalidateAll(){this.lru.clear()}size(){return this.lru.size}}function Lt(t){let n=[0];for(let e=0;e<t.length;e++)if(t[e]===`
|
|
3
|
+
`)n.push(e+1);return n}function bt(t,n){let e=0,r=t.length-1;while(e<r){let i=e+r+1>>1;if(t[i]<=n)e=i;else r=i-1}return{line:e+1,column:n-t[e]}}import{err as fn}from"@zipbul/result";import{parse as gn}from"comment-parser";function Jt(t){try{let n=t.trim();if(n.startsWith("/**"))n=n.slice(3);if(n.endsWith("*/"))n=n.slice(0,-2);let r=gn(`/** ${n} */`)[0]??{description:"",tags:[]};return{description:(r.description??"").trim(),tags:(r.tags??[]).map((i)=>({tag:i.tag??"",name:i.name??"",type:i.type??"",description:i.description??"",optional:i.optional??!1,...i.default!==void 0?{default:i.default}:{}}))}}catch(n){return fn(k("parse","Failed to parse JSDoc comment",n))}}import{isErr as yn}from"@zipbul/result";function at(t){let{program:n,sourceText:e,comments:r}=t,i=Lt(e);function s(o,l){return{start:bt(i,o),end:bt(i,l)}}function p(o){let l=null;for(let a of r){if(a.type!=="Block")continue;if(a.end>o)continue;if(!a.value.startsWith("*"))continue;if(!l||a.end>l.end)l={value:`/*${a.value}*/`,end:a.end}}if(!l)return;for(let a of n.body){let g=a.start??0;if(g===o)continue;if(g>l.end&&g<o)return}return l.value}function m(o){if(!o)return;let l=o.typeAnnotation??o;return e.slice(l.start,l.end)}function c(o){if(!o||o.length===0)return[];return o.map((l)=>{let a=l.expression;if(!a)return{name:"unknown"};if(a.type==="CallExpression"){let g=a.callee?.name??a.callee?.property?.name??"unknown",h=(a.arguments??[]).map((d)=>e.slice(d.start,d.end));return{name:g,arguments:h.length>0?h:void 0}}if(a.type==="Identifier")return{name:a.name??"unknown"};return{name:e.slice(a.start,a.end)}})}function y(o){let l=o.type==="TSParameterProperty"?o.parameter:o;if(l?.type==="RestElement"){let T=`...${l.argument?.name??"unknown"}`,z=l.typeAnnotation,B=z?m(z):void 0,O={name:T,isOptional:!1};if(B)O.type=B;return O}if(l?.type==="AssignmentPattern"){let{left:N,right:T}=l,z=N?.name??"unknown",B=N?.typeAnnotation,O=B?m(B):void 0,W=e.slice(T.start,T.end),v=c(N?.decorators??[]),L={name:z,isOptional:!0,defaultValue:W};if(O)L.type=O;if(v.length>0)L.decorators=v;return L}let a=l?.name??l?.pattern?.name??"unknown",g=!!l?.optional,h=l?.typeAnnotation,d=h?m(h):void 0,S=c(l?.decorators??[]),A={name:a,isOptional:g};if(d)A.type=d;if(S.length>0)A.decorators=S;return A}function f(o,l){let a=[];if(l?.async)a.push("async");if(o.static)a.push("static");if(o.abstract)a.push("abstract");if(o.readonly)a.push("readonly");if(o.override)a.push("override");if(o.declare)a.push("declare");if(o.const)a.push("const");let g=o.accessibility;if(g==="private")a.push("private");else if(g==="protected")a.push("protected");else if(g==="public")a.push("public");return a}function x(o){let l=[];if(o.superClass){let g=e.slice(o.superClass.start,o.superClass.end);l.push({kind:"extends",name:g})}let a=o.implements??[];for(let g of a){let h=g.expression??g,d=e.slice(h.start,h.end);l.push({kind:"implements",name:d})}return l}function w(o){let l=[];for(let a of o.extends??[]){let g=a.expression??a,h=e.slice(g.start,g.end);l.push({kind:"extends",name:h})}return l}function P(o){let l=[];for(let a of o)if(a.type==="MethodDefinition"){let g=a.key?.name??"unknown",h=a.value,d=a.kind??"method",S=d==="constructor"?"constructor":d==="get"?"getter":d==="set"?"setter":"method",A=f(a,h),N=(h?.params??[]).map(y),T=m(h?.returnType),z={kind:"method",name:g,span:s(a.start,a.end),isExported:!1,methodKind:S,modifiers:A,parameters:N.length>0?N:void 0,returnType:T};l.push(z)}else if(a.type==="PropertyDefinition"){let g=a.key?.name??"unknown",h=f(a),d={kind:"property",name:g,span:s(a.start,a.end),isExported:!1,modifiers:h};l.push(d)}return l}function E(o){let l=[];for(let a of o)if(a.type==="TSMethodSignature"){let g=a.key?.name??"unknown",h=(a.params??[]).map(y),d=m(a.returnType);l.push({kind:"method",name:g,span:s(a.start,a.end),isExported:!1,modifiers:[],methodKind:"method",parameters:h.length>0?h:void 0,returnType:d})}else if(a.type==="TSPropertySignature"){let g=a.key?.name??"unknown",h=m(a.typeAnnotation),d={kind:"property",name:g,span:s(a.start,a.end),isExported:!1,modifiers:a.readonly?["readonly"]:[],returnType:h};l.push(d)}return l}function F(o,l){let a=o.type??"";if(a==="FunctionDeclaration"){let g=o.id?.name??"default",h=(o.params??[]).map(y),d=m(o.returnType),S=f(o,o),A=c(o.decorators??[]),N=o.typeParameters?.params?.map((z)=>z.name?.name).filter(Boolean)||void 0,T={kind:"function",name:g,span:s(o.start,o.end),isExported:l,modifiers:S,parameters:h.length>0?h:void 0,returnType:d,decorators:A.length>0?A:void 0};if(N&&N.length>0)T.typeParameters=N;return T}if(a==="ClassDeclaration"||a==="ClassExpression"){let g=o.id?.name??"default",h=x(o),d=P(o.body?.body??[]),S=c(o.decorators??[]),A=f(o,o),N=o.typeParameters?.params?.map((z)=>z.name?.name).filter(Boolean)||void 0,T={kind:"class",name:g,span:s(o.start,o.end),isExported:l,modifiers:A,heritage:h.length>0?h:void 0,members:d.length>0?d:void 0,decorators:S.length>0?S:void 0};if(N&&N.length>0)T.typeParameters=N;return T}if(a==="VariableDeclaration"){let g=[];for(let h of o.declarations??[]){let{id:d,init:S}=h;if(d?.type==="ObjectPattern"){for(let O of d.properties??[]){let W=O.value?.name??O.key?.name??"unknown";g.push({kind:"variable",name:W,span:s(O.start??h.start,O.end??h.end),isExported:l,modifiers:[]})}continue}if(d?.type==="ArrayPattern"){for(let O of d.elements??[]){if(!O||O.type!=="Identifier")continue;let W=O.name??"unknown";g.push({kind:"variable",name:W,span:s(O.start??h.start,O.end??h.end),isExported:l,modifiers:[]})}continue}let A=d?.name??"unknown",N="variable",T,z;if(S?.type==="FunctionExpression"||S?.type==="ArrowFunctionExpression")N="function",T=(S.params??[]).map(y),z=m(S.returnType);let B=[];g.push({kind:N,name:A,span:s(h.start,h.end),isExported:l,modifiers:B,parameters:T,returnType:z})}if(g.length===0)return null;if(g.length===1)return g[0];return g}if(a==="TSTypeAliasDeclaration")return{kind:"type",name:o.id?.name??"unknown",span:s(o.start,o.end),isExported:l,modifiers:[]};if(a==="TSInterfaceDeclaration"){let g=o.id?.name??"unknown",h=w(o),d=E(o.body?.body??[]),S=o.typeParameters?.params?.map((N)=>N.name?.name).filter(Boolean)||void 0,A={kind:"interface",name:g,span:s(o.start,o.end),isExported:l,modifiers:[],heritage:h.length>0?h:void 0,members:d.length>0?d:void 0};if(S&&S.length>0)A.typeParameters=S;return A}if(a==="TSEnumDeclaration"){let g=o.id?.name??"unknown",h=f(o),S=(o.body?.members??[]).map((A)=>({kind:"property",name:A.id?.name??A.id?.value??"unknown",span:s(A.start,A.end),isExported:!1,modifiers:[]}));return{kind:"enum",name:g,span:s(o.start,o.end),isExported:l,modifiers:h,members:S.length>0?S:void 0}}return null}let b=[];for(let o of n.body){let l=null,a=o,g=typeof a.type==="string"?a.type:"";if(g==="ExportNamedDeclaration"){let d=o;if(d.declaration){if(l=F(d.declaration,!0),l&&!Array.isArray(l))l.span=s(d.start,d.end);else if(Array.isArray(l))for(let S of l)S.span=s(d.start,d.end)}}else if(g==="ExportDefaultDeclaration"){let d=o,S=d.declaration;if(S){if(l=F(S,!0),l&&!Array.isArray(l))l.name=S.id?.name??"default",l.isExported=!0,l.span=s(d.start,d.end)}}else l=F(o,!1);let h=Array.isArray(l)?l:l?[l]:[];for(let d of h){let S=o.start??0,A=p(S);if(A){let N=Jt(A);if(!yn(N))d.jsDoc=N}b.push(d)}}return b}import{resolve as xt,dirname as hn,extname as bn}from"path";function St(t,n,e){let r=(i)=>{let s=bn(i);if(s==="")return[i+".ts",i+"/index.ts",i+".mts",i+"/index.mts",i+".cts",i+"/index.cts"];if(s===".js")return[i.slice(0,-3)+".ts"];if(s===".mjs")return[i.slice(0,-4)+".mts"];if(s===".cjs")return[i.slice(0,-4)+".cts"];return[i]};if(n.startsWith(".")){let i=xt(hn(t),n);return r(i)}if(e)for(let[i,s]of e.paths){if(s.length===0)continue;let p=i.indexOf("*");if(p===-1){if(n===i){let m=[];for(let c of s)m.push(...r(xt(e.baseUrl,c)));return m}}else{let m=i.slice(0,p),c=i.slice(p+1);if(n.startsWith(m)&&(c===""||n.endsWith(c))){let y=n.slice(m.length,c===""?void 0:n.length-c.length),f=[];for(let x of s)f.push(...r(xt(e.baseUrl,x.replace("*",y))));return f}}}return[]}function Gt(t,n,e,r=St){let i=new Map,s=t.body??[];for(let p of s){if(p.type!=="ImportDeclaration")continue;let m=p.source?.value??"",c=r(n,m,e);if(c.length===0)continue;let y=c[0],f=p.specifiers??[];for(let x of f)switch(x.type){case"ImportSpecifier":i.set(x.local.name,{path:y,importedName:x.imported.name});break;case"ImportDefaultSpecifier":i.set(x.local.name,{path:y,importedName:"default"});break;case"ImportNamespaceSpecifier":i.set(x.local.name,{path:y,importedName:"*"});break}}return i}var xn=new Set(["loc","start","end","scope"]);function Z(t,n){if(!t||typeof t!=="object")return;if(Array.isArray(t)){for(let r of t)Z(r,n);return}let e=t;n(e);for(let r of Object.keys(e)){if(xn.has(r))continue;let i=e[r];if(i&&typeof i==="object")Z(i,n)}}function Bt(t){if(!t||typeof t!=="object"||Array.isArray(t))return null;let n=t;if((n.type==="StringLiteral"||n.type==="Literal")&&typeof n.value==="string")return n.value;return null}function j(t){if(!t||typeof t!=="object"||Array.isArray(t))return null;let n=t;if(n.type==="Identifier"){let e=n.name;return{root:e,parts:[],full:e}}if(n.type==="ThisExpression")return{root:"this",parts:[],full:"this"};if(n.type==="Super")return{root:"super",parts:[],full:"super"};if(n.type==="MemberExpression"){let e=[],r=n;while(r.type==="MemberExpression"){let p=r.property;if(!p||typeof p.name!=="string")return null;e.unshift(p.name),r=r.object}let i;if(r.type==="Identifier")i=r.name;else if(r.type==="ThisExpression")i="this";else if(r.type==="Super")i="super";else return null;let s=[i,...e].join(".");return{root:i,parts:e,full:s}}return null}function Kt(t,n,e,r=St){let i=[],s=t.body??[];for(let p of s){if(p.type==="ImportDeclaration"){let m=p.source?.value??"",c=r(n,m,e);if(c.length===0)continue;let y=c[0],f=p.importKind==="type";i.push({type:"imports",srcFilePath:n,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,...f?{metaJson:JSON.stringify({isType:!0})}:{}});continue}if(p.type==="ExportAllDeclaration"&&p.source){let m=p.source?.value??"",c=r(n,m,e);if(c.length===0)continue;let y=c[0],f=p.exportKind==="type",x={isReExport:!0};if(f)x.isType=!0;i.push({type:"imports",srcFilePath:n,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,metaJson:JSON.stringify(x)});continue}if(p.type==="ExportNamedDeclaration"&&p.source){let m=p.source?.value??"",c=r(n,m,e);if(c.length===0)continue;let y=c[0];i.push({type:"imports",srcFilePath:n,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,metaJson:JSON.stringify({isReExport:!0})})}}return Z(t,(p)=>{if(p.type!=="ImportExpression")return;let m=Bt(p.source);if(!m)return;let c=r(n,m,e);if(c.length===0)return;let y=c[0];i.push({type:"imports",srcFilePath:n,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,metaJson:JSON.stringify({isDynamic:!0})})}),i}function $t(t,n,e){let r=[],i=[],s=[];function p(){if(i.length>0)return i[i.length-1]??null;return null}function m(y){if(!y)return null;let f=e.get(y.root);if(y.parts.length===0){if(f)return{dstFilePath:f.path,dstSymbolName:f.importedName,resolution:"import"};return{dstFilePath:n,dstSymbolName:y.root,resolution:"local"}}else{if(f&&f.importedName==="*"){let x=y.parts[y.parts.length-1];return{dstFilePath:f.path,dstSymbolName:x,resolution:"namespace"}}return{dstFilePath:n,dstSymbolName:y.full,resolution:"local-member"}}}function c(y){if(!y||typeof y!=="object")return;if(Array.isArray(y)){for(let w of y)c(w);return}let f=y,x=typeof f.type==="string"?f.type:"";if(x==="ClassDeclaration"||x==="ClassExpression"){let w=f,P=w.id?.name??"AnonymousClass";s.push(P),c(w.body),s.pop();return}if(x==="FunctionDeclaration"){let w=f,P=w.id?.name??"anonymous";i.push(P),c(w.body),i.pop();return}if(x==="VariableDeclarator"&&f.init&&(f.init?.type==="FunctionExpression"||f.init?.type==="ArrowFunctionExpression")){let w=f,P=w.id?.name??"anonymous";i.push(P),c(w.init?.body??w.init),i.pop();return}if(x==="MethodDefinition"&&f.value){let w=f,P=s[s.length-1]??"",E=w.key?.name??"anonymous",F=P?`${P}.${E}`:E;i.push(F),c(w.value?.body),i.pop();return}if(x==="FunctionExpression"||x==="ArrowFunctionExpression"){let w=p(),P=w?`${w}.<anonymous>`:"<anonymous>";i.push(P),c(f.body),i.pop();return}if(x==="CallExpression"){let w=f,P=j(w.callee),E=m(P);if(E){let F=p(),b={};if(F===null)b.scope="module";r.push({type:"calls",srcFilePath:n,srcSymbolName:F,dstFilePath:E.dstFilePath,dstSymbolName:E.dstSymbolName,...Object.keys(b).length>0?{metaJson:JSON.stringify(b)}:{}})}c(w.callee);for(let F of w.arguments??[])c(F);return}if(x==="NewExpression"){let w=f,P=j(w.callee),E=m(P);if(E){let F=p(),b={isNew:!0};if(F===null)b.scope="module";r.push({type:"calls",srcFilePath:n,srcSymbolName:F,dstFilePath:E.dstFilePath,dstSymbolName:E.dstSymbolName,metaJson:JSON.stringify(b)})}for(let F of w.arguments??[])c(F);return}for(let w of Object.keys(f)){if(w==="loc"||w==="start"||w==="end"||w==="scope")continue;let P=f[w];if(P&&typeof P==="object")c(P)}}return c(t),r}function Ut(t,n,e){let r=[];return Z(t,(i)=>{if(i.type==="TSInterfaceDeclaration"){let m=i.id?.name??"AnonymousInterface",c=i.extends??[];for(let y of c){let f=y.expression??y,x=j(f);if(!x)continue;let w=wt(x,n,e);r.push({type:"extends",srcFilePath:n,srcSymbolName:m,...w})}return}if(i.type!=="ClassDeclaration"&&i.type!=="ClassExpression")return;let s=i.id?.name??"AnonymousClass";if(i.superClass){let m=j(i.superClass);if(m){let c=wt(m,n,e);r.push({type:"extends",srcFilePath:n,srcSymbolName:s,...c})}}let p=i.implements??[];for(let m of p){let c=m.expression??m,y=j(c);if(!y)continue;let f=wt(y,n,e);r.push({type:"implements",srcFilePath:n,srcSymbolName:s,...f})}}),r}function wt(t,n,e){let r=e.get(t.root);if(r){if(r.importedName==="*"){let i=t.parts[t.parts.length-1]??t.root;return{dstFilePath:r.path,dstSymbolName:i,metaJson:JSON.stringify({isNamespaceImport:!0})}}return{dstFilePath:r.path,dstSymbolName:t.parts.length>0?t.full:r.importedName}}return{dstFilePath:n,dstSymbolName:t.full,metaJson:JSON.stringify({isLocal:!0})}}function ct(t,n,e){let r=Gt(t,n,e),i=Kt(t,n,e),s=$t(t,n,r),p=Ut(t,n,r);return[...i,...s,...p]}import{err as Vt,isErr as Pn}from"@zipbul/result";import{Database as An}from"bun:sqlite";import{mkdirSync as Dn,unlinkSync as Wt,existsSync as Ht}from"fs";import{dirname as Fn,join as Qt}from"path";import{drizzle as En}from"drizzle-orm/bun-sqlite";import{migrate as Tn}from"drizzle-orm/bun-sqlite/migrator";var kt={};un(kt,{watcherOwner:()=>kn,symbols:()=>D,relations:()=>u,files:()=>I,FTS_SETUP_SQL:()=>Ot});import{sql as Sn}from"drizzle-orm";import{sqliteTable as lt,text as C,integer as G,real as wn,index as X,primaryKey as Nn,foreignKey as Nt,check as On}from"drizzle-orm/sqlite-core";var I=lt("files",{project:C("project").notNull(),filePath:C("file_path").notNull(),mtimeMs:wn("mtime_ms").notNull(),size:G("size").notNull(),contentHash:C("content_hash").notNull(),updatedAt:C("updated_at").notNull()},(t)=>[Nn({columns:[t.project,t.filePath]})]),D=lt("symbols",{id:G("id").primaryKey({autoIncrement:!0}),project:C("project").notNull(),filePath:C("file_path").notNull(),kind:C("kind").notNull(),name:C("name").notNull(),startLine:G("start_line").notNull(),startColumn:G("start_column").notNull(),endLine:G("end_line").notNull(),endColumn:G("end_column").notNull(),isExported:G("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()},(t)=>[X("idx_symbols_project_file").on(t.project,t.filePath),X("idx_symbols_project_kind").on(t.project,t.kind),X("idx_symbols_project_name").on(t.project,t.name),X("idx_symbols_fingerprint").on(t.project,t.fingerprint),Nt({columns:[t.project,t.filePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade")]),u=lt("relations",{id:G("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")},(t)=>[X("idx_relations_src").on(t.project,t.srcFilePath),X("idx_relations_dst").on(t.project,t.dstFilePath),X("idx_relations_type").on(t.project,t.type),Nt({columns:[t.project,t.srcFilePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade"),Nt({columns:[t.project,t.dstFilePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade")]),kn=lt("watcher_owner",{id:G("id").primaryKey(),pid:G("pid").notNull(),startedAt:C("started_at").notNull(),heartbeatAt:C("heartbeat_at").notNull()},(t)=>[On("watcher_owner_singleton",Sn`${t.id} = 1`)]),Ot=[`CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(
|
|
4
4
|
name,
|
|
5
5
|
file_path,
|
|
6
6
|
kind,
|
|
@@ -20,7 +20,7 @@ var ct=Object.defineProperty;var mt=(e,t)=>{for(var n in t)ct(e,n,{get:t[n],enum
|
|
|
20
20
|
VALUES ('delete', old.id, old.name, old.file_path, old.kind);
|
|
21
21
|
INSERT INTO symbols_fts(rowid, name, file_path, kind)
|
|
22
22
|
VALUES (new.id, new.name, new.file_path, new.kind);
|
|
23
|
-
END`];class Ne{client=null;drizzle=null;dbPath;txDepth=0;constructor(e){this.dbPath=Ve(e.projectRoot,".zipbul","gildash.db")}get drizzleDb(){if(!this.drizzle)throw Error("Database is not open. Call open() first.");return this.drizzle}open(){try{kt(Ot(this.dbPath),{recursive:!0}),this.client=new Nt(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=vt(this.client,{schema:Re}),Ct(this.drizzle,{migrationsFolder:Ve(import.meta.dirname,"migrations")});for(let e of Fe)this.client.run(e)}catch(e){if(this.isCorruptionError(e)&&Ue(this.dbPath)){this.closeClient(),Ke(this.dbPath);for(let n of["-wal","-shm"]){let r=this.dbPath+n;if(Ue(r))Ke(r)}let t=this.open();if(Rt(t))return We(R("store",`Failed to recover database at ${this.dbPath}`,t.data));return t}return We(R("store",`Failed to open database at ${this.dbPath}`,e))}}close(){this.closeClient(),this.drizzle=null}transaction(e){let t=this.requireClient();if(this.txDepth===0){this.txDepth++;try{return t.transaction(()=>e(this))()}finally{this.txDepth--}}let n=`sp_${this.txDepth++}`;t.run(`SAVEPOINT "${n}"`);try{let r=e(this);return t.run(`RELEASE SAVEPOINT "${n}"`),r}catch(r){throw t.run(`ROLLBACK TO SAVEPOINT "${n}"`),t.run(`RELEASE SAVEPOINT "${n}"`),r}finally{this.txDepth--}}immediateTransaction(e){let t=this.requireClient();this.txDepth++,t.run("BEGIN IMMEDIATE");try{let n=e();return t.run("COMMIT"),n}catch(n){throw t.run("ROLLBACK"),n}finally{this.txDepth--}}query(e){let t=this.requireClient().prepare(e).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(e){let t=new Date().toISOString();this.requireClient().prepare("INSERT INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(e,t,t)}replaceOwner(e){let t=new Date().toISOString();this.requireClient().prepare("INSERT OR REPLACE INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(e,t,t)}touchOwner(e){let t=new Date().toISOString();this.requireClient().prepare("UPDATE watcher_owner SET heartbeat_at = ? WHERE id = 1 AND pid = ?").run(t,e)}deleteOwner(e){this.requireClient().prepare("DELETE FROM watcher_owner WHERE id = 1 AND pid = ?").run(e)}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(e){if(!(e instanceof Error))return!1;let t=e.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 ie,and as Qe}from"drizzle-orm";class ke{db;constructor(e){this.db=e}getFile(e,t){return this.db.drizzleDb.select().from(I).where(Qe(ie(I.project,e),ie(I.filePath,t))).get()??null}upsertFile(e){this.db.drizzleDb.insert(I).values({project:e.project,filePath:e.filePath,mtimeMs:e.mtimeMs,size:e.size,contentHash:e.contentHash,updatedAt:e.updatedAt}).onConflictDoUpdate({target:[I.project,I.filePath],set:{mtimeMs:e.mtimeMs,size:e.size,contentHash:e.contentHash,updatedAt:e.updatedAt}}).run()}getAllFiles(e){return this.db.drizzleDb.select().from(I).where(ie(I.project,e)).all()}getFilesMap(e){let t=this.getAllFiles(e),n=new Map;for(let r of t)n.set(r.filePath,r);return n}deleteFile(e,t){this.db.drizzleDb.delete(I).where(Qe(ie(I.project,e),ie(I.filePath,t))).run()}}import{eq as _,and as Y,sql as Oe,count as Et}from"drizzle-orm";function me(e){return e.trim().split(/\s+/).map((t)=>t.trim()).filter((t)=>t.length>0).map((t)=>`"${t.replaceAll('"','""')}"*`).join(" ")}class ve{db;constructor(e){this.db=e}replaceFileSymbols(e,t,n,r){if(this.db.drizzleDb.delete(O).where(Y(_(O.project,e),_(O.filePath,t))).run(),!r.length)return;let i=new Date().toISOString();for(let s of r)this.db.drizzleDb.insert(O).values({project:e,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:n,indexedAt:s.indexedAt??i}).run()}getFileSymbols(e,t){return this.db.drizzleDb.select().from(O).where(Y(_(O.project,e),_(O.filePath,t))).all()}searchByName(e,t,n={}){let r=n.limit??50,i=me(t);if(!i)return[];return this.db.drizzleDb.select().from(O).where(Y(Oe`${O.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${i})`,_(O.project,e),n.kind?_(O.kind,n.kind):void 0)).orderBy(O.name).limit(r).all()}searchByKind(e,t){return this.db.drizzleDb.select().from(O).where(Y(_(O.project,e),_(O.kind,t))).orderBy(O.name).all()}getStats(e){let t=this.db.drizzleDb.select({symbolCount:Et(),fileCount:Oe`COUNT(DISTINCT ${O.filePath})`}).from(O).where(_(O.project,e)).get();return{symbolCount:t?.symbolCount??0,fileCount:t?.fileCount??0}}getByFingerprint(e,t){return this.db.drizzleDb.select().from(O).where(Y(_(O.project,e),_(O.fingerprint,t))).all()}deleteFileSymbols(e,t){this.db.drizzleDb.delete(O).where(Y(_(O.project,e),_(O.filePath,t))).run()}searchByQuery(e){return this.db.drizzleDb.select().from(O).where(Y(e.ftsQuery?Oe`${O.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${e.ftsQuery})`:void 0,e.project!==void 0?_(O.project,e.project):void 0,e.kind?_(O.kind,e.kind):void 0,e.filePath!==void 0?_(O.filePath,e.filePath):void 0,e.isExported!==void 0?_(O.isExported,e.isExported?1:0):void 0)).orderBy(O.name).limit(e.limit).all()}}import{eq as A,and as H,isNull as Xe,or as At}from"drizzle-orm";class Ce{db;constructor(e){this.db=e}replaceFileRelations(e,t,n){if(this.db.drizzleDb.delete(d).where(H(A(d.project,e),A(d.srcFilePath,t))).run(),!n.length)return;for(let r of n)this.db.drizzleDb.insert(d).values({project:e,type:r.type??"unknown",srcFilePath:r.srcFilePath??t,srcSymbolName:r.srcSymbolName??null,dstFilePath:r.dstFilePath??"",dstSymbolName:r.dstSymbolName??null,metaJson:r.metaJson??null}).run()}getOutgoing(e,t,n){if(n!==void 0)return this.db.drizzleDb.select({project:d.project,type:d.type,srcFilePath:d.srcFilePath,srcSymbolName:d.srcSymbolName,dstFilePath:d.dstFilePath,dstSymbolName:d.dstSymbolName,metaJson:d.metaJson}).from(d).where(H(A(d.project,e),A(d.srcFilePath,t),At(A(d.srcSymbolName,n),Xe(d.srcSymbolName)))).all();return this.db.drizzleDb.select({project:d.project,type:d.type,srcFilePath:d.srcFilePath,srcSymbolName:d.srcSymbolName,dstFilePath:d.dstFilePath,dstSymbolName:d.dstSymbolName,metaJson:d.metaJson}).from(d).where(H(A(d.project,e),A(d.srcFilePath,t))).all()}getIncoming(e,t){return this.db.drizzleDb.select({project:d.project,type:d.type,srcFilePath:d.srcFilePath,srcSymbolName:d.srcSymbolName,dstFilePath:d.dstFilePath,dstSymbolName:d.dstSymbolName,metaJson:d.metaJson}).from(d).where(H(A(d.project,e),A(d.dstFilePath,t))).all()}getByType(e,t){return this.db.drizzleDb.select({project:d.project,type:d.type,srcFilePath:d.srcFilePath,srcSymbolName:d.srcSymbolName,dstFilePath:d.dstFilePath,dstSymbolName:d.dstSymbolName,metaJson:d.metaJson}).from(d).where(H(A(d.project,e),A(d.type,t))).all()}deleteFileRelations(e,t){this.db.drizzleDb.delete(d).where(H(A(d.project,e),A(d.srcFilePath,t))).run()}searchRelations(e){return this.db.drizzleDb.select({project:d.project,type:d.type,srcFilePath:d.srcFilePath,srcSymbolName:d.srcSymbolName,dstFilePath:d.dstFilePath,dstSymbolName:d.dstSymbolName,metaJson:d.metaJson}).from(d).where(H(e.project!==void 0?A(d.project,e.project):void 0,e.srcFilePath!==void 0?A(d.srcFilePath,e.srcFilePath):void 0,e.srcSymbolName!==void 0?A(d.srcSymbolName,e.srcSymbolName):void 0,e.dstFilePath!==void 0?A(d.dstFilePath,e.dstFilePath):void 0,e.dstSymbolName!==void 0?A(d.dstSymbolName,e.dstSymbolName):void 0,e.type!==void 0?A(d.type,e.type):void 0)).limit(e.limit).all()}retargetRelations(e,t,n,r,i){let s=n===null?H(A(d.project,e),A(d.dstFilePath,t),Xe(d.dstSymbolName)):H(A(d.project,e),A(d.dstFilePath,t),A(d.dstSymbolName,n));this.db.drizzleDb.update(d).set({dstFilePath:r,dstSymbolName:i}).where(s).run()}}import{err as Ye}from"@zipbul/result";import{subscribe as Tt}from"@parcel/watcher";import Ee from"path";var Dt=["**/.git/**","**/.zipbul/**","**/dist/**","**/node_modules/**"],It=new Set(["package.json","tsconfig.json"]);function jt(e){return e.replaceAll("\\","/")}function _t(e){if(e==="update")return"change";if(e==="create")return"create";return"delete"}class de{#t;#e;#r;#i;#s;#n;constructor(e,t=Tt,n=console){this.#e=e.projectRoot,this.#r=[...Dt,...e.ignorePatterns??[]],this.#i=new Set((e.extensions??[".ts",".mts",".cts"]).map((r)=>r.toLowerCase())),this.#s=t,this.#n=n}async start(e){try{this.#t=await this.#s(this.#e,(t,n)=>{if(t){this.#n.error(R("watcher","Callback error",t));return}try{for(let r of n){let i=jt(Ee.relative(this.#e,r.path));if(i.startsWith(".."))continue;let s=Ee.basename(i),u=Ee.extname(i).toLowerCase();if(!It.has(s)&&!this.#i.has(u))continue;if(i.endsWith(".d.ts"))continue;e({eventType:_t(r.type),filePath:i})}}catch(r){this.#n.error(R("watcher","Callback error",r))}},{ignore:this.#r})}catch(t){return Ye(R("watcher","Failed to subscribe watcher",t))}}async close(){if(!this.#t)return;try{await this.#t.unsubscribe(),this.#t=void 0}catch(e){return Ye(R("watcher","Failed to close watcher",e))}}}import Ae from"path";import{promises as zt}from"fs";var Mt=["**/node_modules/**","**/.git/**","**/.zipbul/**","**/dist/**"];async function ue(e){let t=[];for await(let n of zt.glob("**/package.json",{cwd:e,exclude:Mt})){let r=Ae.dirname(n).replaceAll("\\","/"),i=Ae.join(e,n),s=await Bun.file(i).json(),u=typeof s?.name==="string"&&s.name.length>0?s.name:Ae.basename(r==="."?e:r);t.push({dir:r,project:u})}return t.sort((n,r)=>r.dir.length-n.dir.length),t}function q(e,t,n="default"){let r=e.replaceAll("\\","/");for(let i of t){if(i.dir===".")return i.project;if(r===i.dir||r.startsWith(`${i.dir}/`))return i.project}return n}import Ze from"path";var G=new Map;async function Lt(e){let t=Bun.file(e);if(!await t.exists())return null;let n=await t.json();return typeof n==="object"&&n!==null?n:null}async function se(e){if(G.has(e))return G.get(e)??null;let t=Ze.join(e,"tsconfig.json"),n=await Lt(t);if(!n)return G.set(e,null),null;let r=typeof n.compilerOptions==="object"&&n.compilerOptions!==null?n.compilerOptions:null;if(!r)return G.set(e,null),null;let i=typeof r.baseUrl==="string"?r.baseUrl:null,s=typeof r.paths==="object"&&r.paths!==null?r.paths:null;if(!i&&!s)return G.set(e,null),null;let u=i?Ze.resolve(e,i):e,m=new Map;if(s)for(let[h,f]of Object.entries(s)){if(!Array.isArray(f))continue;let x=f.filter((P)=>typeof P==="string");m.set(h,x)}let l={baseUrl:u,paths:m};return G.set(e,l),l}function pe(e){if(e){G.delete(e);return}G.clear()}import qe from"path";function Te(e,t){return qe.relative(e,t).replaceAll("\\","/")}function ee(e,t){return qe.resolve(e,t)}function W(e){let t=Bun.hash.xxHash64(e);return BigInt.asUintN(64,BigInt(t)).toString(16).padStart(16,"0")}import{isErr as nt}from"@zipbul/result";import{promises as Jt}from"fs";import{join as Bt}from"path";async function et(e){let{projectRoot:t,extensions:n,ignorePatterns:r,fileRepo:i}=e,s=i.getFilesMap(),u=new Set,m=[],l=[],h=r.map((x)=>new Bun.Glob(x));for await(let x of Jt.glob("**/*",{cwd:t})){if(!n.some((a)=>x.endsWith(a)))continue;if(h.some((a)=>a.match(x)))continue;u.add(x);let P=Bt(t,x),N=Bun.file(P),{size:C,lastModified:v}=N,b=s.get(x);if(!b){let a=await N.text(),g=W(a);m.push({filePath:x,contentHash:g,mtimeMs:v,size:C});continue}if(b.mtimeMs===v&&b.size===C){l.push({filePath:x,contentHash:b.contentHash,mtimeMs:v,size:C});continue}let o=await N.text(),c=W(o);if(c===b.contentHash)l.push({filePath:x,contentHash:c,mtimeMs:v,size:C});else m.push({filePath:x,contentHash:c,mtimeMs:v,size:C})}let f=[];for(let x of s.keys())if(!u.has(x))f.push(x);return{changed:m,unchanged:l,deleted:f}}function Ht(e){if(e.kind==="function"||e.kind==="method"){let t=e.parameters?.length??0,n=e.modifiers.includes("async")?1:0;return`params:${t}|async:${n}`}return null}function $t(e){let t={};if(e.jsDoc)t.jsDoc=e.jsDoc;if(e.kind==="function"||e.kind==="method"){if(e.parameters!==void 0)t.parameters=e.parameters;if(e.returnType!==void 0)t.returnType=e.returnType}if(e.heritage?.length)t.heritage=e.heritage;if(e.decorators?.length)t.decorators=e.decorators;if(e.typeParameters?.length)t.typeParameters=e.typeParameters;if(e.modifiers?.length)t.modifiers=e.modifiers;if(e.members?.length)t.members=e.members.map((n)=>n.name);return Object.keys(t).length>0?JSON.stringify(t):null}function tt(e,t,n,r,i){let s=Ht(e),u=W(`${t}|${e.kind}|${s??""}`);return{project:n,filePath:r,kind:e.kind,name:t,startLine:e.span.start.line,startColumn:e.span.start.column,endLine:e.span.end.line,endColumn:e.span.end.column,isExported:e.isExported?1:0,signature:s,fingerprint:u,detailJson:$t(e),contentHash:i,indexedAt:new Date().toISOString()}}function De(e){let{parsed:t,project:n,filePath:r,contentHash:i,symbolRepo:s}=e,u=ae(t),m=[];for(let l of u){m.push(tt(l,l.name,n,r,i));for(let h of l.members??[])m.push(tt(h,`${l.name}.${h.name}`,n,r,i))}s.replaceFileSymbols(n,r,i,m)}function Ie(e){let{ast:t,project:n,filePath:r,relationRepo:i,projectRoot:s,tsconfigPaths:u}=e,m=ee(s,r),l=le(t,m,u),h=[];for(let f of l){let x=Te(s,f.dstFilePath);if(x.startsWith(".."))continue;let P=Te(s,f.srcFilePath);h.push({project:n,type:f.type,srcFilePath:P,srcSymbolName:f.srcSymbolName??null,dstFilePath:x,dstSymbolName:f.dstSymbolName??null,metaJson:f.metaJson??null})}return i.replaceFileRelations(n,r,h),h.length}var Gt=100;class fe{opts;logger;callbacks=new Set;indexingLock=!1;pendingEvents=[];debounceTimer=null;currentIndexing=null;pendingFullIndex=!1;pendingFullIndexWaiters=[];tsconfigPathsRaw;boundariesRefresh=null;constructor(e){this.opts=e,this.logger=e.logger??console,this.tsconfigPathsRaw=se(e.projectRoot)}get tsconfigPaths(){return this.tsconfigPathsRaw}fullIndex(){return this.startIndex(void 0,!0)}incrementalIndex(e){return this.startIndex(e,!1)}onIndexed(e){return this.callbacks.add(e),()=>this.callbacks.delete(e)}handleWatcherEvent(e){if(e.filePath.endsWith("tsconfig.json")){pe(this.opts.projectRoot),this.tsconfigPathsRaw=se(this.opts.projectRoot),this.fullIndex().catch((t)=>{this.logger.error("[IndexCoordinator] fullIndex failed after tsconfig change:",t)});return}if(e.filePath.endsWith("package.json")){let t=this.opts.discoverProjectsFn??ue;this.boundariesRefresh=t(this.opts.projectRoot).then((n)=>{this.opts.boundaries=n})}if(this.pendingEvents.push(e),this.debounceTimer===null)this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.flushPending()},Gt)}async shutdown(){if(this.debounceTimer!==null)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.currentIndexing)await this.currentIndexing}startIndex(e,t){if(this.indexingLock){if(t)return this.pendingFullIndex=!0,new Promise((r,i)=>{this.pendingFullIndexWaiters.push({resolve:r,reject:i})});return this.currentIndexing}this.indexingLock=!0;let n=this.doIndex(e,t).then((r)=>{return this.fireCallbacks(r),r}).finally(()=>{if(this.indexingLock=!1,this.currentIndexing=null,this.pendingFullIndex){this.pendingFullIndex=!1;let r=this.pendingFullIndexWaiters.splice(0);this.startIndex(void 0,!0).then((i)=>{for(let s of r)s.resolve(i)}).catch((i)=>{for(let s of r)s.reject(i)})}else if(this.pendingEvents.length>0){let r=this.pendingEvents.splice(0);this.startIndex(r,!1).catch((i)=>this.logger.error("[IndexCoordinator] incremental drain error",i))}});return this.currentIndexing=n,n}async doIndex(e,t){let n=Date.now(),{fileRepo:r,symbolRepo:i,relationRepo:s,dbConnection:u}=this.opts;if(this.boundariesRefresh)await this.boundariesRefresh,this.boundariesRefresh=null;let m,l;if(e!==void 0)m=e.filter((b)=>b.eventType==="create"||b.eventType==="change").map((b)=>({filePath:b.filePath,contentHash:"",mtimeMs:0,size:0})),l=e.filter((b)=>b.eventType==="delete").map((b)=>b.filePath);else{let b=new Map;for(let c of this.opts.boundaries)for(let[a,g]of r.getFilesMap(c.project))b.set(a,g);let o=await et({projectRoot:this.opts.projectRoot,extensions:this.opts.extensions,ignorePatterns:this.opts.ignorePatterns,fileRepo:{getFilesMap:()=>b}});m=o.changed,l=o.deleted}let h=await this.tsconfigPathsRaw??void 0,f=new Map;for(let b of l){let o=q(b,this.opts.boundaries),c=i.getFileSymbols(o,b);f.set(b,c)}let x=()=>{for(let b of l){let o=q(b,this.opts.boundaries);i.deleteFileSymbols(o,b),s.deleteFileRelations(o,b),r.deleteFile(o,b)}},P=async()=>{let b=0,o=0,c=[];for(let a of m)try{let g=await this.processFile(a.filePath,a.contentHash||void 0,h);b+=g.symbolCount,o+=g.relCount}catch(g){this.logger.error(`[IndexCoordinator] Failed to index ${a.filePath}:`,g),c.push(a.filePath)}return{symbols:b,relations:o,failedFiles:c}},N=0,C=0,v=[];if(t){let{projectRoot:b,boundaries:o}=this.opts,{parseCache:c}=this.opts,a=await Promise.allSettled(m.map(async(p)=>{let S=ee(b,p.filePath),k=Bun.file(S),w=await k.text(),E=p.contentHash||W(w);return{filePath:p.filePath,text:w,contentHash:E,mtimeMs:k.lastModified,size:k.size}})),g=a.filter((p)=>p.status==="fulfilled").map((p)=>p.value);for(let p of a)if(p.status==="rejected")this.logger.error("[IndexCoordinator] Failed to pre-read file:",p.reason);let y=[];u.transaction(()=>{for(let S of o){let k=r.getAllFiles(S.project);for(let w of k)r.deleteFile(w.project,w.filePath)}let p=this.opts.parseSourceFn??re;for(let S of g){let k=q(S.filePath,o),w=p(ee(b,S.filePath),S.text);if(nt(w))throw w.data;let E=w;y.push({filePath:S.filePath,parsed:E}),r.upsertFile({project:k,filePath:S.filePath,mtimeMs:S.mtimeMs,size:S.size,contentHash:S.contentHash,updatedAt:new Date().toISOString()}),De({parsed:E,project:k,filePath:S.filePath,contentHash:S.contentHash,symbolRepo:i}),C+=Ie({ast:E.program,project:k,filePath:S.filePath,relationRepo:s,projectRoot:b,tsconfigPaths:h}),N+=i.getFileSymbols(k,S.filePath).length}});for(let p of y)c.set(p.filePath,p.parsed)}else{x();let b=await P();N=b.symbols,C=b.relations,v=b.failedFiles}if(!t)for(let[b,o]of f)for(let c of o){if(!c.fingerprint)continue;let a=q(b,this.opts.boundaries),g=i.getByFingerprint(a,c.fingerprint);if(g.length===1){let y=g[0];s.retargetRelations(a,b,c.name,y.filePath,y.name)}}return{indexedFiles:m.length,removedFiles:l.length,totalSymbols:N,totalRelations:C,durationMs:Date.now()-n,changedFiles:m.map((b)=>b.filePath),deletedFiles:[...l],failedFiles:v}}async processFile(e,t,n){let{projectRoot:r,boundaries:i}=this.opts,{fileRepo:s,symbolRepo:u,relationRepo:m,parseCache:l}=this.opts,h=ee(r,e),f=Bun.file(h),x=await f.text(),P=t||W(x),N=q(e,i),v=(this.opts.parseSourceFn??re)(h,x);if(nt(v))throw v.data;let b=v;l.set(e,b),s.upsertFile({project:N,filePath:e,mtimeMs:f.lastModified,size:f.size,contentHash:P,updatedAt:new Date().toISOString()}),De({parsed:b,project:N,filePath:e,contentHash:P,symbolRepo:u});let o=Ie({ast:b.program,project:N,filePath:e,relationRepo:m,projectRoot:r,tsconfigPaths:n});return{symbolCount:u.getFileSymbols(N,e).length,relCount:o}}fireCallbacks(e){for(let t of this.callbacks)try{t(e)}catch(n){this.logger.error("[IndexCoordinator] onIndexed callback threw:",n)}}flushPending(){if(this.indexingLock)return;if(this.pendingEvents.length>0){let e=this.pendingEvents.splice(0);this.startIndex(e,!1).catch((t)=>this.logger.error("[IndexCoordinator] flushPending startIndex error:",t))}}}function Wt(e){try{return process.kill(e,0),!0}catch(t){if(typeof t==="object"&&t&&"code"in t)return t.code!=="ESRCH";return!0}}function Kt(e){let t=new Date(e).getTime();return Number.isNaN(t)?0:t}function rt(e,t,n={}){let r=n.now??Date.now,i=n.isAlive??Wt,s=n.staleAfterSeconds??90;return e.immediateTransaction(()=>{let u=e.selectOwner();if(!u)return e.insertOwner(t),"owner";let m=Math.floor((r()-Kt(u.heartbeat_at))/1000);if(i(u.pid)&&m<s)return"reader";return e.replaceOwner(t),"owner"})}function it(e,t){e.deleteOwner(t)}function st(e,t){e.touchOwner(t)}function je(e){let{symbolRepo:t,project:n,query:r}=e,i=r.project??n,s=r.limit??100,u={kind:r.kind,filePath:r.filePath,isExported:r.isExported,project:i,limit:s};if(r.text){let l=me(r.text);if(l)u.ftsQuery=l}return t.searchByQuery(u).map((l)=>({id:l.id,filePath:l.filePath,kind:l.kind,name:l.name,span:{start:{line:l.startLine,column:l.startColumn},end:{line:l.endLine,column:l.endColumn}},isExported:l.isExported===1,signature:l.signature,fingerprint:l.fingerprint,detail:l.detailJson?(()=>{try{return JSON.parse(l.detailJson)}catch{return{}}})():{}}))}function _e(e){let{relationRepo:t,project:n,query:r}=e,i=r.project??n,s=r.limit??500;return t.searchRelations({srcFilePath:r.srcFilePath,srcSymbolName:r.srcSymbolName,dstFilePath:r.dstFilePath,dstSymbolName:r.dstSymbolName,type:r.type,project:i,limit:s}).map((m)=>({type:m.type,srcFilePath:m.srcFilePath,srcSymbolName:m.srcSymbolName,dstFilePath:m.dstFilePath,dstSymbolName:m.dstSymbolName,metaJson:m.metaJson??void 0}))}class oe{options;adjacencyList=new Map;reverseAdjacencyList=new Map;constructor(e){this.options=e}build(){this.adjacencyList=new Map,this.reverseAdjacencyList=new Map;let e=this.options.relationRepo.getByType(this.options.project,"imports");for(let t of e){let{srcFilePath:n,dstFilePath:r}=t;if(!this.adjacencyList.has(n))this.adjacencyList.set(n,new Set);if(this.adjacencyList.get(n).add(r),!this.reverseAdjacencyList.has(r))this.reverseAdjacencyList.set(r,new Set);this.reverseAdjacencyList.get(r).add(n)}}getDependencies(e){return Array.from(this.adjacencyList.get(e)??[])}getDependents(e){return Array.from(this.reverseAdjacencyList.get(e)??[])}getTransitiveDependents(e){let t=new Set,n=[e];while(n.length>0){let r=n.shift();for(let i of this.reverseAdjacencyList.get(r)??[])if(!t.has(i))t.add(i),n.push(i)}return Array.from(t)}hasCycle(){let e=new Set,t=new Set;for(let n of this.adjacencyList.keys()){if(e.has(n))continue;let r=[{node:n,entered:!1}];while(r.length>0){let i=r.pop();if(i.entered){t.delete(i.node);continue}if(t.has(i.node))return!0;if(e.has(i.node))continue;e.add(i.node),t.add(i.node),r.push({node:i.node,entered:!0});for(let s of this.adjacencyList.get(i.node)??[]){if(t.has(s))return!0;if(!e.has(s))r.push({node:s,entered:!1})}}}return!1}getAffectedByChange(e){let t=new Set;for(let n of e)for(let r of this.getTransitiveDependents(n))t.add(r);return Array.from(t)}}var at=30000,lt=60000,Vt=10;class ze{projectRoot;db;symbolRepo;relationRepo;parseCache;coordinator;watcher;releaseWatcherRoleFn;parseSourceFn;extractSymbolsFn;extractRelationsFn;symbolSearchFn;relationSearchFn;logger;defaultProject;role;timer=null;signalHandlers=[];closed=!1;tsconfigPaths=null;boundaries=[];onIndexedCallbacks=new Set;constructor(e){this.projectRoot=e.projectRoot,this.db=e.db,this.symbolRepo=e.symbolRepo,this.relationRepo=e.relationRepo,this.parseCache=e.parseCache,this.coordinator=e.coordinator,this.watcher=e.watcher,this.releaseWatcherRoleFn=e.releaseWatcherRoleFn,this.parseSourceFn=e.parseSourceFn,this.extractSymbolsFn=e.extractSymbolsFn,this.extractRelationsFn=e.extractRelationsFn,this.symbolSearchFn=e.symbolSearchFn,this.relationSearchFn=e.relationSearchFn,this.logger=e.logger,this.defaultProject=e.defaultProject,this.role=e.role}static async open(e){let{projectRoot:t,extensions:n=[".ts",".mts",".cts"],ignorePatterns:r=[],parseCacheCapacity:i=500,logger:s=console,existsSyncFn:u=Ut,dbConnectionFactory:m,watcherFactory:l,coordinatorFactory:h,repositoryFactory:f,acquireWatcherRoleFn:x=rt,releaseWatcherRoleFn:P=it,updateHeartbeatFn:N=st,discoverProjectsFn:C=ue,parseSourceFn:v=re,extractSymbolsFn:b=ae,extractRelationsFn:o=le,symbolSearchFn:c=je,relationSearchFn:a=_e,loadTsconfigPathsFn:g=se}=e;if(!ot.isAbsolute(t))return T(R("validation",`Gildash: projectRoot must be an absolute path, got: "${t}"`));if(!u(t))return T(R("validation",`Gildash: projectRoot does not exist: "${t}"`));let y=m?m():new Ne({projectRoot:t}),p=y.open();if(te(p))return p;try{let S=await C(t),k=S[0]?.project??ot.basename(t),w=f?f():(()=>{let j=y;return{fileRepo:new ke(j),symbolRepo:new ve(j),relationRepo:new Ce(j),parseCache:new ye(i)}})(),E=await Promise.resolve(x(y,process.pid,{})),z=null,B=null,F=new ze({projectRoot:t,db:y,symbolRepo:w.symbolRepo,relationRepo:w.relationRepo,parseCache:w.parseCache,coordinator:z,watcher:B,releaseWatcherRoleFn:P,parseSourceFn:v,extractSymbolsFn:b,extractRelationsFn:o,symbolSearchFn:c,relationSearchFn:a,logger:s,defaultProject:k,role:E});if(pe(t),F.tsconfigPaths=await g(t),F.boundaries=S,E==="owner"){let j=l?l():new de({projectRoot:t,ignorePatterns:r,extensions:n},void 0,s),M=h?h():new fe({projectRoot:t,boundaries:S,extensions:n,ignorePatterns:r,dbConnection:y,parseCache:w.parseCache,fileRepo:w.fileRepo,symbolRepo:w.symbolRepo,relationRepo:w.relationRepo,logger:s});F.coordinator=M,F.watcher=j,await j.start(($)=>M.handleWatcherEvent?.($)).then(($)=>{if(te($))throw $.data});let ne=setInterval(()=>{N(y,process.pid)},at);F.timer=ne,await M.fullIndex()}else{let j=0,M=async()=>{try{let $=await Promise.resolve(x(y,process.pid,{}));if(j=0,$==="owner"){clearInterval(F.timer),F.timer=null;let U=null,V=null;try{U=l?l():new de({projectRoot:t,ignorePatterns:r,extensions:n},void 0,s),V=h?h():new fe({projectRoot:t,boundaries:S,extensions:n,ignorePatterns:r,dbConnection:y,parseCache:w.parseCache,fileRepo:w.fileRepo,symbolRepo:w.symbolRepo,relationRepo:w.relationRepo,logger:s});for(let L of F.onIndexedCallbacks)V.onIndexed(L);await U.start((L)=>V?.handleWatcherEvent?.(L)).then((L)=>{if(te(L))throw L.data});let ge=setInterval(()=>{N(y,process.pid)},at);F.timer=ge,F.coordinator=V,F.watcher=U,await V.fullIndex()}catch(ge){if(s.error("[Gildash] owner promotion failed, reverting to reader",ge),U){let L=await U.close();if(te(L))s.error("[Gildash] watcher close error during promotion rollback",L.data);F.watcher=null}if(V)await V.shutdown().catch((L)=>s.error("[Gildash] coordinator shutdown error during promotion rollback",L)),F.coordinator=null;if(F.timer===null)F.timer=setInterval(M,lt)}}}catch($){if(j++,s.error("[Gildash] healthcheck error",$),j>=Vt)s.error("[Gildash] healthcheck failed too many times, shutting down"),clearInterval(F.timer),F.timer=null,F.close().catch((U)=>s.error("[Gildash] close error during healthcheck shutdown",U))}},ne=setInterval(M,lt);F.timer=ne}let K=["SIGTERM","SIGINT","beforeExit"];for(let j of K){let M=()=>{F.close().catch((ne)=>s.error("[Gildash] close error during signal",j,ne))};if(j==="beforeExit")process.on("beforeExit",M);else process.on(j,M);F.signalHandlers.push([j,M])}return F}catch(S){return y.close(),T(R("store","Gildash: initialization failed",S))}}async close(){if(this.closed)return;this.closed=!0;let e=[];for(let[t,n]of this.signalHandlers)if(t==="beforeExit")process.off("beforeExit",n);else process.off(t,n);if(this.signalHandlers=[],this.coordinator)try{await this.coordinator.shutdown()}catch(t){e.push(t instanceof Error?t:Error(String(t)))}if(this.watcher){let t=await this.watcher.close();if(te(t))e.push(t.data)}if(this.timer!==null)clearInterval(this.timer),this.timer=null;try{this.releaseWatcherRoleFn(this.db,process.pid)}catch(t){e.push(t instanceof Error?t:Error(String(t)))}try{this.db.close()}catch(t){e.push(t instanceof Error?t:Error(String(t)))}if(e.length>0)return T(R("close","Gildash: one or more errors occurred during close()",e))}onIndexed(e){if(this.onIndexedCallbacks.add(e),!this.coordinator)return()=>{this.onIndexedCallbacks.delete(e)};let t=this.coordinator.onIndexed(e);return()=>{this.onIndexedCallbacks.delete(e),t()}}parseSource(e,t){if(this.closed)return T(R("closed","Gildash: instance is closed"));let n=this.parseSourceFn(e,t);if(te(n))return n;return this.parseCache.set(e,n),n}extractSymbols(e){if(this.closed)return T(R("closed","Gildash: instance is closed"));return this.extractSymbolsFn(e)}extractRelations(e){if(this.closed)return T(R("closed","Gildash: instance is closed"));return this.extractRelationsFn(e.program,e.filePath,this.tsconfigPaths??void 0)}async reindex(){if(this.closed)return T(R("closed","Gildash: instance is closed"));if(!this.coordinator)return T(R("closed","Gildash: reindex() is not available for readers"));try{return await this.coordinator.fullIndex()}catch(e){return T(R("index","Gildash: reindex failed",e))}}get projects(){return[...this.boundaries]}getStats(e){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{return this.symbolRepo.getStats(e??this.defaultProject)}catch(t){return T(R("store","Gildash: getStats failed",t))}}searchSymbols(e){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:this.defaultProject,query:e})}catch(t){return T(R("search","Gildash: searchSymbols failed",t))}}searchRelations(e){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:this.defaultProject,query:e})}catch(t){return T(R("search","Gildash: searchRelations failed",t))}}getDependencies(e,t,n=1e4){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{srcFilePath:e,type:"imports",project:t??this.defaultProject,limit:n}}).map((r)=>r.dstFilePath)}catch(r){return T(R("search","Gildash: getDependencies failed",r))}}getDependents(e,t,n=1e4){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{dstFilePath:e,type:"imports",project:t??this.defaultProject,limit:n}}).map((r)=>r.srcFilePath)}catch(r){return T(R("search","Gildash: getDependents failed",r))}}async getAffected(e,t){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{let n=new oe({relationRepo:this.relationRepo,project:t??this.defaultProject});return await n.build(),n.getAffectedByChange(e)}catch(n){return T(R("search","Gildash: getAffected failed",n))}}async hasCycle(e){if(this.closed)return T(R("closed","Gildash: instance is closed"));try{let t=new oe({relationRepo:this.relationRepo,project:e??this.defaultProject});return await t.build(),t.hasCycle()}catch(t){return T(R("search","Gildash: hasCycle failed",t))}}}export{je as symbolSearch,_e as relationSearch,R as gildashError,ze as Gildash,oe as DependencyGraph};
|
|
23
|
+
END`];class Pt{client=null;drizzle=null;dbPath;txDepth=0;constructor(t){this.dbPath=Qt(t.projectRoot,".zipbul","gildash.db")}get drizzleDb(){if(!this.drizzle)throw Error("Database is not open. Call open() first.");return this.drizzle}open(){try{Dn(Fn(this.dbPath),{recursive:!0}),this.client=new An(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=En(this.client,{schema:kt}),Tn(this.drizzle,{migrationsFolder:Qt(import.meta.dirname,"migrations")});for(let t of Ot)this.client.run(t)}catch(t){if(this.isCorruptionError(t)&&Ht(this.dbPath)){this.closeClient(),Wt(this.dbPath);for(let e of["-wal","-shm"]){let r=this.dbPath+e;if(Ht(r))Wt(r)}let n=this.open();if(Pn(n))return Vt(k("store",`Failed to recover database at ${this.dbPath}`,n.data));return n}return Vt(k("store",`Failed to open database at ${this.dbPath}`,t))}}close(){this.closeClient(),this.drizzle=null}transaction(t){let n=this.requireClient();if(this.txDepth===0){this.txDepth++;try{return n.transaction(()=>t(this))()}finally{this.txDepth--}}let e=`sp_${this.txDepth++}`;n.run(`SAVEPOINT "${e}"`);try{let r=t(this);return n.run(`RELEASE SAVEPOINT "${e}"`),r}catch(r){throw n.run(`ROLLBACK TO SAVEPOINT "${e}"`),n.run(`RELEASE SAVEPOINT "${e}"`),r}finally{this.txDepth--}}immediateTransaction(t){let n=this.requireClient();this.txDepth++,n.run("BEGIN IMMEDIATE");try{let e=t();return n.run("COMMIT"),e}catch(e){throw n.run("ROLLBACK"),e}finally{this.txDepth--}}query(t){let n=this.requireClient().prepare(t).get();if(!n)return null;return Object.values(n)[0]}getTableNames(){return this.requireClient().query("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((n)=>n.name)}selectOwner(){return this.requireClient().prepare("SELECT pid, heartbeat_at FROM watcher_owner WHERE id = 1").get()??void 0}insertOwner(t){let n=new Date().toISOString();this.requireClient().prepare("INSERT INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(t,n,n)}replaceOwner(t){let n=new Date().toISOString();this.requireClient().prepare("INSERT OR REPLACE INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(t,n,n)}touchOwner(t){let n=new Date().toISOString();this.requireClient().prepare("UPDATE watcher_owner SET heartbeat_at = ? WHERE id = 1 AND pid = ?").run(n,t)}deleteOwner(t){this.requireClient().prepare("DELETE FROM watcher_owner WHERE id = 1 AND pid = ?").run(t)}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(t){if(!(t instanceof Error))return!1;let n=t.message.toLowerCase();return n.includes("malformed")||n.includes("corrupt")||n.includes("not a database")||n.includes("disk i/o error")||n.includes("sqlite_corrupt")}}import{eq as it,and as jt}from"drizzle-orm";class At{db;constructor(t){this.db=t}getFile(t,n){return this.db.drizzleDb.select().from(I).where(jt(it(I.project,t),it(I.filePath,n))).get()??null}upsertFile(t){this.db.drizzleDb.insert(I).values({project:t.project,filePath:t.filePath,mtimeMs:t.mtimeMs,size:t.size,contentHash:t.contentHash,updatedAt:t.updatedAt}).onConflictDoUpdate({target:[I.project,I.filePath],set:{mtimeMs:t.mtimeMs,size:t.size,contentHash:t.contentHash,updatedAt:t.updatedAt}}).run()}getAllFiles(t){return this.db.drizzleDb.select().from(I).where(it(I.project,t)).all()}getFilesMap(t){let n=this.getAllFiles(t),e=new Map;for(let r of n)e.set(r.filePath,r);return e}deleteFile(t,n){this.db.drizzleDb.delete(I).where(jt(it(I.project,t),it(I.filePath,n))).run()}}import{eq as M,and as Y,sql as Dt,count as Rn}from"drizzle-orm";function mt(t){return t.trim().split(/\s+/).map((n)=>n.trim()).filter((n)=>n.length>0).map((n)=>`"${n.replaceAll('"','""')}"*`).join(" ")}class Ft{db;constructor(t){this.db=t}replaceFileSymbols(t,n,e,r){if(this.db.drizzleDb.delete(D).where(Y(M(D.project,t),M(D.filePath,n))).run(),!r.length)return;let i=new Date().toISOString();for(let s of r)this.db.drizzleDb.insert(D).values({project:t,filePath:n,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??i}).run()}getFileSymbols(t,n){return this.db.drizzleDb.select().from(D).where(Y(M(D.project,t),M(D.filePath,n))).all()}searchByName(t,n,e={}){let r=e.limit??50,i=mt(n);if(!i)return[];return this.db.drizzleDb.select().from(D).where(Y(Dt`${D.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${i})`,M(D.project,t),e.kind?M(D.kind,e.kind):void 0)).orderBy(D.name).limit(r).all()}searchByKind(t,n){return this.db.drizzleDb.select().from(D).where(Y(M(D.project,t),M(D.kind,n))).orderBy(D.name).all()}getStats(t){let n=this.db.drizzleDb.select({symbolCount:Rn(),fileCount:Dt`COUNT(DISTINCT ${D.filePath})`}).from(D).where(M(D.project,t)).get();return{symbolCount:n?.symbolCount??0,fileCount:n?.fileCount??0}}getByFingerprint(t,n){return this.db.drizzleDb.select().from(D).where(Y(M(D.project,t),M(D.fingerprint,n))).all()}deleteFileSymbols(t,n){this.db.drizzleDb.delete(D).where(Y(M(D.project,t),M(D.filePath,n))).run()}searchByQuery(t){return this.db.drizzleDb.select().from(D).where(Y(t.ftsQuery?Dt`${D.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${t.ftsQuery})`:void 0,t.project!==void 0?M(D.project,t.project):void 0,t.kind?M(D.kind,t.kind):void 0,t.filePath!==void 0?M(D.filePath,t.filePath):void 0,t.isExported!==void 0?M(D.isExported,t.isExported?1:0):void 0)).orderBy(D.name).limit(t.limit).all()}}import{eq as R,and as K,isNull as Xt,or as _n}from"drizzle-orm";class Et{db;constructor(t){this.db=t}replaceFileRelations(t,n,e){if(this.db.drizzleDb.delete(u).where(K(R(u.project,t),R(u.srcFilePath,n))).run(),!e.length)return;for(let r of e)this.db.drizzleDb.insert(u).values({project:t,type:r.type??"unknown",srcFilePath:r.srcFilePath??n,srcSymbolName:r.srcSymbolName??null,dstFilePath:r.dstFilePath??"",dstSymbolName:r.dstSymbolName??null,metaJson:r.metaJson??null}).run()}getOutgoing(t,n,e){if(e!==void 0)return this.db.drizzleDb.select({project:u.project,type:u.type,srcFilePath:u.srcFilePath,srcSymbolName:u.srcSymbolName,dstFilePath:u.dstFilePath,dstSymbolName:u.dstSymbolName,metaJson:u.metaJson}).from(u).where(K(R(u.project,t),R(u.srcFilePath,n),_n(R(u.srcSymbolName,e),Xt(u.srcSymbolName)))).all();return this.db.drizzleDb.select({project:u.project,type:u.type,srcFilePath:u.srcFilePath,srcSymbolName:u.srcSymbolName,dstFilePath:u.dstFilePath,dstSymbolName:u.dstSymbolName,metaJson:u.metaJson}).from(u).where(K(R(u.project,t),R(u.srcFilePath,n))).all()}getIncoming(t,n){return this.db.drizzleDb.select({project:u.project,type:u.type,srcFilePath:u.srcFilePath,srcSymbolName:u.srcSymbolName,dstFilePath:u.dstFilePath,dstSymbolName:u.dstSymbolName,metaJson:u.metaJson}).from(u).where(K(R(u.project,t),R(u.dstFilePath,n))).all()}getByType(t,n){return this.db.drizzleDb.select({project:u.project,type:u.type,srcFilePath:u.srcFilePath,srcSymbolName:u.srcSymbolName,dstFilePath:u.dstFilePath,dstSymbolName:u.dstSymbolName,metaJson:u.metaJson}).from(u).where(K(R(u.project,t),R(u.type,n))).all()}deleteFileRelations(t,n){this.db.drizzleDb.delete(u).where(K(R(u.project,t),R(u.srcFilePath,n))).run()}searchRelations(t){return this.db.drizzleDb.select({project:u.project,type:u.type,srcFilePath:u.srcFilePath,srcSymbolName:u.srcSymbolName,dstFilePath:u.dstFilePath,dstSymbolName:u.dstSymbolName,metaJson:u.metaJson}).from(u).where(K(t.project!==void 0?R(u.project,t.project):void 0,t.srcFilePath!==void 0?R(u.srcFilePath,t.srcFilePath):void 0,t.srcSymbolName!==void 0?R(u.srcSymbolName,t.srcSymbolName):void 0,t.dstFilePath!==void 0?R(u.dstFilePath,t.dstFilePath):void 0,t.dstSymbolName!==void 0?R(u.dstSymbolName,t.dstSymbolName):void 0,t.type!==void 0?R(u.type,t.type):void 0)).limit(t.limit).all()}retargetRelations(t,n,e,r,i){let s=e===null?K(R(u.project,t),R(u.dstFilePath,n),Xt(u.dstSymbolName)):K(R(u.project,t),R(u.dstFilePath,n),R(u.dstSymbolName,e));this.db.drizzleDb.update(u).set({dstFilePath:r,dstSymbolName:i}).where(s).run()}}import{err as Yt}from"@zipbul/result";import{subscribe as Cn}from"@parcel/watcher";import Tt from"path";var In=["**/.git/**","**/.zipbul/**","**/dist/**","**/node_modules/**"],vn=new Set(["package.json","tsconfig.json"]);function Mn(t){return t.replaceAll("\\","/")}function zn(t){if(t==="update")return"change";if(t==="create")return"create";return"delete"}class ut{#n;#t;#r;#i;#s;#e;constructor(t,n=Cn,e=console){this.#t=t.projectRoot,this.#r=[...In,...t.ignorePatterns??[]],this.#i=new Set((t.extensions??[".ts",".mts",".cts"]).map((r)=>r.toLowerCase())),this.#s=n,this.#e=e}async start(t){try{this.#n=await this.#s(this.#t,(n,e)=>{if(n){this.#e.error(k("watcher","Callback error",n));return}try{for(let r of e){let i=Mn(Tt.relative(this.#t,r.path));if(i.startsWith(".."))continue;let s=Tt.basename(i),p=Tt.extname(i).toLowerCase();if(!vn.has(s)&&!this.#i.has(p))continue;if(i.endsWith(".d.ts"))continue;t({eventType:zn(r.type),filePath:i})}}catch(r){this.#e.error(k("watcher","Callback error",r))}},{ignore:this.#r})}catch(n){return Yt(k("watcher","Failed to subscribe watcher",n))}}async close(){if(!this.#n)return;try{await this.#n.unsubscribe(),this.#n=void 0}catch(t){return Yt(k("watcher","Failed to close watcher",t))}}}import Rt from"path";import{promises as Ln}from"fs";var Jn=["**/node_modules/**","**/.git/**","**/.zipbul/**","**/dist/**"];async function pt(t){let n=[];for await(let e of Ln.glob("**/package.json",{cwd:t,exclude:Jn})){let r=Rt.dirname(e).replaceAll("\\","/"),i=Rt.join(t,e),s=await Bun.file(i).json(),p=typeof s?.name==="string"&&s.name.length>0?s.name:Rt.basename(r==="."?t:r);n.push({dir:r,project:p})}return n.sort((e,r)=>r.dir.length-e.dir.length),n}function q(t,n,e="default"){let r=t.replaceAll("\\","/");for(let i of n){if(i.dir===".")return i.project;if(r===i.dir||r.startsWith(`${i.dir}/`))return i.project}return e}import Zt from"path";var U=new Map;async function Gn(t){let n=Bun.file(t);if(!await n.exists())return null;let e=await n.json();return typeof e==="object"&&e!==null?e:null}async function st(t){if(U.has(t))return U.get(t)??null;let n=Zt.join(t,"tsconfig.json"),e=await Gn(n);if(!e)return U.set(t,null),null;let r=typeof e.compilerOptions==="object"&&e.compilerOptions!==null?e.compilerOptions:null;if(!r)return U.set(t,null),null;let i=typeof r.baseUrl==="string"?r.baseUrl:null,s=typeof r.paths==="object"&&r.paths!==null?r.paths:null;if(!i&&!s)return U.set(t,null),null;let p=i?Zt.resolve(t,i):t,m=new Map;if(s)for(let[y,f]of Object.entries(s)){if(!Array.isArray(f))continue;let x=f.filter((w)=>typeof w==="string");m.set(y,x)}let c={baseUrl:p,paths:m};return U.set(t,c),c}function dt(t){if(t){U.delete(t);return}U.clear()}import qt from"path";function _t(t,n){return qt.relative(t,n).replaceAll("\\","/")}function tt(t,n){return qt.resolve(t,n)}function V(t){let n=Bun.hash.xxHash64(t);return BigInt.asUintN(64,BigInt(n)).toString(16).padStart(16,"0")}import{isErr as en}from"@zipbul/result";import{promises as Bn}from"fs";import{join as Kn}from"path";async function tn(t){let{projectRoot:n,extensions:e,ignorePatterns:r,fileRepo:i}=t,s=i.getFilesMap(),p=new Set,m=[],c=[],y=r.map((x)=>new Bun.Glob(x));for await(let x of Bn.glob("**/*",{cwd:n})){if(!e.some((a)=>x.endsWith(a)))continue;if(y.some((a)=>a.match(x)))continue;p.add(x);let w=Kn(n,x),P=Bun.file(w),{size:E,lastModified:F}=P,b=s.get(x);if(!b){let a=await P.text(),g=V(a);m.push({filePath:x,contentHash:g,mtimeMs:F,size:E});continue}if(b.mtimeMs===F&&b.size===E){c.push({filePath:x,contentHash:b.contentHash,mtimeMs:F,size:E});continue}let o=await P.text(),l=V(o);if(l===b.contentHash)c.push({filePath:x,contentHash:l,mtimeMs:F,size:E});else m.push({filePath:x,contentHash:l,mtimeMs:F,size:E})}let f=[];for(let x of s.keys())if(!p.has(x))f.push(x);return{changed:m,unchanged:c,deleted:f}}function $n(t){if(t.kind==="function"||t.kind==="method"){let n=t.parameters?.length??0,e=t.modifiers.includes("async")?1:0;return`params:${n}|async:${e}`}return null}function Un(t){let n={};if(t.jsDoc)n.jsDoc=t.jsDoc;if(t.kind==="function"||t.kind==="method"){if(t.parameters!==void 0)n.parameters=t.parameters;if(t.returnType!==void 0)n.returnType=t.returnType}if(t.heritage?.length)n.heritage=t.heritage;if(t.decorators?.length)n.decorators=t.decorators;if(t.typeParameters?.length)n.typeParameters=t.typeParameters;if(t.modifiers?.length)n.modifiers=t.modifiers;if(t.members?.length)n.members=t.members.map((e)=>e.name);return Object.keys(n).length>0?JSON.stringify(n):null}function nn(t,n,e,r,i){let s=$n(t),p=V(`${n}|${t.kind}|${s??""}`);return{project:e,filePath:r,kind:t.kind,name:n,startLine:t.span.start.line,startColumn:t.span.start.column,endLine:t.span.end.line,endColumn:t.span.end.column,isExported:t.isExported?1:0,signature:s,fingerprint:p,detailJson:Un(t),contentHash:i,indexedAt:new Date().toISOString()}}function Ct(t){let{parsed:n,project:e,filePath:r,contentHash:i,symbolRepo:s}=t,p=at(n),m=[];for(let c of p){m.push(nn(c,c.name,e,r,i));for(let y of c.members??[])m.push(nn(y,`${c.name}.${y.name}`,e,r,i))}s.replaceFileSymbols(e,r,i,m)}function It(t){let{ast:n,project:e,filePath:r,relationRepo:i,projectRoot:s,tsconfigPaths:p}=t,m=tt(s,r),c=ct(n,m,p),y=[];for(let f of c){let x=_t(s,f.dstFilePath);if(x.startsWith(".."))continue;let w=_t(s,f.srcFilePath);y.push({project:e,type:f.type,srcFilePath:w,srcSymbolName:f.srcSymbolName??null,dstFilePath:x,dstSymbolName:f.dstSymbolName??null,metaJson:f.metaJson??null})}return i.replaceFileRelations(e,r,y),y.length}var Vn=100;class ft{opts;logger;callbacks=new Set;indexingLock=!1;pendingEvents=[];debounceTimer=null;currentIndexing=null;pendingFullIndex=!1;pendingFullIndexWaiters=[];tsconfigPathsRaw;boundariesRefresh=null;constructor(t){this.opts=t,this.logger=t.logger??console,this.tsconfigPathsRaw=st(t.projectRoot)}get tsconfigPaths(){return this.tsconfigPathsRaw}fullIndex(){return this.startIndex(void 0,!0)}incrementalIndex(t){return this.startIndex(t,!1)}onIndexed(t){return this.callbacks.add(t),()=>this.callbacks.delete(t)}handleWatcherEvent(t){if(t.filePath.endsWith("tsconfig.json")){dt(this.opts.projectRoot),this.tsconfigPathsRaw=st(this.opts.projectRoot),this.fullIndex().catch((n)=>{this.logger.error("[IndexCoordinator] fullIndex failed after tsconfig change:",n)});return}if(t.filePath.endsWith("package.json")){let n=this.opts.discoverProjectsFn??pt;this.boundariesRefresh=n(this.opts.projectRoot).then((e)=>{this.opts.boundaries=e})}if(this.pendingEvents.push(t),this.debounceTimer===null)this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.flushPending()},Vn)}async shutdown(){if(this.debounceTimer!==null)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.currentIndexing)await this.currentIndexing}startIndex(t,n){if(this.indexingLock){if(n)return this.pendingFullIndex=!0,new Promise((r,i)=>{this.pendingFullIndexWaiters.push({resolve:r,reject:i})});return this.currentIndexing}this.indexingLock=!0;let e=this.doIndex(t,n).then((r)=>{return this.fireCallbacks(r),r}).finally(()=>{if(this.indexingLock=!1,this.currentIndexing=null,this.pendingFullIndex){this.pendingFullIndex=!1;let r=this.pendingFullIndexWaiters.splice(0);this.startIndex(void 0,!0).then((i)=>{for(let s of r)s.resolve(i)}).catch((i)=>{for(let s of r)s.reject(i)})}else if(this.pendingEvents.length>0){let r=this.pendingEvents.splice(0);this.startIndex(r,!1).catch((i)=>this.logger.error("[IndexCoordinator] incremental drain error",i))}});return this.currentIndexing=e,e}async doIndex(t,n){let e=Date.now(),{fileRepo:r,symbolRepo:i,relationRepo:s,dbConnection:p}=this.opts;if(this.boundariesRefresh)await this.boundariesRefresh,this.boundariesRefresh=null;let m,c;if(t!==void 0)m=t.filter((b)=>b.eventType==="create"||b.eventType==="change").map((b)=>({filePath:b.filePath,contentHash:"",mtimeMs:0,size:0})),c=t.filter((b)=>b.eventType==="delete").map((b)=>b.filePath);else{let b=new Map;for(let l of this.opts.boundaries)for(let[a,g]of r.getFilesMap(l.project))b.set(a,g);let o=await tn({projectRoot:this.opts.projectRoot,extensions:this.opts.extensions,ignorePatterns:this.opts.ignorePatterns,fileRepo:{getFilesMap:()=>b}});m=o.changed,c=o.deleted}let y=await this.tsconfigPathsRaw??void 0,f=new Map;for(let b of c){let o=q(b,this.opts.boundaries),l=i.getFileSymbols(o,b);f.set(b,l)}let x=()=>{for(let b of c){let o=q(b,this.opts.boundaries);i.deleteFileSymbols(o,b),s.deleteFileRelations(o,b),r.deleteFile(o,b)}},w=async()=>{let b=0,o=0,l=[];for(let a of m)try{let g=await this.processFile(a.filePath,a.contentHash||void 0,y);b+=g.symbolCount,o+=g.relCount}catch(g){this.logger.error(`[IndexCoordinator] Failed to index ${a.filePath}:`,g),l.push(a.filePath)}return{symbols:b,relations:o,failedFiles:l}},P=0,E=0,F=[];if(n){let{projectRoot:b,boundaries:o}=this.opts,{parseCache:l}=this.opts,a=await Promise.allSettled(m.map(async(d)=>{let S=tt(b,d.filePath),A=Bun.file(S),N=await A.text(),T=d.contentHash||V(N);return{filePath:d.filePath,text:N,contentHash:T,mtimeMs:A.lastModified,size:A.size}})),g=a.filter((d)=>d.status==="fulfilled").map((d)=>d.value);for(let d of a)if(d.status==="rejected")this.logger.error("[IndexCoordinator] Failed to pre-read file:",d.reason);let h=[];p.transaction(()=>{for(let S of o){let A=r.getAllFiles(S.project);for(let N of A)r.deleteFile(N.project,N.filePath)}let d=this.opts.parseSourceFn??rt;for(let S of g){let A=q(S.filePath,o),N=d(tt(b,S.filePath),S.text);if(en(N))throw N.data;let T=N;h.push({filePath:S.filePath,parsed:T}),r.upsertFile({project:A,filePath:S.filePath,mtimeMs:S.mtimeMs,size:S.size,contentHash:S.contentHash,updatedAt:new Date().toISOString()}),Ct({parsed:T,project:A,filePath:S.filePath,contentHash:S.contentHash,symbolRepo:i}),E+=It({ast:T.program,project:A,filePath:S.filePath,relationRepo:s,projectRoot:b,tsconfigPaths:y}),P+=i.getFileSymbols(A,S.filePath).length}});for(let d of h)l.set(d.filePath,d.parsed)}else{x();let b=await w();P=b.symbols,E=b.relations,F=b.failedFiles}if(!n)for(let[b,o]of f)for(let l of o){if(!l.fingerprint)continue;let a=q(b,this.opts.boundaries),g=i.getByFingerprint(a,l.fingerprint);if(g.length===1){let h=g[0];s.retargetRelations(a,b,l.name,h.filePath,h.name)}}return{indexedFiles:m.length,removedFiles:c.length,totalSymbols:P,totalRelations:E,durationMs:Date.now()-e,changedFiles:m.map((b)=>b.filePath),deletedFiles:[...c],failedFiles:F}}async processFile(t,n,e){let{projectRoot:r,boundaries:i}=this.opts,{fileRepo:s,symbolRepo:p,relationRepo:m,parseCache:c}=this.opts,y=tt(r,t),f=Bun.file(y),x=await f.text(),w=n||V(x),P=q(t,i),F=(this.opts.parseSourceFn??rt)(y,x);if(en(F))throw F.data;let b=F;c.set(t,b),s.upsertFile({project:P,filePath:t,mtimeMs:f.lastModified,size:f.size,contentHash:w,updatedAt:new Date().toISOString()}),Ct({parsed:b,project:P,filePath:t,contentHash:w,symbolRepo:p});let o=It({ast:b.program,project:P,filePath:t,relationRepo:m,projectRoot:r,tsconfigPaths:e});return{symbolCount:p.getFileSymbols(P,t).length,relCount:o}}fireCallbacks(t){for(let n of this.callbacks)try{n(t)}catch(e){this.logger.error("[IndexCoordinator] onIndexed callback threw:",e)}}flushPending(){if(this.indexingLock)return;if(this.pendingEvents.length>0){let t=this.pendingEvents.splice(0);this.startIndex(t,!1).catch((n)=>this.logger.error("[IndexCoordinator] flushPending startIndex error:",n))}}}function Wn(t){try{return process.kill(t,0),!0}catch(n){if(typeof n==="object"&&n&&"code"in n)return n.code!=="ESRCH";return!0}}function Hn(t){let n=new Date(t).getTime();return Number.isNaN(n)?0:n}function rn(t,n,e={}){let r=e.now??Date.now,i=e.isAlive??Wn,s=e.staleAfterSeconds??90;return t.immediateTransaction(()=>{let p=t.selectOwner();if(!p)return t.insertOwner(n),"owner";let m=Math.floor((r()-Hn(p.heartbeat_at))/1000);if(i(p.pid)&&m<s)return"reader";return t.replaceOwner(n),"owner"})}function sn(t,n){t.deleteOwner(n)}function on(t,n){t.touchOwner(n)}function vt(t){let{symbolRepo:n,project:e,query:r}=t,i=r.project??e,s=r.limit??100,p={kind:r.kind,filePath:r.filePath,isExported:r.isExported,project:i,limit:s};if(r.text){let c=mt(r.text);if(c)p.ftsQuery=c}return n.searchByQuery(p).map((c)=>({id:c.id,filePath:c.filePath,kind:c.kind,name:c.name,span:{start:{line:c.startLine,column:c.startColumn},end:{line:c.endLine,column:c.endColumn}},isExported:c.isExported===1,signature:c.signature,fingerprint:c.fingerprint,detail:c.detailJson?(()=>{try{return JSON.parse(c.detailJson)}catch{return{}}})():{}}))}function Mt(t){let{relationRepo:n,project:e,query:r}=t,i=r.project??e,s=r.limit??500;return n.searchRelations({srcFilePath:r.srcFilePath,srcSymbolName:r.srcSymbolName,dstFilePath:r.dstFilePath,dstSymbolName:r.dstSymbolName,type:r.type,project:i,limit:s}).map((m)=>({type:m.type,srcFilePath:m.srcFilePath,srcSymbolName:m.srcSymbolName,dstFilePath:m.dstFilePath,dstSymbolName:m.dstSymbolName,metaJson:m.metaJson??void 0}))}class ot{options;adjacencyList=new Map;reverseAdjacencyList=new Map;constructor(t){this.options=t}build(){this.adjacencyList=new Map,this.reverseAdjacencyList=new Map;let t=this.options.relationRepo.getByType(this.options.project,"imports");for(let n of t){let{srcFilePath:e,dstFilePath:r}=n;if(!this.adjacencyList.has(e))this.adjacencyList.set(e,new Set);if(this.adjacencyList.get(e).add(r),!this.reverseAdjacencyList.has(r))this.reverseAdjacencyList.set(r,new Set);this.reverseAdjacencyList.get(r).add(e)}}getDependencies(t){return Array.from(this.adjacencyList.get(t)??[])}getDependents(t){return Array.from(this.reverseAdjacencyList.get(t)??[])}getTransitiveDependents(t){let n=new Set,e=[t];while(e.length>0){let r=e.shift();for(let i of this.reverseAdjacencyList.get(r)??[])if(!n.has(i))n.add(i),e.push(i)}return Array.from(n)}hasCycle(){let t=new Set,n=new Set;for(let e of this.adjacencyList.keys()){if(t.has(e))continue;let r=[{node:e,entered:!1}];while(r.length>0){let i=r.pop();if(i.entered){n.delete(i.node);continue}if(n.has(i.node))return!0;if(t.has(i.node))continue;t.add(i.node),n.add(i.node),r.push({node:i.node,entered:!0});for(let s of this.adjacencyList.get(i.node)??[]){if(n.has(s))return!0;if(!t.has(s))r.push({node:s,entered:!1})}}}return!1}getAffectedByChange(t){let n=new Set;for(let e of t)for(let r of this.getTransitiveDependents(e))n.add(r);return Array.from(n)}}var cn=30000,ln=60000,jn=10;class zt{projectRoot;db;symbolRepo;relationRepo;parseCache;coordinator;watcher;releaseWatcherRoleFn;parseSourceFn;extractSymbolsFn;extractRelationsFn;symbolSearchFn;relationSearchFn;logger;defaultProject;role;timer=null;signalHandlers=[];closed=!1;tsconfigPaths=null;boundaries=[];onIndexedCallbacks=new Set;constructor(t){this.projectRoot=t.projectRoot,this.db=t.db,this.symbolRepo=t.symbolRepo,this.relationRepo=t.relationRepo,this.parseCache=t.parseCache,this.coordinator=t.coordinator,this.watcher=t.watcher,this.releaseWatcherRoleFn=t.releaseWatcherRoleFn,this.parseSourceFn=t.parseSourceFn,this.extractSymbolsFn=t.extractSymbolsFn,this.extractRelationsFn=t.extractRelationsFn,this.symbolSearchFn=t.symbolSearchFn,this.relationSearchFn=t.relationSearchFn,this.logger=t.logger,this.defaultProject=t.defaultProject,this.role=t.role}static async open(t){let{projectRoot:n,extensions:e=[".ts",".mts",".cts"],ignorePatterns:r=[],parseCacheCapacity:i=500,logger:s=console,existsSyncFn:p=Qn,dbConnectionFactory:m,watcherFactory:c,coordinatorFactory:y,repositoryFactory:f,acquireWatcherRoleFn:x=rn,releaseWatcherRoleFn:w=sn,updateHeartbeatFn:P=on,discoverProjectsFn:E=pt,parseSourceFn:F=rt,extractSymbolsFn:b=at,extractRelationsFn:o=ct,symbolSearchFn:l=vt,relationSearchFn:a=Mt,loadTsconfigPathsFn:g=st}=t;if(!an.isAbsolute(n))return _(k("validation",`Gildash: projectRoot must be an absolute path, got: "${n}"`));if(!p(n))return _(k("validation",`Gildash: projectRoot does not exist: "${n}"`));let h=m?m():new Pt({projectRoot:n}),d=h.open();if(nt(d))return d;try{let S=await E(n),A=S[0]?.project??an.basename(n),N=f?f():(()=>{let v=h;return{fileRepo:new At(v),symbolRepo:new Ft(v),relationRepo:new Et(v),parseCache:new ht(i)}})(),T=await Promise.resolve(x(h,process.pid,{})),z=null,B=null,O=new zt({projectRoot:n,db:h,symbolRepo:N.symbolRepo,relationRepo:N.relationRepo,parseCache:N.parseCache,coordinator:z,watcher:B,releaseWatcherRoleFn:w,parseSourceFn:F,extractSymbolsFn:b,extractRelationsFn:o,symbolSearchFn:l,relationSearchFn:a,logger:s,defaultProject:A,role:T});if(dt(n),O.tsconfigPaths=await g(n),O.boundaries=S,T==="owner"){let v=c?c():new ut({projectRoot:n,ignorePatterns:r,extensions:e},void 0,s),L=y?y():new ft({projectRoot:n,boundaries:S,extensions:e,ignorePatterns:r,dbConnection:h,parseCache:N.parseCache,fileRepo:N.fileRepo,symbolRepo:N.symbolRepo,relationRepo:N.relationRepo,logger:s});O.coordinator=L,O.watcher=v,await v.start(($)=>L.handleWatcherEvent?.($)).then(($)=>{if(nt($))throw $.data});let et=setInterval(()=>{P(h,process.pid)},cn);O.timer=et,await L.fullIndex()}else{let v=0,L=async()=>{try{let $=await Promise.resolve(x(h,process.pid,{}));if(v=0,$==="owner"){clearInterval(O.timer),O.timer=null;let H=null,Q=null;try{H=c?c():new ut({projectRoot:n,ignorePatterns:r,extensions:e},void 0,s),Q=y?y():new ft({projectRoot:n,boundaries:S,extensions:e,ignorePatterns:r,dbConnection:h,parseCache:N.parseCache,fileRepo:N.fileRepo,symbolRepo:N.symbolRepo,relationRepo:N.relationRepo,logger:s});for(let J of O.onIndexedCallbacks)Q.onIndexed(J);await H.start((J)=>Q?.handleWatcherEvent?.(J)).then((J)=>{if(nt(J))throw J.data});let gt=setInterval(()=>{P(h,process.pid)},cn);O.timer=gt,O.coordinator=Q,O.watcher=H,await Q.fullIndex()}catch(gt){if(s.error("[Gildash] owner promotion failed, reverting to reader",gt),H){let J=await H.close();if(nt(J))s.error("[Gildash] watcher close error during promotion rollback",J.data);O.watcher=null}if(Q)await Q.shutdown().catch((J)=>s.error("[Gildash] coordinator shutdown error during promotion rollback",J)),O.coordinator=null;if(O.timer===null)O.timer=setInterval(L,ln)}}}catch($){if(v++,s.error("[Gildash] healthcheck error",$),v>=jn)s.error("[Gildash] healthcheck failed too many times, shutting down"),clearInterval(O.timer),O.timer=null,O.close().catch((H)=>s.error("[Gildash] close error during healthcheck shutdown",H))}},et=setInterval(L,ln);O.timer=et}let W=["SIGTERM","SIGINT","beforeExit"];for(let v of W){let L=()=>{O.close().catch((et)=>s.error("[Gildash] close error during signal",v,et))};if(v==="beforeExit")process.on("beforeExit",L);else process.on(v,L);O.signalHandlers.push([v,L])}return O}catch(S){return h.close(),_(k("store","Gildash: initialization failed",S))}}async close(){if(this.closed)return;this.closed=!0;let t=[];for(let[n,e]of this.signalHandlers)if(n==="beforeExit")process.off("beforeExit",e);else process.off(n,e);if(this.signalHandlers=[],this.coordinator)try{await this.coordinator.shutdown()}catch(n){t.push(n instanceof Error?n:Error(String(n)))}if(this.watcher){let n=await this.watcher.close();if(nt(n))t.push(n.data)}if(this.timer!==null)clearInterval(this.timer),this.timer=null;try{this.releaseWatcherRoleFn(this.db,process.pid)}catch(n){t.push(n instanceof Error?n:Error(String(n)))}try{this.db.close()}catch(n){t.push(n instanceof Error?n:Error(String(n)))}if(t.length>0)return _(k("close","Gildash: one or more errors occurred during close()",t))}onIndexed(t){if(this.onIndexedCallbacks.add(t),!this.coordinator)return()=>{this.onIndexedCallbacks.delete(t)};let n=this.coordinator.onIndexed(t);return()=>{this.onIndexedCallbacks.delete(t),n()}}parseSource(t,n){if(this.closed)return _(k("closed","Gildash: instance is closed"));let e=this.parseSourceFn(t,n);if(nt(e))return e;return this.parseCache.set(t,e),e}extractSymbols(t){if(this.closed)return _(k("closed","Gildash: instance is closed"));return this.extractSymbolsFn(t)}extractRelations(t){if(this.closed)return _(k("closed","Gildash: instance is closed"));return this.extractRelationsFn(t.program,t.filePath,this.tsconfigPaths??void 0)}async reindex(){if(this.closed)return _(k("closed","Gildash: instance is closed"));if(!this.coordinator)return _(k("closed","Gildash: reindex() is not available for readers"));try{return await this.coordinator.fullIndex()}catch(t){return _(k("index","Gildash: reindex failed",t))}}get projects(){return[...this.boundaries]}getStats(t){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{return this.symbolRepo.getStats(t??this.defaultProject)}catch(n){return _(k("store","Gildash: getStats failed",n))}}searchSymbols(t){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:this.defaultProject,query:t})}catch(n){return _(k("search","Gildash: searchSymbols failed",n))}}searchRelations(t){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:this.defaultProject,query:t})}catch(n){return _(k("search","Gildash: searchRelations failed",n))}}getDependencies(t,n,e=1e4){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:n??this.defaultProject,query:{srcFilePath:t,type:"imports",project:n??this.defaultProject,limit:e}}).map((r)=>r.dstFilePath)}catch(r){return _(k("search","Gildash: getDependencies failed",r))}}getDependents(t,n,e=1e4){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:n??this.defaultProject,query:{dstFilePath:t,type:"imports",project:n??this.defaultProject,limit:e}}).map((r)=>r.srcFilePath)}catch(r){return _(k("search","Gildash: getDependents failed",r))}}async getAffected(t,n){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{let e=new ot({relationRepo:this.relationRepo,project:n??this.defaultProject});return await e.build(),e.getAffectedByChange(t)}catch(e){return _(k("search","Gildash: getAffected failed",e))}}async hasCycle(t){if(this.closed)return _(k("closed","Gildash: instance is closed"));try{let n=new ot({relationRepo:this.relationRepo,project:t??this.defaultProject});return await n.build(),n.hasCycle()}catch(n){return _(k("search","Gildash: hasCycle failed",n))}}}export{vt as symbolSearch,Mt as relationSearch,k as gildashError,zt as Gildash,ot as DependencyGraph};
|
|
24
24
|
|
|
25
|
-
//# debugId=
|
|
25
|
+
//# debugId=B695837771DC776164756E2164756E21
|
|
26
26
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/gildash.ts", "../src/parser/parse-source.ts", "../src/errors.ts", "../src/common/lru-cache.ts", "../src/parser/parse-cache.ts", "../src/parser/source-position.ts", "../src/parser/jsdoc-parser.ts", "../src/extractor/symbol-extractor.ts", "../src/extractor/extractor-utils.ts", "../src/parser/ast-utils.ts", "../src/extractor/imports-extractor.ts", "../src/extractor/calls-extractor.ts", "../src/extractor/heritage-extractor.ts", "../src/extractor/relation-extractor.ts", "../src/store/connection.ts", "../src/store/schema.ts", "../src/store/repositories/file.repository.ts", "../src/store/repositories/symbol.repository.ts", "../src/store/repositories/fts-utils.ts", "../src/store/repositories/relation.repository.ts", "../src/watcher/project-watcher.ts", "../src/common/project-discovery.ts", "../src/common/tsconfig-resolver.ts", "../src/common/path-utils.ts", "../src/common/hasher.ts", "../src/indexer/index-coordinator.ts", "../src/indexer/file-indexer.ts", "../src/indexer/symbol-indexer.ts", "../src/indexer/relation-indexer.ts", "../src/watcher/ownership.ts", "../src/search/symbol-search.ts", "../src/search/relation-search.ts", "../src/search/dependency-graph.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { err, isErr, type Result } from '@zipbul/result';\nimport path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { ParsedFile } from './parser/types';\nimport { parseSource as defaultParseSource } from './parser/parse-source';\nimport { ParseCache } from './parser/parse-cache';\nimport type { ExtractedSymbol } from './extractor/types';\nimport { extractSymbols as defaultExtractSymbols } from './extractor/symbol-extractor';\nimport { extractRelations as defaultExtractRelations } from './extractor/relation-extractor';\nimport type { CodeRelation } from './extractor/types';\nimport { DbConnection } from './store/connection';\nimport { FileRepository } from './store/repositories/file.repository';\nimport { SymbolRepository } from './store/repositories/symbol.repository';\nimport { RelationRepository } from './store/repositories/relation.repository';\nimport { ProjectWatcher } from './watcher/project-watcher';\nimport { IndexCoordinator } from './indexer/index-coordinator';\nimport type { IndexResult } from './indexer/index-coordinator';\nimport type { IndexCoordinatorOptions } from './indexer/index-coordinator';\nimport type { FileChangeEvent } from './watcher/types';\nimport { acquireWatcherRole, releaseWatcherRole, updateHeartbeat } from './watcher/ownership';\nimport type { WatcherOwnerStore } from './watcher/ownership';\nimport { discoverProjects } from './common/project-discovery';\nimport type { ProjectBoundary } from './common/project-discovery';\nimport { loadTsconfigPaths, clearTsconfigPathsCache } from './common/tsconfig-resolver';\nimport type { TsconfigPaths } from './common/tsconfig-resolver';\nimport { symbolSearch as defaultSymbolSearch } from './search/symbol-search';\nimport type { SymbolSearchQuery, SymbolSearchResult } from './search/symbol-search';\nimport { relationSearch as defaultRelationSearch } from './search/relation-search';\nimport type { RelationSearchQuery } from './search/relation-search';\nimport type { SymbolStats } from './store/repositories/symbol.repository';\nimport { DependencyGraph } from './search/dependency-graph';\nimport { gildashError, type GildashError } from './errors';\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\nconst HEALTHCHECK_INTERVAL_MS = 60_000;\nconst MAX_HEALTHCHECK_RETRIES = 10;\n\n/**\n * Minimal logger interface accepted by {@link Gildash}.\n *\n * Any object with an `error` method (including `console`) satisfies this interface.\n */\nexport interface Logger {\n /** Log one or more error-level messages. */\n error(...args: unknown[]): void;\n}\n\n/**\n * Options for creating a {@link Gildash} instance via {@link Gildash.open}.\n *\n * @example\n * ```ts\n * import { isErr } from '@zipbul/result';\n *\n * const result = await Gildash.open({\n * projectRoot: '/absolute/path/to/project',\n * extensions: ['.ts', '.tsx'],\n * ignorePatterns: ['vendor'],\n * });\n * if (isErr(result)) {\n * console.error(result.data.message);\n * process.exit(1);\n * }\n * const ledger = result;\n * ```\n */\nexport interface GildashOptions {\n /** Absolute path to the project root directory. */\n projectRoot: string;\n /** File extensions to index. Defaults to `['.ts', '.mts', '.cts']`. */\n extensions?: string[];\n /** Glob patterns to ignore during indexing. */\n ignorePatterns?: string[];\n /** Maximum number of parsed ASTs to keep in the LRU cache. Defaults to `500`. */\n parseCacheCapacity?: number;\n /** Logger for error output. Defaults to `console`. */\n logger?: Logger;\n}\n\ninterface GildashInternalOptions {\n existsSyncFn?: (p: string) => boolean;\n dbConnectionFactory?: () => Pick<DbConnection, 'open' | 'close' | 'transaction'> & WatcherOwnerStore;\n watcherFactory?: () => Pick<ProjectWatcher, 'start' | 'close'>;\n coordinatorFactory?: () => Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n };\n repositoryFactory?: () => {\n fileRepo: Pick<FileRepository, 'upsertFile' | 'getAllFiles' | 'getFilesMap' | 'deleteFile'>;\n symbolRepo: SymbolRepository;\n relationRepo: RelationRepository;\n parseCache: Pick<ParseCache, 'set' | 'get' | 'invalidate'>;\n };\n acquireWatcherRoleFn?: typeof acquireWatcherRole;\n releaseWatcherRoleFn?: typeof releaseWatcherRole;\n updateHeartbeatFn?: typeof updateHeartbeat;\n discoverProjectsFn?: typeof discoverProjects;\n parseSourceFn?: typeof defaultParseSource;\n extractSymbolsFn?: typeof defaultExtractSymbols;\n extractRelationsFn?: typeof defaultExtractRelations;\n symbolSearchFn?: typeof defaultSymbolSearch;\n relationSearchFn?: typeof defaultRelationSearch;\n loadTsconfigPathsFn?: typeof loadTsconfigPaths;\n}\n\n/**\n * Main entry point for gildash.\n *\n * `Gildash` indexes TypeScript source code into a local SQLite database,\n * watches for file changes, and provides search / dependency-graph queries.\n *\n * Every public method returns a `Result<T, GildashError>` — either the\n * success value `T` directly, or an `Err<GildashError>` that can be checked\n * with `isErr()` from `@zipbul/result`.\n *\n * Create an instance with the static {@link Gildash.open} factory.\n * Always call {@link Gildash.close} when done to release resources.\n *\n * @example\n * ```ts\n * import { Gildash } from '@zipbul/gildash';\n * import { isErr } from '@zipbul/result';\n *\n * const result = await Gildash.open({ projectRoot: '/my/project' });\n * if (isErr(result)) {\n * console.error(result.data.message);\n * process.exit(1);\n * }\n * const ledger = result;\n *\n * const symbols = ledger.searchSymbols({ text: 'handle', kind: 'function' });\n * if (!isErr(symbols)) {\n * symbols.forEach(s => console.log(s.name));\n * }\n *\n * await ledger.close();\n * ```\n */\nexport class Gildash {\n /** Absolute path to the indexed project root. */\n readonly projectRoot: string;\n\n private readonly db: Pick<DbConnection, 'open' | 'close' | 'transaction'> & WatcherOwnerStore;\n private readonly symbolRepo: SymbolRepository;\n private readonly relationRepo: RelationRepository;\n private readonly parseCache: Pick<ParseCache, 'set' | 'get' | 'invalidate'>;\n private coordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null;\n private watcher: Pick<ProjectWatcher, 'start' | 'close'> | null;\n private readonly releaseWatcherRoleFn: typeof releaseWatcherRole;\n private readonly parseSourceFn: typeof defaultParseSource;\n private readonly extractSymbolsFn: typeof defaultExtractSymbols;\n private readonly extractRelationsFn: typeof defaultExtractRelations;\n private readonly symbolSearchFn: typeof defaultSymbolSearch;\n private readonly relationSearchFn: typeof defaultRelationSearch;\n private readonly logger: Logger;\n private readonly defaultProject: string;\n private readonly role: 'owner' | 'reader';\n private timer: ReturnType<typeof setInterval> | null = null;\n private signalHandlers: Array<[string, () => void]> = [];\n private closed = false;\n private tsconfigPaths: TsconfigPaths | null = null;\n private boundaries: ProjectBoundary[] = [];\n private readonly onIndexedCallbacks = new Set<(result: IndexResult) => void>();\n\n private constructor(opts: {\n projectRoot: string;\n db: Pick<DbConnection, 'open' | 'close' | 'transaction'> & WatcherOwnerStore;\n symbolRepo: SymbolRepository;\n relationRepo: RelationRepository;\n parseCache: Pick<ParseCache, 'set' | 'get' | 'invalidate'>;\n coordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null;\n watcher: Pick<ProjectWatcher, 'start' | 'close'> | null;\n releaseWatcherRoleFn: typeof releaseWatcherRole;\n parseSourceFn: typeof defaultParseSource;\n extractSymbolsFn: typeof defaultExtractSymbols;\n extractRelationsFn: typeof defaultExtractRelations;\n symbolSearchFn: typeof defaultSymbolSearch;\n relationSearchFn: typeof defaultRelationSearch;\n logger: Logger;\n defaultProject: string;\n role: 'owner' | 'reader';\n }) {\n this.projectRoot = opts.projectRoot;\n this.db = opts.db;\n this.symbolRepo = opts.symbolRepo;\n this.relationRepo = opts.relationRepo;\n this.parseCache = opts.parseCache;\n this.coordinator = opts.coordinator;\n this.watcher = opts.watcher;\n this.releaseWatcherRoleFn = opts.releaseWatcherRoleFn;\n this.parseSourceFn = opts.parseSourceFn;\n this.extractSymbolsFn = opts.extractSymbolsFn;\n this.extractRelationsFn = opts.extractRelationsFn;\n this.symbolSearchFn = opts.symbolSearchFn;\n this.relationSearchFn = opts.relationSearchFn;\n this.logger = opts.logger;\n this.defaultProject = opts.defaultProject;\n this.role = opts.role;\n }\n\n /**\n * Create and initialise a new `Gildash` instance.\n *\n * Opens (or creates) a SQLite database alongside the project root,\n * discovers sub-projects, acquires a watcher role, performs initial indexing,\n * and begins watching for file changes.\n *\n * @param options - Configuration for the instance.\n * @returns A fully-initialised `Gildash` ready for queries, or an `Err<GildashError>` on failure.\n *\n * @example\n * ```ts\n * const result = await Gildash.open({\n * projectRoot: '/home/user/my-app',\n * extensions: ['.ts', '.tsx'],\n * });\n * if (isErr(result)) { console.error(result.data.message); process.exit(1); }\n * const ledger = result;\n * ```\n */\n static async open(options: GildashOptions & GildashInternalOptions): Promise<Result<Gildash, GildashError>> {\n const {\n projectRoot,\n extensions = ['.ts', '.mts', '.cts'],\n ignorePatterns = [],\n parseCacheCapacity = 500,\n logger = console,\n existsSyncFn = existsSync,\n dbConnectionFactory,\n watcherFactory,\n coordinatorFactory,\n repositoryFactory,\n acquireWatcherRoleFn = acquireWatcherRole,\n releaseWatcherRoleFn = releaseWatcherRole,\n updateHeartbeatFn = updateHeartbeat,\n discoverProjectsFn = discoverProjects,\n parseSourceFn = defaultParseSource,\n extractSymbolsFn = defaultExtractSymbols,\n extractRelationsFn = defaultExtractRelations,\n symbolSearchFn = defaultSymbolSearch,\n relationSearchFn = defaultRelationSearch,\n loadTsconfigPathsFn = loadTsconfigPaths,\n } = options;\n\n if (!path.isAbsolute(projectRoot)) {\n return err(gildashError('validation', `Gildash: projectRoot must be an absolute path, got: \"${projectRoot}\"`))\n }\n if (!existsSyncFn(projectRoot)) {\n return err(gildashError('validation', `Gildash: projectRoot does not exist: \"${projectRoot}\"`))\n }\n\n const db = dbConnectionFactory\n ? dbConnectionFactory()\n : new DbConnection({ projectRoot });\n const openResult = db.open();\n if (isErr(openResult)) return openResult;\n try {\n\n const boundaries: ProjectBoundary[] = await discoverProjectsFn(projectRoot);\n const defaultProject = boundaries[0]?.project ?? path.basename(projectRoot);\n\n const repos = repositoryFactory\n ? repositoryFactory()\n : (() => {\n const connection = db as DbConnection;\n return {\n fileRepo: new FileRepository(connection),\n symbolRepo: new SymbolRepository(connection),\n relationRepo: new RelationRepository(connection),\n parseCache: new ParseCache(parseCacheCapacity),\n };\n })();\n\n const role = await Promise.resolve(\n acquireWatcherRoleFn(db, process.pid, {}),\n );\n\n let coordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null = null;\n let watcher: Pick<ProjectWatcher, 'start' | 'close'> | null = null;\n\n const instance = new Gildash({\n projectRoot,\n db,\n symbolRepo: repos.symbolRepo,\n relationRepo: repos.relationRepo,\n parseCache: repos.parseCache,\n coordinator,\n watcher,\n releaseWatcherRoleFn: releaseWatcherRoleFn,\n parseSourceFn: parseSourceFn,\n extractSymbolsFn: extractSymbolsFn,\n extractRelationsFn: extractRelationsFn,\n symbolSearchFn: symbolSearchFn,\n relationSearchFn: relationSearchFn,\n logger,\n defaultProject,\n role,\n });\n clearTsconfigPathsCache(projectRoot);\n instance.tsconfigPaths = await loadTsconfigPathsFn(projectRoot);\n instance.boundaries = boundaries;\n if (role === 'owner') {\n const w = watcherFactory\n ? watcherFactory()\n : new ProjectWatcher({ projectRoot, ignorePatterns, extensions }, undefined, logger);\n\n const c = coordinatorFactory\n ? coordinatorFactory()\n : new IndexCoordinator({\n projectRoot,\n boundaries,\n extensions,\n ignorePatterns,\n dbConnection: db,\n parseCache: repos.parseCache,\n fileRepo: repos.fileRepo,\n symbolRepo: repos.symbolRepo,\n relationRepo: repos.relationRepo,\n logger,\n });\n\n instance.coordinator = c;\n instance.watcher = w;\n\n await w.start((event) => c.handleWatcherEvent?.(event)).then((startResult) => {\n if (isErr(startResult)) throw startResult.data;\n });\n\n const timer = setInterval(() => {\n updateHeartbeatFn(db, process.pid);\n }, HEARTBEAT_INTERVAL_MS);\n instance.timer = timer;\n\n await c.fullIndex();\n } else {\n let retryCount = 0;\n const healthcheck = async () => {\n try {\n const newRole = await Promise.resolve(\n acquireWatcherRoleFn(db, process.pid, {}),\n );\n retryCount = 0;\n if (newRole === 'owner') {\n clearInterval(instance.timer!);\n instance.timer = null;\n let promotedWatcher: Pick<ProjectWatcher, 'start' | 'close'> | null = null;\n let promotedCoordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null = null;\n try {\n promotedWatcher = watcherFactory\n ? watcherFactory()\n : new ProjectWatcher({ projectRoot, ignorePatterns, extensions }, undefined, logger);\n promotedCoordinator = coordinatorFactory\n ? coordinatorFactory()\n : new IndexCoordinator({\n projectRoot,\n boundaries,\n extensions,\n ignorePatterns,\n dbConnection: db,\n parseCache: repos.parseCache,\n fileRepo: repos.fileRepo,\n symbolRepo: repos.symbolRepo,\n relationRepo: repos.relationRepo,\n logger,\n });\n for (const cb of instance.onIndexedCallbacks) {\n promotedCoordinator.onIndexed(cb);\n }\n await promotedWatcher.start((event) => promotedCoordinator?.handleWatcherEvent?.(event)).then((startResult) => {\n if (isErr(startResult)) throw startResult.data;\n });\n const hbTimer = setInterval(() => {\n updateHeartbeatFn(db, process.pid);\n }, HEARTBEAT_INTERVAL_MS);\n instance.timer = hbTimer;\n instance.coordinator = promotedCoordinator;\n instance.watcher = promotedWatcher;\n await promotedCoordinator.fullIndex();\n } catch (setupErr) {\n logger.error('[Gildash] owner promotion failed, reverting to reader', setupErr);\n if (promotedWatcher) {\n const closeResult = await promotedWatcher.close();\n if (isErr(closeResult)) logger.error('[Gildash] watcher close error during promotion rollback', closeResult.data);\n instance.watcher = null;\n }\n if (promotedCoordinator) {\n await promotedCoordinator.shutdown().catch((e) =>\n logger.error('[Gildash] coordinator shutdown error during promotion rollback', e),\n );\n instance.coordinator = null;\n }\n if (instance.timer === null) {\n instance.timer = setInterval(healthcheck, HEALTHCHECK_INTERVAL_MS);\n }\n }\n }\n } catch (err) {\n retryCount++;\n logger.error('[Gildash] healthcheck error', err);\n if (retryCount >= MAX_HEALTHCHECK_RETRIES) {\n logger.error('[Gildash] healthcheck failed too many times, shutting down');\n clearInterval(instance.timer!);\n instance.timer = null;\n instance.close().catch((closeErr) =>\n logger.error('[Gildash] close error during healthcheck shutdown', closeErr),\n );\n }\n }\n };\n const timer = setInterval(healthcheck, HEALTHCHECK_INTERVAL_MS);\n instance.timer = timer;\n }\n\n const signals: Array<NodeJS.Signals | 'beforeExit'> = ['SIGTERM', 'SIGINT', 'beforeExit'];\n for (const sig of signals) {\n const handler = () => { instance.close().catch(err => logger.error('[Gildash] close error during signal', sig, err)); };\n if (sig === 'beforeExit') {\n process.on('beforeExit', handler);\n } else {\n process.on(sig, handler);\n }\n instance.signalHandlers.push([sig, handler]);\n }\n\n return instance;\n } catch (error) {\n db.close();\n return err(gildashError('store', 'Gildash: initialization failed', error));\n }\n }\n\n /**\n * Shut down the instance and release all resources.\n *\n * Stops the file watcher, shuts down the index coordinator,\n * releases the watcher ownership role, and closes the database.\n * Calling `close()` more than once is safe (subsequent calls are no-ops).\n *\n * @returns `void` on success, or `Err<GildashError>` with `type='close'` if one or more\n * sub-systems failed during shutdown. The `cause` field contains an array of\n * individual errors from each failed sub-system.\n *\n * @example\n * ```ts\n * const closeResult = await ledger.close();\n * if (isErr(closeResult)) {\n * console.error('Close failed:', closeResult.data.message);\n * // closeResult.data.cause is unknown[] of per-subsystem errors\n * }\n * ```\n */\n async close(): Promise<Result<void, GildashError>> {\n if (this.closed) return;\n this.closed = true;\n\n const closeErrors: unknown[] = [];\n\n for (const [sig, handler] of this.signalHandlers) {\n if (sig === 'beforeExit') {\n process.off('beforeExit', handler);\n } else {\n process.off(sig as NodeJS.Signals, handler);\n }\n }\n this.signalHandlers = [];\n\n if (this.coordinator) {\n try {\n await this.coordinator.shutdown();\n } catch (err) {\n closeErrors.push(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n if (this.watcher) {\n const closeResult = await this.watcher.close();\n if (isErr(closeResult)) closeErrors.push(closeResult.data);\n }\n\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n\n try {\n this.releaseWatcherRoleFn(this.db, process.pid);\n } catch (err) {\n closeErrors.push(err instanceof Error ? err : new Error(String(err)));\n }\n\n try {\n this.db.close();\n } catch (err) {\n closeErrors.push(err instanceof Error ? err : new Error(String(err)));\n }\n\n if (closeErrors.length > 0) {\n return err(gildashError('close', 'Gildash: one or more errors occurred during close()', closeErrors));\n }\n }\n\n /**\n * Register a callback that fires after each indexing run completes.\n *\n * @param callback - Receives the {@link IndexResult} for the completed run.\n * @returns An unsubscribe function. Call it to remove the listener.\n *\n * @example\n * ```ts\n * const off = ledger.onIndexed(result => {\n * console.log(`Indexed ${result.filesProcessed} files`);\n * });\n * // later…\n * off();\n * ```\n */\n onIndexed(callback: (result: IndexResult) => void): () => void {\n this.onIndexedCallbacks.add(callback);\n if (!this.coordinator) {\n return () => { this.onIndexedCallbacks.delete(callback); };\n }\n const unsubscribe = this.coordinator.onIndexed(callback);\n return () => {\n this.onIndexedCallbacks.delete(callback);\n unsubscribe();\n };\n }\n\n /**\n * Parse a TypeScript source string into an AST and cache the result.\n *\n * On success the result is automatically stored in the internal LRU parse cache\n * so that subsequent calls to extraction methods can reuse it.\n *\n * @param filePath - File path used as the cache key and for diagnostics.\n * @param sourceText - Raw TypeScript source code.\n * @returns A {@link ParsedFile}, or `Err<GildashError>` with `type='closed'` if the instance\n * is closed, or `type='parse'` if the parser fails.\n *\n * @example\n * ```ts\n * const parsed = ledger.parseSource('/project/src/app.ts', sourceCode);\n * if (isErr(parsed)) {\n * console.error(parsed.data.message); // e.g. \"Failed to parse file: ...\"\n * return;\n * }\n * // parsed is now a ParsedFile\n * const symbols = ledger.extractSymbols(parsed);\n * ```\n */\n parseSource(filePath: string, sourceText: string): Result<ParsedFile, GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n const result = this.parseSourceFn(filePath, sourceText);\n if (isErr(result)) return result;\n this.parseCache.set(filePath, result);\n return result;\n }\n\n /**\n * Extract all symbol declarations from a previously parsed file.\n *\n * Returns function, class, variable, type-alias, interface, and enum declarations\n * found in the AST.\n *\n * @param parsed - A {@link ParsedFile} obtained from {@link parseSource}.\n * @returns An array of {@link ExtractedSymbol} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed.\n *\n * @example\n * ```ts\n * const symbols = ledger.extractSymbols(parsed);\n * if (isErr(symbols)) return;\n * for (const sym of symbols) {\n * console.log(`${sym.kind}: ${sym.name}`);\n * }\n * ```\n */\n extractSymbols(parsed: ParsedFile): Result<ExtractedSymbol[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n return this.extractSymbolsFn(parsed);\n }\n\n /**\n * Extract inter-file relationships (imports, calls, extends, implements)\n * from a previously parsed file.\n *\n * If tsconfig path aliases were discovered during {@link Gildash.open},\n * they are automatically applied when resolving import targets.\n *\n * @param parsed - A {@link ParsedFile} obtained from {@link parseSource}.\n * @returns An array of {@link CodeRelation} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed.\n *\n * @example\n * ```ts\n * const relations = ledger.extractRelations(parsed);\n * if (isErr(relations)) return;\n * const imports = relations.filter(r => r.type === 'imports');\n * ```\n */\n extractRelations(parsed: ParsedFile): Result<CodeRelation[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n return this.extractRelationsFn(\n parsed.program,\n parsed.filePath,\n this.tsconfigPaths ?? undefined,\n );\n }\n\n /**\n * Trigger a full re-index of all tracked files.\n *\n * Only available to the instance that holds the *owner* role.\n * Reader instances receive `Err<GildashError>` with `type='closed'`.\n *\n * @returns An {@link IndexResult} summary on success, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed / reader,\n * `type='index'` if the indexing pipeline fails.\n *\n * @example\n * ```ts\n * const result = await ledger.reindex();\n * if (isErr(result)) {\n * console.error(result.data.message);\n * return;\n * }\n * console.log(`Indexed ${result.indexedFiles} files in ${result.durationMs}ms`);\n * ```\n */\n async reindex(): Promise<Result<IndexResult, GildashError>> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n if (!this.coordinator) {\n return err(gildashError('closed', 'Gildash: reindex() is not available for readers'));\n }\n try {\n return await this.coordinator.fullIndex();\n } catch (e) {\n return err(gildashError('index', 'Gildash: reindex failed', e));\n }\n }\n\n /**\n * Discovered project boundaries within the project root.\n *\n * Each entry contains a project name and its root directory.\n */\n get projects(): ProjectBoundary[] {\n return [...this.boundaries];\n }\n\n /**\n * Return aggregate symbol statistics for the given project.\n *\n * @param project - Project name. Defaults to the auto-discovered primary project.\n * @returns A {@link SymbolStats} object with counts grouped by symbol kind,\n * or `Err<GildashError>` with `type='closed'` if the instance is closed,\n * `type='store'` if the database query fails.\n *\n * @example\n * ```ts\n * const stats = ledger.getStats();\n * if (isErr(stats)) return;\n * console.log(`Files: ${stats.fileCount}, Symbols: ${stats.symbolCount}`);\n * ```\n */\n getStats(project?: string): Result<SymbolStats, GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.symbolRepo.getStats(project ?? this.defaultProject);\n } catch (e) {\n return err(gildashError('store', 'Gildash: getStats failed', e));\n }\n }\n\n /**\n * Search indexed symbols by name, kind, file path, or export status.\n *\n * @param query - Search filters (see {@link SymbolSearchQuery}). All fields are optional;\n * omitted fields match everything.\n * @returns An array of {@link SymbolSearchResult} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed,\n * `type='search'` if the query fails.\n *\n * @example\n * ```ts\n * const fns = ledger.searchSymbols({ kind: 'function', isExported: true });\n * if (isErr(fns)) return;\n * fns.forEach(fn => console.log(fn.name, fn.filePath));\n * ```\n */\n searchSymbols(query: SymbolSearchQuery): Result<SymbolSearchResult[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.symbolSearchFn({ symbolRepo: this.symbolRepo, project: this.defaultProject, query });\n } catch (e) {\n return err(gildashError('search', 'Gildash: searchSymbols failed', e));\n }\n }\n\n /**\n * Search indexed code relationships (imports, calls, extends, implements).\n *\n * @param query - Search filters (see {@link RelationSearchQuery}). All fields are optional.\n * @returns An array of {@link CodeRelation} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed,\n * `type='search'` if the query fails.\n *\n * @example\n * ```ts\n * const rels = ledger.searchRelations({ srcFilePath: 'src/app.ts', type: 'imports' });\n * if (isErr(rels)) return;\n * rels.forEach(r => console.log(`${r.srcFilePath} -> ${r.dstFilePath}`));\n * ```\n */\n searchRelations(query: RelationSearchQuery): Result<CodeRelation[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.relationSearchFn({ relationRepo: this.relationRepo, project: this.defaultProject, query });\n } catch (e) {\n return err(gildashError('search', 'Gildash: searchRelations failed', e));\n }\n }\n\n /**\n * List the files that a given file directly imports.\n *\n * @param filePath - Absolute path of the source file.\n * @param project - Project name. Defaults to the primary project.\n * @param limit - Maximum results. Defaults to `10_000`.\n * @returns An array of absolute paths that `filePath` imports,\n * or `Err<GildashError>` with `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const deps = ledger.getDependencies('/project/src/app.ts');\n * if (isErr(deps)) return;\n * console.log('Imports:', deps.join(', '));\n * ```\n */\n getDependencies(filePath: string, project?: string, limit = 10_000): Result<string[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.relationSearchFn({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n query: { srcFilePath: filePath, type: 'imports', project: project ?? this.defaultProject, limit },\n }).map(r => r.dstFilePath);\n } catch (e) {\n return err(gildashError('search', 'Gildash: getDependencies failed', e));\n }\n }\n\n /**\n * List the files that directly import a given file.\n *\n * @param filePath - Absolute path of the target file.\n * @param project - Project name. Defaults to the primary project.\n * @param limit - Maximum results. Defaults to `10_000`.\n * @returns An array of absolute paths of files that import `filePath`,\n * or `Err<GildashError>` with `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const dependents = ledger.getDependents('/project/src/utils.ts');\n * if (isErr(dependents)) return;\n * console.log('Imported by:', dependents.join(', '));\n * ```\n */\n getDependents(filePath: string, project?: string, limit = 10_000): Result<string[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.relationSearchFn({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n query: { dstFilePath: filePath, type: 'imports', project: project ?? this.defaultProject, limit },\n }).map(r => r.srcFilePath);\n } catch (e) {\n return err(gildashError('search', 'Gildash: getDependents failed', e));\n }\n }\n\n /**\n * Compute the full set of files transitively affected by changes.\n *\n * Internally builds a full {@link DependencyGraph} and walks all reverse\n * edges from each changed file to find every transitive dependent.\n *\n * @param changedFiles - Absolute paths of files that changed.\n * @param project - Project name. Defaults to the primary project.\n * @returns De-duplicated absolute paths of all transitively-dependent files\n * (excluding the changed files themselves), or `Err<GildashError>` with\n * `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const affected = await ledger.getAffected(['/project/src/utils.ts']);\n * if (isErr(affected)) return;\n * console.log('Affected files:', affected.length);\n * ```\n */\n async getAffected(changedFiles: string[], project?: string): Promise<Result<string[], GildashError>> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n const g = new DependencyGraph({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n });\n await g.build();\n return g.getAffectedByChange(changedFiles);\n } catch (e) {\n return err(gildashError('search', 'Gildash: getAffected failed', e));\n }\n }\n\n /**\n * Check whether the import graph contains a circular dependency.\n *\n * Internally builds a full {@link DependencyGraph} and runs iterative DFS\n * cycle detection.\n *\n * @param project - Project name. Defaults to the primary project.\n * @returns `true` if at least one cycle exists, `false` otherwise,\n * or `Err<GildashError>` with `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const cycleResult = await ledger.hasCycle();\n * if (isErr(cycleResult)) return;\n * if (cycleResult) {\n * console.warn('Circular dependency detected!');\n * }\n * ```\n */\n async hasCycle(project?: string): Promise<Result<boolean, GildashError>> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n const g = new DependencyGraph({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n });\n await g.build();\n return g.hasCycle();\n } catch (e) {\n return err(gildashError('search', 'Gildash: hasCycle failed', e));\n }\n }\n}\n",
|
|
5
|
+
"import { err, isErr, type Result } from '@zipbul/result';\nimport path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { ParsedFile } from './parser/types';\nimport { parseSource as defaultParseSource } from './parser/parse-source';\nimport { ParseCache } from './parser/parse-cache';\nimport type { ExtractedSymbol } from './extractor/types';\nimport { extractSymbols as defaultExtractSymbols } from './extractor/symbol-extractor';\nimport { extractRelations as defaultExtractRelations } from './extractor/relation-extractor';\nimport type { CodeRelation } from './extractor/types';\nimport { DbConnection } from './store/connection';\nimport { FileRepository } from './store/repositories/file.repository';\nimport { SymbolRepository } from './store/repositories/symbol.repository';\nimport { RelationRepository } from './store/repositories/relation.repository';\nimport { ProjectWatcher } from './watcher/project-watcher';\nimport { IndexCoordinator } from './indexer/index-coordinator';\nimport type { IndexResult } from './indexer/index-coordinator';\nimport type { IndexCoordinatorOptions } from './indexer/index-coordinator';\nimport type { FileChangeEvent } from './watcher/types';\nimport { acquireWatcherRole, releaseWatcherRole, updateHeartbeat } from './watcher/ownership';\nimport type { WatcherOwnerStore } from './watcher/ownership';\nimport { discoverProjects } from './common/project-discovery';\nimport type { ProjectBoundary } from './common/project-discovery';\nimport { loadTsconfigPaths, clearTsconfigPathsCache } from './common/tsconfig-resolver';\nimport type { TsconfigPaths } from './common/tsconfig-resolver';\nimport { symbolSearch as defaultSymbolSearch } from './search/symbol-search';\nimport type { SymbolSearchQuery, SymbolSearchResult } from './search/symbol-search';\nimport { relationSearch as defaultRelationSearch } from './search/relation-search';\nimport type { RelationSearchQuery } from './search/relation-search';\nimport type { SymbolStats } from './store/repositories/symbol.repository';\nimport { DependencyGraph } from './search/dependency-graph';\nimport { gildashError, type GildashError } from './errors';\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\nconst HEALTHCHECK_INTERVAL_MS = 60_000;\nconst MAX_HEALTHCHECK_RETRIES = 10;\n\n/**\n * Minimal logger interface accepted by {@link Gildash}.\n *\n * Any object with an `error` method (including `console`) satisfies this interface.\n */\nexport interface Logger {\n /** Log one or more error-level messages. */\n error(...args: unknown[]): void;\n}\n\n/**\n * Options for creating a {@link Gildash} instance via {@link Gildash.open}.\n *\n * @example\n * ```ts\n * import { isErr } from '@zipbul/result';\n *\n * const result = await Gildash.open({\n * projectRoot: '/absolute/path/to/project',\n * extensions: ['.ts', '.tsx'],\n * ignorePatterns: ['vendor'],\n * });\n * if (isErr(result)) {\n * console.error(result.data.message);\n * process.exit(1);\n * }\n * const ledger = result;\n * ```\n */\nexport interface GildashOptions {\n /** Absolute path to the project root directory. */\n projectRoot: string;\n /** File extensions to index. Defaults to `['.ts', '.mts', '.cts']`. */\n extensions?: string[];\n /** Glob patterns to ignore during indexing. */\n ignorePatterns?: string[];\n /** Maximum number of parsed ASTs to keep in the LRU cache. Defaults to `500`. */\n parseCacheCapacity?: number;\n /** Logger for error output. Defaults to `console`. */\n logger?: Logger;\n}\n\ninterface GildashInternalOptions {\n existsSyncFn?: (p: string) => boolean;\n dbConnectionFactory?: () => Pick<DbConnection, 'open' | 'close' | 'transaction'> & WatcherOwnerStore;\n watcherFactory?: () => Pick<ProjectWatcher, 'start' | 'close'>;\n coordinatorFactory?: () => Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n };\n repositoryFactory?: () => {\n fileRepo: Pick<FileRepository, 'upsertFile' | 'getAllFiles' | 'getFilesMap' | 'deleteFile'>;\n symbolRepo: SymbolRepository;\n relationRepo: RelationRepository;\n parseCache: Pick<ParseCache, 'set' | 'get' | 'invalidate'>;\n };\n acquireWatcherRoleFn?: typeof acquireWatcherRole;\n releaseWatcherRoleFn?: typeof releaseWatcherRole;\n updateHeartbeatFn?: typeof updateHeartbeat;\n discoverProjectsFn?: typeof discoverProjects;\n parseSourceFn?: typeof defaultParseSource;\n extractSymbolsFn?: typeof defaultExtractSymbols;\n extractRelationsFn?: typeof defaultExtractRelations;\n symbolSearchFn?: typeof defaultSymbolSearch;\n relationSearchFn?: typeof defaultRelationSearch;\n loadTsconfigPathsFn?: typeof loadTsconfigPaths;\n}\n\n/**\n * Main entry point for gildash.\n *\n * `Gildash` indexes TypeScript source code into a local SQLite database,\n * watches for file changes, and provides search / dependency-graph queries.\n *\n * Every public method returns a `Result<T, GildashError>` — either the\n * success value `T` directly, or an `Err<GildashError>` that can be checked\n * with `isErr()` from `@zipbul/result`.\n *\n * Create an instance with the static {@link Gildash.open} factory.\n * Always call {@link Gildash.close} when done to release resources.\n *\n * @example\n * ```ts\n * import { Gildash } from '@zipbul/gildash';\n * import { isErr } from '@zipbul/result';\n *\n * const result = await Gildash.open({ projectRoot: '/my/project' });\n * if (isErr(result)) {\n * console.error(result.data.message);\n * process.exit(1);\n * }\n * const ledger = result;\n *\n * const symbols = ledger.searchSymbols({ text: 'handle', kind: 'function' });\n * if (!isErr(symbols)) {\n * symbols.forEach(s => console.log(s.name));\n * }\n *\n * await ledger.close();\n * ```\n */\nexport class Gildash {\n /** Absolute path to the indexed project root. */\n readonly projectRoot: string;\n\n private readonly db: Pick<DbConnection, 'open' | 'close' | 'transaction'> & WatcherOwnerStore;\n private readonly symbolRepo: SymbolRepository;\n private readonly relationRepo: RelationRepository;\n private readonly parseCache: Pick<ParseCache, 'set' | 'get' | 'invalidate'>;\n private coordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null;\n private watcher: Pick<ProjectWatcher, 'start' | 'close'> | null;\n private readonly releaseWatcherRoleFn: typeof releaseWatcherRole;\n private readonly parseSourceFn: typeof defaultParseSource;\n private readonly extractSymbolsFn: typeof defaultExtractSymbols;\n private readonly extractRelationsFn: typeof defaultExtractRelations;\n private readonly symbolSearchFn: typeof defaultSymbolSearch;\n private readonly relationSearchFn: typeof defaultRelationSearch;\n private readonly logger: Logger;\n private readonly defaultProject: string;\n /** Current watcher role: `'owner'` (can reindex) or `'reader'` (read-only). */\n readonly role: 'owner' | 'reader';\n private timer: ReturnType<typeof setInterval> | null = null;\n private signalHandlers: Array<[string, () => void]> = [];\n private closed = false;\n private tsconfigPaths: TsconfigPaths | null = null;\n private boundaries: ProjectBoundary[] = [];\n private readonly onIndexedCallbacks = new Set<(result: IndexResult) => void>();\n\n private constructor(opts: {\n projectRoot: string;\n db: Pick<DbConnection, 'open' | 'close' | 'transaction'> & WatcherOwnerStore;\n symbolRepo: SymbolRepository;\n relationRepo: RelationRepository;\n parseCache: Pick<ParseCache, 'set' | 'get' | 'invalidate'>;\n coordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null;\n watcher: Pick<ProjectWatcher, 'start' | 'close'> | null;\n releaseWatcherRoleFn: typeof releaseWatcherRole;\n parseSourceFn: typeof defaultParseSource;\n extractSymbolsFn: typeof defaultExtractSymbols;\n extractRelationsFn: typeof defaultExtractRelations;\n symbolSearchFn: typeof defaultSymbolSearch;\n relationSearchFn: typeof defaultRelationSearch;\n logger: Logger;\n defaultProject: string;\n role: 'owner' | 'reader';\n }) {\n this.projectRoot = opts.projectRoot;\n this.db = opts.db;\n this.symbolRepo = opts.symbolRepo;\n this.relationRepo = opts.relationRepo;\n this.parseCache = opts.parseCache;\n this.coordinator = opts.coordinator;\n this.watcher = opts.watcher;\n this.releaseWatcherRoleFn = opts.releaseWatcherRoleFn;\n this.parseSourceFn = opts.parseSourceFn;\n this.extractSymbolsFn = opts.extractSymbolsFn;\n this.extractRelationsFn = opts.extractRelationsFn;\n this.symbolSearchFn = opts.symbolSearchFn;\n this.relationSearchFn = opts.relationSearchFn;\n this.logger = opts.logger;\n this.defaultProject = opts.defaultProject;\n this.role = opts.role;\n }\n\n /**\n * Create and initialise a new `Gildash` instance.\n *\n * Opens (or creates) a SQLite database alongside the project root,\n * discovers sub-projects, acquires a watcher role, performs initial indexing,\n * and begins watching for file changes.\n *\n * @param options - Configuration for the instance.\n * @returns A fully-initialised `Gildash` ready for queries, or an `Err<GildashError>` on failure.\n *\n * @example\n * ```ts\n * const result = await Gildash.open({\n * projectRoot: '/home/user/my-app',\n * extensions: ['.ts', '.tsx'],\n * });\n * if (isErr(result)) { console.error(result.data.message); process.exit(1); }\n * const ledger = result;\n * ```\n */\n static async open(options: GildashOptions & GildashInternalOptions): Promise<Result<Gildash, GildashError>> {\n const {\n projectRoot,\n extensions = ['.ts', '.mts', '.cts'],\n ignorePatterns = [],\n parseCacheCapacity = 500,\n logger = console,\n existsSyncFn = existsSync,\n dbConnectionFactory,\n watcherFactory,\n coordinatorFactory,\n repositoryFactory,\n acquireWatcherRoleFn = acquireWatcherRole,\n releaseWatcherRoleFn = releaseWatcherRole,\n updateHeartbeatFn = updateHeartbeat,\n discoverProjectsFn = discoverProjects,\n parseSourceFn = defaultParseSource,\n extractSymbolsFn = defaultExtractSymbols,\n extractRelationsFn = defaultExtractRelations,\n symbolSearchFn = defaultSymbolSearch,\n relationSearchFn = defaultRelationSearch,\n loadTsconfigPathsFn = loadTsconfigPaths,\n } = options;\n\n if (!path.isAbsolute(projectRoot)) {\n return err(gildashError('validation', `Gildash: projectRoot must be an absolute path, got: \"${projectRoot}\"`))\n }\n if (!existsSyncFn(projectRoot)) {\n return err(gildashError('validation', `Gildash: projectRoot does not exist: \"${projectRoot}\"`))\n }\n\n const db = dbConnectionFactory\n ? dbConnectionFactory()\n : new DbConnection({ projectRoot });\n const openResult = db.open();\n if (isErr(openResult)) return openResult;\n try {\n\n const boundaries: ProjectBoundary[] = await discoverProjectsFn(projectRoot);\n const defaultProject = boundaries[0]?.project ?? path.basename(projectRoot);\n\n const repos = repositoryFactory\n ? repositoryFactory()\n : (() => {\n const connection = db as DbConnection;\n return {\n fileRepo: new FileRepository(connection),\n symbolRepo: new SymbolRepository(connection),\n relationRepo: new RelationRepository(connection),\n parseCache: new ParseCache(parseCacheCapacity),\n };\n })();\n\n const role = await Promise.resolve(\n acquireWatcherRoleFn(db, process.pid, {}),\n );\n\n let coordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null = null;\n let watcher: Pick<ProjectWatcher, 'start' | 'close'> | null = null;\n\n const instance = new Gildash({\n projectRoot,\n db,\n symbolRepo: repos.symbolRepo,\n relationRepo: repos.relationRepo,\n parseCache: repos.parseCache,\n coordinator,\n watcher,\n releaseWatcherRoleFn: releaseWatcherRoleFn,\n parseSourceFn: parseSourceFn,\n extractSymbolsFn: extractSymbolsFn,\n extractRelationsFn: extractRelationsFn,\n symbolSearchFn: symbolSearchFn,\n relationSearchFn: relationSearchFn,\n logger,\n defaultProject,\n role,\n });\n clearTsconfigPathsCache(projectRoot);\n instance.tsconfigPaths = await loadTsconfigPathsFn(projectRoot);\n instance.boundaries = boundaries;\n if (role === 'owner') {\n const w = watcherFactory\n ? watcherFactory()\n : new ProjectWatcher({ projectRoot, ignorePatterns, extensions }, undefined, logger);\n\n const c = coordinatorFactory\n ? coordinatorFactory()\n : new IndexCoordinator({\n projectRoot,\n boundaries,\n extensions,\n ignorePatterns,\n dbConnection: db,\n parseCache: repos.parseCache,\n fileRepo: repos.fileRepo,\n symbolRepo: repos.symbolRepo,\n relationRepo: repos.relationRepo,\n logger,\n });\n\n instance.coordinator = c;\n instance.watcher = w;\n\n await w.start((event) => c.handleWatcherEvent?.(event)).then((startResult) => {\n if (isErr(startResult)) throw startResult.data;\n });\n\n const timer = setInterval(() => {\n updateHeartbeatFn(db, process.pid);\n }, HEARTBEAT_INTERVAL_MS);\n instance.timer = timer;\n\n await c.fullIndex();\n } else {\n let retryCount = 0;\n const healthcheck = async () => {\n try {\n const newRole = await Promise.resolve(\n acquireWatcherRoleFn(db, process.pid, {}),\n );\n retryCount = 0;\n if (newRole === 'owner') {\n clearInterval(instance.timer!);\n instance.timer = null;\n let promotedWatcher: Pick<ProjectWatcher, 'start' | 'close'> | null = null;\n let promotedCoordinator: (Pick<IndexCoordinator, 'fullIndex' | 'shutdown' | 'onIndexed'> & {\n tsconfigPaths?: Promise<TsconfigPaths | null>;\n handleWatcherEvent?(event: FileChangeEvent): void;\n }) | null = null;\n try {\n promotedWatcher = watcherFactory\n ? watcherFactory()\n : new ProjectWatcher({ projectRoot, ignorePatterns, extensions }, undefined, logger);\n promotedCoordinator = coordinatorFactory\n ? coordinatorFactory()\n : new IndexCoordinator({\n projectRoot,\n boundaries,\n extensions,\n ignorePatterns,\n dbConnection: db,\n parseCache: repos.parseCache,\n fileRepo: repos.fileRepo,\n symbolRepo: repos.symbolRepo,\n relationRepo: repos.relationRepo,\n logger,\n });\n for (const cb of instance.onIndexedCallbacks) {\n promotedCoordinator.onIndexed(cb);\n }\n await promotedWatcher.start((event) => promotedCoordinator?.handleWatcherEvent?.(event)).then((startResult) => {\n if (isErr(startResult)) throw startResult.data;\n });\n const hbTimer = setInterval(() => {\n updateHeartbeatFn(db, process.pid);\n }, HEARTBEAT_INTERVAL_MS);\n instance.timer = hbTimer;\n instance.coordinator = promotedCoordinator;\n instance.watcher = promotedWatcher;\n await promotedCoordinator.fullIndex();\n } catch (setupErr) {\n logger.error('[Gildash] owner promotion failed, reverting to reader', setupErr);\n if (promotedWatcher) {\n const closeResult = await promotedWatcher.close();\n if (isErr(closeResult)) logger.error('[Gildash] watcher close error during promotion rollback', closeResult.data);\n instance.watcher = null;\n }\n if (promotedCoordinator) {\n await promotedCoordinator.shutdown().catch((e) =>\n logger.error('[Gildash] coordinator shutdown error during promotion rollback', e),\n );\n instance.coordinator = null;\n }\n if (instance.timer === null) {\n instance.timer = setInterval(healthcheck, HEALTHCHECK_INTERVAL_MS);\n }\n }\n }\n } catch (err) {\n retryCount++;\n logger.error('[Gildash] healthcheck error', err);\n if (retryCount >= MAX_HEALTHCHECK_RETRIES) {\n logger.error('[Gildash] healthcheck failed too many times, shutting down');\n clearInterval(instance.timer!);\n instance.timer = null;\n instance.close().catch((closeErr) =>\n logger.error('[Gildash] close error during healthcheck shutdown', closeErr),\n );\n }\n }\n };\n const timer = setInterval(healthcheck, HEALTHCHECK_INTERVAL_MS);\n instance.timer = timer;\n }\n\n const signals: Array<NodeJS.Signals | 'beforeExit'> = ['SIGTERM', 'SIGINT', 'beforeExit'];\n for (const sig of signals) {\n const handler = () => { instance.close().catch(err => logger.error('[Gildash] close error during signal', sig, err)); };\n if (sig === 'beforeExit') {\n process.on('beforeExit', handler);\n } else {\n process.on(sig, handler);\n }\n instance.signalHandlers.push([sig, handler]);\n }\n\n return instance;\n } catch (error) {\n db.close();\n return err(gildashError('store', 'Gildash: initialization failed', error));\n }\n }\n\n /**\n * Shut down the instance and release all resources.\n *\n * Stops the file watcher, shuts down the index coordinator,\n * releases the watcher ownership role, and closes the database.\n * Calling `close()` more than once is safe (subsequent calls are no-ops).\n *\n * @returns `void` on success, or `Err<GildashError>` with `type='close'` if one or more\n * sub-systems failed during shutdown. The `cause` field contains an array of\n * individual errors from each failed sub-system.\n *\n * @example\n * ```ts\n * const closeResult = await ledger.close();\n * if (isErr(closeResult)) {\n * console.error('Close failed:', closeResult.data.message);\n * // closeResult.data.cause is unknown[] of per-subsystem errors\n * }\n * ```\n */\n async close(): Promise<Result<void, GildashError>> {\n if (this.closed) return;\n this.closed = true;\n\n const closeErrors: unknown[] = [];\n\n for (const [sig, handler] of this.signalHandlers) {\n if (sig === 'beforeExit') {\n process.off('beforeExit', handler);\n } else {\n process.off(sig as NodeJS.Signals, handler);\n }\n }\n this.signalHandlers = [];\n\n if (this.coordinator) {\n try {\n await this.coordinator.shutdown();\n } catch (err) {\n closeErrors.push(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n if (this.watcher) {\n const closeResult = await this.watcher.close();\n if (isErr(closeResult)) closeErrors.push(closeResult.data);\n }\n\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n\n try {\n this.releaseWatcherRoleFn(this.db, process.pid);\n } catch (err) {\n closeErrors.push(err instanceof Error ? err : new Error(String(err)));\n }\n\n try {\n this.db.close();\n } catch (err) {\n closeErrors.push(err instanceof Error ? err : new Error(String(err)));\n }\n\n if (closeErrors.length > 0) {\n return err(gildashError('close', 'Gildash: one or more errors occurred during close()', closeErrors));\n }\n }\n\n /**\n * Register a callback that fires after each indexing run completes.\n *\n * @param callback - Receives the {@link IndexResult} for the completed run.\n * @returns An unsubscribe function. Call it to remove the listener.\n *\n * @example\n * ```ts\n * const off = ledger.onIndexed(result => {\n * console.log(`Indexed ${result.filesProcessed} files`);\n * });\n * // later…\n * off();\n * ```\n */\n onIndexed(callback: (result: IndexResult) => void): () => void {\n this.onIndexedCallbacks.add(callback);\n if (!this.coordinator) {\n return () => { this.onIndexedCallbacks.delete(callback); };\n }\n const unsubscribe = this.coordinator.onIndexed(callback);\n return () => {\n this.onIndexedCallbacks.delete(callback);\n unsubscribe();\n };\n }\n\n /**\n * Parse a TypeScript source string into an AST and cache the result.\n *\n * On success the result is automatically stored in the internal LRU parse cache\n * so that subsequent calls to extraction methods can reuse it.\n *\n * @param filePath - File path used as the cache key and for diagnostics.\n * @param sourceText - Raw TypeScript source code.\n * @returns A {@link ParsedFile}, or `Err<GildashError>` with `type='closed'` if the instance\n * is closed, or `type='parse'` if the parser fails.\n *\n * @example\n * ```ts\n * const parsed = ledger.parseSource('/project/src/app.ts', sourceCode);\n * if (isErr(parsed)) {\n * console.error(parsed.data.message); // e.g. \"Failed to parse file: ...\"\n * return;\n * }\n * // parsed is now a ParsedFile\n * const symbols = ledger.extractSymbols(parsed);\n * ```\n */\n parseSource(filePath: string, sourceText: string): Result<ParsedFile, GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n const result = this.parseSourceFn(filePath, sourceText);\n if (isErr(result)) return result;\n this.parseCache.set(filePath, result);\n return result;\n }\n\n /**\n * Extract all symbol declarations from a previously parsed file.\n *\n * Returns function, class, variable, type-alias, interface, and enum declarations\n * found in the AST.\n *\n * @param parsed - A {@link ParsedFile} obtained from {@link parseSource}.\n * @returns An array of {@link ExtractedSymbol} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed.\n *\n * @example\n * ```ts\n * const symbols = ledger.extractSymbols(parsed);\n * if (isErr(symbols)) return;\n * for (const sym of symbols) {\n * console.log(`${sym.kind}: ${sym.name}`);\n * }\n * ```\n */\n extractSymbols(parsed: ParsedFile): Result<ExtractedSymbol[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n return this.extractSymbolsFn(parsed);\n }\n\n /**\n * Extract inter-file relationships (imports, calls, extends, implements)\n * from a previously parsed file.\n *\n * If tsconfig path aliases were discovered during {@link Gildash.open},\n * they are automatically applied when resolving import targets.\n *\n * @param parsed - A {@link ParsedFile} obtained from {@link parseSource}.\n * @returns An array of {@link CodeRelation} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed.\n *\n * @example\n * ```ts\n * const relations = ledger.extractRelations(parsed);\n * if (isErr(relations)) return;\n * const imports = relations.filter(r => r.type === 'imports');\n * ```\n */\n extractRelations(parsed: ParsedFile): Result<CodeRelation[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n return this.extractRelationsFn(\n parsed.program,\n parsed.filePath,\n this.tsconfigPaths ?? undefined,\n );\n }\n\n /**\n * Trigger a full re-index of all tracked files.\n *\n * Only available to the instance that holds the *owner* role.\n * Reader instances receive `Err<GildashError>` with `type='closed'`.\n *\n * @returns An {@link IndexResult} summary on success, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed / reader,\n * `type='index'` if the indexing pipeline fails.\n *\n * @example\n * ```ts\n * const result = await ledger.reindex();\n * if (isErr(result)) {\n * console.error(result.data.message);\n * return;\n * }\n * console.log(`Indexed ${result.indexedFiles} files in ${result.durationMs}ms`);\n * ```\n */\n async reindex(): Promise<Result<IndexResult, GildashError>> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n if (!this.coordinator) {\n return err(gildashError('closed', 'Gildash: reindex() is not available for readers'));\n }\n try {\n return await this.coordinator.fullIndex();\n } catch (e) {\n return err(gildashError('index', 'Gildash: reindex failed', e));\n }\n }\n\n /**\n * Discovered project boundaries within the project root.\n *\n * Each entry contains a project name and its root directory.\n */\n get projects(): ProjectBoundary[] {\n return [...this.boundaries];\n }\n\n /**\n * Return aggregate symbol statistics for the given project.\n *\n * @param project - Project name. Defaults to the auto-discovered primary project.\n * @returns A {@link SymbolStats} object with counts grouped by symbol kind,\n * or `Err<GildashError>` with `type='closed'` if the instance is closed,\n * `type='store'` if the database query fails.\n *\n * @example\n * ```ts\n * const stats = ledger.getStats();\n * if (isErr(stats)) return;\n * console.log(`Files: ${stats.fileCount}, Symbols: ${stats.symbolCount}`);\n * ```\n */\n getStats(project?: string): Result<SymbolStats, GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.symbolRepo.getStats(project ?? this.defaultProject);\n } catch (e) {\n return err(gildashError('store', 'Gildash: getStats failed', e));\n }\n }\n\n /**\n * Search indexed symbols by name, kind, file path, or export status.\n *\n * @param query - Search filters (see {@link SymbolSearchQuery}). All fields are optional;\n * omitted fields match everything.\n * @returns An array of {@link SymbolSearchResult} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed,\n * `type='search'` if the query fails.\n *\n * @example\n * ```ts\n * const fns = ledger.searchSymbols({ kind: 'function', isExported: true });\n * if (isErr(fns)) return;\n * fns.forEach(fn => console.log(fn.name, fn.filePath));\n * ```\n */\n searchSymbols(query: SymbolSearchQuery): Result<SymbolSearchResult[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.symbolSearchFn({ symbolRepo: this.symbolRepo, project: this.defaultProject, query });\n } catch (e) {\n return err(gildashError('search', 'Gildash: searchSymbols failed', e));\n }\n }\n\n /**\n * Search indexed code relationships (imports, calls, extends, implements).\n *\n * @param query - Search filters (see {@link RelationSearchQuery}). All fields are optional.\n * @returns An array of {@link CodeRelation} entries, or `Err<GildashError>` with\n * `type='closed'` if the instance is closed,\n * `type='search'` if the query fails.\n *\n * @example\n * ```ts\n * const rels = ledger.searchRelations({ srcFilePath: 'src/app.ts', type: 'imports' });\n * if (isErr(rels)) return;\n * rels.forEach(r => console.log(`${r.srcFilePath} -> ${r.dstFilePath}`));\n * ```\n */\n searchRelations(query: RelationSearchQuery): Result<CodeRelation[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.relationSearchFn({ relationRepo: this.relationRepo, project: this.defaultProject, query });\n } catch (e) {\n return err(gildashError('search', 'Gildash: searchRelations failed', e));\n }\n }\n\n /**\n * List the files that a given file directly imports.\n *\n * @param filePath - Absolute path of the source file.\n * @param project - Project name. Defaults to the primary project.\n * @param limit - Maximum results. Defaults to `10_000`.\n * @returns An array of absolute paths that `filePath` imports,\n * or `Err<GildashError>` with `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const deps = ledger.getDependencies('/project/src/app.ts');\n * if (isErr(deps)) return;\n * console.log('Imports:', deps.join(', '));\n * ```\n */\n getDependencies(filePath: string, project?: string, limit = 10_000): Result<string[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.relationSearchFn({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n query: { srcFilePath: filePath, type: 'imports', project: project ?? this.defaultProject, limit },\n }).map(r => r.dstFilePath);\n } catch (e) {\n return err(gildashError('search', 'Gildash: getDependencies failed', e));\n }\n }\n\n /**\n * List the files that directly import a given file.\n *\n * @param filePath - Absolute path of the target file.\n * @param project - Project name. Defaults to the primary project.\n * @param limit - Maximum results. Defaults to `10_000`.\n * @returns An array of absolute paths of files that import `filePath`,\n * or `Err<GildashError>` with `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const dependents = ledger.getDependents('/project/src/utils.ts');\n * if (isErr(dependents)) return;\n * console.log('Imported by:', dependents.join(', '));\n * ```\n */\n getDependents(filePath: string, project?: string, limit = 10_000): Result<string[], GildashError> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n return this.relationSearchFn({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n query: { dstFilePath: filePath, type: 'imports', project: project ?? this.defaultProject, limit },\n }).map(r => r.srcFilePath);\n } catch (e) {\n return err(gildashError('search', 'Gildash: getDependents failed', e));\n }\n }\n\n /**\n * Compute the full set of files transitively affected by changes.\n *\n * Internally builds a full {@link DependencyGraph} and walks all reverse\n * edges from each changed file to find every transitive dependent.\n *\n * @param changedFiles - Absolute paths of files that changed.\n * @param project - Project name. Defaults to the primary project.\n * @returns De-duplicated absolute paths of all transitively-dependent files\n * (excluding the changed files themselves), or `Err<GildashError>` with\n * `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const affected = await ledger.getAffected(['/project/src/utils.ts']);\n * if (isErr(affected)) return;\n * console.log('Affected files:', affected.length);\n * ```\n */\n async getAffected(changedFiles: string[], project?: string): Promise<Result<string[], GildashError>> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n const g = new DependencyGraph({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n });\n await g.build();\n return g.getAffectedByChange(changedFiles);\n } catch (e) {\n return err(gildashError('search', 'Gildash: getAffected failed', e));\n }\n }\n\n /**\n * Check whether the import graph contains a circular dependency.\n *\n * Internally builds a full {@link DependencyGraph} and runs iterative DFS\n * cycle detection.\n *\n * @param project - Project name. Defaults to the primary project.\n * @returns `true` if at least one cycle exists, `false` otherwise,\n * or `Err<GildashError>` with `type='closed'` / `type='search'`.\n *\n * @example\n * ```ts\n * const cycleResult = await ledger.hasCycle();\n * if (isErr(cycleResult)) return;\n * if (cycleResult) {\n * console.warn('Circular dependency detected!');\n * }\n * ```\n */\n async hasCycle(project?: string): Promise<Result<boolean, GildashError>> {\n if (this.closed) return err(gildashError('closed', 'Gildash: instance is closed'));\n try {\n const g = new DependencyGraph({\n relationRepo: this.relationRepo,\n project: project ?? this.defaultProject,\n });\n await g.build();\n return g.hasCycle();\n } catch (e) {\n return err(gildashError('search', 'Gildash: hasCycle failed', e));\n }\n }\n}\n",
|
|
6
6
|
"import { err, type Result } from '@zipbul/result';\nimport { parseSync as defaultParseSync } from 'oxc-parser';\nimport type { ParsedFile } from './types';\nimport { gildashError, type GildashError } from '../errors';\n\nexport function parseSource(\n filePath: string,\n sourceText: string,\n parseSyncFn: typeof defaultParseSync = defaultParseSync,\n): Result<ParsedFile, GildashError> {\n try {\n const { program, errors, comments } = parseSyncFn(filePath, sourceText);\n return { filePath, program: program as ParsedFile['program'], errors, comments, sourceText };\n } catch (e) {\n return err(gildashError('parse', `Failed to parse file: ${filePath}`, e));\n }\n}\n",
|
|
7
7
|
"/**\n * Discriminated union type representing all possible error categories in Gildash.\n */\nexport type GildashErrorType =\n | 'watcher'\n | 'parse'\n | 'extract'\n | 'index'\n | 'store'\n | 'search'\n | 'closed'\n | 'validation'\n | 'close';\n\n/**\n * Plain-object error value used throughout Gildash's Result-based error handling.\n * Produced by {@link gildashError} and carried as the `data` field of an `Err<GildashError>`.\n */\nexport interface GildashError {\n type: GildashErrorType;\n message: string;\n cause?: unknown;\n}\n\n/**\n * Factory function that creates a {@link GildashError} value.\n *\n * @param type - One of the {@link GildashErrorType} variants.\n * @param message - Human-readable description of the error.\n * @param cause - Optional root cause (any value). When `undefined`, the `cause`\n * property is omitted from the returned object entirely.\n */\nexport function gildashError(type: GildashErrorType, message: string, cause?: unknown): GildashError {\n return cause !== undefined\n ? { type, message, cause }\n : { type, message };\n}\n\n",
|
|
8
8
|
"export class LruCache<K, V> {\n #capacity: number;\n #map = new Map<K, V>();\n\n constructor(capacity: number) {\n this.#capacity = Math.max(1, capacity);\n }\n\n get size(): number {\n return this.#map.size;\n }\n\n has(key: K): boolean {\n return this.#map.has(key);\n }\n\n get(key: K): V | undefined {\n if (!this.#map.has(key)) {\n return undefined;\n }\n const value = this.#map.get(key)!;\n this.#map.delete(key);\n this.#map.set(key, value);\n return value;\n }\n\n set(key: K, value: V): void {\n if (this.#map.has(key)) {\n this.#map.delete(key);\n }\n\n this.#map.set(key, value);\n\n if (this.#map.size > this.#capacity) {\n const oldestKey = this.#map.keys().next().value as K | undefined;\n if (oldestKey !== undefined) {\n this.#map.delete(oldestKey);\n }\n }\n }\n\n delete(key: K): boolean {\n return this.#map.delete(key);\n }\n\n clear(): void {\n this.#map.clear();\n }\n}\n",
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
"import { err, isErr, type Result } from '@zipbul/result';\nimport { Database } from 'bun:sqlite';\nimport { mkdirSync, unlinkSync, existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { drizzle, type BunSQLiteDatabase } from 'drizzle-orm/bun-sqlite';\nimport { migrate } from 'drizzle-orm/bun-sqlite/migrator';\nimport { gildashError, type GildashError } from '../errors';\nimport * as schema from './schema';\nimport { FTS_SETUP_SQL } from './schema';\n\nexport interface DbConnectionOptions {\n projectRoot: string;\n}\n\nexport class DbConnection {\n private client: Database | null = null;\n private drizzle: BunSQLiteDatabase<typeof schema> | null = null;\n private readonly dbPath: string;\n private txDepth = 0;\n\n constructor(opts: DbConnectionOptions) {\n this.dbPath = join(opts.projectRoot, '.zipbul', 'gildash.db');\n }\n\n get drizzleDb(): BunSQLiteDatabase<typeof schema> {\n if (!this.drizzle) throw new Error('Database is not open. Call open() first.');\n return this.drizzle;\n }\n\n open(): Result<void, GildashError> {\n try {\n mkdirSync(dirname(this.dbPath), { recursive: true });\n this.client = new Database(this.dbPath);\n\n this.client.run('PRAGMA journal_mode = WAL');\n this.client.run('PRAGMA foreign_keys = ON');\n this.client.run('PRAGMA busy_timeout = 5000');\n\n this.drizzle = drizzle(this.client, { schema });\n\n migrate(this.drizzle, {\n migrationsFolder: join(import.meta.dirname, 'migrations'),\n });\n\n for (const sql of FTS_SETUP_SQL) {\n this.client.run(sql);\n }\n } catch (e) {\n if (this.isCorruptionError(e) && existsSync(this.dbPath)) {\n this.closeClient();\n unlinkSync(this.dbPath);\n for (const ext of ['-wal', '-shm']) {\n const p = this.dbPath + ext;\n if (existsSync(p)) unlinkSync(p);\n }\n const retryResult = this.open();\n if (isErr(retryResult)) {\n return err(gildashError('store', `Failed to recover database at ${this.dbPath}`, retryResult.data));\n }\n return retryResult;\n }\n return err(gildashError('store', `Failed to open database at ${this.dbPath}`, e));\n }\n }\n\n close(): void {\n this.closeClient();\n this.drizzle = null;\n }\n\n transaction<T>(fn: (tx: DbConnection) => T): T {\n const db = this.requireClient();\n\n if (this.txDepth === 0) {\n this.txDepth++;\n try {\n return db.transaction(() => fn(this))();\n } finally {\n this.txDepth--;\n }\n }\n\n const sp = `sp_${this.txDepth++}`;\n db.run(`SAVEPOINT \"${sp}\"`);\n try {\n const result = fn(this);\n db.run(`RELEASE SAVEPOINT \"${sp}\"`);\n return result;\n } catch (err) {\n db.run(`ROLLBACK TO SAVEPOINT \"${sp}\"`);\n db.run(`RELEASE SAVEPOINT \"${sp}\"`);\n throw err;\n } finally {\n this.txDepth--;\n }\n }\n\n immediateTransaction<T>(fn: () => T): T {\n const db = this.requireClient();\n this.txDepth++;\n db.run('BEGIN IMMEDIATE');\n try {\n const result = fn();\n db.run('COMMIT');\n return result;\n } catch (err) {\n db.run('ROLLBACK');\n throw err;\n } finally {\n this.txDepth--;\n }\n }\n\n query(sql: string): unknown {\n const row = this.requireClient().prepare(sql).get() as Record<string, unknown> | null;\n if (!row) return null;\n return Object.values(row)[0];\n }\n\n getTableNames(): string[] {\n const rows = this.requireClient()\n .query(\"SELECT name FROM sqlite_master WHERE type = 'table'\")\n .all() as Array<{ name: string }>;\n return rows.map((r) => r.name);\n }\n\n selectOwner(): { pid: number; heartbeat_at: string } | undefined {\n const row = this.requireClient()\n .prepare('SELECT pid, heartbeat_at FROM watcher_owner WHERE id = 1')\n .get() as { pid: number; heartbeat_at: string } | null;\n return row ?? undefined;\n }\n\n insertOwner(pid: number): void {\n const now = new Date().toISOString();\n this.requireClient()\n .prepare('INSERT INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)')\n .run(pid, now, now);\n }\n\n replaceOwner(pid: number): void {\n const now = new Date().toISOString();\n this.requireClient()\n .prepare('INSERT OR REPLACE INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)')\n .run(pid, now, now);\n }\n\n touchOwner(pid: number): void {\n const now = new Date().toISOString();\n this.requireClient()\n .prepare('UPDATE watcher_owner SET heartbeat_at = ? WHERE id = 1 AND pid = ?')\n .run(now, pid);\n }\n\n deleteOwner(pid: number): void {\n this.requireClient()\n .prepare('DELETE FROM watcher_owner WHERE id = 1 AND pid = ?')\n .run(pid);\n }\n\n private requireClient(): Database {\n if (!this.client) throw new Error('Database is not open. Call open() first.');\n return this.client;\n }\n\n private closeClient(): void {\n if (this.client) {\n this.client.close();\n this.client = null;\n }\n }\n\n private isCorruptionError(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const msg = err.message.toLowerCase();\n return (\n msg.includes('malformed') ||\n msg.includes('corrupt') ||\n msg.includes('not a database') ||\n msg.includes('disk i/o error') ||\n msg.includes('sqlite_corrupt')\n );\n }\n}\n",
|
|
20
20
|
"import { sql } from 'drizzle-orm';\nimport {\n sqliteTable,\n text,\n integer,\n real,\n index,\n primaryKey,\n foreignKey,\n check,\n} from 'drizzle-orm/sqlite-core';\n\nexport const files = sqliteTable(\n 'files',\n {\n project: text('project').notNull(),\n filePath: text('file_path').notNull(),\n mtimeMs: real('mtime_ms').notNull(),\n size: integer('size').notNull(),\n contentHash: text('content_hash').notNull(),\n updatedAt: text('updated_at').notNull(),\n },\n (table) => [primaryKey({ columns: [table.project, table.filePath] })],\n);\n\nexport const symbols = sqliteTable(\n 'symbols',\n {\n id: integer('id').primaryKey({ autoIncrement: true }),\n project: text('project').notNull(),\n filePath: text('file_path').notNull(),\n kind: text('kind').notNull(),\n name: text('name').notNull(),\n startLine: integer('start_line').notNull(),\n startColumn: integer('start_column').notNull(),\n endLine: integer('end_line').notNull(),\n endColumn: integer('end_column').notNull(),\n isExported: integer('is_exported').notNull().default(0),\n signature: text('signature'),\n fingerprint: text('fingerprint'),\n detailJson: text('detail_json'),\n contentHash: text('content_hash').notNull(),\n indexedAt: text('indexed_at').notNull(),\n },\n (table) => [\n index('idx_symbols_project_file').on(table.project, table.filePath),\n index('idx_symbols_project_kind').on(table.project, table.kind),\n index('idx_symbols_project_name').on(table.project, table.name),\n index('idx_symbols_fingerprint').on(table.project, table.fingerprint),\n foreignKey({\n columns: [table.project, table.filePath],\n foreignColumns: [files.project, files.filePath],\n }).onDelete('cascade'),\n ],\n);\n\nexport const relations = sqliteTable(\n 'relations',\n {\n id: integer('id').primaryKey({ autoIncrement: true }),\n project: text('project').notNull(),\n type: text('type').notNull(),\n srcFilePath: text('src_file_path').notNull(),\n srcSymbolName: text('src_symbol_name'),\n dstFilePath: text('dst_file_path').notNull(),\n dstSymbolName: text('dst_symbol_name'),\n metaJson: text('meta_json'),\n },\n (table) => [\n index('idx_relations_src').on(table.project, table.srcFilePath),\n index('idx_relations_dst').on(table.project, table.dstFilePath),\n index('idx_relations_type').on(table.project, table.type),\n foreignKey({\n columns: [table.project, table.srcFilePath],\n foreignColumns: [files.project, files.filePath],\n }).onDelete('cascade'),\n foreignKey({\n columns: [table.project, table.dstFilePath],\n foreignColumns: [files.project, files.filePath],\n }).onDelete('cascade'),\n ],\n);\n\nexport const watcherOwner = sqliteTable(\n 'watcher_owner',\n {\n id: integer('id').primaryKey(),\n pid: integer('pid').notNull(),\n startedAt: text('started_at').notNull(),\n heartbeatAt: text('heartbeat_at').notNull(),\n },\n (table) => [check('watcher_owner_singleton', sql`${table.id} = 1`)],\n);\n\nexport const FTS_SETUP_SQL: readonly string[] = [\n `CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(\n name,\n file_path,\n kind,\n content=symbols,\n content_rowid=id\n )`,\n\n `CREATE TRIGGER IF NOT EXISTS symbols_ai\n AFTER INSERT ON symbols BEGIN\n INSERT INTO symbols_fts(rowid, name, file_path, kind)\n VALUES (new.id, new.name, new.file_path, new.kind);\n END`,\n\n `CREATE TRIGGER IF NOT EXISTS symbols_ad\n AFTER DELETE ON symbols BEGIN\n INSERT INTO symbols_fts(symbols_fts, rowid, name, file_path, kind)\n VALUES ('delete', old.id, old.name, old.file_path, old.kind);\n END`,\n\n `CREATE TRIGGER IF NOT EXISTS symbols_au\n AFTER UPDATE ON symbols BEGIN\n INSERT INTO symbols_fts(symbols_fts, rowid, name, file_path, kind)\n VALUES ('delete', old.id, old.name, old.file_path, old.kind);\n INSERT INTO symbols_fts(rowid, name, file_path, kind)\n VALUES (new.id, new.name, new.file_path, new.kind);\n END`,\n];\n",
|
|
21
21
|
"import { eq, and } from 'drizzle-orm';\nimport { files } from '../schema';\nimport type { DbConnection } from '../connection';\n\nexport interface FileRecord {\n project: string;\n filePath: string;\n mtimeMs: number;\n size: number;\n contentHash: string;\n updatedAt: string;\n}\n\nexport class FileRepository {\n constructor(private readonly db: DbConnection) {}\n\n getFile(project: string, filePath: string): FileRecord | null {\n return this.db.drizzleDb\n .select()\n .from(files)\n .where(and(eq(files.project, project), eq(files.filePath, filePath)))\n .get() ?? null;\n }\n\n upsertFile(record: FileRecord): void {\n this.db.drizzleDb\n .insert(files)\n .values({\n project: record.project,\n filePath: record.filePath,\n mtimeMs: record.mtimeMs,\n size: record.size,\n contentHash: record.contentHash,\n updatedAt: record.updatedAt,\n })\n .onConflictDoUpdate({\n target: [files.project, files.filePath],\n set: {\n mtimeMs: record.mtimeMs,\n size: record.size,\n contentHash: record.contentHash,\n updatedAt: record.updatedAt,\n },\n })\n .run();\n }\n\n getAllFiles(project: string): FileRecord[] {\n return this.db.drizzleDb\n .select()\n .from(files)\n .where(eq(files.project, project))\n .all();\n }\n\n getFilesMap(project: string): Map<string, FileRecord> {\n const rows = this.getAllFiles(project);\n const map = new Map<string, FileRecord>();\n for (const r of rows) map.set(r.filePath, r);\n return map;\n }\n\n deleteFile(project: string, filePath: string): void {\n this.db.drizzleDb\n .delete(files)\n .where(and(eq(files.project, project), eq(files.filePath, filePath)))\n .run();\n }\n}\n",
|
|
22
|
-
"import { eq, and, sql, count } from 'drizzle-orm';\nimport { symbols } from '../schema';\nimport type { DbConnection } from '../connection';\nimport { toFtsPrefixQuery } from './fts-utils';\n\nexport interface SymbolRecord {\n project: string;\n filePath: string;\n kind: string;\n name: string;\n startLine: number;\n startColumn: number;\n endLine: number;\n endColumn: number;\n isExported: number;\n signature: string | null;\n fingerprint: string | null;\n detailJson: string | null;\n contentHash: string;\n indexedAt: string;\n}\n\nexport interface SearchOptions {\n kind?: string;\n limit?: number;\n}\n\nexport interface SymbolStats {\n symbolCount: number;\n fileCount: number;\n}\n\nexport class SymbolRepository {\n constructor(private readonly db: DbConnection) {}\n\n replaceFileSymbols(\n project: string,\n filePath: string,\n contentHash: string,\n syms: ReadonlyArray<Partial<SymbolRecord>>,\n ): void {\n this.db.drizzleDb\n .delete(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.filePath, filePath)))\n .run();\n\n if (!syms.length) return;\n\n const now = new Date().toISOString();\n for (const sym of syms) {\n this.db.drizzleDb.insert(symbols).values({\n project,\n filePath,\n kind: sym.kind ?? 'unknown',\n name: sym.name ?? '',\n startLine: sym.startLine ?? 0,\n startColumn: sym.startColumn ?? 0,\n endLine: sym.endLine ?? 0,\n endColumn: sym.endColumn ?? 0,\n isExported: sym.isExported ?? 0,\n signature: sym.signature ?? null,\n fingerprint: sym.fingerprint ?? null,\n detailJson: sym.detailJson ?? null,\n contentHash,\n indexedAt: sym.indexedAt ?? now,\n }).run();\n }\n }\n\n getFileSymbols(project: string, filePath: string): SymbolRecord[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.filePath, filePath)))\n .all();\n }\n\n searchByName(project: string, query: string, opts: SearchOptions = {}): SymbolRecord[] {\n const limit = opts.limit ?? 50;\n const ftsQuery = toFtsPrefixQuery(query);\n\n if (!ftsQuery) return [];\n\n let builder = this.db.drizzleDb\n .select()\n .from(symbols)\n .where(\n and(\n sql`${symbols.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${ftsQuery})`,\n eq(symbols.project, project),\n opts.kind ? eq(symbols.kind, opts.kind) : undefined,\n ),\n )\n .orderBy(symbols.name)\n .limit(limit);\n\n return builder.all();\n }\n\n searchByKind(project: string, kind: string): SymbolRecord[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.kind, kind)))\n .orderBy(symbols.name)\n .all();\n }\n\n getStats(project: string): SymbolStats {\n const row = this.db.drizzleDb\n .select({\n symbolCount: count(),\n fileCount: sql<number>`COUNT(DISTINCT ${symbols.filePath})`,\n })\n .from(symbols)\n .where(eq(symbols.project, project))\n .get();\n return {\n symbolCount: row?.symbolCount ?? 0,\n fileCount: row?.fileCount ?? 0,\n };\n }\n\n getByFingerprint(project: string, fingerprint: string): SymbolRecord[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.fingerprint, fingerprint)))\n .all();\n }\n\n deleteFileSymbols(project: string, filePath: string): void {\n this.db.drizzleDb\n .delete(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.filePath, filePath)))\n .run();\n }\n\n searchByQuery(opts: {\n ftsQuery?: string;\n kind?: string;\n filePath?: string;\n isExported?: boolean;\n project?: string;\n limit: number;\n }): (SymbolRecord & { id: number })[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(\n and(\n opts.ftsQuery\n ? sql`${symbols.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${opts.ftsQuery})`\n : undefined,\n opts.project !== undefined ? eq(symbols.project, opts.project) : undefined,\n opts.kind ? eq(symbols.kind, opts.kind) : undefined,\n opts.filePath !== undefined ? eq(symbols.filePath, opts.filePath) : undefined,\n opts.isExported !== undefined\n ? eq(symbols.isExported, opts.isExported ? 1 : 0)\n : undefined,\n ),\n )\n .orderBy(symbols.name)\n .limit(opts.limit)\n .all() as (SymbolRecord & { id: number })[];\n }\n}\n",
|
|
22
|
+
"import { eq, and, sql, count } from 'drizzle-orm';\nimport { symbols } from '../schema';\nimport type { DbConnection } from '../connection';\nimport { toFtsPrefixQuery } from './fts-utils';\n\nexport interface SymbolRecord {\n project: string;\n filePath: string;\n kind: string;\n name: string;\n startLine: number;\n startColumn: number;\n endLine: number;\n endColumn: number;\n isExported: number;\n signature: string | null;\n fingerprint: string | null;\n detailJson: string | null;\n contentHash: string;\n indexedAt: string;\n}\n\nexport interface SearchOptions {\n kind?: string;\n limit?: number;\n}\n\n/**\n * Aggregate symbol statistics for a project.\n *\n * Returned by {@link Gildash.getStats}.\n */\nexport interface SymbolStats {\n /** Total number of indexed symbols. */\n symbolCount: number;\n /** Total number of indexed source files. */\n fileCount: number;\n}\n\nexport class SymbolRepository {\n constructor(private readonly db: DbConnection) {}\n\n replaceFileSymbols(\n project: string,\n filePath: string,\n contentHash: string,\n syms: ReadonlyArray<Partial<SymbolRecord>>,\n ): void {\n this.db.drizzleDb\n .delete(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.filePath, filePath)))\n .run();\n\n if (!syms.length) return;\n\n const now = new Date().toISOString();\n for (const sym of syms) {\n this.db.drizzleDb.insert(symbols).values({\n project,\n filePath,\n kind: sym.kind ?? 'unknown',\n name: sym.name ?? '',\n startLine: sym.startLine ?? 0,\n startColumn: sym.startColumn ?? 0,\n endLine: sym.endLine ?? 0,\n endColumn: sym.endColumn ?? 0,\n isExported: sym.isExported ?? 0,\n signature: sym.signature ?? null,\n fingerprint: sym.fingerprint ?? null,\n detailJson: sym.detailJson ?? null,\n contentHash,\n indexedAt: sym.indexedAt ?? now,\n }).run();\n }\n }\n\n getFileSymbols(project: string, filePath: string): SymbolRecord[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.filePath, filePath)))\n .all();\n }\n\n searchByName(project: string, query: string, opts: SearchOptions = {}): SymbolRecord[] {\n const limit = opts.limit ?? 50;\n const ftsQuery = toFtsPrefixQuery(query);\n\n if (!ftsQuery) return [];\n\n let builder = this.db.drizzleDb\n .select()\n .from(symbols)\n .where(\n and(\n sql`${symbols.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${ftsQuery})`,\n eq(symbols.project, project),\n opts.kind ? eq(symbols.kind, opts.kind) : undefined,\n ),\n )\n .orderBy(symbols.name)\n .limit(limit);\n\n return builder.all();\n }\n\n searchByKind(project: string, kind: string): SymbolRecord[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.kind, kind)))\n .orderBy(symbols.name)\n .all();\n }\n\n getStats(project: string): SymbolStats {\n const row = this.db.drizzleDb\n .select({\n symbolCount: count(),\n fileCount: sql<number>`COUNT(DISTINCT ${symbols.filePath})`,\n })\n .from(symbols)\n .where(eq(symbols.project, project))\n .get();\n return {\n symbolCount: row?.symbolCount ?? 0,\n fileCount: row?.fileCount ?? 0,\n };\n }\n\n getByFingerprint(project: string, fingerprint: string): SymbolRecord[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.fingerprint, fingerprint)))\n .all();\n }\n\n deleteFileSymbols(project: string, filePath: string): void {\n this.db.drizzleDb\n .delete(symbols)\n .where(and(eq(symbols.project, project), eq(symbols.filePath, filePath)))\n .run();\n }\n\n searchByQuery(opts: {\n ftsQuery?: string;\n kind?: string;\n filePath?: string;\n isExported?: boolean;\n project?: string;\n limit: number;\n }): (SymbolRecord & { id: number })[] {\n return this.db.drizzleDb\n .select()\n .from(symbols)\n .where(\n and(\n opts.ftsQuery\n ? sql`${symbols.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${opts.ftsQuery})`\n : undefined,\n opts.project !== undefined ? eq(symbols.project, opts.project) : undefined,\n opts.kind ? eq(symbols.kind, opts.kind) : undefined,\n opts.filePath !== undefined ? eq(symbols.filePath, opts.filePath) : undefined,\n opts.isExported !== undefined\n ? eq(symbols.isExported, opts.isExported ? 1 : 0)\n : undefined,\n ),\n )\n .orderBy(symbols.name)\n .limit(opts.limit)\n .all() as (SymbolRecord & { id: number })[];\n }\n}\n",
|
|
23
23
|
"export function toFtsPrefixQuery(text: string): string {\n return text\n .trim()\n .split(/\\s+/)\n .map((token) => token.trim())\n .filter((token) => token.length > 0)\n .map((token) => `\"${token.replaceAll('\"', '\"\"')}\"*`)\n .join(' ');\n}\n",
|
|
24
24
|
"import { eq, and, isNull, or, sql } from 'drizzle-orm';\nimport { relations as relationsTable } from '../schema';\nimport type { DbConnection } from '../connection';\n\nexport interface RelationRecord {\n project: string;\n type: string;\n srcFilePath: string;\n srcSymbolName: string | null;\n dstFilePath: string;\n dstSymbolName: string | null;\n metaJson: string | null;\n}\n\nexport class RelationRepository {\n constructor(private readonly db: DbConnection) {}\n\n replaceFileRelations(\n project: string,\n srcFilePath: string,\n rels: ReadonlyArray<Partial<RelationRecord>>,\n ): void {\n this.db.drizzleDb\n .delete(relationsTable)\n .where(and(eq(relationsTable.project, project), eq(relationsTable.srcFilePath, srcFilePath)))\n .run();\n\n if (!rels.length) return;\n\n for (const rel of rels) {\n this.db.drizzleDb.insert(relationsTable).values({\n project,\n type: rel.type ?? 'unknown',\n srcFilePath: rel.srcFilePath ?? srcFilePath,\n srcSymbolName: rel.srcSymbolName ?? null,\n dstFilePath: rel.dstFilePath ?? '',\n dstSymbolName: rel.dstSymbolName ?? null,\n metaJson: rel.metaJson ?? null,\n }).run();\n }\n }\n\n getOutgoing(project: string, srcFilePath: string, srcSymbolName?: string): RelationRecord[] {\n if (srcSymbolName !== undefined) {\n return this.db.drizzleDb\n .select({\n project: relationsTable.project,\n type: relationsTable.type,\n srcFilePath: relationsTable.srcFilePath,\n srcSymbolName: relationsTable.srcSymbolName,\n dstFilePath: relationsTable.dstFilePath,\n dstSymbolName: relationsTable.dstSymbolName,\n metaJson: relationsTable.metaJson,\n })\n .from(relationsTable)\n .where(\n and(\n eq(relationsTable.project, project),\n eq(relationsTable.srcFilePath, srcFilePath),\n or(\n eq(relationsTable.srcSymbolName, srcSymbolName),\n isNull(relationsTable.srcSymbolName),\n ),\n ),\n )\n .all();\n }\n\n return this.db.drizzleDb\n .select({\n project: relationsTable.project,\n type: relationsTable.type,\n srcFilePath: relationsTable.srcFilePath,\n srcSymbolName: relationsTable.srcSymbolName,\n dstFilePath: relationsTable.dstFilePath,\n dstSymbolName: relationsTable.dstSymbolName,\n metaJson: relationsTable.metaJson,\n })\n .from(relationsTable)\n .where(\n and(\n eq(relationsTable.project, project),\n eq(relationsTable.srcFilePath, srcFilePath),\n ),\n )\n .all();\n }\n\n getIncoming(project: string, dstFilePath: string): RelationRecord[] {\n return this.db.drizzleDb\n .select({\n project: relationsTable.project,\n type: relationsTable.type,\n srcFilePath: relationsTable.srcFilePath,\n srcSymbolName: relationsTable.srcSymbolName,\n dstFilePath: relationsTable.dstFilePath,\n dstSymbolName: relationsTable.dstSymbolName,\n metaJson: relationsTable.metaJson,\n })\n .from(relationsTable)\n .where(\n and(\n eq(relationsTable.project, project),\n eq(relationsTable.dstFilePath, dstFilePath),\n ),\n )\n .all();\n }\n\n getByType(project: string, type: string): RelationRecord[] {\n return this.db.drizzleDb\n .select({\n project: relationsTable.project,\n type: relationsTable.type,\n srcFilePath: relationsTable.srcFilePath,\n srcSymbolName: relationsTable.srcSymbolName,\n dstFilePath: relationsTable.dstFilePath,\n dstSymbolName: relationsTable.dstSymbolName,\n metaJson: relationsTable.metaJson,\n })\n .from(relationsTable)\n .where(\n and(\n eq(relationsTable.project, project),\n eq(relationsTable.type, type),\n ),\n )\n .all();\n }\n\n deleteFileRelations(project: string, srcFilePath: string): void {\n this.db.drizzleDb\n .delete(relationsTable)\n .where(and(eq(relationsTable.project, project), eq(relationsTable.srcFilePath, srcFilePath)))\n .run();\n }\n\n searchRelations(opts: {\n srcFilePath?: string;\n srcSymbolName?: string;\n dstFilePath?: string;\n dstSymbolName?: string;\n type?: string;\n project?: string;\n limit: number;\n }): RelationRecord[] {\n return this.db.drizzleDb\n .select({\n project: relationsTable.project,\n type: relationsTable.type,\n srcFilePath: relationsTable.srcFilePath,\n srcSymbolName: relationsTable.srcSymbolName,\n dstFilePath: relationsTable.dstFilePath,\n dstSymbolName: relationsTable.dstSymbolName,\n metaJson: relationsTable.metaJson,\n })\n .from(relationsTable)\n .where(\n and(\n opts.project !== undefined ? eq(relationsTable.project, opts.project) : undefined,\n opts.srcFilePath !== undefined\n ? eq(relationsTable.srcFilePath, opts.srcFilePath)\n : undefined,\n opts.srcSymbolName !== undefined\n ? eq(relationsTable.srcSymbolName, opts.srcSymbolName)\n : undefined,\n opts.dstFilePath !== undefined\n ? eq(relationsTable.dstFilePath, opts.dstFilePath)\n : undefined,\n opts.dstSymbolName !== undefined\n ? eq(relationsTable.dstSymbolName, opts.dstSymbolName)\n : undefined,\n opts.type !== undefined ? eq(relationsTable.type, opts.type) : undefined,\n ),\n )\n .limit(opts.limit)\n .all();\n }\n\n retargetRelations(\n project: string,\n oldFile: string,\n oldSymbol: string | null,\n newFile: string,\n newSymbol: string | null,\n ): void {\n const condition = oldSymbol === null\n ? and(\n eq(relationsTable.project, project),\n eq(relationsTable.dstFilePath, oldFile),\n isNull(relationsTable.dstSymbolName),\n )\n : and(\n eq(relationsTable.project, project),\n eq(relationsTable.dstFilePath, oldFile),\n eq(relationsTable.dstSymbolName, oldSymbol),\n );\n\n this.db.drizzleDb\n .update(relationsTable)\n .set({ dstFilePath: newFile, dstSymbolName: newSymbol })\n .where(condition)\n .run();\n }\n}\n",
|
|
25
25
|
"import { err, type Result } from '@zipbul/result';\nimport type {\n AsyncSubscription,\n SubscribeCallback,\n} from \"@parcel/watcher\";\nimport { subscribe as parcelSubscribe } from \"@parcel/watcher\";\n\ntype FileEvent = Parameters<SubscribeCallback>[1][number];\ntype SubscribeOptions = NonNullable<Parameters<typeof parcelSubscribe>[2]>;\nimport path from \"node:path\";\nimport { gildashError, type GildashError } from \"../errors\";\nimport type { FileChangeEvent, FileChangeEventType, WatcherOptions } from \"./types\";\nimport type { Logger } from \"../gildash\";\n\ntype SubscribeFn = (\n directoryPath: string,\n callback: SubscribeCallback,\n options?: SubscribeOptions,\n) => Promise<AsyncSubscription>;\n\nconst WATCHER_IGNORE_GLOBS: readonly string[] = [\n \"**/.git/**\",\n \"**/.zipbul/**\",\n \"**/dist/**\",\n \"**/node_modules/**\",\n];\n\nconst CONFIG_FILE_NAMES = new Set([\"package.json\", \"tsconfig.json\"]);\n\nfunction normalizePath(value: string): string {\n return value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction mapEventType(type: FileEvent[\"type\"]): FileChangeEventType {\n if (type === \"update\") {\n return \"change\";\n }\n\n if (type === \"create\") {\n return \"create\";\n }\n\n return \"delete\";\n}\n\nexport class ProjectWatcher {\n #subscription: AsyncSubscription | undefined;\n #rootPath: string;\n #ignoreGlobs: string[];\n #extensions: Set<string>;\n #subscribe: SubscribeFn;\n #logger: Logger;\n\n constructor(options: WatcherOptions, subscribeFn: SubscribeFn = parcelSubscribe, logger: Logger = console) {\n this.#rootPath = options.projectRoot;\n this.#ignoreGlobs = [...WATCHER_IGNORE_GLOBS, ...(options.ignorePatterns ?? [])];\n this.#extensions = new Set(\n (options.extensions ?? [\".ts\", \".mts\", \".cts\"]).map((ext) =>\n ext.toLowerCase(),\n ),\n );\n this.#subscribe = subscribeFn;\n this.#logger = logger;\n }\n\n async start(onChange: (event: FileChangeEvent) => void): Promise<Result<void, GildashError>> {\n try {\n this.#subscription = await this.#subscribe(\n this.#rootPath,\n (error, events) => {\n if (error) {\n this.#logger.error(gildashError('watcher', 'Callback error', error));\n return;\n }\n\n try {\n for (const rawEvent of events) {\n const relativePath = normalizePath(path.relative(this.#rootPath, rawEvent.path));\n\n if (relativePath.startsWith(\"..\")) {\n continue;\n }\n\n const baseName = path.basename(relativePath);\n const extension = path.extname(relativePath).toLowerCase();\n const isConfigFile = CONFIG_FILE_NAMES.has(baseName);\n\n if (!isConfigFile && !this.#extensions.has(extension)) {\n continue;\n }\n\n if (relativePath.endsWith(\".d.ts\")) {\n continue;\n }\n\n onChange({\n eventType: mapEventType(rawEvent.type),\n filePath: relativePath,\n });\n }\n } catch (callbackError) {\n this.#logger.error(gildashError('watcher', 'Callback error', callbackError));\n }\n },\n {\n ignore: this.#ignoreGlobs,\n },\n );\n } catch (error) {\n return err(gildashError('watcher', 'Failed to subscribe watcher', error));\n }\n }\n\n async close(): Promise<Result<void, GildashError>> {\n if (!this.#subscription) {\n return;\n }\n\n try {\n await this.#subscription.unsubscribe();\n this.#subscription = undefined;\n } catch (error) {\n return err(gildashError('watcher', 'Failed to close watcher', error));\n }\n }\n}\n",
|
|
26
|
-
"import path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\n\nexport interface ProjectBoundary {\n dir: string;\n project: string;\n}\n\nconst DISCOVERY_EXCLUDE = [\"**/node_modules/**\", \"**/.git/**\", \"**/.zipbul/**\", \"**/dist/**\"];\n\nexport async function discoverProjects(projectRoot: string): Promise<ProjectBoundary[]> {\n const boundaries: ProjectBoundary[] = [];\n\n for await (const relativePackageJson of fs.glob(\"**/package.json\", {\n cwd: projectRoot,\n exclude: DISCOVERY_EXCLUDE,\n })) {\n const packageDir = path.dirname(relativePackageJson).replaceAll(\"\\\\\", \"/\");\n const packagePath = path.join(projectRoot, relativePackageJson);\n const content = await Bun.file(packagePath).json();\n\n const packageName =\n typeof content?.name === \"string\" && content.name.length > 0\n ? content.name\n : path.basename(packageDir === \".\" ? projectRoot : packageDir);\n\n boundaries.push({\n dir: packageDir,\n project: packageName,\n });\n }\n\n boundaries.sort((left, right) => right.dir.length - left.dir.length);\n return boundaries;\n}\n\nexport function resolveFileProject(\n filePath: string,\n boundaries: ProjectBoundary[],\n rootProject = \"default\",\n): string {\n const normalizedFilePath = filePath.replaceAll(\"\\\\\", \"/\");\n for (const boundary of boundaries) {\n if (boundary.dir === \".\") {\n return boundary.project;\n }\n\n if (\n normalizedFilePath === boundary.dir ||\n normalizedFilePath.startsWith(`${boundary.dir}/`)\n ) {\n return boundary.project;\n }\n }\n\n return rootProject;\n}\n",
|
|
26
|
+
"import path from \"node:path\";\nimport { promises as fs } from \"node:fs\";\n\n/**\n * A discovered sub-project within the indexed project root.\n *\n * Returned by {@link Gildash.projects}.\n */\nexport interface ProjectBoundary {\n /** Relative directory path from the project root. */\n dir: string;\n /** Unique project name (typically the `name` field from `package.json`). */\n project: string;\n}\n\nconst DISCOVERY_EXCLUDE = [\"**/node_modules/**\", \"**/.git/**\", \"**/.zipbul/**\", \"**/dist/**\"];\n\nexport async function discoverProjects(projectRoot: string): Promise<ProjectBoundary[]> {\n const boundaries: ProjectBoundary[] = [];\n\n for await (const relativePackageJson of fs.glob(\"**/package.json\", {\n cwd: projectRoot,\n exclude: DISCOVERY_EXCLUDE,\n })) {\n const packageDir = path.dirname(relativePackageJson).replaceAll(\"\\\\\", \"/\");\n const packagePath = path.join(projectRoot, relativePackageJson);\n const content = await Bun.file(packagePath).json();\n\n const packageName =\n typeof content?.name === \"string\" && content.name.length > 0\n ? content.name\n : path.basename(packageDir === \".\" ? projectRoot : packageDir);\n\n boundaries.push({\n dir: packageDir,\n project: packageName,\n });\n }\n\n boundaries.sort((left, right) => right.dir.length - left.dir.length);\n return boundaries;\n}\n\nexport function resolveFileProject(\n filePath: string,\n boundaries: ProjectBoundary[],\n rootProject = \"default\",\n): string {\n const normalizedFilePath = filePath.replaceAll(\"\\\\\", \"/\");\n for (const boundary of boundaries) {\n if (boundary.dir === \".\") {\n return boundary.project;\n }\n\n if (\n normalizedFilePath === boundary.dir ||\n normalizedFilePath.startsWith(`${boundary.dir}/`)\n ) {\n return boundary.project;\n }\n }\n\n return rootProject;\n}\n",
|
|
27
27
|
"import path from \"node:path\";\n\nexport interface TsconfigPaths {\n baseUrl: string;\n paths: Map<string, string[]>;\n}\n\nconst cache = new Map<string, TsconfigPaths | null>();\n\nasync function readConfig(configPath: string): Promise<Record<string, unknown> | null> {\n const file = Bun.file(configPath);\n if (!(await file.exists())) {\n return null;\n }\n\n const parsed = await file.json();\n return typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, unknown>) : null;\n}\n\nexport async function loadTsconfigPaths(projectRoot: string): Promise<TsconfigPaths | null> {\n if (cache.has(projectRoot)) {\n return cache.get(projectRoot) ?? null;\n }\n\n const tsconfigPath = path.join(projectRoot, \"tsconfig.json\");\n\n const config = await readConfig(tsconfigPath);\n if (!config) {\n cache.set(projectRoot, null);\n return null;\n }\n\n const compilerOptions =\n typeof config.compilerOptions === \"object\" && config.compilerOptions !== null\n ? (config.compilerOptions as Record<string, unknown>)\n : null;\n\n if (!compilerOptions) {\n cache.set(projectRoot, null);\n return null;\n }\n\n const rawBaseUrl = typeof compilerOptions.baseUrl === \"string\" ? compilerOptions.baseUrl : null;\n const rawPaths =\n typeof compilerOptions.paths === \"object\" && compilerOptions.paths !== null\n ? (compilerOptions.paths as Record<string, unknown>)\n : null;\n\n if (!rawBaseUrl && !rawPaths) {\n cache.set(projectRoot, null);\n return null;\n }\n\n const resolvedBaseUrl = rawBaseUrl ? path.resolve(projectRoot, rawBaseUrl) : projectRoot;\n const paths = new Map<string, string[]>();\n\n if (rawPaths) {\n for (const [pattern, targets] of Object.entries(rawPaths)) {\n if (!Array.isArray(targets)) {\n continue;\n }\n\n const normalizedTargets = targets.filter((value): value is string => typeof value === \"string\");\n paths.set(pattern, normalizedTargets);\n }\n }\n\n const result: TsconfigPaths = {\n baseUrl: resolvedBaseUrl,\n paths,\n };\n\n cache.set(projectRoot, result);\n return result;\n}\n\nexport function clearTsconfigPathsCache(projectRoot?: string): void {\n if (projectRoot) {\n cache.delete(projectRoot);\n return;\n }\n\n cache.clear();\n}\n",
|
|
28
28
|
"import path from \"node:path\";\n\nexport function toRelativePath(projectRoot: string, absolutePath: string): string {\n return path.relative(projectRoot, absolutePath).replaceAll(\"\\\\\", \"/\");\n}\n\nexport function toAbsolutePath(projectRoot: string, relativePath: string): string {\n return path.resolve(projectRoot, relativePath);\n}\n",
|
|
29
29
|
"export function hashString(input: string): string {\n const raw = Bun.hash.xxHash64(input);\n const unsigned = BigInt.asUintN(64, BigInt(raw));\n return unsigned.toString(16).padStart(16, \"0\");\n}\n\nexport async function hashFile(filePath: string): Promise<string> {\n const text = await Bun.file(filePath).text();\n return hashString(text);\n}\n",
|
|
30
|
-
"import type { FileChangeEvent } from '../watcher/types';\nimport type { ProjectBoundary } from '../common/project-discovery';\nimport { resolveFileProject, discoverProjects } from '../common/project-discovery';\nimport { loadTsconfigPaths, clearTsconfigPathsCache } from '../common/tsconfig-resolver';\nimport type { TsconfigPaths } from '../common/tsconfig-resolver';\nimport { toAbsolutePath } from '../common/path-utils';\nimport { hashString } from '../common/hasher';\nimport { isErr } from '@zipbul/result';\nimport { parseSource } from '../parser/parse-source';\nimport { detectChanges } from './file-indexer';\nimport { indexFileSymbols } from './symbol-indexer';\nimport { indexFileRelations } from './relation-indexer';\nimport type { DbConnection } from '../store/connection';\nimport type { FileRecord } from '../store/repositories/file.repository';\nimport type { SymbolRecord } from '../store/repositories/symbol.repository';\nimport type { RelationRecord } from '../store/repositories/relation.repository';\nimport type { Logger } from '../gildash';\n\nexport const WATCHER_DEBOUNCE_MS = 100;\n\nexport interface IndexResult {\n indexedFiles: number;\n removedFiles: number;\n totalSymbols: number;\n totalRelations: number;\n durationMs: number;\n changedFiles: string[];\n deletedFiles: string[];\n failedFiles: string[];\n}\n\nexport interface IndexCoordinatorOptions {\n projectRoot: string;\n boundaries: ProjectBoundary[];\n extensions: string[];\n ignorePatterns: string[];\n dbConnection: { transaction<T>(fn: (tx: DbConnection) => T): T };\n parseCache: {\n set(key: string, value: unknown): void;\n get(key: string): unknown;\n invalidate(key: string): void;\n };\n fileRepo: {\n getFilesMap(project: string): Map<string, FileRecord>;\n getAllFiles(project: string): FileRecord[];\n upsertFile(record: FileRecord): void;\n deleteFile(project: string, filePath: string): void;\n };\n symbolRepo: {\n replaceFileSymbols(project: string, filePath: string, contentHash: string, symbols: ReadonlyArray<Partial<SymbolRecord>>): void;\n getFileSymbols(project: string, filePath: string): SymbolRecord[];\n getByFingerprint(project: string, fingerprint: string): SymbolRecord[];\n deleteFileSymbols(project: string, filePath: string): void;\n };\n relationRepo: {\n replaceFileRelations(project: string, filePath: string, relations: ReadonlyArray<Partial<RelationRecord>>): void;\n retargetRelations(project: string, oldFile: string, oldSymbol: string | null, newFile: string, newSymbol: string | null): void;\n deleteFileRelations(project: string, filePath: string): void;\n };\n parseSourceFn?: typeof parseSource;\n discoverProjectsFn?: typeof discoverProjects;\n logger?: Logger;\n}\n\nexport class IndexCoordinator {\n private readonly opts: IndexCoordinatorOptions;\n private readonly logger: Logger;\n\n private readonly callbacks = new Set<(result: IndexResult) => void>();\n\n private indexingLock = false;\n\n private pendingEvents: FileChangeEvent[] = [];\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n private currentIndexing: Promise<IndexResult> | null = null;\n\n private pendingFullIndex = false;\n\n private pendingFullIndexWaiters: Array<{ resolve: (r: IndexResult) => void; reject: (e: unknown) => void }> = [];\n\n private tsconfigPathsRaw: Promise<TsconfigPaths | null>;\n\n private boundariesRefresh: Promise<void> | null = null;\n\n constructor(opts: IndexCoordinatorOptions) {\n this.opts = opts;\n this.logger = opts.logger ?? console;\n this.tsconfigPathsRaw = loadTsconfigPaths(opts.projectRoot);\n }\n\n get tsconfigPaths(): Promise<TsconfigPaths | null> {\n return this.tsconfigPathsRaw;\n }\n\n fullIndex(): Promise<IndexResult> {\n return this.startIndex(undefined, true);\n }\n\n incrementalIndex(events?: FileChangeEvent[]): Promise<IndexResult> {\n return this.startIndex(events, false);\n }\n\n onIndexed(cb: (result: IndexResult) => void): () => void {\n this.callbacks.add(cb);\n return () => this.callbacks.delete(cb);\n }\n\n handleWatcherEvent(event: FileChangeEvent): void {\n if (event.filePath.endsWith('tsconfig.json')) {\n clearTsconfigPathsCache(this.opts.projectRoot);\n this.tsconfigPathsRaw = loadTsconfigPaths(this.opts.projectRoot);\n this.fullIndex().catch((err) => {\n this.logger.error('[IndexCoordinator] fullIndex failed after tsconfig change:', err);\n });\n return;\n }\n\n if (event.filePath.endsWith('package.json')) {\n const discover = this.opts.discoverProjectsFn ?? discoverProjects;\n this.boundariesRefresh = discover(this.opts.projectRoot).then((b) => {\n this.opts.boundaries = b;\n });\n }\n\n this.pendingEvents.push(event);\n\n if (this.debounceTimer === null) {\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.flushPending();\n }, WATCHER_DEBOUNCE_MS);\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n if (this.currentIndexing) {\n await this.currentIndexing;\n }\n }\n\n private startIndex(events: FileChangeEvent[] | undefined, useTransaction: boolean): Promise<IndexResult> {\n if (this.indexingLock) {\n if (useTransaction) {\n this.pendingFullIndex = true;\n return new Promise<IndexResult>((resolve, reject) => {\n this.pendingFullIndexWaiters.push({ resolve, reject });\n });\n }\n return this.currentIndexing!;\n }\n this.indexingLock = true;\n\n const work = this.doIndex(events, useTransaction)\n .then((result) => {\n this.fireCallbacks(result);\n return result;\n })\n .finally(() => {\n this.indexingLock = false;\n this.currentIndexing = null;\n if (this.pendingFullIndex) {\n this.pendingFullIndex = false;\n const waiters = this.pendingFullIndexWaiters.splice(0);\n this.startIndex(undefined, true)\n .then((result) => {\n for (const waiter of waiters) waiter.resolve(result);\n })\n .catch((error) => {\n for (const waiter of waiters) waiter.reject(error);\n });\n } else if (this.pendingEvents.length > 0) {\n const drained = this.pendingEvents.splice(0);\n this.startIndex(drained, false).catch((err) =>\n this.logger.error('[IndexCoordinator] incremental drain error', err),\n );\n }\n });\n\n this.currentIndexing = work;\n return work;\n }\n\n private async doIndex(events: FileChangeEvent[] | undefined, useTransaction: boolean): Promise<IndexResult> {\n const start = Date.now();\n const { fileRepo, symbolRepo, relationRepo, dbConnection } = this.opts;\n\n if (this.boundariesRefresh) {\n await this.boundariesRefresh;\n this.boundariesRefresh = null;\n }\n\n let changed: Array<{ filePath: string; contentHash: string; mtimeMs: number; size: number }>;\n let deleted: string[];\n\n if (events !== undefined) {\n changed = events\n .filter((e) => e.eventType === 'create' || e.eventType === 'change')\n .map((e) => ({\n filePath: e.filePath,\n contentHash: '',\n mtimeMs: 0,\n size: 0,\n }));\n deleted = events.filter((e) => e.eventType === 'delete').map((e) => e.filePath);\n } else {\n const existingMap = new Map<string, FileRecord>();\n for (const boundary of this.opts.boundaries) {\n for (const [key, val] of fileRepo.getFilesMap(boundary.project)) {\n existingMap.set(key, val);\n }\n }\n const result = await detectChanges({\n projectRoot: this.opts.projectRoot,\n extensions: this.opts.extensions,\n ignorePatterns: this.opts.ignorePatterns,\n fileRepo: { getFilesMap: () => existingMap },\n });\n changed = result.changed;\n deleted = result.deleted;\n }\n\n const tsconfigPaths = (await this.tsconfigPathsRaw) ?? undefined;\n\n const deletedSymbols = new Map<string, SymbolRecord[]>();\n for (const filePath of deleted) {\n const project = resolveFileProject(filePath, this.opts.boundaries);\n const syms = symbolRepo.getFileSymbols(project, filePath);\n deletedSymbols.set(filePath, syms);\n }\n\n const processDeleted = () => {\n for (const filePath of deleted) {\n const project = resolveFileProject(filePath, this.opts.boundaries);\n symbolRepo.deleteFileSymbols(project, filePath);\n relationRepo.deleteFileRelations(project, filePath);\n fileRepo.deleteFile(project, filePath);\n }\n };\n\n const processChanged = async (): Promise<{ symbols: number; relations: number; failedFiles: string[] }> => {\n let symbols = 0;\n let relations = 0;\n const failedFiles: string[] = [];\n for (const file of changed) {\n try {\n const r = await this.processFile(file.filePath, file.contentHash || undefined, tsconfigPaths);\n symbols += r.symbolCount;\n relations += r.relCount;\n } catch (err) {\n this.logger.error(`[IndexCoordinator] Failed to index ${file.filePath}:`, err);\n failedFiles.push(file.filePath);\n }\n }\n return { symbols, relations, failedFiles };\n };\n\n let totalSymbols = 0;\n let totalRelations = 0;\n let allFailedFiles: string[] = [];\n\n if (useTransaction) {\n const { projectRoot, boundaries } = this.opts;\n const { parseCache } = this.opts;\n const prereadResults = await Promise.allSettled(\n changed.map(async (file) => {\n const absPath = toAbsolutePath(projectRoot, file.filePath);\n const bunFile = Bun.file(absPath);\n const text = await bunFile.text();\n const contentHash = file.contentHash || hashString(text);\n return { filePath: file.filePath, text, contentHash, mtimeMs: bunFile.lastModified, size: bunFile.size };\n }),\n );\n const preread = prereadResults\n .filter((r): r is PromiseFulfilledResult<{ filePath: string; text: string; contentHash: string; mtimeMs: number; size: number }> => r.status === 'fulfilled')\n .map((r) => r.value);\n for (const r of prereadResults) {\n if (r.status === 'rejected') {\n this.logger.error('[IndexCoordinator] Failed to pre-read file:', r.reason);\n }\n }\n\n const parsedCacheEntries: Array<{ filePath: string; parsed: unknown }> = [];\n\n dbConnection.transaction(() => {\n for (const boundary of boundaries) {\n const projectFiles = fileRepo.getAllFiles(boundary.project);\n for (const f of projectFiles) {\n fileRepo.deleteFile(f.project, f.filePath);\n }\n }\n const parseFn = this.opts.parseSourceFn ?? parseSource;\n for (const fd of preread) {\n const project = resolveFileProject(fd.filePath, boundaries);\n const parseResult = parseFn(toAbsolutePath(projectRoot, fd.filePath), fd.text);\n if (isErr(parseResult)) throw parseResult.data;\n const parsed = parseResult;\n parsedCacheEntries.push({ filePath: fd.filePath, parsed });\n fileRepo.upsertFile({\n project,\n filePath: fd.filePath,\n mtimeMs: fd.mtimeMs,\n size: fd.size,\n contentHash: fd.contentHash,\n updatedAt: new Date().toISOString(),\n });\n indexFileSymbols({ parsed, project, filePath: fd.filePath, contentHash: fd.contentHash, symbolRepo });\n totalRelations += indexFileRelations({\n ast: parsed.program,\n project,\n filePath: fd.filePath,\n relationRepo,\n projectRoot,\n tsconfigPaths,\n });\n totalSymbols += symbolRepo.getFileSymbols(project, fd.filePath).length;\n }\n });\n\n for (const entry of parsedCacheEntries) {\n parseCache.set(entry.filePath, entry.parsed);\n }\n } else {\n processDeleted();\n const counts = await processChanged();\n totalSymbols = counts.symbols;\n totalRelations = counts.relations;\n allFailedFiles = counts.failedFiles;\n }\n\n if (!useTransaction) {\n for (const [oldFile, syms] of deletedSymbols) {\n for (const sym of syms) {\n if (!sym.fingerprint) continue;\n const oldProject = resolveFileProject(oldFile, this.opts.boundaries);\n const matches = symbolRepo.getByFingerprint(oldProject, sym.fingerprint);\n if (matches.length === 1) {\n const newSym = matches[0]!;\n relationRepo.retargetRelations(\n oldProject,\n oldFile,\n sym.name,\n newSym.filePath,\n newSym.name,\n );\n }\n }\n }\n }\n\n return {\n indexedFiles: changed.length,\n removedFiles: deleted.length,\n totalSymbols,\n totalRelations,\n durationMs: Date.now() - start,\n changedFiles: changed.map((f) => f.filePath),\n deletedFiles: [...deleted],\n failedFiles: allFailedFiles,\n };\n }\n\n private async processFile(\n filePath: string,\n knownHash: string | undefined,\n tsconfigPaths: TsconfigPaths | undefined,\n ): Promise<{ symbolCount: number; relCount: number }> {\n const { projectRoot, boundaries } = this.opts;\n const { fileRepo, symbolRepo, relationRepo, parseCache } = this.opts;\n\n const absPath = toAbsolutePath(projectRoot, filePath);\n const bunFile = Bun.file(absPath);\n const text = await bunFile.text();\n const contentHash = knownHash || hashString(text);\n\n const project = resolveFileProject(filePath, boundaries);\n\n const parseFn = this.opts.parseSourceFn ?? parseSource;\n const parseResult = parseFn(absPath, text);\n if (isErr(parseResult)) throw parseResult.data;\n const parsed = parseResult;\n parseCache.set(filePath, parsed);\n\n fileRepo.upsertFile({\n project,\n filePath,\n mtimeMs: bunFile.lastModified,\n size: bunFile.size,\n contentHash,\n updatedAt: new Date().toISOString(),\n });\n\n indexFileSymbols({ parsed, project, filePath, contentHash, symbolRepo });\n\n const relCount = indexFileRelations({\n ast: parsed.program,\n project,\n filePath,\n relationRepo,\n projectRoot,\n tsconfigPaths,\n });\n\n const symbolCount = symbolRepo.getFileSymbols(project, filePath).length;\n return { symbolCount, relCount };\n }\n\n private fireCallbacks(result: IndexResult): void {\n for (const cb of this.callbacks) {\n try {\n cb(result);\n } catch (err) {\n this.logger.error('[IndexCoordinator] onIndexed callback threw:', err);\n }\n }\n }\n\n private flushPending(): void {\n if (this.indexingLock) {\n return;\n }\n if (this.pendingEvents.length > 0) {\n const events = this.pendingEvents.splice(0);\n this.startIndex(events, false).catch((err) =>\n this.logger.error('[IndexCoordinator] flushPending startIndex error:', err),\n );\n }\n }\n}\n",
|
|
30
|
+
"import type { FileChangeEvent } from '../watcher/types';\nimport type { ProjectBoundary } from '../common/project-discovery';\nimport { resolveFileProject, discoverProjects } from '../common/project-discovery';\nimport { loadTsconfigPaths, clearTsconfigPathsCache } from '../common/tsconfig-resolver';\nimport type { TsconfigPaths } from '../common/tsconfig-resolver';\nimport { toAbsolutePath } from '../common/path-utils';\nimport { hashString } from '../common/hasher';\nimport { isErr } from '@zipbul/result';\nimport { parseSource } from '../parser/parse-source';\nimport { detectChanges } from './file-indexer';\nimport { indexFileSymbols } from './symbol-indexer';\nimport { indexFileRelations } from './relation-indexer';\nimport type { DbConnection } from '../store/connection';\nimport type { FileRecord } from '../store/repositories/file.repository';\nimport type { SymbolRecord } from '../store/repositories/symbol.repository';\nimport type { RelationRecord } from '../store/repositories/relation.repository';\nimport type { Logger } from '../gildash';\n\nexport const WATCHER_DEBOUNCE_MS = 100;\n\n/**\n * Summary returned after an indexing run completes.\n *\n * Received via {@link Gildash.reindex} and the {@link Gildash.onIndexed} callback.\n */\nexport interface IndexResult {\n /** Number of files that were (re-)indexed. */\n indexedFiles: number;\n /** Number of files removed from the index. */\n removedFiles: number;\n /** Total symbol count after indexing. */\n totalSymbols: number;\n /** Total relation count after indexing. */\n totalRelations: number;\n /** Wall-clock duration of the indexing run in milliseconds. */\n durationMs: number;\n /** Absolute paths of files that changed and were re-indexed. */\n changedFiles: string[];\n /** Absolute paths of files that were deleted from the index. */\n deletedFiles: string[];\n /** Absolute paths of files that failed to index. */\n failedFiles: string[];\n}\n\nexport interface IndexCoordinatorOptions {\n projectRoot: string;\n boundaries: ProjectBoundary[];\n extensions: string[];\n ignorePatterns: string[];\n dbConnection: { transaction<T>(fn: (tx: DbConnection) => T): T };\n parseCache: {\n set(key: string, value: unknown): void;\n get(key: string): unknown;\n invalidate(key: string): void;\n };\n fileRepo: {\n getFilesMap(project: string): Map<string, FileRecord>;\n getAllFiles(project: string): FileRecord[];\n upsertFile(record: FileRecord): void;\n deleteFile(project: string, filePath: string): void;\n };\n symbolRepo: {\n replaceFileSymbols(project: string, filePath: string, contentHash: string, symbols: ReadonlyArray<Partial<SymbolRecord>>): void;\n getFileSymbols(project: string, filePath: string): SymbolRecord[];\n getByFingerprint(project: string, fingerprint: string): SymbolRecord[];\n deleteFileSymbols(project: string, filePath: string): void;\n };\n relationRepo: {\n replaceFileRelations(project: string, filePath: string, relations: ReadonlyArray<Partial<RelationRecord>>): void;\n retargetRelations(project: string, oldFile: string, oldSymbol: string | null, newFile: string, newSymbol: string | null): void;\n deleteFileRelations(project: string, filePath: string): void;\n };\n parseSourceFn?: typeof parseSource;\n discoverProjectsFn?: typeof discoverProjects;\n logger?: Logger;\n}\n\nexport class IndexCoordinator {\n private readonly opts: IndexCoordinatorOptions;\n private readonly logger: Logger;\n\n private readonly callbacks = new Set<(result: IndexResult) => void>();\n\n private indexingLock = false;\n\n private pendingEvents: FileChangeEvent[] = [];\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n private currentIndexing: Promise<IndexResult> | null = null;\n\n private pendingFullIndex = false;\n\n private pendingFullIndexWaiters: Array<{ resolve: (r: IndexResult) => void; reject: (e: unknown) => void }> = [];\n\n private tsconfigPathsRaw: Promise<TsconfigPaths | null>;\n\n private boundariesRefresh: Promise<void> | null = null;\n\n constructor(opts: IndexCoordinatorOptions) {\n this.opts = opts;\n this.logger = opts.logger ?? console;\n this.tsconfigPathsRaw = loadTsconfigPaths(opts.projectRoot);\n }\n\n get tsconfigPaths(): Promise<TsconfigPaths | null> {\n return this.tsconfigPathsRaw;\n }\n\n fullIndex(): Promise<IndexResult> {\n return this.startIndex(undefined, true);\n }\n\n incrementalIndex(events?: FileChangeEvent[]): Promise<IndexResult> {\n return this.startIndex(events, false);\n }\n\n onIndexed(cb: (result: IndexResult) => void): () => void {\n this.callbacks.add(cb);\n return () => this.callbacks.delete(cb);\n }\n\n handleWatcherEvent(event: FileChangeEvent): void {\n if (event.filePath.endsWith('tsconfig.json')) {\n clearTsconfigPathsCache(this.opts.projectRoot);\n this.tsconfigPathsRaw = loadTsconfigPaths(this.opts.projectRoot);\n this.fullIndex().catch((err) => {\n this.logger.error('[IndexCoordinator] fullIndex failed after tsconfig change:', err);\n });\n return;\n }\n\n if (event.filePath.endsWith('package.json')) {\n const discover = this.opts.discoverProjectsFn ?? discoverProjects;\n this.boundariesRefresh = discover(this.opts.projectRoot).then((b) => {\n this.opts.boundaries = b;\n });\n }\n\n this.pendingEvents.push(event);\n\n if (this.debounceTimer === null) {\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.flushPending();\n }, WATCHER_DEBOUNCE_MS);\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n if (this.currentIndexing) {\n await this.currentIndexing;\n }\n }\n\n private startIndex(events: FileChangeEvent[] | undefined, useTransaction: boolean): Promise<IndexResult> {\n if (this.indexingLock) {\n if (useTransaction) {\n this.pendingFullIndex = true;\n return new Promise<IndexResult>((resolve, reject) => {\n this.pendingFullIndexWaiters.push({ resolve, reject });\n });\n }\n return this.currentIndexing!;\n }\n this.indexingLock = true;\n\n const work = this.doIndex(events, useTransaction)\n .then((result) => {\n this.fireCallbacks(result);\n return result;\n })\n .finally(() => {\n this.indexingLock = false;\n this.currentIndexing = null;\n if (this.pendingFullIndex) {\n this.pendingFullIndex = false;\n const waiters = this.pendingFullIndexWaiters.splice(0);\n this.startIndex(undefined, true)\n .then((result) => {\n for (const waiter of waiters) waiter.resolve(result);\n })\n .catch((error) => {\n for (const waiter of waiters) waiter.reject(error);\n });\n } else if (this.pendingEvents.length > 0) {\n const drained = this.pendingEvents.splice(0);\n this.startIndex(drained, false).catch((err) =>\n this.logger.error('[IndexCoordinator] incremental drain error', err),\n );\n }\n });\n\n this.currentIndexing = work;\n return work;\n }\n\n private async doIndex(events: FileChangeEvent[] | undefined, useTransaction: boolean): Promise<IndexResult> {\n const start = Date.now();\n const { fileRepo, symbolRepo, relationRepo, dbConnection } = this.opts;\n\n if (this.boundariesRefresh) {\n await this.boundariesRefresh;\n this.boundariesRefresh = null;\n }\n\n let changed: Array<{ filePath: string; contentHash: string; mtimeMs: number; size: number }>;\n let deleted: string[];\n\n if (events !== undefined) {\n changed = events\n .filter((e) => e.eventType === 'create' || e.eventType === 'change')\n .map((e) => ({\n filePath: e.filePath,\n contentHash: '',\n mtimeMs: 0,\n size: 0,\n }));\n deleted = events.filter((e) => e.eventType === 'delete').map((e) => e.filePath);\n } else {\n const existingMap = new Map<string, FileRecord>();\n for (const boundary of this.opts.boundaries) {\n for (const [key, val] of fileRepo.getFilesMap(boundary.project)) {\n existingMap.set(key, val);\n }\n }\n const result = await detectChanges({\n projectRoot: this.opts.projectRoot,\n extensions: this.opts.extensions,\n ignorePatterns: this.opts.ignorePatterns,\n fileRepo: { getFilesMap: () => existingMap },\n });\n changed = result.changed;\n deleted = result.deleted;\n }\n\n const tsconfigPaths = (await this.tsconfigPathsRaw) ?? undefined;\n\n const deletedSymbols = new Map<string, SymbolRecord[]>();\n for (const filePath of deleted) {\n const project = resolveFileProject(filePath, this.opts.boundaries);\n const syms = symbolRepo.getFileSymbols(project, filePath);\n deletedSymbols.set(filePath, syms);\n }\n\n const processDeleted = () => {\n for (const filePath of deleted) {\n const project = resolveFileProject(filePath, this.opts.boundaries);\n symbolRepo.deleteFileSymbols(project, filePath);\n relationRepo.deleteFileRelations(project, filePath);\n fileRepo.deleteFile(project, filePath);\n }\n };\n\n const processChanged = async (): Promise<{ symbols: number; relations: number; failedFiles: string[] }> => {\n let symbols = 0;\n let relations = 0;\n const failedFiles: string[] = [];\n for (const file of changed) {\n try {\n const r = await this.processFile(file.filePath, file.contentHash || undefined, tsconfigPaths);\n symbols += r.symbolCount;\n relations += r.relCount;\n } catch (err) {\n this.logger.error(`[IndexCoordinator] Failed to index ${file.filePath}:`, err);\n failedFiles.push(file.filePath);\n }\n }\n return { symbols, relations, failedFiles };\n };\n\n let totalSymbols = 0;\n let totalRelations = 0;\n let allFailedFiles: string[] = [];\n\n if (useTransaction) {\n const { projectRoot, boundaries } = this.opts;\n const { parseCache } = this.opts;\n const prereadResults = await Promise.allSettled(\n changed.map(async (file) => {\n const absPath = toAbsolutePath(projectRoot, file.filePath);\n const bunFile = Bun.file(absPath);\n const text = await bunFile.text();\n const contentHash = file.contentHash || hashString(text);\n return { filePath: file.filePath, text, contentHash, mtimeMs: bunFile.lastModified, size: bunFile.size };\n }),\n );\n const preread = prereadResults\n .filter((r): r is PromiseFulfilledResult<{ filePath: string; text: string; contentHash: string; mtimeMs: number; size: number }> => r.status === 'fulfilled')\n .map((r) => r.value);\n for (const r of prereadResults) {\n if (r.status === 'rejected') {\n this.logger.error('[IndexCoordinator] Failed to pre-read file:', r.reason);\n }\n }\n\n const parsedCacheEntries: Array<{ filePath: string; parsed: unknown }> = [];\n\n dbConnection.transaction(() => {\n for (const boundary of boundaries) {\n const projectFiles = fileRepo.getAllFiles(boundary.project);\n for (const f of projectFiles) {\n fileRepo.deleteFile(f.project, f.filePath);\n }\n }\n const parseFn = this.opts.parseSourceFn ?? parseSource;\n for (const fd of preread) {\n const project = resolveFileProject(fd.filePath, boundaries);\n const parseResult = parseFn(toAbsolutePath(projectRoot, fd.filePath), fd.text);\n if (isErr(parseResult)) throw parseResult.data;\n const parsed = parseResult;\n parsedCacheEntries.push({ filePath: fd.filePath, parsed });\n fileRepo.upsertFile({\n project,\n filePath: fd.filePath,\n mtimeMs: fd.mtimeMs,\n size: fd.size,\n contentHash: fd.contentHash,\n updatedAt: new Date().toISOString(),\n });\n indexFileSymbols({ parsed, project, filePath: fd.filePath, contentHash: fd.contentHash, symbolRepo });\n totalRelations += indexFileRelations({\n ast: parsed.program,\n project,\n filePath: fd.filePath,\n relationRepo,\n projectRoot,\n tsconfigPaths,\n });\n totalSymbols += symbolRepo.getFileSymbols(project, fd.filePath).length;\n }\n });\n\n for (const entry of parsedCacheEntries) {\n parseCache.set(entry.filePath, entry.parsed);\n }\n } else {\n processDeleted();\n const counts = await processChanged();\n totalSymbols = counts.symbols;\n totalRelations = counts.relations;\n allFailedFiles = counts.failedFiles;\n }\n\n if (!useTransaction) {\n for (const [oldFile, syms] of deletedSymbols) {\n for (const sym of syms) {\n if (!sym.fingerprint) continue;\n const oldProject = resolveFileProject(oldFile, this.opts.boundaries);\n const matches = symbolRepo.getByFingerprint(oldProject, sym.fingerprint);\n if (matches.length === 1) {\n const newSym = matches[0]!;\n relationRepo.retargetRelations(\n oldProject,\n oldFile,\n sym.name,\n newSym.filePath,\n newSym.name,\n );\n }\n }\n }\n }\n\n return {\n indexedFiles: changed.length,\n removedFiles: deleted.length,\n totalSymbols,\n totalRelations,\n durationMs: Date.now() - start,\n changedFiles: changed.map((f) => f.filePath),\n deletedFiles: [...deleted],\n failedFiles: allFailedFiles,\n };\n }\n\n private async processFile(\n filePath: string,\n knownHash: string | undefined,\n tsconfigPaths: TsconfigPaths | undefined,\n ): Promise<{ symbolCount: number; relCount: number }> {\n const { projectRoot, boundaries } = this.opts;\n const { fileRepo, symbolRepo, relationRepo, parseCache } = this.opts;\n\n const absPath = toAbsolutePath(projectRoot, filePath);\n const bunFile = Bun.file(absPath);\n const text = await bunFile.text();\n const contentHash = knownHash || hashString(text);\n\n const project = resolveFileProject(filePath, boundaries);\n\n const parseFn = this.opts.parseSourceFn ?? parseSource;\n const parseResult = parseFn(absPath, text);\n if (isErr(parseResult)) throw parseResult.data;\n const parsed = parseResult;\n parseCache.set(filePath, parsed);\n\n fileRepo.upsertFile({\n project,\n filePath,\n mtimeMs: bunFile.lastModified,\n size: bunFile.size,\n contentHash,\n updatedAt: new Date().toISOString(),\n });\n\n indexFileSymbols({ parsed, project, filePath, contentHash, symbolRepo });\n\n const relCount = indexFileRelations({\n ast: parsed.program,\n project,\n filePath,\n relationRepo,\n projectRoot,\n tsconfigPaths,\n });\n\n const symbolCount = symbolRepo.getFileSymbols(project, filePath).length;\n return { symbolCount, relCount };\n }\n\n private fireCallbacks(result: IndexResult): void {\n for (const cb of this.callbacks) {\n try {\n cb(result);\n } catch (err) {\n this.logger.error('[IndexCoordinator] onIndexed callback threw:', err);\n }\n }\n }\n\n private flushPending(): void {\n if (this.indexingLock) {\n return;\n }\n if (this.pendingEvents.length > 0) {\n const events = this.pendingEvents.splice(0);\n this.startIndex(events, false).catch((err) =>\n this.logger.error('[IndexCoordinator] flushPending startIndex error:', err),\n );\n }\n }\n}\n",
|
|
31
31
|
"import { promises as fsPromises } from 'node:fs';\nimport { join } from 'node:path';\nimport { hashString } from '../common/hasher';\n\nexport interface FileChangeRecord {\n filePath: string;\n contentHash: string;\n mtimeMs: number;\n size: number;\n}\n\nexport interface DetectChangesResult {\n changed: FileChangeRecord[];\n unchanged: FileChangeRecord[];\n deleted: string[];\n}\n\ninterface FileRepoPart {\n getFilesMap(): Map<string, { filePath: string; mtimeMs: number; size: number; contentHash: string }>;\n}\n\nexport interface DetectChangesOptions {\n projectRoot: string;\n extensions: string[];\n ignorePatterns: string[];\n fileRepo: FileRepoPart;\n}\n\nexport async function detectChanges(opts: DetectChangesOptions): Promise<DetectChangesResult> {\n const { projectRoot, extensions, ignorePatterns, fileRepo } = opts;\n\n const existingMap = fileRepo.getFilesMap();\n const seenPaths = new Set<string>();\n const changed: FileChangeRecord[] = [];\n const unchanged: FileChangeRecord[] = [];\n\n const ignoreGlobs = ignorePatterns.map((p) => new Bun.Glob(p));\n\n for await (const relativePath of fsPromises.glob('**/*', { cwd: projectRoot })) {\n if (!extensions.some((ext) => relativePath.endsWith(ext))) continue;\n\n if (ignoreGlobs.some((g) => g.match(relativePath))) continue;\n\n seenPaths.add(relativePath);\n\n const absPath = join(projectRoot, relativePath);\n const bunFile = Bun.file(absPath);\n const { size, lastModified: mtimeMs } = bunFile;\n\n const existing = existingMap.get(relativePath);\n\n if (!existing) {\n const text = await bunFile.text();\n const contentHash = hashString(text);\n changed.push({ filePath: relativePath, contentHash, mtimeMs, size });\n continue;\n }\n\n if (existing.mtimeMs === mtimeMs && existing.size === size) {\n unchanged.push({ filePath: relativePath, contentHash: existing.contentHash, mtimeMs, size });\n continue;\n }\n\n const text = await bunFile.text();\n const contentHash = hashString(text);\n if (contentHash === existing.contentHash) {\n unchanged.push({ filePath: relativePath, contentHash, mtimeMs, size });\n } else {\n changed.push({ filePath: relativePath, contentHash, mtimeMs, size });\n }\n }\n\n const deleted: string[] = [];\n for (const filePath of existingMap.keys()) {\n if (!seenPaths.has(filePath)) {\n deleted.push(filePath);\n }\n }\n\n return { changed, unchanged, deleted };\n}\n",
|
|
32
32
|
"import type { ParsedFile } from '../parser/types';\nimport type { ExtractedSymbol } from '../extractor/types';\nimport { extractSymbols } from '../extractor/symbol-extractor';\nimport { hashString } from '../common/hasher';\n\nexport interface SymbolDbRow {\n project: string;\n filePath: string;\n kind: string;\n name: string;\n startLine: number;\n startColumn: number;\n endLine: number;\n endColumn: number;\n isExported: number;\n signature: string | null;\n fingerprint: string | null;\n detailJson: string | null;\n contentHash: string;\n indexedAt: string;\n}\n\ninterface SymbolRepoPart {\n replaceFileSymbols(\n project: string,\n filePath: string,\n contentHash: string,\n symbols: SymbolDbRow[],\n ): void;\n}\n\nexport interface IndexFileSymbolsOptions {\n parsed: ParsedFile;\n project: string;\n filePath: string;\n contentHash: string;\n symbolRepo: SymbolRepoPart;\n}\n\nfunction buildSignature(sym: ExtractedSymbol): string | null {\n if (sym.kind === 'function' || sym.kind === 'method') {\n const paramCount = sym.parameters?.length ?? 0;\n const isAsync = sym.modifiers.includes('async') ? 1 : 0;\n return `params:${paramCount}|async:${isAsync}`;\n }\n return null;\n}\n\nfunction buildDetailJson(sym: ExtractedSymbol): string | null {\n const detail: Record<string, unknown> = {};\n\n if (sym.jsDoc) detail.jsDoc = sym.jsDoc;\n\n if (sym.kind === 'function' || sym.kind === 'method') {\n if (sym.parameters !== undefined) detail.parameters = sym.parameters;\n if (sym.returnType !== undefined) detail.returnType = sym.returnType;\n }\n\n if (sym.heritage?.length) detail.heritage = sym.heritage;\n if (sym.decorators?.length) detail.decorators = sym.decorators;\n if (sym.typeParameters?.length) detail.typeParameters = sym.typeParameters;\n if (sym.modifiers?.length) detail.modifiers = sym.modifiers;\n if (sym.members?.length) detail.members = sym.members.map((m) => m.name);\n\n return Object.keys(detail).length > 0 ? JSON.stringify(detail) : null;\n}\n\nfunction buildRow(\n sym: ExtractedSymbol,\n name: string,\n project: string,\n filePath: string,\n contentHash: string,\n): SymbolDbRow {\n const signature = buildSignature(sym);\n const fingerprint = hashString(`${name}|${sym.kind}|${signature ?? ''}`);\n\n return {\n project,\n filePath,\n kind: sym.kind,\n name,\n startLine: sym.span.start.line,\n startColumn: sym.span.start.column,\n endLine: sym.span.end.line,\n endColumn: sym.span.end.column,\n isExported: sym.isExported ? 1 : 0,\n signature,\n fingerprint,\n detailJson: buildDetailJson(sym),\n contentHash,\n indexedAt: new Date().toISOString(),\n };\n}\n\nexport function indexFileSymbols(opts: IndexFileSymbolsOptions): void {\n const { parsed, project, filePath, contentHash, symbolRepo } = opts;\n\n const extracted = extractSymbols(parsed);\n const rows: SymbolDbRow[] = [];\n\n for (const sym of extracted) {\n rows.push(buildRow(sym, sym.name, project, filePath, contentHash));\n\n for (const member of sym.members ?? []) {\n rows.push(buildRow(member, `${sym.name}.${member.name}`, project, filePath, contentHash));\n }\n }\n\n symbolRepo.replaceFileSymbols(project, filePath, contentHash, rows);\n}\n",
|
|
33
33
|
"import type { Program } from 'oxc-parser';\nimport { extractRelations } from '../extractor/relation-extractor';\nimport { toAbsolutePath, toRelativePath } from '../common/path-utils';\nimport type { TsconfigPaths } from '../common/tsconfig-resolver';\n\nexport interface RelationDbRow {\n project: string;\n type: string;\n srcFilePath: string;\n srcSymbolName: string | null;\n dstFilePath: string;\n dstSymbolName: string | null;\n metaJson: string | null;\n}\n\ninterface RelationRepoPart {\n replaceFileRelations(\n project: string,\n filePath: string,\n relations: RelationDbRow[],\n ): void;\n}\n\nexport interface IndexFileRelationsOptions {\n ast: Program;\n project: string;\n filePath: string;\n relationRepo: RelationRepoPart;\n projectRoot: string;\n tsconfigPaths?: TsconfigPaths;\n}\n\nexport function indexFileRelations(opts: IndexFileRelationsOptions): number {\n const { ast, project, filePath, relationRepo, projectRoot, tsconfigPaths } = opts;\n\n const absFilePath = toAbsolutePath(projectRoot, filePath);\n const rawRelations = extractRelations(ast, absFilePath, tsconfigPaths);\n\n const rows: RelationDbRow[] = [];\n\n for (const rel of rawRelations) {\n const relDst = toRelativePath(projectRoot, rel.dstFilePath);\n\n if (relDst.startsWith('..')) continue;\n\n const relSrc = toRelativePath(projectRoot, rel.srcFilePath);\n\n rows.push({\n project,\n type: rel.type,\n srcFilePath: relSrc,\n srcSymbolName: rel.srcSymbolName ?? null,\n dstFilePath: relDst,\n dstSymbolName: rel.dstSymbolName ?? null,\n metaJson: rel.metaJson ?? null,\n });\n }\n\n relationRepo.replaceFileRelations(project, filePath, rows);\n return rows.length;\n}\n",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"import type { CodeRelation } from '../extractor/types';\nimport type { RelationRecord } from '../store/repositories/relation.repository';\n\n/**\n * Filters for {@link relationSearch}.\n *\n * All fields are optional. Omitted fields impose no constraint.\n */\nexport interface RelationSearchQuery {\n /** Source file path. */\n srcFilePath?: string;\n /** Source symbol name. */\n srcSymbolName?: string;\n /** Destination file path. */\n dstFilePath?: string;\n /** Destination symbol name. */\n dstSymbolName?: string;\n /** Relationship type: `'imports'`, `'calls'`, `'extends'`, or `'implements'`. */\n type?: CodeRelation['type'];\n /** Limit results to this project. */\n project?: string;\n /** Maximum number of results. Defaults to `500`. */\n limit?: number;\n}\n\nexport interface IRelationRepo {\n searchRelations(opts: {\n srcFilePath?: string;\n srcSymbolName?: string;\n dstFilePath?: string;\n dstSymbolName?: string;\n type?: string;\n project?: string;\n limit: number;\n }): RelationRecord[];\n}\n\n/**\n * Search the relation index using the given query filters.\n *\n * @param options - Relation repository, default project, and search query.\n * @returns An array of {@link CodeRelation} entries matching the query.\n */\nexport function relationSearch(options: {\n relationRepo: IRelationRepo;\n project?: string;\n query: RelationSearchQuery;\n}): CodeRelation[] {\n const { relationRepo, project, query } = options;\n const effectiveProject = query.project ?? project;\n const limit = query.limit ?? 500;\n\n const records = relationRepo.searchRelations({\n srcFilePath: query.srcFilePath,\n srcSymbolName: query.srcSymbolName,\n dstFilePath: query.dstFilePath,\n dstSymbolName: query.dstSymbolName,\n type: query.type,\n project: effectiveProject,\n limit,\n });\n\n return records.map(r => ({\n type: r.type as CodeRelation['type'],\n srcFilePath: r.srcFilePath,\n srcSymbolName: r.srcSymbolName,\n dstFilePath: r.dstFilePath,\n dstSymbolName: r.dstSymbolName,\n metaJson: r.metaJson ?? undefined,\n }));\n}\n",
|
|
37
37
|
"import type { RelationRecord } from '../store/repositories/relation.repository';\n\nexport interface IDependencyGraphRepo {\n getByType(project: string, type: string): RelationRecord[];\n}\n\n/**\n * Directed import graph for dependency analysis.\n *\n * Build the graph once with {@link DependencyGraph.build}, then query\n * dependencies, dependents, cycles, and change-impact.\n *\n * @example\n * ```ts\n * const graph = new DependencyGraph({ relationRepo, project: 'my-app' });\n * graph.build();\n * graph.getDependencies('/src/a.ts'); // files that a.ts imports\n * graph.getDependents('/src/a.ts'); // files that import a.ts\n * graph.hasCycle(); // true if a circular import exists\n * ```\n */\nexport class DependencyGraph {\n private adjacencyList = new Map<string, Set<string>>();\n private reverseAdjacencyList = new Map<string, Set<string>>();\n\n constructor(\n private readonly options: {\n relationRepo: IDependencyGraphRepo;\n project: string;\n },\n ) {}\n\n /**\n * Populate the graph by reading all `imports` relations from the store.\n *\n * Must be called before any query method.\n */\n build(): void {\n this.adjacencyList = new Map();\n this.reverseAdjacencyList = new Map();\n\n const relations = this.options.relationRepo.getByType(\n this.options.project,\n 'imports',\n );\n\n for (const rel of relations) {\n const { srcFilePath, dstFilePath } = rel;\n\n if (!this.adjacencyList.has(srcFilePath)) {\n this.adjacencyList.set(srcFilePath, new Set());\n }\n this.adjacencyList.get(srcFilePath)!.add(dstFilePath);\n\n if (!this.reverseAdjacencyList.has(dstFilePath)) {\n this.reverseAdjacencyList.set(dstFilePath, new Set());\n }\n this.reverseAdjacencyList.get(dstFilePath)!.add(srcFilePath);\n }\n }\n\n /**\n * Return the files that `filePath` directly imports.\n *\n * @param filePath - Absolute file path.\n */\n getDependencies(filePath: string): string[] {\n return Array.from(this.adjacencyList.get(filePath) ?? []);\n }\n\n /**\n * Return the files that directly import `filePath`.\n *\n * @param filePath - Absolute file path.\n */\n getDependents(filePath: string): string[] {\n return Array.from(this.reverseAdjacencyList.get(filePath) ?? []);\n }\n\n /**\n * Return all files that transitively depend on `filePath`\n * (breadth-first reverse walk).\n *\n * @param filePath - Absolute file path.\n */\n getTransitiveDependents(filePath: string): string[] {\n const visited = new Set<string>();\n const queue: string[] = [filePath];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const dependent of this.reverseAdjacencyList.get(current) ?? []) {\n if (!visited.has(dependent)) {\n visited.add(dependent);\n queue.push(dependent);\n }\n }\n }\n\n return Array.from(visited);\n }\n\n /**\n * Detect whether the import graph contains at least one cycle.\n *\n * Uses iterative DFS with a path-tracking set.\n *\n * @returns `true` if a circular dependency exists.\n */\n hasCycle(): boolean {\n const visited = new Set<string>();\n const inPath = new Set<string>();\n\n for (const startNode of this.adjacencyList.keys()) {\n if (visited.has(startNode)) continue;\n\n const stack: Array<{ node: string; entered: boolean }> = [{ node: startNode, entered: false }];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n\n if (current.entered) {\n inPath.delete(current.node);\n continue;\n }\n\n if (inPath.has(current.node)) {\n return true;\n }\n\n if (visited.has(current.node)) {\n continue;\n }\n\n visited.add(current.node);\n inPath.add(current.node);\n stack.push({ node: current.node, entered: true });\n\n for (const neighbor of this.adjacencyList.get(current.node) ?? []) {\n if (inPath.has(neighbor)) {\n return true;\n }\n if (!visited.has(neighbor)) {\n stack.push({ node: neighbor, entered: false });\n }\n }\n }\n }\n\n return false;\n }\n\n /**\n * Compute all files transitively affected by a set of changed files.\n *\n * Combines {@link getTransitiveDependents} for every changed file\n * and de-duplicates the result.\n *\n * @param changedFiles - Absolute paths of files that changed.\n * @returns Paths of all transitively-dependent files.\n */\n getAffectedByChange(changedFiles: string[]): string[] {\n const allAffected = new Set<string>();\n\n for (const file of changedFiles) {\n for (const dep of this.getTransitiveDependents(file)) {\n allAffected.add(dep);\n }\n }\n\n return Array.from(allAffected);\n }\n}\n"
|
|
38
38
|
],
|
|
39
|
-
"mappings": "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",
|
|
40
|
-
"debugId": "
|
|
39
|
+
"mappings": "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",
|
|
40
|
+
"debugId": "B695837771DC776164756E2164756E21",
|
|
41
41
|
"names": []
|
|
42
42
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A discovered sub-project within the indexed project root.
|
|
3
|
+
*
|
|
4
|
+
* Returned by {@link Gildash.projects}.
|
|
5
|
+
*/
|
|
1
6
|
export interface ProjectBoundary {
|
|
7
|
+
/** Relative directory path from the project root. */
|
|
2
8
|
dir: string;
|
|
9
|
+
/** Unique project name (typically the `name` field from `package.json`). */
|
|
3
10
|
project: string;
|
|
4
11
|
}
|
|
5
12
|
export declare function discoverProjects(projectRoot: string): Promise<ProjectBoundary[]>;
|
package/dist/src/gildash.d.ts
CHANGED
|
@@ -141,7 +141,8 @@ export declare class Gildash {
|
|
|
141
141
|
private readonly relationSearchFn;
|
|
142
142
|
private readonly logger;
|
|
143
143
|
private readonly defaultProject;
|
|
144
|
-
|
|
144
|
+
/** Current watcher role: `'owner'` (can reindex) or `'reader'` (read-only). */
|
|
145
|
+
readonly role: 'owner' | 'reader';
|
|
145
146
|
private timer;
|
|
146
147
|
private signalHandlers;
|
|
147
148
|
private closed;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -7,3 +7,8 @@ export type { SymbolSearchQuery, SymbolSearchResult } from "./search/symbol-sear
|
|
|
7
7
|
export { relationSearch } from "./search/relation-search";
|
|
8
8
|
export type { RelationSearchQuery } from "./search/relation-search";
|
|
9
9
|
export { DependencyGraph } from "./search/dependency-graph";
|
|
10
|
+
export type { IndexResult } from "./indexer/index-coordinator";
|
|
11
|
+
export type { ProjectBoundary } from "./common/project-discovery";
|
|
12
|
+
export type { CodeRelation, SymbolKind } from "./extractor/types";
|
|
13
|
+
export type { SymbolStats } from "./store/repositories/symbol.repository";
|
|
14
|
+
export type { WatcherRole } from "./watcher/types";
|
|
@@ -9,14 +9,27 @@ import type { SymbolRecord } from '../store/repositories/symbol.repository';
|
|
|
9
9
|
import type { RelationRecord } from '../store/repositories/relation.repository';
|
|
10
10
|
import type { Logger } from '../gildash';
|
|
11
11
|
export declare const WATCHER_DEBOUNCE_MS = 100;
|
|
12
|
+
/**
|
|
13
|
+
* Summary returned after an indexing run completes.
|
|
14
|
+
*
|
|
15
|
+
* Received via {@link Gildash.reindex} and the {@link Gildash.onIndexed} callback.
|
|
16
|
+
*/
|
|
12
17
|
export interface IndexResult {
|
|
18
|
+
/** Number of files that were (re-)indexed. */
|
|
13
19
|
indexedFiles: number;
|
|
20
|
+
/** Number of files removed from the index. */
|
|
14
21
|
removedFiles: number;
|
|
22
|
+
/** Total symbol count after indexing. */
|
|
15
23
|
totalSymbols: number;
|
|
24
|
+
/** Total relation count after indexing. */
|
|
16
25
|
totalRelations: number;
|
|
26
|
+
/** Wall-clock duration of the indexing run in milliseconds. */
|
|
17
27
|
durationMs: number;
|
|
28
|
+
/** Absolute paths of files that changed and were re-indexed. */
|
|
18
29
|
changedFiles: string[];
|
|
30
|
+
/** Absolute paths of files that were deleted from the index. */
|
|
19
31
|
deletedFiles: string[];
|
|
32
|
+
/** Absolute paths of files that failed to index. */
|
|
20
33
|
failedFiles: string[];
|
|
21
34
|
}
|
|
22
35
|
export interface IndexCoordinatorOptions {
|
|
@@ -19,8 +19,15 @@ export interface SearchOptions {
|
|
|
19
19
|
kind?: string;
|
|
20
20
|
limit?: number;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Aggregate symbol statistics for a project.
|
|
24
|
+
*
|
|
25
|
+
* Returned by {@link Gildash.getStats}.
|
|
26
|
+
*/
|
|
22
27
|
export interface SymbolStats {
|
|
28
|
+
/** Total number of indexed symbols. */
|
|
23
29
|
symbolCount: number;
|
|
30
|
+
/** Total number of indexed source files. */
|
|
24
31
|
fileCount: number;
|
|
25
32
|
}
|
|
26
33
|
export declare class SymbolRepository {
|
|
@@ -8,4 +8,10 @@ export interface WatcherOptions {
|
|
|
8
8
|
ignorePatterns?: string[];
|
|
9
9
|
extensions?: string[];
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* The role acquired by a {@link Gildash} instance.
|
|
13
|
+
*
|
|
14
|
+
* - `'owner'` — the instance owns the file watcher and can trigger re-indexing.
|
|
15
|
+
* - `'reader'` — the instance shares the database but cannot trigger re-indexing.
|
|
16
|
+
*/
|
|
11
17
|
export type WatcherRole = "owner" | "reader";
|