scip-query 0.5.0 → 0.6.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.
Files changed (199) hide show
  1. package/dist/chunk-2DSS2NGF.js +10 -0
  2. package/dist/chunk-2RLP74AO.js +2 -0
  3. package/dist/chunk-4QJ7LVW5.js +2 -0
  4. package/dist/chunk-4TYGGOLO.js +5 -0
  5. package/dist/chunk-5IADAU5B.js +7 -0
  6. package/dist/chunk-7754WFFV.js +18 -0
  7. package/dist/chunk-7VOF4ZG6.js +2 -0
  8. package/dist/chunk-7Z4COVMC.js +2 -0
  9. package/dist/chunk-AJ5PWKD4.js +2 -0
  10. package/dist/chunk-BDBRZPX3.js +7 -0
  11. package/dist/chunk-BE6EQIWY.js +2 -0
  12. package/dist/chunk-BQ3INTYT.js +8 -0
  13. package/dist/chunk-D7KLLMPB.js +2 -0
  14. package/dist/chunk-D7YBWSON.js +29 -0
  15. package/dist/chunk-DE5ZBHMK.js +39 -0
  16. package/dist/chunk-DHYIJHXZ.js +33 -0
  17. package/dist/chunk-EEF3YEHW.js +2 -0
  18. package/dist/chunk-F2LLHRRZ.js +2 -0
  19. package/dist/chunk-FCC3XJTI.js +2 -0
  20. package/dist/chunk-GNXRLK5G.js +2 -0
  21. package/dist/chunk-GXVB36TG.js +62 -0
  22. package/dist/chunk-HMKJTAZD.js +2 -0
  23. package/dist/chunk-IBGBI3VU.js +2 -0
  24. package/dist/chunk-IYFZS4PV.js +84 -0
  25. package/dist/chunk-JH3A7HTU.js +2 -0
  26. package/dist/chunk-JS2RNIC7.js +2 -0
  27. package/dist/chunk-K5FQFCSN.js +41 -0
  28. package/dist/chunk-K6GBKEQE.js +6 -0
  29. package/dist/chunk-KO7YJRWP.js +12 -0
  30. package/dist/chunk-KYT47WU2.js +4 -0
  31. package/dist/chunk-LORWXBOO.js +2 -0
  32. package/dist/chunk-LX4H4LLG.js +89 -0
  33. package/dist/chunk-N3Z2SJCR.js +2 -0
  34. package/dist/chunk-NTDA4A2D.js +25 -0
  35. package/dist/chunk-NXMYYHDO.js +24 -0
  36. package/dist/chunk-PZ6ESKRH.js +7 -0
  37. package/dist/chunk-QXE6EDY2.js +6 -0
  38. package/dist/chunk-RJ7SPBJ5.js +5 -0
  39. package/dist/chunk-RWE6FHG3.js +3 -0
  40. package/dist/chunk-SDX6MDBL.js +2 -0
  41. package/dist/chunk-SG35Y7J2.js +2 -0
  42. package/dist/chunk-STOGKRJH.js +4 -0
  43. package/dist/chunk-TINPMWJK.js +2 -0
  44. package/dist/chunk-UJB62HV3.js +2 -0
  45. package/dist/chunk-VEUMRDHW.js +2 -0
  46. package/dist/chunk-WCDXJGYT.js +65 -0
  47. package/dist/chunk-WTSTDJZ7.js +6 -0
  48. package/dist/chunk-XAZTIDST.js +2 -0
  49. package/dist/chunk-XVDASCN7.js +35 -0
  50. package/dist/chunk-Y7H6D2EV.js +2 -0
  51. package/dist/chunk-Y7LOQSWY.js +2 -0
  52. package/dist/chunk-YIPCV7M7.js +70 -0
  53. package/dist/chunk-ZSRXMNMK.js +5 -0
  54. package/dist/chunk-ZXKURFVB.js +56 -0
  55. package/dist/cli.js +509 -8758
  56. package/dist/{db-6F9R9e_t.d.ts → db-BSTtBG_H.d.ts} +146 -1
  57. package/dist/index.d.ts +11 -2
  58. package/dist/index.js +13 -1616
  59. package/dist/postinstall.js +4 -100
  60. package/dist/queries/affected.d.ts +1 -1
  61. package/dist/queries/affected.js +1 -8
  62. package/dist/queries/bottlenecks.d.ts +1 -1
  63. package/dist/queries/bottlenecks.js +1 -8
  64. package/dist/queries/by-kind.d.ts +1 -4
  65. package/dist/queries/by-kind.js +1 -10
  66. package/dist/queries/call-graph.d.ts +1 -1
  67. package/dist/queries/call-graph.js +1 -8
  68. package/dist/queries/change-surface.d.ts +1 -1
  69. package/dist/queries/change-surface.js +1 -8
  70. package/dist/queries/code.d.ts +1 -1
  71. package/dist/queries/code.js +1 -8
  72. package/dist/queries/complexity-hotspots.d.ts +5 -10
  73. package/dist/queries/complexity-hotspots.js +1 -8
  74. package/dist/queries/complexity.d.ts +1 -1
  75. package/dist/queries/complexity.js +1 -8
  76. package/dist/queries/convergence.d.ts +1 -1
  77. package/dist/queries/convergence.js +1 -8
  78. package/dist/queries/coupling.d.ts +1 -1
  79. package/dist/queries/coupling.js +1 -10
  80. package/dist/queries/cycles.d.ts +1 -1
  81. package/dist/queries/cycles.js +1 -8
  82. package/dist/queries/dataflow.d.ts +1 -1
  83. package/dist/queries/dataflow.js +1 -8
  84. package/dist/queries/dead.d.ts +1 -1
  85. package/dist/queries/dead.js +1 -9
  86. package/dist/queries/deep-chains.d.ts +9 -1
  87. package/dist/queries/deep-chains.js +1 -8
  88. package/dist/queries/deps.d.ts +1 -1
  89. package/dist/queries/deps.js +1 -10
  90. package/dist/queries/diff-impact.d.ts +1 -1
  91. package/dist/queries/diff-impact.js +1 -7
  92. package/dist/queries/drift.d.ts +1 -1
  93. package/dist/queries/drift.js +1 -8
  94. package/dist/queries/extract-candidates.d.ts +1 -1
  95. package/dist/queries/extract-candidates.js +1 -8
  96. package/dist/queries/fan.d.ts +1 -1
  97. package/dist/queries/fan.js +1 -14
  98. package/dist/queries/files.d.ts +1 -1
  99. package/dist/queries/files.js +1 -6
  100. package/dist/queries/health.d.ts +1 -1
  101. package/dist/queries/health.js +1 -20
  102. package/dist/queries/hierarchy.d.ts +1 -1
  103. package/dist/queries/hierarchy.js +1 -8
  104. package/dist/queries/hotspots.d.ts +1 -1
  105. package/dist/queries/hotspots.js +1 -8
  106. package/dist/queries/imports.d.ts +1 -1
  107. package/dist/queries/imports.js +1 -12
  108. package/dist/queries/index.d.ts +1 -1
  109. package/dist/queries/index.js +1 -197
  110. package/dist/queries/isolated.d.ts +1 -1
  111. package/dist/queries/isolated.js +1 -9
  112. package/dist/queries/members.d.ts +1 -1
  113. package/dist/queries/members.js +1 -8
  114. package/dist/queries/methods.d.ts +1 -1
  115. package/dist/queries/methods.js +1 -8
  116. package/dist/queries/outline.d.ts +1 -1
  117. package/dist/queries/outline.js +1 -8
  118. package/dist/queries/passthrough-candidates.d.ts +1 -1
  119. package/dist/queries/passthrough-candidates.js +1 -8
  120. package/dist/queries/redundant-reexports.d.ts +1 -1
  121. package/dist/queries/redundant-reexports.js +1 -9
  122. package/dist/queries/refs.d.ts +1 -1
  123. package/dist/queries/refs.js +1 -8
  124. package/dist/queries/similar-chains.d.ts +1 -1
  125. package/dist/queries/similar-chains.js +1 -8
  126. package/dist/queries/similar-files.d.ts +1 -1
  127. package/dist/queries/similar-files.js +1 -8
  128. package/dist/queries/similar-signatures.d.ts +1 -1
  129. package/dist/queries/similar-signatures.js +1 -8
  130. package/dist/queries/similar.d.ts +1 -1
  131. package/dist/queries/similar.js +1 -10
  132. package/dist/queries/slice.d.ts +1 -1
  133. package/dist/queries/slice.js +1 -8
  134. package/dist/queries/stale-abstractions.d.ts +15 -5
  135. package/dist/queries/stale-abstractions.js +1 -8
  136. package/dist/queries/stats.d.ts +1 -1
  137. package/dist/queries/stats.js +1 -6
  138. package/dist/queries/surface.d.ts +1 -1
  139. package/dist/queries/surface.js +1 -8
  140. package/dist/queries/symbols.d.ts +1 -1
  141. package/dist/queries/symbols.js +1 -9
  142. package/dist/queries/system.d.ts +1 -1
  143. package/dist/queries/system.js +1 -9
  144. package/dist/queries/trace.d.ts +1 -1
  145. package/dist/queries/trace.js +1 -9
  146. package/dist/queries/wrapper-candidates.d.ts +1 -1
  147. package/dist/queries/wrapper-candidates.js +1 -8
  148. package/dist/reindex-worker.js +7 -672
  149. package/package.json +20 -2
  150. package/dist/chunk-2MQ5DPY6.js +0 -61
  151. package/dist/chunk-2QTYIOJ5.js +0 -165
  152. package/dist/chunk-3VI4YXCL.js +0 -172
  153. package/dist/chunk-3VV2G6U7.js +0 -34
  154. package/dist/chunk-44PFXVXG.js +0 -76
  155. package/dist/chunk-6SLFQR36.js +0 -64
  156. package/dist/chunk-74RFWB5T.js +0 -24
  157. package/dist/chunk-7DBPRGMS.js +0 -221
  158. package/dist/chunk-DTB724R3.js +0 -110
  159. package/dist/chunk-FLOYI6I4.js +0 -185
  160. package/dist/chunk-FO2CBB7U.js +0 -23
  161. package/dist/chunk-GJT3MO2T.js +0 -17
  162. package/dist/chunk-HAP4LJKX.js +0 -66
  163. package/dist/chunk-JCOJQ4I6.js +0 -93
  164. package/dist/chunk-JGQMOS4V.js +0 -59
  165. package/dist/chunk-JMD4WJ2Q.js +0 -213
  166. package/dist/chunk-JSQPZOPO.js +0 -64
  167. package/dist/chunk-JSXGC2EH.js +0 -151
  168. package/dist/chunk-JZN3DRCT.js +0 -59
  169. package/dist/chunk-KMWYB3CX.js +0 -71
  170. package/dist/chunk-MRM755FU.js +0 -37
  171. package/dist/chunk-N2XO3Z5F.js +0 -69
  172. package/dist/chunk-OLW5UL36.js +0 -76
  173. package/dist/chunk-OMCRXXDX.js +0 -2600
  174. package/dist/chunk-OWJOHUZE.js +0 -44
  175. package/dist/chunk-P3VCDYMJ.js +0 -269
  176. package/dist/chunk-PEDH3D4G.js +0 -53
  177. package/dist/chunk-POAN4SCR.js +0 -46
  178. package/dist/chunk-PTMGEBU3.js +0 -101
  179. package/dist/chunk-PU44HK7P.js +0 -87
  180. package/dist/chunk-QJI7EECA.js +0 -327
  181. package/dist/chunk-R5HICGMB.js +0 -110
  182. package/dist/chunk-RJ2D6YWQ.js +0 -49
  183. package/dist/chunk-RZ5GYPBP.js +0 -79
  184. package/dist/chunk-SRLQNO6O.js +0 -101
  185. package/dist/chunk-UGS7HJI4.js +0 -84
  186. package/dist/chunk-VKUUXOE7.js +0 -105
  187. package/dist/chunk-VPUJSJCI.js +0 -84
  188. package/dist/chunk-VRWVV3EP.js +0 -72
  189. package/dist/chunk-WJWQEU4A.js +0 -162
  190. package/dist/chunk-WJZHDUSB.js +0 -40
  191. package/dist/chunk-WWOCQ5W4.js +0 -34
  192. package/dist/chunk-X3Q2OVRL.js +0 -77
  193. package/dist/chunk-Y3P7QKKN.js +0 -27
  194. package/dist/chunk-Y6FAHY4N.js +0 -81
  195. package/dist/chunk-YMSJCSRG.js +0 -213
  196. package/dist/chunk-ZDL3U4W2.js +0 -124
  197. package/dist/chunk-ZXNX5JRE.js +0 -216
  198. package/dist/queries/clean-signature.d.ts +0 -17
  199. package/dist/queries/clean-signature.js +0 -9
package/dist/index.js CHANGED
@@ -1,179 +1,4 @@
1
- import "./chunk-FVH3Y44U.js";
2
- import {
3
- surface
4
- } from "./chunk-VRWVV3EP.js";
5
- import {
6
- symbols
7
- } from "./chunk-MRM755FU.js";
8
- import {
9
- system
10
- } from "./chunk-OLW5UL36.js";
11
- import {
12
- trace
13
- } from "./chunk-KMWYB3CX.js";
14
- import {
15
- redundantReexports
16
- } from "./chunk-FLOYI6I4.js";
17
- import {
18
- refs
19
- } from "./chunk-X3Q2OVRL.js";
20
- import {
21
- similarChains
22
- } from "./chunk-JMD4WJ2Q.js";
23
- import {
24
- similarFiles
25
- } from "./chunk-JCOJQ4I6.js";
26
- import {
27
- similarSignatures
28
- } from "./chunk-WJWQEU4A.js";
29
- import {
30
- slice
31
- } from "./chunk-SRLQNO6O.js";
32
- import {
33
- hotspots
34
- } from "./chunk-JGQMOS4V.js";
35
- import {
36
- importedBy,
37
- imports,
38
- unusedImports
39
- } from "./chunk-3VI4YXCL.js";
40
- import {
41
- members
42
- } from "./chunk-Y3P7QKKN.js";
43
- import {
44
- methods
45
- } from "./chunk-WWOCQ5W4.js";
46
- import {
47
- outline
48
- } from "./chunk-JZN3DRCT.js";
49
- import {
50
- deps,
51
- rdeps
52
- } from "./chunk-PEDH3D4G.js";
53
- import {
54
- diffImpact
55
- } from "./chunk-JSXGC2EH.js";
56
- import {
57
- fanIn,
58
- fanOut,
59
- topFanIn,
60
- topFanOut
61
- } from "./chunk-ZDL3U4W2.js";
62
- import {
63
- files
64
- } from "./chunk-FO2CBB7U.js";
65
- import {
66
- health
67
- } from "./chunk-7DBPRGMS.js";
68
- import {
69
- stats
70
- } from "./chunk-74RFWB5T.js";
71
- import {
72
- wrapperCandidates
73
- } from "./chunk-VKUUXOE7.js";
74
- import {
75
- similar,
76
- similarAll
77
- } from "./chunk-QJI7EECA.js";
78
- import {
79
- staleAbstractions
80
- } from "./chunk-6SLFQR36.js";
81
- import {
82
- isolated
83
- } from "./chunk-3VV2G6U7.js";
84
- import {
85
- passthroughCandidates
86
- } from "./chunk-RJ2D6YWQ.js";
87
- import {
88
- drift
89
- } from "./chunk-2QTYIOJ5.js";
90
- import {
91
- extractCandidates
92
- } from "./chunk-PTMGEBU3.js";
93
- import {
94
- hierarchy
95
- } from "./chunk-N2XO3Z5F.js";
96
- import {
97
- complexityHotspots
98
- } from "./chunk-WJZHDUSB.js";
99
- import {
100
- complexity
101
- } from "./chunk-DTB724R3.js";
102
- import {
103
- convergence
104
- } from "./chunk-44PFXVXG.js";
105
- import {
106
- coupling,
107
- topCoupling
108
- } from "./chunk-VPUJSJCI.js";
109
- import {
110
- cycles
111
- } from "./chunk-2MQ5DPY6.js";
112
- import {
113
- dataflow
114
- } from "./chunk-HAP4LJKX.js";
115
- import {
116
- dead
117
- } from "./chunk-R5HICGMB.js";
118
- import "./chunk-UGS7HJI4.js";
119
- import {
120
- deepChains
121
- } from "./chunk-OWJOHUZE.js";
122
- import {
123
- affected
124
- } from "./chunk-PU44HK7P.js";
125
- import {
126
- bottlenecks
127
- } from "./chunk-RZ5GYPBP.js";
128
- import {
129
- byKind,
130
- kindCounts
131
- } from "./chunk-ZXNX5JRE.js";
132
- import {
133
- callGraph
134
- } from "./chunk-POAN4SCR.js";
135
- import {
136
- changeSurface
137
- } from "./chunk-JSQPZOPO.js";
138
- import "./chunk-GJT3MO2T.js";
139
- import {
140
- code
141
- } from "./chunk-Y6FAHY4N.js";
142
- import "./chunk-OMCRXXDX.js";
143
- import {
144
- leafName,
145
- parseSymbol,
146
- shortenSymbol
147
- } from "./chunk-YMSJCSRG.js";
148
-
149
- // src/db.ts
150
- import Database from "better-sqlite3";
151
- import { statSync } from "fs";
152
- var ScipDatabase = class {
153
- db;
154
- config;
155
- pathFilter;
156
- constructor(config, pathFilter) {
157
- this.config = config;
158
- this.pathFilter = pathFilter ?? null;
159
- this.db = new Database(config.dbPath, { readonly: true });
160
- this.db.pragma("busy_timeout = 5000");
161
- }
162
- /** Check if a path should be excluded based on .gitignore rules */
163
- isIgnored(relativePath) {
164
- return this.pathFilter?.isIgnored(relativePath) ?? false;
165
- }
166
- /**
167
- * The local-symbol predicate: only match symbols that are defined
168
- * in files NOT excluded by gitignore. This replaces the old hardcoded
169
- * `NOT LIKE 'node_modules/%'` check.
170
- *
171
- * Since SQLite can't evaluate JS gitignore rules inline, we use a
172
- * simpler approach: query broadly, then filter in JS. For queries
173
- * that need SQL-level filtering, use excludedPathPatterns().
174
- */
175
- get localSymbolPredicate() {
176
- return `(
1
+ import"./chunk-FVH3Y44U.js";import{a as cn}from"./chunk-D7YBWSON.js";import{a as tn}from"./chunk-JH3A7HTU.js";import{a as ln}from"./chunk-XVDASCN7.js";import{a as sn}from"./chunk-STOGKRJH.js";import{a as rn}from"./chunk-PZ6ESKRH.js";import{a as Ln}from"./chunk-Y7LOQSWY.js";import{a as Tn}from"./chunk-4QJ7LVW5.js";import{a as Vn}from"./chunk-XAZTIDST.js";import{a as Kn}from"./chunk-AJ5PWKD4.js";import{a as dn,b as gn,c as hn}from"./chunk-DE5ZBHMK.js";import{a as fn}from"./chunk-BE6EQIWY.js";import{a as nn}from"./chunk-JS2RNIC7.js";import{a as mn}from"./chunk-2RLP74AO.js";import{a as Qn}from"./chunk-YIPCV7M7.js";import{a as On}from"./chunk-NXMYYHDO.js";import{a as yn,b as xn,c as bn,d as vn}from"./chunk-GXVB36TG.js";import{a as en}from"./chunk-KYT47WU2.js";import{a as Hn}from"./chunk-UJB62HV3.js";import{a as Mn}from"./chunk-5IADAU5B.js";import{a as Dn,b as $n}from"./chunk-K6GBKEQE.js";import"./chunk-LORWXBOO.js";import{a as Un}from"./chunk-RJ7SPBJ5.js";import{a as Zt}from"./chunk-N3Z2SJCR.js";import{a as wn}from"./chunk-7Z4COVMC.js";import{a as Wn}from"./chunk-7VOF4ZG6.js";import{a as Bn}from"./chunk-7754WFFV.js";import{a as Fn}from"./chunk-F2LLHRRZ.js";import{a as _n}from"./chunk-RWE6FHG3.js";import{a as pn}from"./chunk-NTDA4A2D.js";import{a as Jn}from"./chunk-BDBRZPX3.js";import{a as Gn}from"./chunk-HMKJTAZD.js";import{a as Sn,b as In}from"./chunk-ZXKURFVB.js";import{a as Cn}from"./chunk-EEF3YEHW.js";import{a as Xn}from"./chunk-SG35Y7J2.js";import{a as un}from"./chunk-KO7YJRWP.js";import"./chunk-GNXRLK5G.js";import"./chunk-VEUMRDHW.js";import"./chunk-ZSRXMNMK.js";import{a as jn}from"./chunk-IBGBI3VU.js";import{a as on,b as an}from"./chunk-DHYIJHXZ.js";import{a as Nn}from"./chunk-D7KLLMPB.js";import{a as kn}from"./chunk-K5FQFCSN.js";import{a as Pn,b as En}from"./chunk-SDX6MDBL.js";import{a as Rn}from"./chunk-FCC3XJTI.js";import{a as An}from"./chunk-2DSS2NGF.js";import{a as zn}from"./chunk-QXE6EDY2.js";import"./chunk-WTSTDJZ7.js";import{a as qn}from"./chunk-Y7H6D2EV.js";import"./chunk-WCDXJGYT.js";import"./chunk-BQ3INTYT.js";import"./chunk-LX4H4LLG.js";import"./chunk-IYFZS4PV.js";import{a as Te,b as Le,c as Fe}from"./chunk-TINPMWJK.js";import Ne from"better-sqlite3";import{statSync as te}from"fs";var F=class{db;config;pathFilter;constructor(e,n){this.config=e,this.pathFilter=n??null,this.db=new Ne(e.dbPath,{readonly:!0}),this.db.pragma("busy_timeout = 5000")}isIgnored(e){return this.pathFilter?.isIgnored(e)??!1}get localSymbolPredicate(){return`(
177
2
  EXISTS (
178
3
  SELECT 1
179
4
  FROM defn_enclosing_ranges local_der
@@ -190,103 +15,8 @@ var ScipDatabase = class {
190
15
  AND local_m.role = 1
191
16
  ${this.pathExclusionsFor("local_d").trimStart()}
192
17
  )
193
- )`;
194
- }
195
- /**
196
- * SQL WHERE clause fragments to exclude common build/dependency paths.
197
- * Complements the JS-level gitignore filtering for performance.
198
- */
199
- get pathExclusions() {
200
- return this.pathExclusionsFor("d");
201
- }
202
- /** Reusable SQL fragment: filter out synthetic/internal symbol noise */
203
- get symbolNoise() {
204
- return this.symbolNoiseFor("gs");
205
- }
206
- /** Build SQL path exclusions for one or more document table aliases */
207
- pathExclusionsFor(...aliases) {
208
- return aliases.flatMap((alias) => [
209
- `AND ${alias}.relative_path NOT LIKE 'node_modules/%'`,
210
- `AND ${alias}.relative_path NOT LIKE '.git/%'`
211
- ]).join("\n ");
212
- }
213
- /** Build SQL symbol exclusions for the given global_symbols alias */
214
- symbolNoiseFor(alias) {
215
- return `AND ${alias}.symbol NOT LIKE '%().(%' AND ${alias}.symbol NOT LIKE '%typeLiteral%'`;
216
- }
217
- /** Run a raw SQL query and return all rows */
218
- all(sql, ...params) {
219
- return this.db.prepare(sql).all(...params);
220
- }
221
- /** Run a raw SQL query and return the first row */
222
- get(sql, ...params) {
223
- return this.db.prepare(sql).get(...params);
224
- }
225
- /** Get the database file size in bytes */
226
- sizeBytes() {
227
- try {
228
- return statSync(this.config.dbPath).size;
229
- } catch {
230
- return 0;
231
- }
232
- }
233
- /** Get the last modification time of the database file */
234
- lastModified() {
235
- try {
236
- return statSync(this.config.dbPath).mtime;
237
- } catch {
238
- return null;
239
- }
240
- }
241
- close() {
242
- this.db.close();
243
- }
244
- };
245
-
246
- // src/gitignore-filter.ts
247
- import ignore from "ignore";
248
- import { readFileSync, existsSync } from "fs";
249
- import { dirname, isAbsolute, join, relative, resolve } from "path";
250
- function createGitignoreFilter(projectRoot) {
251
- const ig = ignore();
252
- let loaded = false;
253
- const gitignorePaths = findGitignoreFiles(projectRoot);
254
- for (const gitignorePath of gitignorePaths) {
255
- try {
256
- const content = readFileSync(gitignorePath, "utf-8");
257
- ig.add(content);
258
- loaded = true;
259
- } catch {
260
- }
261
- }
262
- if (!loaded) {
263
- ig.add(DEFAULT_IGNORES);
264
- }
265
- return {
266
- isIgnored: (relativePath) => safeIgnores(ig, projectRoot, relativePath),
267
- filter: (paths) => paths.filter((p) => !safeIgnores(ig, projectRoot, p))
268
- };
269
- }
270
- function findGitignoreFiles(projectRoot) {
271
- const files2 = [];
272
- const rootGitignore = join(projectRoot, ".gitignore");
273
- if (existsSync(rootGitignore)) {
274
- files2.push(rootGitignore);
275
- }
276
- let dir = dirname(projectRoot);
277
- let depth = 0;
278
- while (dir !== dirname(dir) && depth < 5) {
279
- const parentGitignore = join(dir, ".gitignore");
280
- if (existsSync(parentGitignore)) {
281
- files2.push(parentGitignore);
282
- }
283
- if (existsSync(join(dir, ".git"))) break;
284
- dir = dirname(dir);
285
- depth++;
286
- }
287
- return files2;
288
- }
289
- var DEFAULT_IGNORES = `
18
+ )`}get pathExclusions(){return this.pathExclusionsFor("d")}get symbolNoise(){return this.symbolNoiseFor("gs")}pathExclusionsFor(...e){return e.flatMap(n=>[`AND ${n}.relative_path NOT LIKE 'node_modules/%'`,`AND ${n}.relative_path NOT LIKE '.git/%'`]).join(`
19
+ `)}symbolNoiseFor(e){return`AND ${e}.symbol NOT LIKE '%().(%' AND ${e}.symbol NOT LIKE '%typeLiteral%'`}all(e,...n){return this.db.prepare(e).all(...n)}get(e,...n){return this.db.prepare(e).get(...n)}sizeBytes(){try{return te(this.config.dbPath).size}catch{return 0}}lastModified(){try{return te(this.config.dbPath).mtime}catch{return null}}close(){this.db.close()}};import Ae from"ignore";import{readFileSync as Oe,existsSync as N}from"fs";import{dirname as A,isAbsolute as ne,join as O,relative as Be,resolve as Me}from"path";function B(t){let e=Ae(),n=!1,r=We(t);for(let i of r)try{let s=Oe(i,"utf-8");e.add(s),n=!0}catch{}return n||e.add(Ue),{isIgnored:i=>re(e,t,i),filter:i=>i.filter(s=>!re(e,t,s))}}function We(t){let e=[],n=O(t,".gitignore");N(n)&&e.push(n);let r=A(t),i=0;for(;r!==A(r)&&i<5;){let s=O(r,".gitignore");if(N(s)&&e.push(s),N(O(r,".git")))break;r=A(r),i++}return e}var Ue=`
290
20
  # Dependencies
291
21
  node_modules/
292
22
  vendor/
@@ -343,1347 +73,14 @@ Thumbs.db
343
73
 
344
74
  # Type definitions (often noise in queries)
345
75
  *.d.ts
346
- `;
347
- function safeIgnores(ig, projectRoot, inputPath) {
348
- const relativePath = normalizeForIgnore(projectRoot, inputPath);
349
- if (!relativePath) {
350
- return false;
351
- }
352
- try {
353
- return ig.ignores(relativePath);
354
- } catch {
355
- return false;
356
- }
357
- }
358
- function normalizeForIgnore(projectRoot, inputPath) {
359
- if (!inputPath || inputPath === ".") {
360
- return null;
361
- }
362
- if (!isAbsolute(inputPath) && !inputPath.startsWith("..")) {
363
- return inputPath.replaceAll("\\", "/");
364
- }
365
- const absolutePath = isAbsolute(inputPath) ? inputPath : resolve(projectRoot, inputPath);
366
- const relativePath = relative(projectRoot, absolutePath).replaceAll("\\", "/");
367
- if (!relativePath || relativePath === "." || relativePath.startsWith("..")) {
368
- return null;
369
- }
370
- return relativePath;
371
- }
372
-
373
- // src/reindex/index.ts
374
- import { execFileSync as execFileSync3 } from "child_process";
375
- import { existsSync as existsSync5, renameSync, rmSync } from "fs";
376
- import { basename, dirname as dirname2, extname as extname2, join as join5 } from "path";
377
-
378
- // src/scip-cli.ts
379
- import { execFileSync as execFileSync2 } from "child_process";
380
- import { platform as platform2, arch } from "os";
381
-
382
- // src/reindex/install.ts
383
- import { execFileSync } from "child_process";
384
- import { existsSync as existsSync2 } from "fs";
385
- import { platform } from "os";
386
- import { join as join2 } from "path";
387
- var IS_WINDOWS = platform() === "win32";
388
- function isBinaryAvailable(name) {
389
- const cmd = IS_WINDOWS ? "where" : "which";
390
- try {
391
- execFileSync(cmd, [name], { stdio: "pipe" });
392
- return true;
393
- } catch {
394
- return false;
395
- }
396
- }
397
- function getBinaryCandidates(config) {
398
- return [config.indexerBinary, ...config.binaryAliases ?? []];
399
- }
400
- function describeIndexerBinary(config) {
401
- const candidates = getBinaryCandidates(config);
402
- return candidates.length === 1 ? candidates[0] : candidates.join(" or ");
403
- }
404
- function resolveIndexerBinary(config) {
405
- for (const candidate of getBinaryCandidates(config)) {
406
- if (isBinaryAvailable(candidate)) {
407
- return candidate;
408
- }
409
- }
410
- return null;
411
- }
412
- function isIndexerInstalled(config) {
413
- return resolveIndexerBinary(config) !== null;
414
- }
415
- function resolveProjectLocalIndexerBinary(config, projectRoot) {
416
- for (const relativePath of config.projectLocalBinaries ?? []) {
417
- const candidate = join2(projectRoot, relativePath);
418
- if (existsSync2(candidate)) {
419
- return candidate;
420
- }
421
- }
422
- return null;
423
- }
424
- function getIndexerExecutionEnv(config, baseEnv = process.env, binary = config.indexerBinary) {
425
- if (config.indexerBinary !== "scip-dotnet") {
426
- return baseEnv;
427
- }
428
- if (canRunDotnetIndexer(binary, baseEnv)) {
429
- return baseEnv;
430
- }
431
- const dotnetRoot = resolveWorkingDotnetRoot(binary, baseEnv);
432
- if (!dotnetRoot) {
433
- return baseEnv;
434
- }
435
- return {
436
- ...baseEnv,
437
- DOTNET_ROOT: dotnetRoot
438
- };
439
- }
440
- function tryInstallIndexer(config, onStatus) {
441
- const methods2 = config.installMethods;
442
- const binaryLabel = describeIndexerBinary(config);
443
- if (!methods2?.length) {
444
- onStatus(`No auto-install method available for ${binaryLabel}.`);
445
- if (config.installUrl) {
446
- onStatus(`Install manually from: ${config.installUrl}`);
447
- }
448
- return false;
449
- }
450
- for (const method of methods2) {
451
- if (!isBinaryAvailable(method.prerequisite)) {
452
- continue;
453
- }
454
- onStatus(`Installing ${binaryLabel} via ${method.label}...`);
455
- try {
456
- execFileSync(method.binary, method.args, {
457
- stdio: "inherit",
458
- timeout: 3e5,
459
- env: process.env
460
- });
461
- const resolvedBinary = resolveIndexerBinary(config);
462
- if (resolvedBinary) {
463
- const resolutionNote = resolvedBinary === config.indexerBinary ? "" : ` (using ${resolvedBinary})`;
464
- onStatus(`Successfully installed ${binaryLabel} via ${method.label}${resolutionNote}`);
465
- return true;
466
- }
467
- onStatus(`${method.label} command completed but ${binaryLabel} was not found on PATH`);
468
- } catch (err) {
469
- const msg = err instanceof Error ? err.message : String(err);
470
- onStatus(`${method.label} install failed: ${msg}`);
471
- }
472
- }
473
- onStatus(`Could not auto-install ${binaryLabel}.`);
474
- if (config.installUrl) {
475
- onStatus(`Install manually from: ${config.installUrl}`);
476
- }
477
- return false;
478
- }
479
- function resolveWorkingDotnetRoot(binary, env) {
480
- for (const dotnetRoot of getDotnetRootCandidates(env)) {
481
- if (canRunDotnetIndexer(binary, { ...env, DOTNET_ROOT: dotnetRoot })) {
482
- return dotnetRoot;
483
- }
484
- }
485
- return null;
486
- }
487
- function getDotnetRootCandidates(env) {
488
- const candidates = [];
489
- const configured = env["DOTNET_ROOT"];
490
- if (configured && existsSync2(configured)) {
491
- candidates.push(configured);
492
- }
493
- if (platform() === "darwin" && isBinaryAvailable("brew")) {
494
- try {
495
- const prefix = execFileSync("brew", ["--prefix", "dotnet@9"], {
496
- stdio: "pipe",
497
- env
498
- }).toString().trim();
499
- const candidate = join2(prefix, "libexec");
500
- if (existsSync2(candidate) && !candidates.includes(candidate)) {
501
- candidates.push(candidate);
502
- }
503
- } catch {
504
- }
505
- }
506
- return candidates;
507
- }
508
- function canRunDotnetIndexer(binary, env) {
509
- try {
510
- execFileSync(binary, ["--version"], {
511
- stdio: "pipe",
512
- env
513
- });
514
- return true;
515
- } catch {
516
- return false;
517
- }
518
- }
519
-
520
- // src/scip-cli.ts
521
- var IS_WINDOWS2 = platform2() === "win32";
522
- var SCIP_VERSION = "v0.7.0";
523
- function isScipInstalled() {
524
- try {
525
- const cmd = IS_WINDOWS2 ? "where" : "which";
526
- execFileSync2(cmd, ["scip"], { stdio: "pipe" });
527
- return true;
528
- } catch {
529
- return false;
530
- }
531
- }
532
- function getScipVersion() {
533
- try {
534
- const output = execFileSync2("scip", ["--version"], { stdio: "pipe" }).toString().trim();
535
- return output;
536
- } catch {
537
- return null;
538
- }
539
- }
540
- function getScipDownloadUrl() {
541
- const os = platform2();
542
- const cpu = arch();
543
- let osName;
544
- let archName;
545
- let ext;
546
- switch (os) {
547
- case "darwin":
548
- osName = "darwin";
549
- ext = "tar.gz";
550
- break;
551
- case "linux":
552
- osName = "linux";
553
- ext = "tar.gz";
554
- break;
555
- case "win32":
556
- osName = "windows";
557
- ext = "zip";
558
- break;
559
- default:
560
- return null;
561
- }
562
- switch (cpu) {
563
- case "arm64":
564
- archName = "arm64";
565
- break;
566
- case "x64":
567
- archName = "amd64";
568
- break;
569
- default:
570
- return null;
571
- }
572
- const filename = `scip-${osName}-${archName}.${ext}`;
573
- const url = `https://github.com/sourcegraph/scip/releases/download/${SCIP_VERSION}/${filename}`;
574
- return { url, filename };
575
- }
576
- function printScipInstallInstructions() {
577
- const download = getScipDownloadUrl();
578
- console.log("\nThe `scip` CLI is required but not found on PATH.\n");
579
- if (platform2() === "darwin") {
580
- console.log("Install via Homebrew:");
581
- console.log(" brew install sourcegraph/scip/scip\n");
582
- console.log("Or download manually:");
583
- } else {
584
- console.log("Download from:");
585
- }
586
- if (download) {
587
- console.log(` ${download.url}
588
- `);
589
- } else {
590
- console.log(` https://github.com/sourcegraph/scip/releases/tag/${SCIP_VERSION}
591
- `);
592
- }
593
- console.log("After installing, ensure `scip` is on your PATH and run `scip-query reindex`.");
594
- }
595
- function tryInstallScipCli(onStatus) {
596
- if (platform2() === "darwin" && isBinaryAvailable("brew")) {
597
- onStatus("Installing scip CLI via Homebrew...");
598
- try {
599
- execFileSync2("brew", ["install", "sourcegraph/scip/scip"], {
600
- stdio: "inherit",
601
- timeout: 3e5,
602
- env: process.env
603
- });
604
- if (isBinaryAvailable("scip")) {
605
- onStatus("Successfully installed scip CLI via Homebrew");
606
- return true;
607
- }
608
- } catch (err) {
609
- const msg = err instanceof Error ? err.message : String(err);
610
- onStatus(`Homebrew install failed: ${msg}`);
611
- }
612
- }
613
- if (isBinaryAvailable("go")) {
614
- onStatus("Installing scip CLI via go install...");
615
- try {
616
- execFileSync2("go", ["install", "github.com/sourcegraph/scip/cmd/scip@latest"], {
617
- stdio: "inherit",
618
- timeout: 3e5,
619
- env: process.env
620
- });
621
- if (isBinaryAvailable("scip")) {
622
- onStatus("Successfully installed scip CLI via go install");
623
- return true;
624
- }
625
- } catch (err) {
626
- const msg = err instanceof Error ? err.message : String(err);
627
- onStatus(`go install failed: ${msg}`);
628
- }
629
- }
630
- onStatus("Could not auto-install scip CLI.");
631
- onStatus("Install manually from: https://github.com/sourcegraph/scip/releases");
632
- return false;
633
- }
634
-
635
- // src/reindex/detect.ts
636
- import { existsSync as existsSync3, readdirSync } from "fs";
637
- import { extname, join as join3 } from "path";
638
- var IGNORED_DIRS = /* @__PURE__ */ new Set([
639
- ".git",
640
- ".hg",
641
- ".svn",
642
- ".idea",
643
- ".vscode",
644
- "node_modules",
645
- "vendor",
646
- "dist",
647
- "build",
648
- "target",
649
- "bin",
650
- "obj",
651
- ".dart_tool",
652
- ".gradle",
653
- ".next",
654
- ".venv",
655
- "venv",
656
- "__pycache__"
657
- ]);
658
- var LANGUAGE_MARKERS = [
659
- { language: "typescript", files: ["tsconfig.json", "tsconfig.base.json"], extensions: [".ts", ".tsx", ".mts", ".cts"] },
660
- { language: "rust", files: ["Cargo.toml"], extensions: [".rs"] },
661
- { language: "go", files: ["go.mod"], extensions: [".go"] },
662
- { language: "java", files: ["pom.xml", "build.gradle", "build.gradle.kts"], extensions: [".java"] },
663
- { language: "kotlin", files: ["build.gradle.kts"], extensions: [".kt", ".kts"] },
664
- { language: "scala", files: ["build.sbt"], extensions: [".scala"] },
665
- { language: "python", files: ["pyproject.toml", "setup.py", "setup.cfg", "Pipfile"], extensions: [".py", ".pyi"] },
666
- { language: "ruby", files: ["Gemfile"], extensions: [".rb"] },
667
- { language: "cpp", files: ["compile_commands.json", "CMakeLists.txt", "Makefile"], extensions: [".cc", ".cpp", ".cxx", ".hpp", ".hh", ".hxx"] },
668
- { language: "c", files: ["compile_commands.json", "CMakeLists.txt", "Makefile"], extensions: [".c", ".h"] },
669
- { language: "csharp", globs: ["*.csproj", "*.sln"], extensions: [".cs"] },
670
- { language: "vb", globs: ["*.vbproj"], extensions: [".vb"] },
671
- { language: "dart", files: ["pubspec.yaml"], extensions: [".dart"] },
672
- { language: "php", files: ["composer.json"], extensions: [".php"] },
673
- { language: "javascript", files: ["package.json"], extensions: [".js", ".jsx", ".mjs", ".cjs"] }
674
- // Last — very common
675
- ];
676
- function detectLanguages(projectRoot) {
677
- const detected = [];
678
- const rootEntries = safeReadDir(projectRoot);
679
- const extensionSet = collectExtensions(projectRoot);
680
- for (const marker of LANGUAGE_MARKERS) {
681
- if (hasMarkerFile(projectRoot, marker.files)) {
682
- detected.push(marker.language);
683
- continue;
684
- }
685
- if (matchesRootGlob(rootEntries, marker.globs)) {
686
- detected.push(marker.language);
687
- continue;
688
- }
689
- if (hasExtension(extensionSet, marker.extensions)) {
690
- detected.push(marker.language);
691
- }
692
- }
693
- if (detected.includes("typescript")) {
694
- removeLanguage(detected, "javascript");
695
- }
696
- if (detected.includes("cpp") && !extensionSet.has(".c")) {
697
- removeLanguage(detected, "c");
698
- }
699
- return detected;
700
- }
701
- function safeReadDir(projectRoot) {
702
- try {
703
- return readdirSync(projectRoot);
704
- } catch {
705
- return [];
706
- }
707
- }
708
- function hasMarkerFile(projectRoot, files2) {
709
- if (!files2?.length) {
710
- return false;
711
- }
712
- return files2.some((file) => existsSync3(join3(projectRoot, file)));
713
- }
714
- function matchesRootGlob(entries, globs) {
715
- if (!globs?.length) {
716
- return false;
717
- }
718
- return entries.some((entry) => globs.some((glob) => matchesSimpleGlob(entry, glob)));
719
- }
720
- function matchesSimpleGlob(entry, pattern) {
721
- if (pattern === "*") {
722
- return true;
723
- }
724
- if (!pattern.includes("*")) {
725
- return entry === pattern;
726
- }
727
- const [prefix, suffix] = pattern.split("*");
728
- return entry.startsWith(prefix ?? "") && entry.endsWith(suffix ?? "");
729
- }
730
- function collectExtensions(projectRoot) {
731
- const found = /* @__PURE__ */ new Set();
732
- const stack = [projectRoot];
733
- while (stack.length > 0) {
734
- const current = stack.pop();
735
- if (!current) {
736
- continue;
737
- }
738
- let entries;
739
- try {
740
- entries = readdirSync(current, { withFileTypes: true });
741
- } catch {
742
- continue;
743
- }
744
- for (const entry of entries) {
745
- if (entry.name.startsWith(".") && !entry.name.endsWith("proj") && !entry.name.endsWith("sln")) {
746
- if (entry.isDirectory()) {
747
- continue;
748
- }
749
- }
750
- const fullPath = join3(current, entry.name);
751
- if (entry.isDirectory()) {
752
- if (!IGNORED_DIRS.has(entry.name)) {
753
- stack.push(fullPath);
754
- }
755
- continue;
756
- }
757
- const extension = extname(entry.name).toLowerCase();
758
- if (extension) {
759
- found.add(extension);
760
- }
761
- }
762
- }
763
- return found;
764
- }
765
- function hasExtension(extensionSet, extensions) {
766
- if (!extensions?.length) {
767
- return false;
768
- }
769
- return extensions.some((extension) => extensionSet.has(extension));
770
- }
771
- function removeLanguage(detected, language) {
772
- const index = detected.indexOf(language);
773
- if (index !== -1) {
774
- detected.splice(index, 1);
775
- }
776
- }
777
-
778
- // src/reindex/indexers.ts
779
- import { existsSync as existsSync4, readdirSync as readdirSync2 } from "fs";
780
- import { join as join4 } from "path";
781
- var INDEXER_CONFIGS = {
782
- typescript: {
783
- language: "typescript",
784
- indexerBinary: "scip-typescript",
785
- checkCommand: "npx scip-typescript --version",
786
- indexArgs: ({ outputPath, pnpmWorkspaces }) => {
787
- const args = ["scip-typescript", "index", "--infer-tsconfig", "--output", outputPath, "--no-progress-bar"];
788
- if (pnpmWorkspaces) args.splice(2, 0, "--pnpm-workspaces");
789
- return { binary: "npx", args };
790
- },
791
- markerFiles: ["tsconfig.json"],
792
- installMethods: [
793
- { label: "npm", prerequisite: "npm", binary: "npm", args: ["install", "-g", "@sourcegraph/scip-typescript"] }
794
- ],
795
- installUrl: "https://github.com/sourcegraph/scip-typescript"
796
- },
797
- javascript: {
798
- language: "javascript",
799
- indexerBinary: "scip-typescript",
800
- checkCommand: "npx scip-typescript --version",
801
- indexArgs: ({ outputPath }) => ({
802
- binary: "npx",
803
- args: ["scip-typescript", "index", "--infer-tsconfig", "--output", outputPath, "--no-progress-bar"]
804
- }),
805
- markerFiles: ["package.json"],
806
- installMethods: [
807
- { label: "npm", prerequisite: "npm", binary: "npm", args: ["install", "-g", "@sourcegraph/scip-typescript"] }
808
- ],
809
- installUrl: "https://github.com/sourcegraph/scip-typescript"
810
- },
811
- java: {
812
- language: "java",
813
- indexerBinary: "scip-java",
814
- checkCommand: "scip-java --version",
815
- indexArgs: ({ outputPath }) => ({
816
- binary: "scip-java",
817
- args: ["index", "--output", outputPath]
818
- }),
819
- markerFiles: ["pom.xml", "build.gradle"],
820
- installMethods: [],
821
- installUrl: "https://github.com/sourcegraph/scip-java/releases"
822
- },
823
- scala: {
824
- language: "scala",
825
- indexerBinary: "scip-java",
826
- checkCommand: "scip-java --version",
827
- indexArgs: ({ outputPath }) => ({
828
- binary: "scip-java",
829
- args: ["index", "--output", outputPath]
830
- }),
831
- markerFiles: ["build.sbt"],
832
- installMethods: [],
833
- installUrl: "https://github.com/sourcegraph/scip-java/releases"
834
- },
835
- kotlin: {
836
- language: "kotlin",
837
- indexerBinary: "scip-java",
838
- checkCommand: "scip-java --version",
839
- indexArgs: ({ outputPath }) => ({
840
- binary: "scip-java",
841
- args: ["index", "--output", outputPath]
842
- }),
843
- markerFiles: ["build.gradle.kts"],
844
- installMethods: [],
845
- installUrl: "https://github.com/sourcegraph/scip-java/releases"
846
- },
847
- rust: {
848
- language: "rust",
849
- indexerBinary: "rust-analyzer",
850
- checkCommand: "rust-analyzer --version",
851
- indexArgs: ({ outputPath }) => ({
852
- binary: "rust-analyzer",
853
- args: ["scip", ".", "--output", outputPath]
854
- }),
855
- markerFiles: ["Cargo.toml"],
856
- installMethods: [
857
- { label: "rustup", prerequisite: "rustup", binary: "rustup", args: ["component", "add", "rust-analyzer"] }
858
- ],
859
- installUrl: "https://github.com/rust-lang/rust-analyzer"
860
- },
861
- python: {
862
- language: "python",
863
- indexerBinary: "scip-python",
864
- binaryAliases: ["scip-python-plus"],
865
- checkCommand: "scip-python --version",
866
- indexArgs: ({ outputPath, indexerBinary }) => ({
867
- binary: indexerBinary,
868
- args: ["index", "--output", outputPath, "--project-name", "project"]
869
- }),
870
- markerFiles: ["pyproject.toml", "setup.py"],
871
- installMethods: [
872
- { label: "npm", prerequisite: "npm", binary: "npm", args: ["install", "-g", "scip-python-plus"] }
873
- ],
874
- installUrl: "https://github.com/PlunderStruck/scip-python"
875
- },
876
- ruby: {
877
- language: "ruby",
878
- indexerBinary: "scip-ruby",
879
- checkCommand: "scip-ruby --version",
880
- indexArgs: ({ indexerBinary }) => ({
881
- binary: indexerBinary,
882
- args: ["--dir", "."]
883
- }),
884
- defaultOutputPath: "index.scip",
885
- markerFiles: ["Gemfile"],
886
- installMethods: [],
887
- installUrl: "https://github.com/sourcegraph/scip-ruby/releases"
888
- },
889
- go: {
890
- language: "go",
891
- indexerBinary: "scip-go",
892
- checkCommand: "scip-go --version",
893
- indexArgs: ({ outputPath }) => ({
894
- binary: "scip-go",
895
- args: ["--output", outputPath]
896
- }),
897
- markerFiles: ["go.mod"],
898
- installMethods: [
899
- { label: "go install", prerequisite: "go", binary: "go", args: ["install", "github.com/sourcegraph/scip-go@latest"] }
900
- ],
901
- installUrl: "https://github.com/sourcegraph/scip-go"
902
- },
903
- cpp: {
904
- language: "cpp",
905
- indexerBinary: "scip-clang",
906
- checkCommand: "scip-clang --version",
907
- indexArgs: ({ outputPath }) => ({
908
- binary: "scip-clang",
909
- args: ["--compdb-path", "compile_commands.json", "--index-output-path", outputPath]
910
- }),
911
- markerFiles: ["CMakeLists.txt", "Makefile"],
912
- installMethods: [],
913
- installUrl: "https://github.com/sourcegraph/scip-clang/releases"
914
- },
915
- c: {
916
- language: "c",
917
- indexerBinary: "scip-clang",
918
- checkCommand: "scip-clang --version",
919
- indexArgs: ({ outputPath }) => ({
920
- binary: "scip-clang",
921
- args: ["--compdb-path", "compile_commands.json", "--index-output-path", outputPath]
922
- }),
923
- markerFiles: ["CMakeLists.txt", "Makefile"],
924
- installMethods: [],
925
- installUrl: "https://github.com/sourcegraph/scip-clang/releases"
926
- },
927
- csharp: {
928
- language: "csharp",
929
- indexerBinary: "scip-dotnet",
930
- checkCommand: "scip-dotnet --version",
931
- indexArgs: ({ projectRoot, outputPath }) => ({
932
- binary: "scip-dotnet",
933
- args: ["index", resolveDotnetProject(projectRoot, [".sln", ".csproj"]) ?? projectRoot, "--output", outputPath, "--working-directory", projectRoot]
934
- }),
935
- markerFiles: ["*.csproj", "*.sln"],
936
- installMethods: [
937
- { label: "dotnet", prerequisite: "dotnet", binary: "dotnet", args: ["tool", "install", "--global", "scip-dotnet"] }
938
- ],
939
- installUrl: "https://github.com/sourcegraph/scip-dotnet/releases"
940
- },
941
- vb: {
942
- language: "vb",
943
- indexerBinary: "scip-dotnet",
944
- checkCommand: "scip-dotnet --version",
945
- indexArgs: ({ projectRoot, outputPath }) => ({
946
- binary: "scip-dotnet",
947
- args: ["index", resolveDotnetProject(projectRoot, [".sln", ".vbproj"]) ?? projectRoot, "--output", outputPath, "--working-directory", projectRoot]
948
- }),
949
- markerFiles: ["*.vbproj", "*.sln"],
950
- installMethods: [
951
- { label: "dotnet", prerequisite: "dotnet", binary: "dotnet", args: ["tool", "install", "--global", "scip-dotnet"] }
952
- ],
953
- installUrl: "https://github.com/sourcegraph/scip-dotnet/releases"
954
- },
955
- dart: {
956
- language: "dart",
957
- indexerBinary: "scip-dart",
958
- checkCommand: "scip-dart --version",
959
- indexArgs: ({ indexerBinary, outputPath }) => ({
960
- binary: indexerBinary,
961
- args: ["--output", outputPath]
962
- }),
963
- markerFiles: ["pubspec.yaml"],
964
- installMethods: [
965
- { label: "dart pub", prerequisite: "dart", binary: "dart", args: ["pub", "global", "activate", "scip_dart"] }
966
- ],
967
- installUrl: "https://github.com/Workiva/scip-dart/releases"
968
- },
969
- php: {
970
- language: "php",
971
- indexerBinary: "scip-php",
972
- projectLocalBinaries: ["vendor/davidrjenni/scip-php/bin/scip-php", "vendor/bin/scip-php"],
973
- checkCommand: "scip-php --version",
974
- indexArgs: ({ projectRoot, indexerBinary }) => {
975
- const localBinary = join4(projectRoot, "vendor", "bin", "scip-php");
976
- const nestedLocalBinary = join4(projectRoot, "vendor", "davidrjenni", "scip-php", "bin", "scip-php");
977
- const targetBinary = existsSync4(nestedLocalBinary) ? nestedLocalBinary : existsSync4(localBinary) ? localBinary : indexerBinary;
978
- return {
979
- binary: "php",
980
- args: [
981
- "-d",
982
- "error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED",
983
- targetBinary
984
- ]
985
- };
986
- },
987
- defaultOutputPath: "index.scip",
988
- markerFiles: ["composer.json"],
989
- installMethods: [],
990
- installUrl: "https://github.com/davidrjenni/scip-php/releases"
991
- }
992
- };
993
- function getIndexerConfig(language) {
994
- return INDEXER_CONFIGS[language];
995
- }
996
- function resolveDotnetProject(projectRoot, suffixes) {
997
- let entries;
998
- try {
999
- entries = readdirSync2(projectRoot);
1000
- } catch {
1001
- return null;
1002
- }
1003
- for (const entry of entries) {
1004
- if (suffixes.some((suffix) => entry.endsWith(suffix))) {
1005
- return join4(projectRoot, entry);
1006
- }
1007
- }
1008
- return null;
1009
- }
1010
-
1011
- // src/reindex/merge.ts
1012
- import { readFileSync as readFileSync2, writeFileSync } from "fs";
1013
- import { create } from "@bufbuild/protobuf";
1014
- import {
1015
- deserializeSCIP,
1016
- serializeSCIP,
1017
- DocumentSchema,
1018
- IndexSchema,
1019
- SymbolInformationSchema
1020
- } from "@c4312/scip";
1021
- function mergeScipIndexes(indexes) {
1022
- if (indexes.length === 0) {
1023
- throw new Error("Cannot merge zero SCIP indexes");
1024
- }
1025
- if (indexes.length === 1) {
1026
- return indexes[0];
1027
- }
1028
- const metadata = mergeMetadata(indexes);
1029
- const documents = mergeDocuments(indexes.flatMap((index) => index.documents ?? []));
1030
- const externalSymbols = mergeSymbolInfos(indexes.flatMap((index) => index.externalSymbols ?? []));
1031
- return create(IndexSchema, {
1032
- metadata,
1033
- documents,
1034
- externalSymbols
1035
- });
1036
- }
1037
- function mergeScipFiles(inputPaths, outputPath) {
1038
- if (inputPaths.length === 0) {
1039
- throw new Error("Cannot merge zero SCIP files");
1040
- }
1041
- const indexes = inputPaths.map((path) => deserializeSCIP(readFileSync2(path)));
1042
- const merged = mergeScipIndexes(indexes);
1043
- writeFileSync(outputPath, Buffer.from(serializeSCIP(merged)));
1044
- return {
1045
- documentCount: merged.documents.length,
1046
- externalSymbolCount: merged.externalSymbols.length,
1047
- inputCount: inputPaths.length
1048
- };
1049
- }
1050
- function mergeMetadata(indexes) {
1051
- const first = indexes[0]?.metadata;
1052
- if (!first) {
1053
- return void 0;
1054
- }
1055
- const expectedProjectRoot = first.projectRoot;
1056
- for (const index of indexes.slice(1)) {
1057
- const actualProjectRoot = index.metadata?.projectRoot;
1058
- if (expectedProjectRoot && actualProjectRoot && actualProjectRoot !== expectedProjectRoot) {
1059
- throw new Error(
1060
- `Cannot merge SCIP indexes with different project roots: ${expectedProjectRoot} vs ${actualProjectRoot}`
1061
- );
1062
- }
1063
- }
1064
- return first;
1065
- }
1066
- function mergeDocuments(documents) {
1067
- const byPath = /* @__PURE__ */ new Map();
1068
- for (const document of documents) {
1069
- const existing = byPath.get(document.relativePath);
1070
- if (!existing) {
1071
- byPath.set(document.relativePath, document);
1072
- continue;
1073
- }
1074
- byPath.set(document.relativePath, create(DocumentSchema, {
1075
- language: existing.language || document.language,
1076
- relativePath: existing.relativePath || document.relativePath,
1077
- occurrences: [...existing.occurrences, ...document.occurrences],
1078
- symbols: mergeSymbolInfos([...existing.symbols, ...document.symbols]),
1079
- text: chooseText(existing.text, document.text),
1080
- positionEncoding: existing.positionEncoding || document.positionEncoding
1081
- }));
1082
- }
1083
- return [...byPath.values()];
1084
- }
1085
- function mergeSymbolInfos(symbols2) {
1086
- const bySymbol = /* @__PURE__ */ new Map();
1087
- for (const symbol of symbols2) {
1088
- const existing = bySymbol.get(symbol.symbol);
1089
- if (!existing) {
1090
- bySymbol.set(symbol.symbol, symbol);
1091
- continue;
1092
- }
1093
- bySymbol.set(symbol.symbol, create(SymbolInformationSchema, {
1094
- symbol: existing.symbol,
1095
- documentation: uniqueStrings([...existing.documentation, ...symbol.documentation]),
1096
- relationships: mergeRelationships([...existing.relationships, ...symbol.relationships]),
1097
- kind: existing.kind || symbol.kind,
1098
- displayName: existing.displayName || symbol.displayName,
1099
- enclosingSymbol: existing.enclosingSymbol || symbol.enclosingSymbol,
1100
- signatureDocumentation: existing.signatureDocumentation ?? symbol.signatureDocumentation
1101
- }));
1102
- }
1103
- return [...bySymbol.values()];
1104
- }
1105
- function mergeRelationships(relationships) {
1106
- const seen = /* @__PURE__ */ new Set();
1107
- const merged = [];
1108
- for (const relationship of relationships) {
1109
- const key = [
1110
- relationship.symbol,
1111
- relationship.isReference ? "1" : "0",
1112
- relationship.isImplementation ? "1" : "0",
1113
- relationship.isTypeDefinition ? "1" : "0",
1114
- relationship.isDefinition ? "1" : "0"
1115
- ].join("|");
1116
- if (seen.has(key)) {
1117
- continue;
1118
- }
1119
- seen.add(key);
1120
- merged.push(relationship);
1121
- }
1122
- return merged;
1123
- }
1124
- function chooseText(left, right) {
1125
- if (!left) return right;
1126
- if (!right) return left;
1127
- return left.length >= right.length ? left : right;
1128
- }
1129
- function uniqueStrings(values) {
1130
- return [...new Set(values)];
1131
- }
1132
-
1133
- // src/reindex/index.ts
1134
- async function reindex(opts) {
1135
- const {
1136
- projectRoot,
1137
- maxHeapMb = 8192,
1138
- onStatus = console.log,
1139
- skipAutoInstall = false
1140
- } = opts;
1141
- const outputScip = opts.outputScip ?? join5(projectRoot, "index.scip");
1142
- const outputDb = opts.outputDb ?? join5(projectRoot, "index.db");
1143
- const start = Date.now();
1144
- const languages = opts.languages ?? detectLanguages(projectRoot);
1145
- if (languages.length === 0) {
1146
- throw new Error(
1147
- "No supported languages detected in this project. Looked for: tsconfig.json, Cargo.toml, go.mod, pyproject.toml, etc."
1148
- );
1149
- }
1150
- onStatus(`Detected languages: ${languages.join(", ")}`);
1151
- if (!isBinaryAvailable("scip")) {
1152
- if (skipAutoInstall) {
1153
- throw new Error(
1154
- "The scip CLI is required but not found on PATH.\nInstall from: https://github.com/sourcegraph/scip/releases"
1155
- );
1156
- }
1157
- onStatus("scip CLI not found on PATH. Attempting auto-install...");
1158
- if (!tryInstallScipCli(onStatus)) {
1159
- throw new Error(
1160
- "The scip CLI is required but could not be installed.\nInstall manually from: https://github.com/sourcegraph/scip/releases"
1161
- );
1162
- }
1163
- }
1164
- const env = {
1165
- ...process.env,
1166
- NODE_OPTIONS: `--max-old-space-size=${maxHeapMb}`
1167
- };
1168
- const languageOutputs = languages.map((language, index) => ({
1169
- language,
1170
- scipPath: languages.length > 1 ? tempScipPath(outputScip, language, index) : outputScip
1171
- }));
1172
- for (const { language: lang, scipPath } of languageOutputs) {
1173
- const config = getIndexerConfig(lang);
1174
- const binaryLabel = describeIndexerBinary(config);
1175
- const projectLocalBinary = resolveProjectLocalIndexerBinary(config, projectRoot);
1176
- if (!projectLocalBinary && !isIndexerInstalled(config)) {
1177
- if (skipAutoInstall) {
1178
- throw new Error(
1179
- `${binaryLabel} is required to index ${lang} but not found on PATH.
1180
- ` + (config.installUrl ? `Install from: ${config.installUrl}` : `Make sure ${binaryLabel} is installed and available on PATH.`)
1181
- );
1182
- }
1183
- onStatus(`${binaryLabel} not found. Attempting auto-install...`);
1184
- if (!tryInstallIndexer(config, onStatus)) {
1185
- throw new Error(
1186
- `${binaryLabel} is required to index ${lang} but could not be installed.
1187
- ` + (config.installUrl ? `Install manually from: ${config.installUrl}` : `Make sure ${binaryLabel} is installed and available on PATH.`)
1188
- );
1189
- }
1190
- }
1191
- const resolvedBinary = projectLocalBinary ?? resolveIndexerBinary(config);
1192
- if (!resolvedBinary) {
1193
- throw new Error(
1194
- `${binaryLabel} is required to index ${lang} but was not found on PATH after installation checks.
1195
- ` + (config.installUrl ? `Install manually from: ${config.installUrl}` : `Make sure ${binaryLabel} is installed and available on PATH.`)
1196
- );
1197
- }
1198
- onStatus(`Indexing ${lang} with ${resolvedBinary}...`);
1199
- const indexerEnv = getIndexerExecutionEnv(config, env, resolvedBinary);
1200
- const { binary, args } = config.indexArgs({
1201
- projectRoot,
1202
- outputPath: scipPath,
1203
- pnpmWorkspaces: opts.pnpmWorkspaces,
1204
- indexerBinary: resolvedBinary
1205
- });
1206
- try {
1207
- execFileSync3(binary, args, {
1208
- cwd: projectRoot,
1209
- env: indexerEnv,
1210
- stdio: "pipe",
1211
- maxBuffer: 50 * 1024 * 1024
1212
- });
1213
- } catch (err) {
1214
- const msg = err instanceof Error ? err.message : String(err);
1215
- throw new Error(
1216
- `Failed to index ${lang} with ${resolvedBinary}: ${msg}
1217
- Make sure ${binaryLabel} is installed and available on PATH.`,
1218
- { cause: err }
1219
- );
1220
- }
1221
- moveDefaultOutputIfNeeded(config, projectRoot, scipPath);
1222
- }
1223
- if (languageOutputs.length > 1) {
1224
- onStatus(`Merging ${languageOutputs.length} language indexes...`);
1225
- mergeScipFiles(languageOutputs.map((entry) => entry.scipPath), outputScip);
1226
- }
1227
- onStatus("Converting to SQLite...");
1228
- if (!existsSync5(outputScip)) {
1229
- throw new Error(`SCIP index not found at ${outputScip} after indexing`);
1230
- }
1231
- try {
1232
- execFileSync3("scip", ["expt-convert", "--output", outputDb, outputScip], {
1233
- env,
1234
- stdio: "pipe",
1235
- maxBuffer: 50 * 1024 * 1024
1236
- });
1237
- } catch (err) {
1238
- const msg = err instanceof Error ? err.message : String(err);
1239
- throw new Error(`Failed to convert SCIP index to SQLite: ${msg}`, { cause: err });
1240
- } finally {
1241
- for (const { scipPath } of languageOutputs) {
1242
- if (scipPath !== outputScip) {
1243
- rmSync(scipPath, { force: true });
1244
- }
1245
- }
1246
- }
1247
- const durationMs = Date.now() - start;
1248
- onStatus(`Done in ${(durationMs / 1e3).toFixed(1)}s`);
1249
- return { languages, indexPath: outputScip, dbPath: outputDb, durationMs };
1250
- }
1251
- function moveDefaultOutputIfNeeded(config, projectRoot, outputScip) {
1252
- if (!config.defaultOutputPath) {
1253
- return;
1254
- }
1255
- const defaultOutputPath = join5(projectRoot, config.defaultOutputPath);
1256
- if (outputScip !== defaultOutputPath && existsSync5(defaultOutputPath)) {
1257
- renameSync(defaultOutputPath, outputScip);
1258
- }
1259
- }
1260
- function tempScipPath(outputScip, language, index) {
1261
- const extension = extname2(outputScip) || ".scip";
1262
- const stem = basename(outputScip, extension);
1263
- return join5(dirname2(outputScip), `${stem}.${index + 1}.${language}${extension}`);
1264
- }
1265
-
1266
- // src/config.ts
1267
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync } from "fs";
1268
- import { join as join6, resolve as resolve2 } from "path";
1269
- import { createHash } from "crypto";
1270
- import { homedir } from "os";
1271
- var CONFIG_FILENAME = ".scipquery.json";
1272
- var DEFAULT_WATCH = {
1273
- enabled: false,
1274
- debounceMs: 3e4,
1275
- cooldownMs: 6e4,
1276
- ignore: []
1277
- };
1278
- function loadProjectConfig(projectRoot) {
1279
- const configPath = join6(projectRoot, CONFIG_FILENAME);
1280
- if (!existsSync6(configPath)) {
1281
- return {};
1282
- }
1283
- try {
1284
- const raw = readFileSync3(configPath, "utf-8");
1285
- return JSON.parse(raw);
1286
- } catch {
1287
- return {};
1288
- }
1289
- }
1290
- function resolveWatchConfig(config) {
1291
- return {
1292
- ...DEFAULT_WATCH,
1293
- ...config.watch
1294
- };
1295
- }
1296
- function resolveCacheDir(projectRoot, config) {
1297
- const envOverride = process.env["SCIP_QUERY_CACHE_DIR"];
1298
- if (envOverride) return ensureDir(envOverride);
1299
- if (config?.dbPath) return ensureDir(resolve2(projectRoot, config.dbPath));
1300
- const xdgCache = process.env["XDG_CACHE_HOME"];
1301
- const cacheBase = xdgCache || join6(homedir(), ".cache");
1302
- const projectHash = createHash("sha256").update(resolve2(projectRoot)).digest("hex").slice(0, 12);
1303
- const dir = join6(cacheBase, "scip-query", "projects", projectHash);
1304
- return ensureDir(dir);
1305
- }
1306
- function resolveIndexPaths(projectRoot, config) {
1307
- const cacheDir = resolveCacheDir(projectRoot, config);
1308
- return {
1309
- cacheDir,
1310
- dbPath: join6(cacheDir, "index.db"),
1311
- indexPath: join6(cacheDir, "index.scip"),
1312
- metaPath: join6(cacheDir, "meta.json")
1313
- };
1314
- }
1315
- function initProjectConfig(projectRoot, languages) {
1316
- const configPath = join6(projectRoot, CONFIG_FILENAME);
1317
- if (existsSync6(configPath)) {
1318
- return configPath;
1319
- }
1320
- const config = {
1321
- languages,
1322
- watch: {
1323
- enabled: false,
1324
- debounceMs: 3e4,
1325
- cooldownMs: 6e4
1326
- }
1327
- };
1328
- writeFileSync2(configPath, JSON.stringify(config, null, 2) + "\n");
1329
- return configPath;
1330
- }
1331
- function ensureDir(dir) {
1332
- mkdirSync(dir, { recursive: true });
1333
- return dir;
1334
- }
1335
-
1336
- // src/watch.ts
1337
- import { watch } from "fs";
1338
- import { existsSync as existsSync7, renameSync as renameSync2 } from "fs";
1339
- import { join as join7, relative as relative2 } from "path";
1340
- import { fork } from "child_process";
1341
- import ignore2 from "ignore";
1342
- var Watcher = class {
1343
- projectRoot;
1344
- watchConfig;
1345
- indexPaths;
1346
- languages;
1347
- pnpmWorkspaces;
1348
- onStatus;
1349
- onReindexComplete;
1350
- onError;
1351
- // State machine
1352
- status = { state: "idle" };
1353
- debounceTimer = null;
1354
- cooldownTimer = null;
1355
- dirty = false;
1356
- changedFiles = 0;
1357
- reindexInFlight = false;
1358
- lastReindexEnd = 0;
1359
- // fs.watch watchers (one per watched directory)
1360
- fsWatchers = [];
1361
- gitignoreFilter;
1362
- extraIgnore;
1363
- stopped = false;
1364
- constructor(opts) {
1365
- this.projectRoot = opts.projectRoot;
1366
- this.watchConfig = resolveWatchConfig(opts.config);
1367
- this.indexPaths = resolveIndexPaths(opts.projectRoot, opts.config);
1368
- this.languages = opts.languages;
1369
- this.pnpmWorkspaces = opts.config.indexer?.typescript?.pnpmWorkspaces ?? false;
1370
- this.onStatus = opts.onStatus ?? (() => {
1371
- });
1372
- this.onReindexComplete = opts.onReindexComplete ?? (() => {
1373
- });
1374
- this.onError = opts.onError ?? ((e) => console.error(e.message));
1375
- this.gitignoreFilter = createGitignoreFilter(opts.projectRoot);
1376
- this.extraIgnore = ignore2();
1377
- if (this.watchConfig.ignore.length > 0) {
1378
- this.extraIgnore.add(this.watchConfig.ignore);
1379
- }
1380
- }
1381
- /** Start watching for file changes */
1382
- start() {
1383
- this.stopped = false;
1384
- this.setStatus({ state: "idle" });
1385
- try {
1386
- const watcher = watch(
1387
- this.projectRoot,
1388
- { recursive: true },
1389
- (_event, filename) => {
1390
- if (filename && !this.stopped) {
1391
- this.handleFileChange(filename);
1392
- }
1393
- }
1394
- );
1395
- this.fsWatchers.push(watcher);
1396
- } catch {
1397
- this.onError(new Error(
1398
- "Failed to start file watcher. On Linux, you may need to increase inotify limits: sysctl -w fs.inotify.max_user_watches=524288"
1399
- ));
1400
- }
1401
- }
1402
- /** Stop watching and clean up */
1403
- stop() {
1404
- this.stopped = true;
1405
- for (const w of this.fsWatchers) w.close();
1406
- this.fsWatchers = [];
1407
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
1408
- if (this.cooldownTimer) clearTimeout(this.cooldownTimer);
1409
- this.setStatus({ state: "idle" });
1410
- }
1411
- // ── Internal ─────────────────────────────────────────────
1412
- handleFileChange(filename) {
1413
- const rel = relative2(this.projectRoot, join7(this.projectRoot, filename));
1414
- if (this.gitignoreFilter.isIgnored(rel)) return;
1415
- if (this.extraIgnore.ignores(rel)) return;
1416
- if (filename.endsWith("index.db") || filename.endsWith("index.scip") || filename.endsWith("index.db.tmp") || filename.endsWith(".scipquery.json")) {
1417
- return;
1418
- }
1419
- this.changedFiles++;
1420
- if (this.reindexInFlight) {
1421
- this.dirty = true;
1422
- this.setStatus({
1423
- state: "indexing",
1424
- startedAt: this.status.startedAt
1425
- });
1426
- return;
1427
- }
1428
- if (this.status.state === "cooldown") {
1429
- this.dirty = true;
1430
- this.setStatus({ state: "cooldown", until: this.status.until, dirty: true });
1431
- return;
1432
- }
1433
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
1434
- const reindexAt = Date.now() + this.watchConfig.debounceMs;
1435
- this.setStatus({ state: "waiting", changedFiles: this.changedFiles, reindexAt });
1436
- this.debounceTimer = setTimeout(() => {
1437
- this.debounceTimer = null;
1438
- this.triggerReindex();
1439
- }, this.watchConfig.debounceMs);
1440
- }
1441
- triggerReindex() {
1442
- if (this.reindexInFlight || this.stopped) return;
1443
- const timeSinceLastReindex = Date.now() - this.lastReindexEnd;
1444
- if (this.lastReindexEnd > 0 && timeSinceLastReindex < this.watchConfig.cooldownMs) {
1445
- const remaining = this.watchConfig.cooldownMs - timeSinceLastReindex;
1446
- this.dirty = true;
1447
- const until = Date.now() + remaining;
1448
- this.setStatus({ state: "cooldown", until, dirty: true });
1449
- this.cooldownTimer = setTimeout(() => {
1450
- this.cooldownTimer = null;
1451
- if (this.dirty && !this.stopped) {
1452
- this.dirty = false;
1453
- this.triggerReindex();
1454
- }
1455
- }, remaining);
1456
- return;
1457
- }
1458
- this.reindexInFlight = true;
1459
- this.dirty = false;
1460
- this.changedFiles = 0;
1461
- const startedAt = Date.now();
1462
- this.setStatus({ state: "indexing", startedAt });
1463
- this.runReindex().then((durationMs) => {
1464
- this.reindexInFlight = false;
1465
- this.lastReindexEnd = Date.now();
1466
- this.onReindexComplete(durationMs);
1467
- if (this.dirty && !this.stopped) {
1468
- const until = Date.now() + this.watchConfig.cooldownMs;
1469
- this.setStatus({ state: "cooldown", until, dirty: true });
1470
- this.cooldownTimer = setTimeout(() => {
1471
- this.cooldownTimer = null;
1472
- if (this.dirty && !this.stopped) {
1473
- this.dirty = false;
1474
- this.triggerReindex();
1475
- } else {
1476
- this.setStatus({ state: "idle" });
1477
- }
1478
- }, this.watchConfig.cooldownMs);
1479
- } else {
1480
- this.setStatus({ state: "idle" });
1481
- }
1482
- }).catch((err) => {
1483
- this.reindexInFlight = false;
1484
- this.lastReindexEnd = Date.now();
1485
- this.onError(err instanceof Error ? err : new Error(String(err)));
1486
- this.setStatus({ state: "idle" });
1487
- });
1488
- }
1489
- /**
1490
- * Run the reindex in a forked child process.
1491
- * Writes to index.db.tmp, then atomically renames to index.db.
1492
- */
1493
- runReindex() {
1494
- return new Promise((resolve4, reject) => {
1495
- const start = Date.now();
1496
- const tmpDb = this.indexPaths.dbPath + ".tmp";
1497
- const tmpScip = tempScipPath2(this.indexPaths.indexPath);
1498
- const child = fork(
1499
- new URL("./reindex-worker.js", import.meta.url).pathname,
1500
- [],
1501
- {
1502
- env: {
1503
- ...process.env,
1504
- SCIP_REINDEX_PROJECT_ROOT: this.projectRoot,
1505
- SCIP_REINDEX_OUTPUT_SCIP: tmpScip,
1506
- SCIP_REINDEX_OUTPUT_DB: tmpDb,
1507
- SCIP_REINDEX_LANGUAGES: this.languages?.join(",") ?? "",
1508
- SCIP_REINDEX_PNPM_WORKSPACES: this.pnpmWorkspaces ? "1" : ""
1509
- },
1510
- stdio: "pipe"
1511
- }
1512
- );
1513
- child.on("exit", (code2) => {
1514
- if (code2 === 0) {
1515
- try {
1516
- if (existsSync7(tmpDb)) {
1517
- renameSync2(tmpDb, this.indexPaths.dbPath);
1518
- }
1519
- if (existsSync7(tmpScip)) {
1520
- renameSync2(tmpScip, this.indexPaths.indexPath);
1521
- }
1522
- resolve4(Date.now() - start);
1523
- } catch (err) {
1524
- reject(new Error(`Atomic swap failed: ${err}`));
1525
- }
1526
- } else {
1527
- reject(new Error(`Reindex worker exited with code ${code2}`));
1528
- }
1529
- });
1530
- child.on("error", reject);
1531
- });
1532
- }
1533
- setStatus(status) {
1534
- this.status = status;
1535
- this.onStatus(status);
1536
- }
1537
- };
1538
- function tempScipPath2(indexPath) {
1539
- return indexPath.endsWith(".scip") ? indexPath.slice(0, -".scip".length) + ".tmp.scip" : indexPath + ".tmp.scip";
1540
- }
1541
-
1542
- // src/setup.ts
1543
- import {
1544
- existsSync as existsSync8,
1545
- mkdirSync as mkdirSync2,
1546
- symlinkSync,
1547
- readlinkSync,
1548
- unlinkSync
1549
- } from "fs";
1550
- import { join as join8, dirname as dirname3, resolve as resolve3 } from "path";
1551
- import { homedir as homedir2, platform as platform3 } from "os";
1552
- import { fileURLToPath } from "url";
1553
- var IS_WINDOWS3 = platform3() === "win32";
1554
- var BUILTIN_SKILLS = [
1555
- "concrete-plan",
1556
- "scip-explore",
1557
- "scip-debloat",
1558
- "scip-verify",
1559
- "scip-language-playbook"
1560
- ];
1561
- function installSkills(opts = {}) {
1562
- const log = opts.quiet ? () => {
1563
- } : console.log;
1564
- const thisFile = fileURLToPath(import.meta.url);
1565
- const skillsSource = resolve3(dirname3(thisFile), "..", "skills");
1566
- const targets = [
1567
- join8(homedir2(), ".claude", "skills"),
1568
- join8(homedir2(), ".codex", "skills")
1569
- ];
1570
- const result = {
1571
- installed: [],
1572
- skipped: [],
1573
- alreadyLinked: []
1574
- };
1575
- for (const targetDir of targets) {
1576
- const parentDir = dirname3(targetDir);
1577
- if (!existsSync8(parentDir)) {
1578
- continue;
1579
- }
1580
- mkdirSync2(targetDir, { recursive: true });
1581
- const toolName = targetDir.includes(".codex") ? "Codex" : "Claude";
1582
- for (const skill of BUILTIN_SKILLS) {
1583
- const source = join8(skillsSource, skill);
1584
- const target = join8(targetDir, skill);
1585
- if (!existsSync8(source)) {
1586
- result.skipped.push(`${toolName}/${skill}`);
1587
- continue;
1588
- }
1589
- if (existsSync8(target)) {
1590
- try {
1591
- const existing = readlinkSync(target);
1592
- if (resolve3(existing) === resolve3(source)) {
1593
- result.alreadyLinked.push(`${toolName}/${skill}`);
1594
- log(` ok: ${skill} \u2192 ${toolName} (already linked)`);
1595
- continue;
1596
- }
1597
- } catch {
1598
- result.skipped.push(`${toolName}/${skill}`);
1599
- log(` skip: ${skill} \u2192 ${toolName} (exists, not a symlink)`);
1600
- continue;
1601
- }
1602
- unlinkSync(target);
1603
- }
1604
- symlinkSync(source, target, IS_WINDOWS3 ? "junction" : "dir");
1605
- result.installed.push(`${toolName}/${skill}`);
1606
- log(` done: ${skill} \u2192 ${toolName}`);
1607
- }
1608
- }
1609
- return result;
1610
- }
1611
- export {
1612
- INDEXER_CONFIGS,
1613
- ScipDatabase,
1614
- Watcher,
1615
- affected,
1616
- bottlenecks,
1617
- byKind,
1618
- callGraph,
1619
- changeSurface,
1620
- code,
1621
- complexity,
1622
- complexityHotspots,
1623
- convergence,
1624
- coupling,
1625
- createGitignoreFilter,
1626
- cycles,
1627
- dataflow,
1628
- dead,
1629
- deepChains,
1630
- deps,
1631
- detectLanguages,
1632
- diffImpact,
1633
- drift,
1634
- extractCandidates,
1635
- fanIn,
1636
- fanOut,
1637
- files,
1638
- getIndexerConfig,
1639
- getScipVersion,
1640
- health,
1641
- hierarchy,
1642
- hotspots,
1643
- importedBy,
1644
- imports,
1645
- initProjectConfig,
1646
- installSkills,
1647
- isBinaryAvailable,
1648
- isIndexerInstalled,
1649
- isScipInstalled,
1650
- isolated,
1651
- kindCounts,
1652
- leafName,
1653
- loadProjectConfig,
1654
- members,
1655
- mergeScipFiles,
1656
- mergeScipIndexes,
1657
- methods,
1658
- outline,
1659
- parseSymbol,
1660
- passthroughCandidates,
1661
- printScipInstallInstructions,
1662
- rdeps,
1663
- redundantReexports,
1664
- refs,
1665
- reindex,
1666
- resolveCacheDir,
1667
- resolveIndexPaths,
1668
- shortenSymbol,
1669
- similar,
1670
- similarAll,
1671
- similarChains,
1672
- similarFiles,
1673
- similarSignatures,
1674
- slice,
1675
- staleAbstractions,
1676
- stats,
1677
- surface,
1678
- symbols,
1679
- system,
1680
- topCoupling,
1681
- topFanIn,
1682
- topFanOut,
1683
- trace,
1684
- tryInstallIndexer,
1685
- tryInstallScipCli,
1686
- unusedImports,
1687
- wrapperCandidates
1688
- };
76
+ `;function re(t,e,n){let r=qe(e,n);if(!r)return!1;try{return t.ignores(r)}catch{return!1}}function qe(t,e){if(!e||e===".")return null;if(!ne(e)&&!e.startsWith(".."))return e.replaceAll("\\","/");let n=ne(e)?e:Me(t,e),r=Be(t,n).replaceAll("\\","/");return!r||r==="."||r.startsWith("..")?null:r}import{execFileSync as ye}from"child_process";import{existsSync as xe,renameSync as be,rmSync as Ct}from"fs";import{basename as kt,dirname as wt,extname as Pt,join as T}from"path";import{execFileSync as S}from"child_process";import{platform as k,arch as He}from"os";var ie=k()==="win32",se="v0.7.0";function C(t){let e=ie?"where":"which";try{return S(e,[t],{stdio:"pipe"}),!0}catch{return!1}}function Ge(){try{return S(ie?"where":"which",["scip"],{stdio:"pipe"}),!0}catch{return!1}}function ze(){try{return S("scip",["--version"],{stdio:"pipe"}).toString().trim()}catch{return null}}function Je(){let t=k(),e=He(),n,r,i;switch(t){case"darwin":n="darwin",i="tar.gz";break;case"linux":n="linux",i="tar.gz";break;case"win32":n="windows",i="zip";break;default:return null}switch(e){case"arm64":r="arm64";break;case"x64":r="amd64";break;default:return null}let s=`scip-${n}-${r}.${i}`;return{url:`https://github.com/sourcegraph/scip/releases/download/${se}/${s}`,filename:s}}function Xe(){let t=Je();console.log("\nThe `scip` CLI is required but not found on PATH.\n"),k()==="darwin"?(console.log("Install via Homebrew:"),console.log(` brew install sourcegraph/scip/scip
77
+ `),console.log("Or download manually:")):console.log("Download from:"),console.log(t?` ${t.url}
78
+ `:` https://github.com/sourcegraph/scip/releases/tag/${se}
79
+ `),console.log("After installing, ensure `scip` is on your PATH and run `scip-query reindex`.")}function w(t){if(k()==="darwin"&&C("brew")){t("Installing scip CLI via Homebrew...");try{if(S("brew",["install","sourcegraph/scip/scip"],{stdio:"inherit",timeout:3e5,env:process.env}),C("scip"))return t("Successfully installed scip CLI via Homebrew"),!0}catch(e){let n=e instanceof Error?e.message:String(e);t(`Homebrew install failed: ${n}`)}}if(C("go")){t("Installing scip CLI via go install...");try{if(S("go",["install","github.com/sourcegraph/scip/cmd/scip@latest"],{stdio:"inherit",timeout:3e5,env:process.env}),C("scip"))return t("Successfully installed scip CLI via go install"),!0}catch(e){let n=e instanceof Error?e.message:String(e);t(`go install failed: ${n}`)}}return t("Could not auto-install scip CLI."),t("Install manually from: https://github.com/sourcegraph/scip/releases"),!1}import{existsSync as Ke,readdirSync as ae}from"fs";import{extname as Qe,join as le}from"path";var Ve=new Set([".git",".hg",".svn",".idea",".vscode","node_modules","vendor","dist","build","target","bin","obj",".dart_tool",".gradle",".next",".venv","venv","__pycache__"]),Ye=[{language:"typescript",files:["tsconfig.json","tsconfig.base.json"],extensions:[".ts",".tsx",".mts",".cts"]},{language:"rust",files:["Cargo.toml"],extensions:[".rs"]},{language:"go",files:["go.mod"],extensions:[".go"]},{language:"java",files:["pom.xml","build.gradle","build.gradle.kts"],extensions:[".java"]},{language:"kotlin",files:["build.gradle.kts"],extensions:[".kt",".kts"]},{language:"scala",files:["build.sbt"],extensions:[".scala"]},{language:"python",files:["pyproject.toml","setup.py","setup.cfg","Pipfile"],extensions:[".py",".pyi"]},{language:"ruby",files:["Gemfile"],extensions:[".rb"]},{language:"cpp",files:["compile_commands.json","CMakeLists.txt","Makefile"],extensions:[".cc",".cpp",".cxx",".hpp",".hh",".hxx"]},{language:"c",files:["compile_commands.json","CMakeLists.txt","Makefile"],extensions:[".c",".h"]},{language:"csharp",globs:["*.csproj","*.sln"],extensions:[".cs"]},{language:"vb",globs:["*.vbproj"],extensions:[".vb"]},{language:"dart",files:["pubspec.yaml"],extensions:[".dart"]},{language:"php",files:["composer.json"],extensions:[".php"]},{language:"javascript",files:["package.json"],extensions:[".js",".jsx",".mjs",".cjs"]}];function P(t){let e=[],n=Ze(t),r=rt(t);for(let i of Ye){if(et(t,i.files)){e.push(i.language);continue}if(tt(n,i.globs)){e.push(i.language);continue}it(r,i.extensions)&&e.push(i.language)}return e.includes("typescript")&&oe(e,"javascript"),e.includes("cpp")&&!r.has(".c")&&oe(e,"c"),e}function Ze(t){try{return ae(t)}catch{return[]}}function et(t,e){return e?.length?e.some(n=>Ke(le(t,n))):!1}function tt(t,e){return e?.length?t.some(n=>e.some(r=>nt(n,r))):!1}function nt(t,e){if(e==="*")return!0;if(!e.includes("*"))return t===e;let[n,r]=e.split("*");return t.startsWith(n??"")&&t.endsWith(r??"")}function rt(t){let e=new Set,n=[t];for(;n.length>0;){let r=n.pop();if(!r)continue;let i;try{i=ae(r,{withFileTypes:!0})}catch{continue}for(let s of i){if(s.name.startsWith(".")&&!s.name.endsWith("proj")&&!s.name.endsWith("sln")&&s.isDirectory())continue;let a=le(r,s.name);if(s.isDirectory()){Ve.has(s.name)||n.push(a);continue}let m=Qe(s.name).toLowerCase();m&&e.add(m)}}return e}function it(t,e){return e?.length?e.some(n=>t.has(n)):!1}function oe(t,e){let n=t.indexOf(e);n!==-1&&t.splice(n,1)}import{existsSync as ce,readdirSync as st}from"fs";import{join as M}from"path";var W={typescript:{language:"typescript",indexerBinary:"scip-typescript",checkCommand:"npx scip-typescript --version",indexArgs:({outputPath:t,pnpmWorkspaces:e})=>{let n=["scip-typescript","index","--infer-tsconfig","--output",t,"--no-progress-bar"];return e&&n.splice(2,0,"--pnpm-workspaces"),{binary:"npx",args:n}},markerFiles:["tsconfig.json"],installMethods:[{label:"npm",prerequisite:"npm",binary:"npm",args:["install","-g","@sourcegraph/scip-typescript"]}],installUrl:"https://github.com/sourcegraph/scip-typescript",bundledNpmPackage:"@sourcegraph/scip-typescript"},javascript:{language:"javascript",indexerBinary:"scip-typescript",checkCommand:"npx scip-typescript --version",indexArgs:({outputPath:t})=>({binary:"npx",args:["scip-typescript","index","--infer-tsconfig","--output",t,"--no-progress-bar"]}),markerFiles:["package.json"],installMethods:[{label:"npm",prerequisite:"npm",binary:"npm",args:["install","-g","@sourcegraph/scip-typescript"]}],installUrl:"https://github.com/sourcegraph/scip-typescript",bundledNpmPackage:"@sourcegraph/scip-typescript"},java:{language:"java",indexerBinary:"scip-java",checkCommand:"scip-java --version",indexArgs:({outputPath:t})=>({binary:"scip-java",args:["index","--output",t]}),markerFiles:["pom.xml","build.gradle"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-java/releases"},scala:{language:"scala",indexerBinary:"scip-java",checkCommand:"scip-java --version",indexArgs:({outputPath:t})=>({binary:"scip-java",args:["index","--output",t]}),markerFiles:["build.sbt"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-java/releases"},kotlin:{language:"kotlin",indexerBinary:"scip-java",checkCommand:"scip-java --version",indexArgs:({outputPath:t})=>({binary:"scip-java",args:["index","--output",t]}),markerFiles:["build.gradle.kts"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-java/releases"},rust:{language:"rust",indexerBinary:"rust-analyzer",checkCommand:"rust-analyzer --version",indexArgs:({outputPath:t})=>({binary:"rust-analyzer",args:["scip",".","--output",t]}),markerFiles:["Cargo.toml"],installMethods:[{label:"rustup",prerequisite:"rustup",binary:"rustup",args:["component","add","rust-analyzer"]}],installUrl:"https://github.com/rust-lang/rust-analyzer"},python:{language:"python",indexerBinary:"scip-python",binaryAliases:["scip-python-plus"],checkCommand:"npx scip-python --version",indexArgs:({outputPath:t})=>({binary:"npx",args:["scip-python","index","--output",t,"--project-name","project"]}),markerFiles:["pyproject.toml","setup.py"],installMethods:[{label:"npm",prerequisite:"npm",binary:"npm",args:["install","-g","scip-python-plus"]}],installUrl:"https://github.com/PlunderStruck/scip-python",bundledNpmPackage:"scip-python-plus"},ruby:{language:"ruby",indexerBinary:"scip-ruby",checkCommand:"scip-ruby --version",indexArgs:({indexerBinary:t})=>({binary:t,args:["--dir","."]}),defaultOutputPath:"index.scip",markerFiles:["Gemfile"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-ruby/releases"},go:{language:"go",indexerBinary:"scip-go",checkCommand:"scip-go --version",indexArgs:({outputPath:t})=>({binary:"scip-go",args:["--output",t]}),markerFiles:["go.mod"],installMethods:[{label:"go install",prerequisite:"go",binary:"go",args:["install","github.com/sourcegraph/scip-go@latest"]}],installUrl:"https://github.com/sourcegraph/scip-go"},cpp:{language:"cpp",indexerBinary:"scip-clang",checkCommand:"scip-clang --version",indexArgs:({outputPath:t})=>({binary:"scip-clang",args:["--compdb-path","compile_commands.json","--index-output-path",t]}),markerFiles:["CMakeLists.txt","Makefile"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-clang/releases"},c:{language:"c",indexerBinary:"scip-clang",checkCommand:"scip-clang --version",indexArgs:({outputPath:t})=>({binary:"scip-clang",args:["--compdb-path","compile_commands.json","--index-output-path",t]}),markerFiles:["CMakeLists.txt","Makefile"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-clang/releases"},csharp:{language:"csharp",indexerBinary:"scip-dotnet",checkCommand:"scip-dotnet --version",indexArgs:({projectRoot:t,outputPath:e})=>({binary:"scip-dotnet",args:["index",ue(t,[".sln",".csproj"])??t,"--output",e,"--working-directory",t]}),markerFiles:["*.csproj","*.sln"],installMethods:[{label:"dotnet",prerequisite:"dotnet",binary:"dotnet",args:["tool","install","--global","scip-dotnet"]}],installUrl:"https://github.com/sourcegraph/scip-dotnet/releases"},vb:{language:"vb",indexerBinary:"scip-dotnet",checkCommand:"scip-dotnet --version",indexArgs:({projectRoot:t,outputPath:e})=>({binary:"scip-dotnet",args:["index",ue(t,[".sln",".vbproj"])??t,"--output",e,"--working-directory",t]}),markerFiles:["*.vbproj","*.sln"],installMethods:[{label:"dotnet",prerequisite:"dotnet",binary:"dotnet",args:["tool","install","--global","scip-dotnet"]}],installUrl:"https://github.com/sourcegraph/scip-dotnet/releases"},dart:{language:"dart",indexerBinary:"scip-dart",checkCommand:"scip-dart --version",indexArgs:({indexerBinary:t,outputPath:e})=>({binary:t,args:["--output",e]}),markerFiles:["pubspec.yaml"],installMethods:[{label:"dart pub",prerequisite:"dart",binary:"dart",args:["pub","global","activate","scip_dart"]}],installUrl:"https://github.com/Workiva/scip-dart/releases"},php:{language:"php",indexerBinary:"scip-php",projectLocalBinaries:["vendor/davidrjenni/scip-php/bin/scip-php","vendor/bin/scip-php"],checkCommand:"scip-php --version",indexArgs:({projectRoot:t,indexerBinary:e})=>{let n=M(t,"vendor","bin","scip-php"),r=M(t,"vendor","davidrjenni","scip-php","bin","scip-php");return{binary:"php",args:["-d","error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED",ce(r)?r:ce(n)?n:e]}},defaultOutputPath:"index.scip",markerFiles:["composer.json"],installMethods:[],installUrl:"https://github.com/davidrjenni/scip-php/releases"}};function E(t){return W[t]}function ue(t,e){let n;try{n=st(t)}catch{return null}for(let r of n)if(e.some(i=>r.endsWith(i)))return M(t,r);return null}import{readFileSync as ot,writeFileSync as at}from"fs";import{create as U}from"@bufbuild/protobuf";import{deserializeSCIP as lt,serializeSCIP as ct,DocumentSchema as ut,IndexSchema as pt,SymbolInformationSchema as dt}from"@c4312/scip";function q(t){if(t.length===0)throw new Error("Cannot merge zero SCIP indexes");if(t.length===1)return t[0];let e=gt(t),n=ht(t.flatMap(i=>i.documents??[])),r=pe(t.flatMap(i=>i.externalSymbols??[]));return U(pt,{metadata:e,documents:n,externalSymbols:r})}function j(t,e){if(t.length===0)throw new Error("Cannot merge zero SCIP files");let n=t.map(i=>lt(ot(i))),r=q(n);return at(e,Buffer.from(ct(r))),{documentCount:r.documents.length,externalSymbolCount:r.externalSymbols.length,inputCount:t.length}}function gt(t){let e=t[0]?.metadata;if(!e)return;let n=e.projectRoot;for(let r of t.slice(1)){let i=r.metadata?.projectRoot;if(n&&i&&i!==n)throw new Error(`Cannot merge SCIP indexes with different project roots: ${n} vs ${i}`)}return e}function ht(t){let e=new Map;for(let n of t){let r=e.get(n.relativePath);if(!r){e.set(n.relativePath,n);continue}e.set(n.relativePath,U(ut,{language:r.language||n.language,relativePath:r.relativePath||n.relativePath,occurrences:[...r.occurrences,...n.occurrences],symbols:pe([...r.symbols,...n.symbols]),text:ft(r.text,n.text),positionEncoding:r.positionEncoding||n.positionEncoding}))}return[...e.values()]}function pe(t){let e=new Map;for(let n of t){let r=e.get(n.symbol);if(!r){e.set(n.symbol,n);continue}e.set(n.symbol,U(dt,{symbol:r.symbol,documentation:yt([...r.documentation,...n.documentation]),relationships:mt([...r.relationships,...n.relationships]),kind:r.kind||n.kind,displayName:r.displayName||n.displayName,enclosingSymbol:r.enclosingSymbol||n.enclosingSymbol,signatureDocumentation:r.signatureDocumentation??n.signatureDocumentation}))}return[...e.values()]}function mt(t){let e=new Set,n=[];for(let r of t){let i=[r.symbol,r.isReference?"1":"0",r.isImplementation?"1":"0",r.isTypeDefinition?"1":"0",r.isDefinition?"1":"0"].join("|");e.has(i)||(e.add(i),n.push(r))}return n}function ft(t,e){return t?e?t.length>=e.length?t:e:t:e}function yt(t){return[...new Set(t)]}import{execFileSync as _}from"child_process";import{existsSync as H}from"fs";import{createRequire as xt}from"module";import{platform as de}from"os";import{join as ge}from"path";var bt=xt(import.meta.url),vt=de()==="win32";function f(t){let e=vt?"where":"which";try{return _(e,[t],{stdio:"pipe"}),!0}catch{return!1}}function he(t){return[t.indexerBinary,...t.binaryAliases??[]]}function R(t){let e=he(t);return e.length===1?e[0]:e.join(" or ")}function I(t){for(let e of he(t))if(f(e))return e;return me(t)?t.indexerBinary:null}function D(t){return I(t)!==null||me(t)}function me(t){if(!t.bundledNpmPackage)return!1;try{return bt.resolve(`${t.bundledNpmPackage}/package.json`),!0}catch{return!1}}function G(t,e){for(let n of t.projectLocalBinaries??[]){let r=ge(e,n);if(H(r))return r}return null}function z(t,e=process.env,n=t.indexerBinary){if(t.indexerBinary!=="scip-dotnet"||fe(n,e))return e;let r=St(n,e);return r?{...e,DOTNET_ROOT:r}:e}function $(t,e){let n=t.installMethods,r=R(t);if(!n?.length)return e(`No auto-install method available for ${r}.`),t.installUrl&&e(`Install manually from: ${t.installUrl}`),!1;for(let i of n)if(f(i.prerequisite)){e(`Installing ${r} via ${i.label}...`);try{_(i.binary,i.args,{stdio:"inherit",timeout:3e5,env:process.env});let s=I(t);if(s){let a=s===t.indexerBinary?"":` (using ${s})`;return e(`Successfully installed ${r} via ${i.label}${a}`),!0}e(`${i.label} command completed but ${r} was not found on PATH`)}catch(s){let a=s instanceof Error?s.message:String(s);e(`${i.label} install failed: ${a}`)}}return e(`Could not auto-install ${r}.`),t.installUrl&&e(`Install manually from: ${t.installUrl}`),!1}function St(t,e){for(let n of It(e))if(fe(t,{...e,DOTNET_ROOT:n}))return n;return null}function It(t){let e=[],n=t.DOTNET_ROOT;if(n&&H(n)&&e.push(n),de()==="darwin"&&f("brew"))try{let r=_("brew",["--prefix","dotnet@9"],{stdio:"pipe",env:t}).toString().trim(),i=ge(r,"libexec");H(i)&&!e.includes(i)&&e.push(i)}catch{}return e}function fe(t,e){try{return _(t,["--version"],{stdio:"pipe",env:e}),!0}catch{return!1}}async function Et(t){let{projectRoot:e,maxHeapMb:n=8192,onStatus:r=console.log,skipAutoInstall:i=!1}=t,s=t.outputScip??T(e,"index.scip"),a=t.outputDb??T(e,"index.db"),m=Date.now(),l=t.languages??P(e);if(l.length===0)throw new Error("No supported languages detected in this project. Looked for: tsconfig.json, Cargo.toml, go.mod, pyproject.toml, etc.");if(r(`Detected languages: ${l.join(", ")}`),!f("scip")){if(i)throw new Error(`The scip CLI is required but not found on PATH.
80
+ Install from: https://github.com/sourcegraph/scip/releases`);if(r("scip CLI not found on PATH. Attempting auto-install..."),!w(r))throw new Error(`The scip CLI is required but could not be installed.
81
+ Install manually from: https://github.com/sourcegraph/scip/releases`)}let u={...process.env,NODE_OPTIONS:`--max-old-space-size=${n}`},x=l.map((o,h)=>({language:o,scipPath:l.length>1?_t(s,o,h):s})),c=[],g=[];for(let{language:o,scipPath:h}of x){let d=E(o),b=R(d),Z=G(d,e);if(!Z&&!D(d)){if(i){let p=`${b} not found on PATH (auto-install disabled). ${d.installUrl??""}`.trim();r(`Skipping ${o}: ${p}`),g.push({language:o,reason:p});continue}if(r(`${b} not found. Attempting auto-install...`),!$(d,r)){let p=`${b} could not be auto-installed. ${d.installUrl?`Install manually from ${d.installUrl}`:`Install ${b} and put it on PATH.`}`;r(`Skipping ${o}: ${p}`),g.push({language:o,reason:p});continue}}let v=Z??I(d);if(!v){let p=`${b} was not found after installation checks.`;r(`Skipping ${o}: ${p}`),g.push({language:o,reason:p});continue}r(`Indexing ${o} with ${v}...`);let _e=z(d,u,v),{binary:Re,args:De}=d.indexArgs({projectRoot:e,outputPath:h,pnpmWorkspaces:t.pnpmWorkspaces,indexerBinary:v});try{ye(Re,De,{cwd:e,env:_e,stdio:"pipe",maxBuffer:50*1024*1024})}catch(p){let $e=p instanceof Error?p.message:String(p),ee=`${v} indexer failed: ${$e.split(`
82
+ `)[0]}`;r(`Skipping ${o}: ${ee}`),g.push({language:o,reason:ee});continue}jt(d,e,h),c.push({language:o,scipPath:h})}if(c.length===0){let o=g.map(h=>` - ${h.language}: ${h.reason}`).join(`
83
+ `);throw new Error(`No language indexers ran successfully. Install at least one indexer for the languages in this project.
84
+ `+o)}if(g.length>0&&r(`Indexed ${c.length} of ${l.length} languages; skipped ${g.map(o=>o.language).join(", ")}.`),l.length>1&&(c.length>1?(r(`Merging ${c.length} language indexes...`),j(c.map(o=>o.scipPath),s)):c[0].scipPath!==s&&be(c[0].scipPath,s)),r("Converting to SQLite..."),!xe(s))throw new Error(`SCIP index not found at ${s} after indexing`);try{ye("scip",["expt-convert","--output",a,s],{env:u,stdio:"pipe",maxBuffer:50*1024*1024})}catch(o){let h=o instanceof Error?o.message:String(o);throw new Error(`Failed to convert SCIP index to SQLite: ${h}`,{cause:o})}finally{for(let{scipPath:o}of x)o!==s&&Ct(o,{force:!0})}let Y=Date.now()-m;return r(`Done in ${(Y/1e3).toFixed(1)}s`),{languages:c.map(o=>o.language),indexPath:s,dbPath:a,durationMs:Y,skipped:g}}function jt(t,e,n){if(!t.defaultOutputPath)return;let r=T(e,t.defaultOutputPath);n!==r&&xe(r)&&be(r,n)}function _t(t,e,n){let r=Pt(t)||".scip",i=kt(t,r);return T(wt(t),`${i}.${n+1}.${e}${r}`)}import{readFileSync as Rt,writeFileSync as Dt,existsSync as Se,mkdirSync as $t}from"fs";import{join as y,resolve as ve}from"path";import{createHash as Tt}from"crypto";import{homedir as Lt}from"os";var Ie=".scipquery.json",Ft={enabled:!1,debounceMs:3e4,cooldownMs:6e4,ignore:[]};function Nt(t){let e=y(t,Ie);if(!Se(e))return{};try{let n=Rt(e,"utf-8");return JSON.parse(n)}catch{return{}}}function Ce(t){return{...Ft,...t.watch}}function ke(t,e){let n=process.env.SCIP_QUERY_CACHE_DIR;if(n)return J(n);if(e?.dbPath)return J(ve(t,e.dbPath));let i=process.env.XDG_CACHE_HOME||y(Lt(),".cache"),s=Tt("sha256").update(ve(t)).digest("hex").slice(0,12),a=y(i,"scip-query","projects",s);return J(a)}function X(t,e){let n=ke(t,e);return{cacheDir:n,dbPath:y(n,"index.db"),indexPath:y(n,"index.scip"),metaPath:y(n,"meta.json")}}function At(t,e){let n=y(t,Ie);return Se(n)||Dt(n,JSON.stringify({languages:e,watch:{enabled:!1,debounceMs:3e4,cooldownMs:6e4}},null,2)+`
85
+ `),n}function J(t){return $t(t,{recursive:!0}),t}import{watch as Ot}from"fs";import{existsSync as we,renameSync as Pe}from"fs";import{join as Bt,relative as Mt}from"path";import{fork as Wt}from"child_process";import Ut from"ignore";var K=class{projectRoot;watchConfig;indexPaths;languages;pnpmWorkspaces;onStatus;onReindexComplete;onError;status={state:"idle"};debounceTimer=null;cooldownTimer=null;dirty=!1;changedFiles=0;reindexInFlight=!1;lastReindexEnd=0;fsWatchers=[];gitignoreFilter;extraIgnore;stopped=!1;constructor(e){this.projectRoot=e.projectRoot,this.watchConfig=Ce(e.config),this.indexPaths=X(e.projectRoot,e.config),this.languages=e.languages,this.pnpmWorkspaces=e.config.indexer?.typescript?.pnpmWorkspaces??!1,this.onStatus=e.onStatus??(()=>{}),this.onReindexComplete=e.onReindexComplete??(()=>{}),this.onError=e.onError??(n=>console.error(n.message)),this.gitignoreFilter=B(e.projectRoot),this.extraIgnore=Ut(),this.watchConfig.ignore.length>0&&this.extraIgnore.add(this.watchConfig.ignore)}start(){this.stopped=!1,this.setStatus({state:"idle"});try{let e=Ot(this.projectRoot,{recursive:!0},(n,r)=>{r&&!this.stopped&&this.handleFileChange(r)});this.fsWatchers.push(e)}catch{this.onError(new Error("Failed to start file watcher. On Linux, you may need to increase inotify limits: sysctl -w fs.inotify.max_user_watches=524288"))}}stop(){this.stopped=!0;for(let e of this.fsWatchers)e.close();this.fsWatchers=[],this.debounceTimer&&clearTimeout(this.debounceTimer),this.cooldownTimer&&clearTimeout(this.cooldownTimer),this.setStatus({state:"idle"})}handleFileChange(e){let n=Mt(this.projectRoot,Bt(this.projectRoot,e));if(this.gitignoreFilter.isIgnored(n)||this.extraIgnore.ignores(n)||e.endsWith("index.db")||e.endsWith("index.scip")||e.endsWith("index.db.tmp")||e.endsWith(".scipquery.json"))return;if(this.changedFiles++,this.reindexInFlight){this.dirty=!0,this.setStatus({state:"indexing",startedAt:this.status.startedAt});return}if(this.status.state==="cooldown"){this.dirty=!0,this.setStatus({state:"cooldown",until:this.status.until,dirty:!0});return}this.debounceTimer&&clearTimeout(this.debounceTimer);let r=Date.now()+this.watchConfig.debounceMs;this.setStatus({state:"waiting",changedFiles:this.changedFiles,reindexAt:r}),this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.triggerReindex()},this.watchConfig.debounceMs)}triggerReindex(){if(this.reindexInFlight||this.stopped)return;let e=Date.now()-this.lastReindexEnd;if(this.lastReindexEnd>0&&e<this.watchConfig.cooldownMs){let r=this.watchConfig.cooldownMs-e;this.dirty=!0;let i=Date.now()+r;this.setStatus({state:"cooldown",until:i,dirty:!0}),this.cooldownTimer=setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped&&(this.dirty=!1,this.triggerReindex())},r);return}this.reindexInFlight=!0,this.dirty=!1,this.changedFiles=0;let n=Date.now();this.setStatus({state:"indexing",startedAt:n}),this.runReindex().then(r=>{if(this.reindexInFlight=!1,this.lastReindexEnd=Date.now(),this.onReindexComplete(r),this.dirty&&!this.stopped){let i=Date.now()+this.watchConfig.cooldownMs;this.setStatus({state:"cooldown",until:i,dirty:!0}),this.cooldownTimer=setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped?(this.dirty=!1,this.triggerReindex()):this.setStatus({state:"idle"})},this.watchConfig.cooldownMs)}else this.setStatus({state:"idle"})}).catch(r=>{this.reindexInFlight=!1,this.lastReindexEnd=Date.now(),this.onError(r instanceof Error?r:new Error(String(r))),this.setStatus({state:"idle"})})}runReindex(){return new Promise((e,n)=>{let r=Date.now(),i=this.indexPaths.dbPath+".tmp",s=qt(this.indexPaths.indexPath),a=Wt(new URL("./reindex-worker.js",import.meta.url).pathname,[],{env:{...process.env,SCIP_REINDEX_PROJECT_ROOT:this.projectRoot,SCIP_REINDEX_OUTPUT_SCIP:s,SCIP_REINDEX_OUTPUT_DB:i,SCIP_REINDEX_LANGUAGES:this.languages?.join(",")??"",SCIP_REINDEX_PNPM_WORKSPACES:this.pnpmWorkspaces?"1":""},stdio:"pipe"});a.on("exit",m=>{if(m===0)try{we(i)&&Pe(i,this.indexPaths.dbPath),we(s)&&Pe(s,this.indexPaths.indexPath),e(Date.now()-r)}catch(l){n(new Error(`Atomic swap failed: ${l}`))}else n(new Error(`Reindex worker exited with code ${m}`))}),a.on("error",n)})}setStatus(e){this.status=e,this.onStatus(e)}};function qt(t){return t.endsWith(".scip")?t.slice(0,-5)+".tmp.scip":t+".tmp.scip"}import{existsSync as Q,mkdirSync as Ht,symlinkSync as Gt,readlinkSync as zt,unlinkSync as Jt}from"fs";import{join as L,dirname as Ee,resolve as V}from"path";import{homedir as je,platform as Xt}from"os";import{fileURLToPath as Kt}from"url";var Qt=Xt()==="win32",Vt=["concrete-plan","scip-explore","scip-debloat","scip-verify","scip-language-playbook"];function Yt(t={}){let e=t.quiet?()=>{}:console.log,n=Kt(import.meta.url),r=V(Ee(n),"..","skills"),i=[L(je(),".claude","skills"),L(je(),".codex","skills")],s={installed:[],skipped:[],alreadyLinked:[]};for(let a of i){let m=Ee(a);if(!Q(m))continue;Ht(a,{recursive:!0});let l=a.includes(".codex")?"Codex":"Claude";for(let u of Vt){let x=L(r,u),c=L(a,u);if(!Q(x)){s.skipped.push(`${l}/${u}`);continue}if(Q(c)){try{let g=zt(c);if(V(g)===V(x)){s.alreadyLinked.push(`${l}/${u}`),e(` ok: ${u} \u2192 ${l} (already linked)`);continue}}catch{s.skipped.push(`${l}/${u}`),e(` skip: ${u} \u2192 ${l} (exists, not a symlink)`);continue}Jt(c)}Gt(x,c,Qt?"junction":"dir"),s.installed.push(`${l}/${u}`),e(` done: ${u} \u2192 ${l}`)}}return s}export{W as INDEXER_CONFIGS,F as ScipDatabase,K as Watcher,Nn as affected,kn as bottlenecks,Pn as byKind,Rn as callGraph,An as changeSurface,zn as code,Jn as complexity,qn as complexityHotspots,Gn as convergence,Sn as coupling,B as createGitignoreFilter,Cn as cycles,Xn as dataflow,un as dead,jn as deepChains,on as deps,P as detectLanguages,On as diffImpact,Bn as drift,Fn as extractCandidates,yn as fanIn,xn as fanOut,en as files,E as getIndexerConfig,ze as getScipVersion,Hn as health,_n as hierarchy,pn as hotspots,gn as importedBy,dn as imports,At as initProjectConfig,Yt as installSkills,f as isBinaryAvailable,D as isIndexerInstalled,Ge as isScipInstalled,wn as isolated,En as kindCounts,Fe as leafName,Nt as loadProjectConfig,fn as members,j as mergeScipFiles,q as mergeScipIndexes,nn as methods,mn as outline,Te as parseSymbol,Wn as passthroughCandidates,Xe as printScipInstallInstructions,an as rdeps,Qn as redundantReexports,rn as refs,Et as reindex,ke as resolveCacheDir,X as resolveIndexPaths,Le as shortenSymbol,Dn as similar,$n as similarAll,Ln as similarChains,Tn as similarFiles,Vn as similarSignatures,Kn as slice,Un as staleAbstractions,Zt as stats,cn as surface,tn as symbols,ln as system,In as topCoupling,bn as topFanIn,vn as topFanOut,sn as trace,$ as tryInstallIndexer,w as tryInstallScipCli,hn as unusedImports,Mn as wrapperCandidates};
1689
86
  //# sourceMappingURL=index.js.map