@zipbul/gildash 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +454 -0
- package/README.md +65 -0
- package/dist/index.js +4 -4
- package/dist/index.js.map +6 -6
- package/dist/src/gildash.d.ts +34 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/parser/types.d.ts +18 -0
- package/dist/src/search/symbol-search.d.ts +3 -0
- package/dist/src/store/repositories/file.repository.d.ts +12 -0
- package/dist/src/store/repositories/symbol.repository.d.ts +1 -0
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
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(
|
|
2
|
+
var lt=Object.defineProperty;var ut=(n,t)=>{for(var e in t)lt(n,e,{get:t[e],enumerable:!0,configurable:!0,set:(r)=>t[e]=()=>r})};import{err as T,isErr as tn}from"@zipbul/result";import at from"path";import{existsSync as Qt}from"fs";import{err as pt}from"@zipbul/result";import{parseSync as dt}from"oxc-parser";function k(n,t,e){return e!==void 0?{type:n,message:t,cause:e}:{type:n,message:t}}function rn(n,t,e=dt){try{let{program:r,errors:i,comments:s}=e(n,t);return{filePath:n,program:r,errors:i,comments:s,sourceText:t}}catch(r){return pt(k("parse",`Failed to parse file: ${n}`,r))}}class hn{#t;#n=new Map;constructor(n){this.#t=Math.max(1,n)}get size(){return this.#n.size}has(n){return this.#n.has(n)}get(n){if(!this.#n.has(n))return;let t=this.#n.get(n);return this.#n.delete(n),this.#n.set(n,t),t}set(n,t){if(this.#n.has(n))this.#n.delete(n);if(this.#n.set(n,t),this.#n.size>this.#t){let e=this.#n.keys().next().value;if(e!==void 0)this.#n.delete(e)}}delete(n){return this.#n.delete(n)}clear(){this.#n.clear()}}class bn{lru;constructor(n=500){this.lru=new hn(n)}get(n){return this.lru.get(n)}set(n,t){this.lru.set(n,t)}invalidate(n){this.lru.delete(n)}invalidateAll(){this.lru.clear()}size(){return this.lru.size}}function zn(n){let t=[0];for(let e=0;e<n.length;e++)if(n[e]===`
|
|
3
|
+
`)t.push(e+1);return t}function xn(n,t){let e=0,r=n.length-1;while(e<r){let i=e+r+1>>1;if(n[i]<=t)e=i;else r=i-1}return{line:e+1,column:t-n[e]}}import{err as ft}from"@zipbul/result";import{parse as gt}from"comment-parser";function Gn(n){try{let t=n.trim();if(t.startsWith("/**"))t=t.slice(3);if(t.endsWith("*/"))t=t.slice(0,-2);let r=gt(`/** ${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 ft(k("parse","Failed to parse JSDoc comment",t))}}import{isErr as yt}from"@zipbul/result";function cn(n){let{program:t,sourceText:e,comments:r}=n,i=zn(e);function s(o,m){return{start:xn(i,o),end:xn(i,m)}}function p(o){let m=null;for(let a of r){if(a.type!=="Block")continue;if(a.end>o)continue;if(!a.value.startsWith("*"))continue;if(!m||a.end>m.end)m={value:`/*${a.value}*/`,end:a.end}}if(!m)return;for(let a of t.body){let g=a.start??0;if(g===o)continue;if(g>m.end&&g<o)return}return m.value}function l(o){if(!o)return;let m=o.typeAnnotation??o;return e.slice(m.start,m.end)}function c(o){if(!o||o.length===0)return[];return o.map((m)=>{let a=m.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 m=o.type==="TSParameterProperty"?o.parameter:o;if(m?.type==="RestElement"){let R=`...${m.argument?.name??"unknown"}`,L=m.typeAnnotation,B=L?l(L):void 0,O={name:R,isOptional:!1};if(B)O.type=B;return O}if(m?.type==="AssignmentPattern"){let{left:N,right:R}=m,L=N?.name??"unknown",B=N?.typeAnnotation,O=B?l(B):void 0,W=e.slice(R.start,R.end),v=c(N?.decorators??[]),J={name:L,isOptional:!0,defaultValue:W};if(O)J.type=O;if(v.length>0)J.decorators=v;return J}let a=m?.name??m?.pattern?.name??"unknown",g=!!m?.optional,h=m?.typeAnnotation,d=h?l(h):void 0,S=c(m?.decorators??[]),P={name:a,isOptional:g};if(d)P.type=d;if(S.length>0)P.decorators=S;return P}function f(o,m){let a=[];if(m?.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 m=[];if(o.superClass){let g=e.slice(o.superClass.start,o.superClass.end);m.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);m.push({kind:"implements",name:d})}return m}function w(o){let m=[];for(let a of o.extends??[]){let g=a.expression??a,h=e.slice(g.start,g.end);m.push({kind:"extends",name:h})}return m}function A(o){let m=[];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",P=f(a,h),N=(h?.params??[]).map(y),R=l(h?.returnType),L={kind:"method",name:g,span:s(a.start,a.end),isExported:!1,methodKind:S,modifiers:P,parameters:N.length>0?N:void 0,returnType:R};m.push(L)}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};m.push(d)}return m}function F(o){let m=[];for(let a of o)if(a.type==="TSMethodSignature"){let g=a.key?.name??"unknown",h=(a.params??[]).map(y),d=l(a.returnType);m.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=l(a.typeAnnotation),d={kind:"property",name:g,span:s(a.start,a.end),isExported:!1,modifiers:a.readonly?["readonly"]:[],returnType:h};m.push(d)}return m}function E(o,m){let a=o.type??"";if(a==="FunctionDeclaration"){let g=o.id?.name??"default",h=(o.params??[]).map(y),d=l(o.returnType),S=f(o,o),P=c(o.decorators??[]),N=o.typeParameters?.params?.map((L)=>L.name?.name).filter(Boolean)||void 0,R={kind:"function",name:g,span:s(o.start,o.end),isExported:m,modifiers:S,parameters:h.length>0?h:void 0,returnType:d,decorators:P.length>0?P:void 0};if(N&&N.length>0)R.typeParameters=N;return R}if(a==="ClassDeclaration"||a==="ClassExpression"){let g=o.id?.name??"default",h=x(o),d=A(o.body?.body??[]),S=c(o.decorators??[]),P=f(o,o),N=o.typeParameters?.params?.map((L)=>L.name?.name).filter(Boolean)||void 0,R={kind:"class",name:g,span:s(o.start,o.end),isExported:m,modifiers:P,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)R.typeParameters=N;return R}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:m,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:m,modifiers:[]})}continue}let P=d?.name??"unknown",N="variable",R,L;if(S?.type==="FunctionExpression"||S?.type==="ArrowFunctionExpression")N="function",R=(S.params??[]).map(y),L=l(S.returnType);let B=[];g.push({kind:N,name:P,span:s(h.start,h.end),isExported:m,modifiers:B,parameters:R,returnType:L})}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:m,modifiers:[]};if(a==="TSInterfaceDeclaration"){let g=o.id?.name??"unknown",h=w(o),d=F(o.body?.body??[]),S=o.typeParameters?.params?.map((N)=>N.name?.name).filter(Boolean)||void 0,P={kind:"interface",name:g,span:s(o.start,o.end),isExported:m,modifiers:[],heritage:h.length>0?h:void 0,members:d.length>0?d:void 0};if(S&&S.length>0)P.typeParameters=S;return P}if(a==="TSEnumDeclaration"){let g=o.id?.name??"unknown",h=f(o),S=(o.body?.members??[]).map((P)=>({kind:"property",name:P.id?.name??P.id?.value??"unknown",span:s(P.start,P.end),isExported:!1,modifiers:[]}));return{kind:"enum",name:g,span:s(o.start,o.end),isExported:m,modifiers:h,members:S.length>0?S:void 0}}return null}let b=[];for(let o of t.body){let m=null,a=o,g=typeof a.type==="string"?a.type:"";if(g==="ExportNamedDeclaration"){let d=o;if(d.declaration){if(m=E(d.declaration,!0),m&&!Array.isArray(m))m.span=s(d.start,d.end);else if(Array.isArray(m))for(let S of m)S.span=s(d.start,d.end)}}else if(g==="ExportDefaultDeclaration"){let d=o,S=d.declaration;if(S){if(m=E(S,!0),m&&!Array.isArray(m))m.name=S.id?.name??"default",m.isExported=!0,m.span=s(d.start,d.end)}}else m=E(o,!1);let h=Array.isArray(m)?m:m?[m]:[];for(let d of h){let S=o.start??0,P=p(S);if(P){let N=Gn(P);if(!yt(N))d.jsDoc=N}b.push(d)}}return b}import{resolve as Sn,dirname as ht,extname as bt}from"path";function wn(n,t,e){let r=(i)=>{let s=bt(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=Sn(ht(n),t);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(t===i){let l=[];for(let c of s)l.push(...r(Sn(e.baseUrl,c)));return l}}else{let l=i.slice(0,p),c=i.slice(p+1);if(t.startsWith(l)&&(c===""||t.endsWith(c))){let y=t.slice(l.length,c===""?void 0:t.length-c.length),f=[];for(let x of s)f.push(...r(Sn(e.baseUrl,x.replace("*",y))));return f}}}return[]}function Bn(n,t,e,r=wn){let i=new Map,s=n.body??[];for(let p of s){if(p.type!=="ImportDeclaration")continue;let l=p.source?.value??"",c=r(t,l,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 xt=new Set(["loc","start","end","scope"]);function j(n,t){if(!n||typeof n!=="object")return;if(Array.isArray(n)){for(let r of n)j(r,t);return}let e=n;t(e);for(let r of Object.keys(e)){if(xt.has(r))continue;let i=e[r];if(i&&typeof i==="object")j(i,t)}}function Kn(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n;if((t.type==="StringLiteral"||t.type==="Literal")&&typeof t.value==="string")return t.value;return null}function X(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n;if(t.type==="Identifier"){let e=t.name;return{root:e,parts:[],full:e}}if(t.type==="ThisExpression")return{root:"this",parts:[],full:"this"};if(t.type==="Super")return{root:"super",parts:[],full:"super"};if(t.type==="MemberExpression"){let e=[],r=t;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 $n(n,t,e,r=wn){let i=[],s=n.body??[];for(let p of s){if(p.type==="ImportDeclaration"){let l=p.source?.value??"",c=r(t,l,e);if(c.length===0)continue;let y=c[0],f=p.importKind==="type";i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,...f?{metaJson:JSON.stringify({isType:!0})}:{}});continue}if(p.type==="ExportAllDeclaration"&&p.source){let l=p.source?.value??"",c=r(t,l,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:t,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,metaJson:JSON.stringify(x)});continue}if(p.type==="ExportNamedDeclaration"&&p.source){let l=p.source?.value??"",c=r(t,l,e);if(c.length===0)continue;let y=c[0];i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,metaJson:JSON.stringify({isReExport:!0})})}}return j(n,(p)=>{if(p.type!=="ImportExpression")return;let l=Kn(p.source);if(!l)return;let c=r(t,l,e);if(c.length===0)return;let y=c[0];i.push({type:"imports",srcFilePath:t,srcSymbolName:null,dstFilePath:y,dstSymbolName:null,metaJson:JSON.stringify({isDynamic:!0})})}),i}function Un(n,t,e){let r=[],i=[],s=[];function p(){if(i.length>0)return i[i.length-1]??null;return null}function l(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:t,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:t,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,A=w.id?.name??"AnonymousClass";s.push(A),c(w.body),s.pop();return}if(x==="FunctionDeclaration"){let w=f,A=w.id?.name??"anonymous";i.push(A),c(w.body),i.pop();return}if(x==="VariableDeclarator"&&f.init&&(f.init?.type==="FunctionExpression"||f.init?.type==="ArrowFunctionExpression")){let w=f,A=w.id?.name??"anonymous";i.push(A),c(w.init?.body??w.init),i.pop();return}if(x==="MethodDefinition"&&f.value){let w=f,A=s[s.length-1]??"",F=w.key?.name??"anonymous",E=A?`${A}.${F}`:F;i.push(E),c(w.value?.body),i.pop();return}if(x==="FunctionExpression"||x==="ArrowFunctionExpression"){let w=p(),A=w?`${w}.<anonymous>`:"<anonymous>";i.push(A),c(f.body),i.pop();return}if(x==="CallExpression"){let w=f,A=X(w.callee),F=l(A);if(F){let E=p(),b={};if(E===null)b.scope="module";r.push({type:"calls",srcFilePath:t,srcSymbolName:E,dstFilePath:F.dstFilePath,dstSymbolName:F.dstSymbolName,...Object.keys(b).length>0?{metaJson:JSON.stringify(b)}:{}})}c(w.callee);for(let E of w.arguments??[])c(E);return}if(x==="NewExpression"){let w=f,A=X(w.callee),F=l(A);if(F){let E=p(),b={isNew:!0};if(E===null)b.scope="module";r.push({type:"calls",srcFilePath:t,srcSymbolName:E,dstFilePath:F.dstFilePath,dstSymbolName:F.dstSymbolName,metaJson:JSON.stringify(b)})}for(let E of w.arguments??[])c(E);return}for(let w of Object.keys(f)){if(w==="loc"||w==="start"||w==="end"||w==="scope")continue;let A=f[w];if(A&&typeof A==="object")c(A)}}return c(n),r}function Vn(n,t,e){let r=[];return j(n,(i)=>{if(i.type==="TSInterfaceDeclaration"){let l=i.id?.name??"AnonymousInterface",c=i.extends??[];for(let y of c){let f=y.expression??y,x=X(f);if(!x)continue;let w=Nn(x,t,e);r.push({type:"extends",srcFilePath:t,srcSymbolName:l,...w})}return}if(i.type!=="ClassDeclaration"&&i.type!=="ClassExpression")return;let s=i.id?.name??"AnonymousClass";if(i.superClass){let l=X(i.superClass);if(l){let c=Nn(l,t,e);r.push({type:"extends",srcFilePath:t,srcSymbolName:s,...c})}}let p=i.implements??[];for(let l of p){let c=l.expression??l,y=X(c);if(!y)continue;let f=Nn(y,t,e);r.push({type:"implements",srcFilePath:t,srcSymbolName:s,...f})}}),r}function Nn(n,t,e){let r=e.get(n.root);if(r){if(r.importedName==="*"){let i=n.parts[n.parts.length-1]??n.root;return{dstFilePath:r.path,dstSymbolName:i,metaJson:JSON.stringify({isNamespaceImport:!0})}}return{dstFilePath:r.path,dstSymbolName:n.parts.length>0?n.full:r.importedName}}return{dstFilePath:t,dstSymbolName:n.full,metaJson:JSON.stringify({isLocal:!0})}}function mn(n,t,e){let r=Bn(n,t,e),i=$n(n,t,e),s=Un(n,t,r),p=Vn(n,t,r);return[...i,...s,...p]}import{err as Wn,isErr as At}from"@zipbul/result";import{Database as Pt}from"bun:sqlite";import{mkdirSync as Dt,unlinkSync as Hn,existsSync as Qn}from"fs";import{dirname as Et,join as Xn}from"path";import{drizzle as Tt}from"drizzle-orm/bun-sqlite";import{migrate as Ft}from"drizzle-orm/bun-sqlite/migrator";var An={};ut(An,{watcherOwner:()=>kt,symbols:()=>D,relations:()=>u,files:()=>I,FTS_SETUP_SQL:()=>kn});import{sql as St}from"drizzle-orm";import{sqliteTable as ln,text as C,integer as G,real as wt,index as Y,primaryKey as Nt,foreignKey as On,check as Ot}from"drizzle-orm/sqlite-core";var I=ln("files",{project:C("project").notNull(),filePath:C("file_path").notNull(),mtimeMs:wt("mtime_ms").notNull(),size:G("size").notNull(),contentHash:C("content_hash").notNull(),updatedAt:C("updated_at").notNull()},(n)=>[Nt({columns:[n.project,n.filePath]})]),D=ln("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()},(n)=>[Y("idx_symbols_project_file").on(n.project,n.filePath),Y("idx_symbols_project_kind").on(n.project,n.kind),Y("idx_symbols_project_name").on(n.project,n.name),Y("idx_symbols_fingerprint").on(n.project,n.fingerprint),On({columns:[n.project,n.filePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade")]),u=ln("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")},(n)=>[Y("idx_relations_src").on(n.project,n.srcFilePath),Y("idx_relations_dst").on(n.project,n.dstFilePath),Y("idx_relations_type").on(n.project,n.type),On({columns:[n.project,n.srcFilePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade"),On({columns:[n.project,n.dstFilePath],foreignColumns:[I.project,I.filePath]}).onDelete("cascade")]),kt=ln("watcher_owner",{id:G("id").primaryKey(),pid:G("pid").notNull(),startedAt:C("started_at").notNull(),heartbeatAt:C("heartbeat_at").notNull()},(n)=>[Ot("watcher_owner_singleton",St`${n.id} = 1`)]),kn=[`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 mn=Object.defineProperty;var un=(t,n)=>{for(var e in n)mn(t,e,{get:n[e],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 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};
|
|
23
|
+
END`];class Pn{client=null;drizzle=null;dbPath;txDepth=0;constructor(n){this.dbPath=Xn(n.projectRoot,".zipbul","gildash.db")}get drizzleDb(){if(!this.drizzle)throw Error("Database is not open. Call open() first.");return this.drizzle}open(){try{Dt(Et(this.dbPath),{recursive:!0}),this.client=new Pt(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=Tt(this.client,{schema:An}),Ft(this.drizzle,{migrationsFolder:Xn(import.meta.dirname,"migrations")});for(let n of kn)this.client.run(n)}catch(n){if(this.isCorruptionError(n)&&Qn(this.dbPath)){this.closeClient(),Hn(this.dbPath);for(let e of["-wal","-shm"]){let r=this.dbPath+e;if(Qn(r))Hn(r)}let t=this.open();if(At(t))return Wn(k("store",`Failed to recover database at ${this.dbPath}`,t.data));return t}return Wn(k("store",`Failed to open database at ${this.dbPath}`,n))}}close(){this.closeClient(),this.drizzle=null}transaction(n){let t=this.requireClient();if(this.txDepth===0){this.txDepth++;try{return t.transaction(()=>n(this))()}finally{this.txDepth--}}let e=`sp_${this.txDepth++}`;t.run(`SAVEPOINT "${e}"`);try{let r=n(this);return t.run(`RELEASE SAVEPOINT "${e}"`),r}catch(r){throw t.run(`ROLLBACK TO SAVEPOINT "${e}"`),t.run(`RELEASE SAVEPOINT "${e}"`),r}finally{this.txDepth--}}immediateTransaction(n){let t=this.requireClient();this.txDepth++,t.run("BEGIN IMMEDIATE");try{let e=n();return t.run("COMMIT"),e}catch(e){throw t.run("ROLLBACK"),e}finally{this.txDepth--}}query(n){let t=this.requireClient().prepare(n).get();if(!t)return null;return Object.values(t)[0]}getTableNames(){return this.requireClient().query("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((t)=>t.name)}selectOwner(){return this.requireClient().prepare("SELECT pid, heartbeat_at FROM watcher_owner WHERE id = 1").get()??void 0}insertOwner(n){let t=new Date().toISOString();this.requireClient().prepare("INSERT INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(n,t,t)}replaceOwner(n){let t=new Date().toISOString();this.requireClient().prepare("INSERT OR REPLACE INTO watcher_owner (id, pid, started_at, heartbeat_at) VALUES (1, ?, ?, ?)").run(n,t,t)}touchOwner(n){let t=new Date().toISOString();this.requireClient().prepare("UPDATE watcher_owner SET heartbeat_at = ? WHERE id = 1 AND pid = ?").run(t,n)}deleteOwner(n){this.requireClient().prepare("DELETE FROM watcher_owner WHERE id = 1 AND pid = ?").run(n)}requireClient(){if(!this.client)throw Error("Database is not open. Call open() first.");return this.client}closeClient(){if(this.client)this.client.close(),this.client=null}isCorruptionError(n){if(!(n instanceof Error))return!1;let t=n.message.toLowerCase();return t.includes("malformed")||t.includes("corrupt")||t.includes("not a database")||t.includes("disk i/o error")||t.includes("sqlite_corrupt")}}import{eq as sn,and as Yn}from"drizzle-orm";class Dn{db;constructor(n){this.db=n}getFile(n,t){return this.db.drizzleDb.select().from(I).where(Yn(sn(I.project,n),sn(I.filePath,t))).get()??null}upsertFile(n){this.db.drizzleDb.insert(I).values({project:n.project,filePath:n.filePath,mtimeMs:n.mtimeMs,size:n.size,contentHash:n.contentHash,updatedAt:n.updatedAt}).onConflictDoUpdate({target:[I.project,I.filePath],set:{mtimeMs:n.mtimeMs,size:n.size,contentHash:n.contentHash,updatedAt:n.updatedAt}}).run()}getAllFiles(n){return this.db.drizzleDb.select().from(I).where(sn(I.project,n)).all()}getFilesMap(n){let t=this.getAllFiles(n),e=new Map;for(let r of t)e.set(r.filePath,r);return e}deleteFile(n,t){this.db.drizzleDb.delete(I).where(Yn(sn(I.project,n),sn(I.filePath,t))).run()}}import{eq as M,and as Z,sql as En,count as Rt}from"drizzle-orm";function un(n){return n.trim().split(/\s+/).map((t)=>t.trim()).filter((t)=>t.length>0).map((t)=>`"${t.replaceAll('"','""')}"*`).join(" ")}class Tn{db;constructor(n){this.db=n}replaceFileSymbols(n,t,e,r){if(this.db.drizzleDb.delete(D).where(Z(M(D.project,n),M(D.filePath,t))).run(),!r.length)return;let i=new Date().toISOString();for(let s of r)this.db.drizzleDb.insert(D).values({project:n,filePath:t,kind:s.kind??"unknown",name:s.name??"",startLine:s.startLine??0,startColumn:s.startColumn??0,endLine:s.endLine??0,endColumn:s.endColumn??0,isExported:s.isExported??0,signature:s.signature??null,fingerprint:s.fingerprint??null,detailJson:s.detailJson??null,contentHash:e,indexedAt:s.indexedAt??i}).run()}getFileSymbols(n,t){return this.db.drizzleDb.select().from(D).where(Z(M(D.project,n),M(D.filePath,t))).all()}searchByName(n,t,e={}){let r=e.limit??50,i=un(t);if(!i)return[];return this.db.drizzleDb.select().from(D).where(Z(En`${D.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${i})`,M(D.project,n),e.kind?M(D.kind,e.kind):void 0)).orderBy(D.name).limit(r).all()}searchByKind(n,t){return this.db.drizzleDb.select().from(D).where(Z(M(D.project,n),M(D.kind,t))).orderBy(D.name).all()}getStats(n){let t=this.db.drizzleDb.select({symbolCount:Rt(),fileCount:En`COUNT(DISTINCT ${D.filePath})`}).from(D).where(M(D.project,n)).get();return{symbolCount:t?.symbolCount??0,fileCount:t?.fileCount??0}}getByFingerprint(n,t){return this.db.drizzleDb.select().from(D).where(Z(M(D.project,n),M(D.fingerprint,t))).all()}deleteFileSymbols(n,t){this.db.drizzleDb.delete(D).where(Z(M(D.project,n),M(D.filePath,t))).run()}searchByQuery(n){return this.db.drizzleDb.select().from(D).where(Z(n.ftsQuery?En`${D.id} IN (SELECT rowid FROM symbols_fts WHERE symbols_fts MATCH ${n.ftsQuery})`:void 0,n.exactName?M(D.name,n.exactName):void 0,n.project!==void 0?M(D.project,n.project):void 0,n.kind?M(D.kind,n.kind):void 0,n.filePath!==void 0?M(D.filePath,n.filePath):void 0,n.isExported!==void 0?M(D.isExported,n.isExported?1:0):void 0)).orderBy(D.name).limit(n.limit).all()}}import{eq as _,and as K,isNull as Zn,or as _t}from"drizzle-orm";class Fn{db;constructor(n){this.db=n}replaceFileRelations(n,t,e){if(this.db.drizzleDb.delete(u).where(K(_(u.project,n),_(u.srcFilePath,t))).run(),!e.length)return;for(let r of e)this.db.drizzleDb.insert(u).values({project:n,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(n,t,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(_(u.project,n),_(u.srcFilePath,t),_t(_(u.srcSymbolName,e),Zn(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(_(u.project,n),_(u.srcFilePath,t))).all()}getIncoming(n,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(_(u.project,n),_(u.dstFilePath,t))).all()}getByType(n,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(_(u.project,n),_(u.type,t))).all()}deleteFileRelations(n,t){this.db.drizzleDb.delete(u).where(K(_(u.project,n),_(u.srcFilePath,t))).run()}searchRelations(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(n.project!==void 0?_(u.project,n.project):void 0,n.srcFilePath!==void 0?_(u.srcFilePath,n.srcFilePath):void 0,n.srcSymbolName!==void 0?_(u.srcSymbolName,n.srcSymbolName):void 0,n.dstFilePath!==void 0?_(u.dstFilePath,n.dstFilePath):void 0,n.dstSymbolName!==void 0?_(u.dstSymbolName,n.dstSymbolName):void 0,n.type!==void 0?_(u.type,n.type):void 0)).limit(n.limit).all()}retargetRelations(n,t,e,r,i){let s=e===null?K(_(u.project,n),_(u.dstFilePath,t),Zn(u.dstSymbolName)):K(_(u.project,n),_(u.dstFilePath,t),_(u.dstSymbolName,e));this.db.drizzleDb.update(u).set({dstFilePath:r,dstSymbolName:i}).where(s).run()}}import{err as jn}from"@zipbul/result";import{subscribe as Ct}from"@parcel/watcher";import Rn from"path";var It=["**/.git/**","**/.zipbul/**","**/dist/**","**/node_modules/**"],vt=new Set(["package.json","tsconfig.json"]);function Mt(n){return n.replaceAll("\\","/")}function Lt(n){if(n==="update")return"change";if(n==="create")return"create";return"delete"}class pn{#t;#n;#r;#i;#s;#e;constructor(n,t=Ct,e=console){this.#n=n.projectRoot,this.#r=[...It,...n.ignorePatterns??[]],this.#i=new Set((n.extensions??[".ts",".mts",".cts"]).map((r)=>r.toLowerCase())),this.#s=t,this.#e=e}async start(n){try{this.#t=await this.#s(this.#n,(t,e)=>{if(t){this.#e.error(k("watcher","Callback error",t));return}try{for(let r of e){let i=Mt(Rn.relative(this.#n,r.path));if(i.startsWith(".."))continue;let s=Rn.basename(i),p=Rn.extname(i).toLowerCase();if(!vt.has(s)&&!this.#i.has(p))continue;if(i.endsWith(".d.ts"))continue;n({eventType:Lt(r.type),filePath:i})}}catch(r){this.#e.error(k("watcher","Callback error",r))}},{ignore:this.#r})}catch(t){return jn(k("watcher","Failed to subscribe watcher",t))}}async close(){if(!this.#t)return;try{await this.#t.unsubscribe(),this.#t=void 0}catch(n){return jn(k("watcher","Failed to close watcher",n))}}}import _n from"path";import{promises as Jt}from"fs";var zt=["**/node_modules/**","**/.git/**","**/.zipbul/**","**/dist/**"];async function dn(n){let t=[];for await(let e of Jt.glob("**/package.json",{cwd:n,exclude:zt})){let r=_n.dirname(e).replaceAll("\\","/"),i=_n.join(n,e),s=await Bun.file(i).json(),p=typeof s?.name==="string"&&s.name.length>0?s.name:_n.basename(r==="."?n:r);t.push({dir:r,project:p})}return t.sort((e,r)=>r.dir.length-e.dir.length),t}function q(n,t,e="default"){let r=n.replaceAll("\\","/");for(let i of t){if(i.dir===".")return i.project;if(r===i.dir||r.startsWith(`${i.dir}/`))return i.project}return e}import qn from"path";var U=new Map;async function Gt(n){let t=Bun.file(n);if(!await t.exists())return null;let e=await t.json();return typeof e==="object"&&e!==null?e:null}async function on(n){if(U.has(n))return U.get(n)??null;let t=qn.join(n,"tsconfig.json"),e=await Gt(t);if(!e)return U.set(n,null),null;let r=typeof e.compilerOptions==="object"&&e.compilerOptions!==null?e.compilerOptions:null;if(!r)return U.set(n,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(n,null),null;let p=i?qn.resolve(n,i):n,l=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");l.set(y,x)}let c={baseUrl:p,paths:l};return U.set(n,c),c}function fn(n){if(n){U.delete(n);return}U.clear()}import nt from"path";function Cn(n,t){return nt.relative(n,t).replaceAll("\\","/")}function nn(n,t){return nt.resolve(n,t)}function V(n){let t=Bun.hash.xxHash64(n);return BigInt.asUintN(64,BigInt(t)).toString(16).padStart(16,"0")}import{isErr as rt}from"@zipbul/result";import{promises as Bt}from"fs";import{join as Kt}from"path";async function tt(n){let{projectRoot:t,extensions:e,ignorePatterns:r,fileRepo:i}=n,s=i.getFilesMap(),p=new Set,l=[],c=[],y=r.map((x)=>new Bun.Glob(x));for await(let x of Bt.glob("**/*",{cwd:t})){if(!e.some((a)=>x.endsWith(a)))continue;if(y.some((a)=>a.match(x)))continue;p.add(x);let w=Kt(t,x),A=Bun.file(w),{size:F,lastModified:E}=A,b=s.get(x);if(!b){let a=await A.text(),g=V(a);l.push({filePath:x,contentHash:g,mtimeMs:E,size:F});continue}if(b.mtimeMs===E&&b.size===F){c.push({filePath:x,contentHash:b.contentHash,mtimeMs:E,size:F});continue}let o=await A.text(),m=V(o);if(m===b.contentHash)c.push({filePath:x,contentHash:m,mtimeMs:E,size:F});else l.push({filePath:x,contentHash:m,mtimeMs:E,size:F})}let f=[];for(let x of s.keys())if(!p.has(x))f.push(x);return{changed:l,unchanged:c,deleted:f}}function $t(n){if(n.kind==="function"||n.kind==="method"){let t=n.parameters?.length??0,e=n.modifiers.includes("async")?1:0;return`params:${t}|async:${e}`}return null}function Ut(n){let t={};if(n.jsDoc)t.jsDoc=n.jsDoc;if(n.kind==="function"||n.kind==="method"){if(n.parameters!==void 0)t.parameters=n.parameters;if(n.returnType!==void 0)t.returnType=n.returnType}if(n.heritage?.length)t.heritage=n.heritage;if(n.decorators?.length)t.decorators=n.decorators;if(n.typeParameters?.length)t.typeParameters=n.typeParameters;if(n.modifiers?.length)t.modifiers=n.modifiers;if(n.members?.length)t.members=n.members.map((e)=>e.name);return Object.keys(t).length>0?JSON.stringify(t):null}function et(n,t,e,r,i){let s=$t(n),p=V(`${t}|${n.kind}|${s??""}`);return{project:e,filePath:r,kind:n.kind,name:t,startLine:n.span.start.line,startColumn:n.span.start.column,endLine:n.span.end.line,endColumn:n.span.end.column,isExported:n.isExported?1:0,signature:s,fingerprint:p,detailJson:Ut(n),contentHash:i,indexedAt:new Date().toISOString()}}function In(n){let{parsed:t,project:e,filePath:r,contentHash:i,symbolRepo:s}=n,p=cn(t),l=[];for(let c of p){l.push(et(c,c.name,e,r,i));for(let y of c.members??[])l.push(et(y,`${c.name}.${y.name}`,e,r,i))}s.replaceFileSymbols(e,r,i,l)}function vn(n){let{ast:t,project:e,filePath:r,relationRepo:i,projectRoot:s,tsconfigPaths:p}=n,l=nn(s,r),c=mn(t,l,p),y=[];for(let f of c){let x=Cn(s,f.dstFilePath);if(x.startsWith(".."))continue;let w=Cn(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 Vt=100;class gn{opts;logger;callbacks=new Set;indexingLock=!1;pendingEvents=[];debounceTimer=null;currentIndexing=null;pendingFullIndex=!1;pendingFullIndexWaiters=[];tsconfigPathsRaw;boundariesRefresh=null;constructor(n){this.opts=n,this.logger=n.logger??console,this.tsconfigPathsRaw=on(n.projectRoot)}get tsconfigPaths(){return this.tsconfigPathsRaw}fullIndex(){return this.startIndex(void 0,!0)}incrementalIndex(n){return this.startIndex(n,!1)}onIndexed(n){return this.callbacks.add(n),()=>this.callbacks.delete(n)}handleWatcherEvent(n){if(n.filePath.endsWith("tsconfig.json")){fn(this.opts.projectRoot),this.tsconfigPathsRaw=on(this.opts.projectRoot),this.fullIndex().catch((t)=>{this.logger.error("[IndexCoordinator] fullIndex failed after tsconfig change:",t)});return}if(n.filePath.endsWith("package.json")){let t=this.opts.discoverProjectsFn??dn;this.boundariesRefresh=t(this.opts.projectRoot).then((e)=>{this.opts.boundaries=e})}if(this.pendingEvents.push(n),this.debounceTimer===null)this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.flushPending()},Vt)}async shutdown(){if(this.debounceTimer!==null)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.currentIndexing)await this.currentIndexing}startIndex(n,t){if(this.indexingLock){if(t)return this.pendingFullIndex=!0,new Promise((r,i)=>{this.pendingFullIndexWaiters.push({resolve:r,reject:i})});return this.currentIndexing}this.indexingLock=!0;let e=this.doIndex(n,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=e,e}async doIndex(n,t){let e=Date.now(),{fileRepo:r,symbolRepo:i,relationRepo:s,dbConnection:p}=this.opts;if(this.boundariesRefresh)await this.boundariesRefresh,this.boundariesRefresh=null;let l,c;if(n!==void 0)l=n.filter((b)=>b.eventType==="create"||b.eventType==="change").map((b)=>({filePath:b.filePath,contentHash:"",mtimeMs:0,size:0})),c=n.filter((b)=>b.eventType==="delete").map((b)=>b.filePath);else{let b=new Map;for(let m of this.opts.boundaries)for(let[a,g]of r.getFilesMap(m.project))b.set(a,g);let o=await tt({projectRoot:this.opts.projectRoot,extensions:this.opts.extensions,ignorePatterns:this.opts.ignorePatterns,fileRepo:{getFilesMap:()=>b}});l=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),m=i.getFileSymbols(o,b);f.set(b,m)}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,m=[];for(let a of l)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),m.push(a.filePath)}return{symbols:b,relations:o,failedFiles:m}},A=0,F=0,E=[];if(t){let{projectRoot:b,boundaries:o}=this.opts,{parseCache:m}=this.opts,a=await Promise.allSettled(l.map(async(d)=>{let S=nn(b,d.filePath),P=Bun.file(S),N=await P.text(),R=d.contentHash||V(N);return{filePath:d.filePath,text:N,contentHash:R,mtimeMs:P.lastModified,size:P.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 P=r.getAllFiles(S.project);for(let N of P)r.deleteFile(N.project,N.filePath)}let d=this.opts.parseSourceFn??rn;for(let S of g){let P=q(S.filePath,o),N=d(nn(b,S.filePath),S.text);if(rt(N))throw N.data;let R=N;h.push({filePath:S.filePath,parsed:R}),r.upsertFile({project:P,filePath:S.filePath,mtimeMs:S.mtimeMs,size:S.size,contentHash:S.contentHash,updatedAt:new Date().toISOString()}),In({parsed:R,project:P,filePath:S.filePath,contentHash:S.contentHash,symbolRepo:i}),F+=vn({ast:R.program,project:P,filePath:S.filePath,relationRepo:s,projectRoot:b,tsconfigPaths:y}),A+=i.getFileSymbols(P,S.filePath).length}});for(let d of h)m.set(d.filePath,d.parsed)}else{x();let b=await w();A=b.symbols,F=b.relations,E=b.failedFiles}if(!t)for(let[b,o]of f)for(let m of o){if(!m.fingerprint)continue;let a=q(b,this.opts.boundaries),g=i.getByFingerprint(a,m.fingerprint);if(g.length===1){let h=g[0];s.retargetRelations(a,b,m.name,h.filePath,h.name)}}return{indexedFiles:l.length,removedFiles:c.length,totalSymbols:A,totalRelations:F,durationMs:Date.now()-e,changedFiles:l.map((b)=>b.filePath),deletedFiles:[...c],failedFiles:E}}async processFile(n,t,e){let{projectRoot:r,boundaries:i}=this.opts,{fileRepo:s,symbolRepo:p,relationRepo:l,parseCache:c}=this.opts,y=nn(r,n),f=Bun.file(y),x=await f.text(),w=t||V(x),A=q(n,i),E=(this.opts.parseSourceFn??rn)(y,x);if(rt(E))throw E.data;let b=E;c.set(n,b),s.upsertFile({project:A,filePath:n,mtimeMs:f.lastModified,size:f.size,contentHash:w,updatedAt:new Date().toISOString()}),In({parsed:b,project:A,filePath:n,contentHash:w,symbolRepo:p});let o=vn({ast:b.program,project:A,filePath:n,relationRepo:l,projectRoot:r,tsconfigPaths:e});return{symbolCount:p.getFileSymbols(A,n).length,relCount:o}}fireCallbacks(n){for(let t of this.callbacks)try{t(n)}catch(e){this.logger.error("[IndexCoordinator] onIndexed callback threw:",e)}}flushPending(){if(this.indexingLock)return;if(this.pendingEvents.length>0){let n=this.pendingEvents.splice(0);this.startIndex(n,!1).catch((t)=>this.logger.error("[IndexCoordinator] flushPending startIndex error:",t))}}}function Wt(n){try{return process.kill(n,0),!0}catch(t){if(typeof t==="object"&&t&&"code"in t)return t.code!=="ESRCH";return!0}}function Ht(n){let t=new Date(n).getTime();return Number.isNaN(t)?0:t}function it(n,t,e={}){let r=e.now??Date.now,i=e.isAlive??Wt,s=e.staleAfterSeconds??90;return n.immediateTransaction(()=>{let p=n.selectOwner();if(!p)return n.insertOwner(t),"owner";let l=Math.floor((r()-Ht(p.heartbeat_at))/1000);if(i(p.pid)&&l<s)return"reader";return n.replaceOwner(t),"owner"})}function st(n,t){n.deleteOwner(t)}function ot(n,t){n.touchOwner(t)}function Mn(n){let{symbolRepo:t,project:e,query:r}=n,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)if(r.exact)p.exactName=r.text;else{let c=un(r.text);if(c)p.ftsQuery=c}return t.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 Ln(n){let{relationRepo:t,project:e,query:r}=n,i=r.project??e,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((l)=>({type:l.type,srcFilePath:l.srcFilePath,srcSymbolName:l.srcSymbolName,dstFilePath:l.dstFilePath,dstSymbolName:l.dstSymbolName,metaJson:l.metaJson??void 0}))}class an{options;adjacencyList=new Map;reverseAdjacencyList=new Map;constructor(n){this.options=n}build(){this.adjacencyList=new Map,this.reverseAdjacencyList=new Map;let n=this.options.relationRepo.getByType(this.options.project,"imports");for(let t of n){let{srcFilePath:e,dstFilePath:r}=t;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(n){return Array.from(this.adjacencyList.get(n)??[])}getDependents(n){return Array.from(this.reverseAdjacencyList.get(n)??[])}getTransitiveDependents(n){let t=new Set,e=[n];while(e.length>0){let r=e.shift();for(let i of this.reverseAdjacencyList.get(r)??[])if(!t.has(i))t.add(i),e.push(i)}return Array.from(t)}hasCycle(){let n=new Set,t=new Set;for(let e of this.adjacencyList.keys()){if(n.has(e))continue;let r=[{node:e,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(n.has(i.node))continue;n.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(!n.has(s))r.push({node:s,entered:!1})}}}return!1}getAffectedByChange(n){let t=new Set;for(let e of n)for(let r of this.getTransitiveDependents(e))t.add(r);return Array.from(t)}}var ct=30000,mt=60000,Xt=10;class Jn{projectRoot;db;symbolRepo;relationRepo;fileRepo;parseCache;coordinator;watcher;releaseWatcherRoleFn;parseSourceFn;extractSymbolsFn;extractRelationsFn;symbolSearchFn;relationSearchFn;logger;defaultProject;role;timer=null;signalHandlers=[];closed=!1;tsconfigPaths=null;boundaries=[];onIndexedCallbacks=new Set;constructor(n){this.projectRoot=n.projectRoot,this.db=n.db,this.symbolRepo=n.symbolRepo,this.relationRepo=n.relationRepo,this.fileRepo=n.fileRepo,this.parseCache=n.parseCache,this.coordinator=n.coordinator,this.watcher=n.watcher,this.releaseWatcherRoleFn=n.releaseWatcherRoleFn,this.parseSourceFn=n.parseSourceFn,this.extractSymbolsFn=n.extractSymbolsFn,this.extractRelationsFn=n.extractRelationsFn,this.symbolSearchFn=n.symbolSearchFn,this.relationSearchFn=n.relationSearchFn,this.logger=n.logger,this.defaultProject=n.defaultProject,this.role=n.role}static async open(n){let{projectRoot:t,extensions:e=[".ts",".mts",".cts"],ignorePatterns:r=[],parseCacheCapacity:i=500,logger:s=console,existsSyncFn:p=Qt,dbConnectionFactory:l,watcherFactory:c,coordinatorFactory:y,repositoryFactory:f,acquireWatcherRoleFn:x=it,releaseWatcherRoleFn:w=st,updateHeartbeatFn:A=ot,discoverProjectsFn:F=dn,parseSourceFn:E=rn,extractSymbolsFn:b=cn,extractRelationsFn:o=mn,symbolSearchFn:m=Mn,relationSearchFn:a=Ln,loadTsconfigPathsFn:g=on}=n;if(!at.isAbsolute(t))return T(k("validation",`Gildash: projectRoot must be an absolute path, got: "${t}"`));if(!p(t))return T(k("validation",`Gildash: projectRoot does not exist: "${t}"`));let h=l?l():new Pn({projectRoot:t}),d=h.open();if(tn(d))return d;try{let S=await F(t),P=S[0]?.project??at.basename(t),N=f?f():(()=>{let v=h;return{fileRepo:new Dn(v),symbolRepo:new Tn(v),relationRepo:new Fn(v),parseCache:new bn(i)}})(),R=await Promise.resolve(x(h,process.pid,{})),L=null,B=null,O=new Jn({projectRoot:t,db:h,symbolRepo:N.symbolRepo,relationRepo:N.relationRepo,fileRepo:N.fileRepo,parseCache:N.parseCache,coordinator:L,watcher:B,releaseWatcherRoleFn:w,parseSourceFn:E,extractSymbolsFn:b,extractRelationsFn:o,symbolSearchFn:m,relationSearchFn:a,logger:s,defaultProject:P,role:R});if(fn(t),O.tsconfigPaths=await g(t),O.boundaries=S,R==="owner"){let v=c?c():new pn({projectRoot:t,ignorePatterns:r,extensions:e},void 0,s),J=y?y():new gn({projectRoot:t,boundaries:S,extensions:e,ignorePatterns:r,dbConnection:h,parseCache:N.parseCache,fileRepo:N.fileRepo,symbolRepo:N.symbolRepo,relationRepo:N.relationRepo,logger:s});O.coordinator=J,O.watcher=v,await v.start(($)=>J.handleWatcherEvent?.($)).then(($)=>{if(tn($))throw $.data});let en=setInterval(()=>{A(h,process.pid)},ct);O.timer=en,await J.fullIndex()}else{let v=0,J=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 pn({projectRoot:t,ignorePatterns:r,extensions:e},void 0,s),Q=y?y():new gn({projectRoot:t,boundaries:S,extensions:e,ignorePatterns:r,dbConnection:h,parseCache:N.parseCache,fileRepo:N.fileRepo,symbolRepo:N.symbolRepo,relationRepo:N.relationRepo,logger:s});for(let z of O.onIndexedCallbacks)Q.onIndexed(z);await H.start((z)=>Q?.handleWatcherEvent?.(z)).then((z)=>{if(tn(z))throw z.data});let yn=setInterval(()=>{A(h,process.pid)},ct);O.timer=yn,O.coordinator=Q,O.watcher=H,await Q.fullIndex()}catch(yn){if(s.error("[Gildash] owner promotion failed, reverting to reader",yn),H){let z=await H.close();if(tn(z))s.error("[Gildash] watcher close error during promotion rollback",z.data);O.watcher=null}if(Q)await Q.shutdown().catch((z)=>s.error("[Gildash] coordinator shutdown error during promotion rollback",z)),O.coordinator=null;if(O.timer===null)O.timer=setInterval(J,mt)}}}catch($){if(v++,s.error("[Gildash] healthcheck error",$),v>=Xt)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))}},en=setInterval(J,mt);O.timer=en}let W=["SIGTERM","SIGINT","beforeExit"];for(let v of W){let J=()=>{O.close().catch((en)=>s.error("[Gildash] close error during signal",v,en))};if(v==="beforeExit")process.on("beforeExit",J);else process.on(v,J);O.signalHandlers.push([v,J])}return O}catch(S){return h.close(),T(k("store","Gildash: initialization failed",S))}}async close(){if(this.closed)return;this.closed=!0;let n=[];for(let[t,e]of this.signalHandlers)if(t==="beforeExit")process.off("beforeExit",e);else process.off(t,e);if(this.signalHandlers=[],this.coordinator)try{await this.coordinator.shutdown()}catch(t){n.push(t instanceof Error?t:Error(String(t)))}if(this.watcher){let t=await this.watcher.close();if(tn(t))n.push(t.data)}if(this.timer!==null)clearInterval(this.timer),this.timer=null;try{this.releaseWatcherRoleFn(this.db,process.pid)}catch(t){n.push(t instanceof Error?t:Error(String(t)))}try{this.db.close()}catch(t){n.push(t instanceof Error?t:Error(String(t)))}if(n.length>0)return T(k("close","Gildash: one or more errors occurred during close()",n))}onIndexed(n){if(this.onIndexedCallbacks.add(n),!this.coordinator)return()=>{this.onIndexedCallbacks.delete(n)};let t=this.coordinator.onIndexed(n);return()=>{this.onIndexedCallbacks.delete(n),t()}}parseSource(n,t){if(this.closed)return T(k("closed","Gildash: instance is closed"));let e=this.parseSourceFn(n,t);if(tn(e))return e;return this.parseCache.set(n,e),e}extractSymbols(n){if(this.closed)return T(k("closed","Gildash: instance is closed"));return this.extractSymbolsFn(n)}extractRelations(n){if(this.closed)return T(k("closed","Gildash: instance is closed"));return this.extractRelationsFn(n.program,n.filePath,this.tsconfigPaths??void 0)}async reindex(){if(this.closed)return T(k("closed","Gildash: instance is closed"));if(!this.coordinator)return T(k("closed","Gildash: reindex() is not available for readers"));try{return await this.coordinator.fullIndex()}catch(n){return T(k("index","Gildash: reindex failed",n))}}get projects(){return[...this.boundaries]}getStats(n){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{return this.symbolRepo.getStats(n??this.defaultProject)}catch(t){return T(k("store","Gildash: getStats failed",t))}}searchSymbols(n){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{return this.symbolSearchFn({symbolRepo:this.symbolRepo,project:this.defaultProject,query:n})}catch(t){return T(k("search","Gildash: searchSymbols failed",t))}}searchRelations(n){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:this.defaultProject,query:n})}catch(t){return T(k("search","Gildash: searchRelations failed",t))}}getDependencies(n,t,e=1e4){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{srcFilePath:n,type:"imports",project:t??this.defaultProject,limit:e}}).map((r)=>r.dstFilePath)}catch(r){return T(k("search","Gildash: getDependencies failed",r))}}getDependents(n,t,e=1e4){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{return this.relationSearchFn({relationRepo:this.relationRepo,project:t??this.defaultProject,query:{dstFilePath:n,type:"imports",project:t??this.defaultProject,limit:e}}).map((r)=>r.srcFilePath)}catch(r){return T(k("search","Gildash: getDependents failed",r))}}async getAffected(n,t){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{let e=new an({relationRepo:this.relationRepo,project:t??this.defaultProject});return await e.build(),e.getAffectedByChange(n)}catch(e){return T(k("search","Gildash: getAffected failed",e))}}async hasCycle(n){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{let t=new an({relationRepo:this.relationRepo,project:n??this.defaultProject});return await t.build(),t.hasCycle()}catch(t){return T(k("search","Gildash: hasCycle failed",t))}}getParsedAst(n){if(this.closed)return;return this.parseCache.get(n)}getFileInfo(n,t){if(this.closed)return T(k("closed","Gildash: instance is closed"));try{return this.fileRepo.getFile(t??this.defaultProject,n)}catch(e){return T(k("store","Gildash: getFileInfo failed",e))}}getSymbolsByFile(n,t){return this.searchSymbols({filePath:n,project:t??void 0,limit:1e4})}}export{Mn as symbolSearch,Ln as relationSearch,k as gildashError,Jn as Gildash,an as DependencyGraph};
|
|
24
24
|
|
|
25
|
-
//# debugId=
|
|
25
|
+
//# debugId=FFD967C0260E6D8A64756E2164756E21
|
|
26
26
|
//# sourceMappingURL=index.js.map
|