@creeperhost/modlens-mcp 1.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 (382) hide show
  1. package/README.md +938 -0
  2. package/dist/access-flags.d.ts +58 -0
  3. package/dist/access-flags.d.ts.map +1 -0
  4. package/dist/access-flags.js +79 -0
  5. package/dist/access-flags.js.map +1 -0
  6. package/dist/access-flags.test.d.ts +2 -0
  7. package/dist/access-flags.test.d.ts.map +1 -0
  8. package/dist/access-flags.test.js +189 -0
  9. package/dist/access-flags.test.js.map +1 -0
  10. package/dist/batch-ingest.d.ts +2 -0
  11. package/dist/batch-ingest.d.ts.map +1 -0
  12. package/dist/batch-ingest.js +54 -0
  13. package/dist/batch-ingest.js.map +1 -0
  14. package/dist/batch-resolve-mixins.d.ts +2 -0
  15. package/dist/batch-resolve-mixins.d.ts.map +1 -0
  16. package/dist/batch-resolve-mixins.js +36 -0
  17. package/dist/batch-resolve-mixins.js.map +1 -0
  18. package/dist/cache.d.ts +16 -0
  19. package/dist/cache.d.ts.map +1 -0
  20. package/dist/cache.js +36 -0
  21. package/dist/cache.js.map +1 -0
  22. package/dist/cli.d.ts +2 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +1318 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/curseforge.d.ts +53 -0
  27. package/dist/curseforge.d.ts.map +1 -0
  28. package/dist/curseforge.js +104 -0
  29. package/dist/curseforge.js.map +1 -0
  30. package/dist/db-backend.d.ts +17 -0
  31. package/dist/db-backend.d.ts.map +1 -0
  32. package/dist/db-backend.js +40 -0
  33. package/dist/db-backend.js.map +1 -0
  34. package/dist/db.d.ts +11 -0
  35. package/dist/db.d.ts.map +1 -0
  36. package/dist/db.js +55 -0
  37. package/dist/db.js.map +1 -0
  38. package/dist/embed-queue.d.ts +12 -0
  39. package/dist/embed-queue.d.ts.map +1 -0
  40. package/dist/embed-queue.js +103 -0
  41. package/dist/embed-queue.js.map +1 -0
  42. package/dist/embeddings.d.ts +21 -0
  43. package/dist/embeddings.d.ts.map +1 -0
  44. package/dist/embeddings.js +55 -0
  45. package/dist/embeddings.js.map +1 -0
  46. package/dist/env-path.d.ts +19 -0
  47. package/dist/env-path.d.ts.map +1 -0
  48. package/dist/env-path.js +40 -0
  49. package/dist/env-path.js.map +1 -0
  50. package/dist/fetch-utils.d.ts +24 -0
  51. package/dist/fetch-utils.d.ts.map +1 -0
  52. package/dist/fetch-utils.js +73 -0
  53. package/dist/fetch-utils.js.map +1 -0
  54. package/dist/fetch-utils.test.d.ts +2 -0
  55. package/dist/fetch-utils.test.d.ts.map +1 -0
  56. package/dist/fetch-utils.test.js +133 -0
  57. package/dist/fetch-utils.test.js.map +1 -0
  58. package/dist/generated/sqlite/browser.d.ts +55 -0
  59. package/dist/generated/sqlite/browser.d.ts.map +1 -0
  60. package/dist/generated/sqlite/browser.js +18 -0
  61. package/dist/generated/sqlite/browser.js.map +1 -0
  62. package/dist/generated/sqlite/client.d.ts +72 -0
  63. package/dist/generated/sqlite/client.d.ts.map +1 -0
  64. package/dist/generated/sqlite/client.js +33 -0
  65. package/dist/generated/sqlite/client.js.map +1 -0
  66. package/dist/generated/sqlite/commonInputTypes.d.ts +387 -0
  67. package/dist/generated/sqlite/commonInputTypes.d.ts.map +1 -0
  68. package/dist/generated/sqlite/commonInputTypes.js +11 -0
  69. package/dist/generated/sqlite/commonInputTypes.js.map +1 -0
  70. package/dist/generated/sqlite/enums.d.ts +2 -0
  71. package/dist/generated/sqlite/enums.d.ts.map +1 -0
  72. package/dist/generated/sqlite/enums.js +11 -0
  73. package/dist/generated/sqlite/enums.js.map +1 -0
  74. package/dist/generated/sqlite/internal/class.d.ts +226 -0
  75. package/dist/generated/sqlite/internal/class.d.ts.map +1 -0
  76. package/dist/generated/sqlite/internal/class.js +84 -0
  77. package/dist/generated/sqlite/internal/class.js.map +1 -0
  78. package/dist/generated/sqlite/internal/prismaNamespace.d.ts +1344 -0
  79. package/dist/generated/sqlite/internal/prismaNamespace.d.ts.map +1 -0
  80. package/dist/generated/sqlite/internal/prismaNamespace.js +220 -0
  81. package/dist/generated/sqlite/internal/prismaNamespace.js.map +1 -0
  82. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts +204 -0
  83. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts.map +1 -0
  84. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js +191 -0
  85. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js.map +1 -0
  86. package/dist/generated/sqlite/models/DocEntry.d.ts +1223 -0
  87. package/dist/generated/sqlite/models/DocEntry.d.ts.map +1 -0
  88. package/dist/generated/sqlite/models/DocEntry.js +2 -0
  89. package/dist/generated/sqlite/models/DocEntry.js.map +1 -0
  90. package/dist/generated/sqlite/models/McSourceFile.d.ts +1289 -0
  91. package/dist/generated/sqlite/models/McSourceFile.d.ts.map +1 -0
  92. package/dist/generated/sqlite/models/McSourceFile.js +2 -0
  93. package/dist/generated/sqlite/models/McSourceFile.js.map +1 -0
  94. package/dist/generated/sqlite/models/McVersion.d.ts +1315 -0
  95. package/dist/generated/sqlite/models/McVersion.d.ts.map +1 -0
  96. package/dist/generated/sqlite/models/McVersion.js +2 -0
  97. package/dist/generated/sqlite/models/McVersion.js.map +1 -0
  98. package/dist/generated/sqlite/models/McVersionDiff.d.ts +1061 -0
  99. package/dist/generated/sqlite/models/McVersionDiff.d.ts.map +1 -0
  100. package/dist/generated/sqlite/models/McVersionDiff.js +2 -0
  101. package/dist/generated/sqlite/models/McVersionDiff.js.map +1 -0
  102. package/dist/generated/sqlite/models/Mod.d.ts +2396 -0
  103. package/dist/generated/sqlite/models/Mod.d.ts.map +1 -0
  104. package/dist/generated/sqlite/models/Mod.js +2 -0
  105. package/dist/generated/sqlite/models/Mod.js.map +1 -0
  106. package/dist/generated/sqlite/models/ModClass.d.ts +1254 -0
  107. package/dist/generated/sqlite/models/ModClass.d.ts.map +1 -0
  108. package/dist/generated/sqlite/models/ModClass.js +2 -0
  109. package/dist/generated/sqlite/models/ModClass.js.map +1 -0
  110. package/dist/generated/sqlite/models/ModSourceFile.d.ts +1283 -0
  111. package/dist/generated/sqlite/models/ModSourceFile.d.ts.map +1 -0
  112. package/dist/generated/sqlite/models/ModSourceFile.js +2 -0
  113. package/dist/generated/sqlite/models/ModSourceFile.js.map +1 -0
  114. package/dist/generated/sqlite/models/ModTag.d.ts +1278 -0
  115. package/dist/generated/sqlite/models/ModTag.d.ts.map +1 -0
  116. package/dist/generated/sqlite/models/ModTag.js +2 -0
  117. package/dist/generated/sqlite/models/ModTag.js.map +1 -0
  118. package/dist/generated/sqlite/models/ModVersionDiff.d.ts +1073 -0
  119. package/dist/generated/sqlite/models/ModVersionDiff.d.ts.map +1 -0
  120. package/dist/generated/sqlite/models/ModVersionDiff.js +2 -0
  121. package/dist/generated/sqlite/models/ModVersionDiff.js.map +1 -0
  122. package/dist/generated/sqlite/models/Primer.d.ts +1319 -0
  123. package/dist/generated/sqlite/models/Primer.d.ts.map +1 -0
  124. package/dist/generated/sqlite/models/Primer.js +2 -0
  125. package/dist/generated/sqlite/models/Primer.js.map +1 -0
  126. package/dist/generated/sqlite/models.d.ts +12 -0
  127. package/dist/generated/sqlite/models.d.ts.map +1 -0
  128. package/dist/generated/sqlite/models.js +2 -0
  129. package/dist/generated/sqlite/models.js.map +1 -0
  130. package/dist/jar.d.ts +7 -0
  131. package/dist/jar.d.ts.map +1 -0
  132. package/dist/jar.js +52 -0
  133. package/dist/jar.js.map +1 -0
  134. package/dist/java-tools.d.ts +46 -0
  135. package/dist/java-tools.d.ts.map +1 -0
  136. package/dist/java-tools.js +263 -0
  137. package/dist/java-tools.js.map +1 -0
  138. package/dist/launcher.d.ts +3 -0
  139. package/dist/launcher.d.ts.map +1 -0
  140. package/dist/launcher.js +105 -0
  141. package/dist/launcher.js.map +1 -0
  142. package/dist/mappings.d.ts +95 -0
  143. package/dist/mappings.d.ts.map +1 -0
  144. package/dist/mappings.js +1094 -0
  145. package/dist/mappings.js.map +1 -0
  146. package/dist/mappings.test.d.ts +2 -0
  147. package/dist/mappings.test.d.ts.map +1 -0
  148. package/dist/mappings.test.js +161 -0
  149. package/dist/mappings.test.js.map +1 -0
  150. package/dist/minecraft.d.ts +21 -0
  151. package/dist/minecraft.d.ts.map +1 -0
  152. package/dist/minecraft.js +70 -0
  153. package/dist/minecraft.js.map +1 -0
  154. package/dist/modpacks-ch.d.ts +224 -0
  155. package/dist/modpacks-ch.d.ts.map +1 -0
  156. package/dist/modpacks-ch.js +146 -0
  157. package/dist/modpacks-ch.js.map +1 -0
  158. package/dist/modrinth.d.ts +67 -0
  159. package/dist/modrinth.d.ts.map +1 -0
  160. package/dist/modrinth.js +88 -0
  161. package/dist/modrinth.js.map +1 -0
  162. package/dist/platform-adapter.d.ts +23 -0
  163. package/dist/platform-adapter.d.ts.map +1 -0
  164. package/dist/platform-adapter.js +2 -0
  165. package/dist/platform-adapter.js.map +1 -0
  166. package/dist/platform.d.ts +47 -0
  167. package/dist/platform.d.ts.map +1 -0
  168. package/dist/platform.js +175 -0
  169. package/dist/platform.js.map +1 -0
  170. package/dist/processor.d.ts +51 -0
  171. package/dist/processor.d.ts.map +1 -0
  172. package/dist/processor.js +655 -0
  173. package/dist/processor.js.map +1 -0
  174. package/dist/processor.test.d.ts +2 -0
  175. package/dist/processor.test.d.ts.map +1 -0
  176. package/dist/processor.test.js +629 -0
  177. package/dist/processor.test.js.map +1 -0
  178. package/dist/repositories/embeddings-sqlite.d.ts +38 -0
  179. package/dist/repositories/embeddings-sqlite.d.ts.map +1 -0
  180. package/dist/repositories/embeddings-sqlite.js +208 -0
  181. package/dist/repositories/embeddings-sqlite.js.map +1 -0
  182. package/dist/repositories/embeddings.d.ts +40 -0
  183. package/dist/repositories/embeddings.d.ts.map +1 -0
  184. package/dist/repositories/embeddings.js +136 -0
  185. package/dist/repositories/embeddings.js.map +1 -0
  186. package/dist/repositories/index.d.ts +2 -0
  187. package/dist/repositories/index.d.ts.map +1 -0
  188. package/dist/repositories/index.js +15 -0
  189. package/dist/repositories/index.js.map +1 -0
  190. package/dist/repositories/mcVersion.d.ts +16 -0
  191. package/dist/repositories/mcVersion.d.ts.map +1 -0
  192. package/dist/repositories/mcVersion.js +52 -0
  193. package/dist/repositories/mcVersion.js.map +1 -0
  194. package/dist/repositories/mod.d.ts +241 -0
  195. package/dist/repositories/mod.d.ts.map +1 -0
  196. package/dist/repositories/mod.js +342 -0
  197. package/dist/repositories/mod.js.map +1 -0
  198. package/dist/repositories/packs.d.ts +44 -0
  199. package/dist/repositories/packs.d.ts.map +1 -0
  200. package/dist/repositories/packs.js +138 -0
  201. package/dist/repositories/packs.js.map +1 -0
  202. package/dist/search-adapter.d.ts +34 -0
  203. package/dist/search-adapter.d.ts.map +1 -0
  204. package/dist/search-adapter.js +195 -0
  205. package/dist/search-adapter.js.map +1 -0
  206. package/dist/search.d.ts +6 -0
  207. package/dist/search.d.ts.map +1 -0
  208. package/dist/search.js +54 -0
  209. package/dist/search.js.map +1 -0
  210. package/dist/search.test.d.ts +2 -0
  211. package/dist/search.test.d.ts.map +1 -0
  212. package/dist/search.test.js +71 -0
  213. package/dist/search.test.js.map +1 -0
  214. package/dist/security.d.ts +98 -0
  215. package/dist/security.d.ts.map +1 -0
  216. package/dist/security.js +446 -0
  217. package/dist/security.js.map +1 -0
  218. package/dist/security.test.d.ts +2 -0
  219. package/dist/security.test.d.ts.map +1 -0
  220. package/dist/security.test.js +687 -0
  221. package/dist/security.test.js.map +1 -0
  222. package/dist/server.d.ts +2 -0
  223. package/dist/server.d.ts.map +1 -0
  224. package/dist/server.js +1465 -0
  225. package/dist/server.js.map +1 -0
  226. package/dist/setup.d.ts +2 -0
  227. package/dist/setup.d.ts.map +1 -0
  228. package/dist/setup.js +1113 -0
  229. package/dist/setup.js.map +1 -0
  230. package/dist/tools/bytecode.d.ts +129 -0
  231. package/dist/tools/bytecode.d.ts.map +1 -0
  232. package/dist/tools/bytecode.js +679 -0
  233. package/dist/tools/bytecode.js.map +1 -0
  234. package/dist/tools/catalog.d.ts +54 -0
  235. package/dist/tools/catalog.d.ts.map +1 -0
  236. package/dist/tools/catalog.js +249 -0
  237. package/dist/tools/catalog.js.map +1 -0
  238. package/dist/tools/compat-check.d.ts +23 -0
  239. package/dist/tools/compat-check.d.ts.map +1 -0
  240. package/dist/tools/compat-check.js +250 -0
  241. package/dist/tools/compat-check.js.map +1 -0
  242. package/dist/tools/compat-check.test.d.ts +2 -0
  243. package/dist/tools/compat-check.test.d.ts.map +1 -0
  244. package/dist/tools/compat-check.test.js +179 -0
  245. package/dist/tools/compat-check.test.js.map +1 -0
  246. package/dist/tools/diagnostics.d.ts +10 -0
  247. package/dist/tools/diagnostics.d.ts.map +1 -0
  248. package/dist/tools/diagnostics.js +133 -0
  249. package/dist/tools/diagnostics.js.map +1 -0
  250. package/dist/tools/diagnostics.test.d.ts +2 -0
  251. package/dist/tools/diagnostics.test.d.ts.map +1 -0
  252. package/dist/tools/diagnostics.test.js +168 -0
  253. package/dist/tools/diagnostics.test.js.map +1 -0
  254. package/dist/tools/docs.d.ts +19 -0
  255. package/dist/tools/docs.d.ts.map +1 -0
  256. package/dist/tools/docs.js +230 -0
  257. package/dist/tools/docs.js.map +1 -0
  258. package/dist/tools/embed-registry.d.ts +125 -0
  259. package/dist/tools/embed-registry.d.ts.map +1 -0
  260. package/dist/tools/embed-registry.js +560 -0
  261. package/dist/tools/embed-registry.js.map +1 -0
  262. package/dist/tools/gradle.d.ts +16 -0
  263. package/dist/tools/gradle.d.ts.map +1 -0
  264. package/dist/tools/gradle.js +182 -0
  265. package/dist/tools/gradle.js.map +1 -0
  266. package/dist/tools/graphify.d.ts +144 -0
  267. package/dist/tools/graphify.d.ts.map +1 -0
  268. package/dist/tools/graphify.js +798 -0
  269. package/dist/tools/graphify.js.map +1 -0
  270. package/dist/tools/graphify.test.d.ts +2 -0
  271. package/dist/tools/graphify.test.d.ts.map +1 -0
  272. package/dist/tools/graphify.test.js +39 -0
  273. package/dist/tools/graphify.test.js.map +1 -0
  274. package/dist/tools/ingest.d.ts +85 -0
  275. package/dist/tools/ingest.d.ts.map +1 -0
  276. package/dist/tools/ingest.js +477 -0
  277. package/dist/tools/ingest.js.map +1 -0
  278. package/dist/tools/ingest.test.d.ts +2 -0
  279. package/dist/tools/ingest.test.d.ts.map +1 -0
  280. package/dist/tools/ingest.test.js +340 -0
  281. package/dist/tools/ingest.test.js.map +1 -0
  282. package/dist/tools/kubejs.d.ts +37 -0
  283. package/dist/tools/kubejs.d.ts.map +1 -0
  284. package/dist/tools/kubejs.js +245 -0
  285. package/dist/tools/kubejs.js.map +1 -0
  286. package/dist/tools/mappings.d.ts +17 -0
  287. package/dist/tools/mappings.d.ts.map +1 -0
  288. package/dist/tools/mappings.js +85 -0
  289. package/dist/tools/mappings.js.map +1 -0
  290. package/dist/tools/mc-fts.d.ts +101 -0
  291. package/dist/tools/mc-fts.d.ts.map +1 -0
  292. package/dist/tools/mc-fts.js +279 -0
  293. package/dist/tools/mc-fts.js.map +1 -0
  294. package/dist/tools/mcmeta.d.ts +41 -0
  295. package/dist/tools/mcmeta.d.ts.map +1 -0
  296. package/dist/tools/mcmeta.js +365 -0
  297. package/dist/tools/mcmeta.js.map +1 -0
  298. package/dist/tools/mixin-scan.d.ts +113 -0
  299. package/dist/tools/mixin-scan.d.ts.map +1 -0
  300. package/dist/tools/mixin-scan.js +433 -0
  301. package/dist/tools/mixin-scan.js.map +1 -0
  302. package/dist/tools/mod-data.d.ts +83 -0
  303. package/dist/tools/mod-data.d.ts.map +1 -0
  304. package/dist/tools/mod-data.js +630 -0
  305. package/dist/tools/mod-data.js.map +1 -0
  306. package/dist/tools/mod-tags.d.ts +59 -0
  307. package/dist/tools/mod-tags.d.ts.map +1 -0
  308. package/dist/tools/mod-tags.js +279 -0
  309. package/dist/tools/mod-tags.js.map +1 -0
  310. package/dist/tools/mod-tags.test.d.ts +2 -0
  311. package/dist/tools/mod-tags.test.d.ts.map +1 -0
  312. package/dist/tools/mod-tags.test.js +75 -0
  313. package/dist/tools/mod-tags.test.js.map +1 -0
  314. package/dist/tools/modpacks-ch.d.ts +257 -0
  315. package/dist/tools/modpacks-ch.d.ts.map +1 -0
  316. package/dist/tools/modpacks-ch.js +516 -0
  317. package/dist/tools/modpacks-ch.js.map +1 -0
  318. package/dist/tools/packtools.d.ts +113 -0
  319. package/dist/tools/packtools.d.ts.map +1 -0
  320. package/dist/tools/packtools.js +809 -0
  321. package/dist/tools/packtools.js.map +1 -0
  322. package/dist/tools/packtools.test.d.ts +2 -0
  323. package/dist/tools/packtools.test.d.ts.map +1 -0
  324. package/dist/tools/packtools.test.js +99 -0
  325. package/dist/tools/packtools.test.js.map +1 -0
  326. package/dist/tools/platform.d.ts +68 -0
  327. package/dist/tools/platform.d.ts.map +1 -0
  328. package/dist/tools/platform.js +452 -0
  329. package/dist/tools/platform.js.map +1 -0
  330. package/dist/tools/primers.d.ts +36 -0
  331. package/dist/tools/primers.d.ts.map +1 -0
  332. package/dist/tools/primers.js +451 -0
  333. package/dist/tools/primers.js.map +1 -0
  334. package/dist/tools/reports.d.ts +19 -0
  335. package/dist/tools/reports.d.ts.map +1 -0
  336. package/dist/tools/reports.js +573 -0
  337. package/dist/tools/reports.js.map +1 -0
  338. package/dist/tools/source.d.ts +10 -0
  339. package/dist/tools/source.d.ts.map +1 -0
  340. package/dist/tools/source.js +101 -0
  341. package/dist/tools/source.js.map +1 -0
  342. package/dist/tools/vanilla-data.d.ts +127 -0
  343. package/dist/tools/vanilla-data.d.ts.map +1 -0
  344. package/dist/tools/vanilla-data.js +824 -0
  345. package/dist/tools/vanilla-data.js.map +1 -0
  346. package/dist/tools/vanilla.d.ts +171 -0
  347. package/dist/tools/vanilla.d.ts.map +1 -0
  348. package/dist/tools/vanilla.js +612 -0
  349. package/dist/tools/vanilla.js.map +1 -0
  350. package/dist/tools/version-diff.d.ts +113 -0
  351. package/dist/tools/version-diff.d.ts.map +1 -0
  352. package/dist/tools/version-diff.js +519 -0
  353. package/dist/tools/version-diff.js.map +1 -0
  354. package/dist/tools/version-diff.test.d.ts +2 -0
  355. package/dist/tools/version-diff.test.d.ts.map +1 -0
  356. package/dist/tools/version-diff.test.js +102 -0
  357. package/dist/tools/version-diff.test.js.map +1 -0
  358. package/dist/validate.d.ts +19 -0
  359. package/dist/validate.d.ts.map +1 -0
  360. package/dist/validate.js +54 -0
  361. package/dist/validate.js.map +1 -0
  362. package/dist/validate.test.d.ts +2 -0
  363. package/dist/validate.test.d.ts.map +1 -0
  364. package/dist/validate.test.js +73 -0
  365. package/dist/validate.test.js.map +1 -0
  366. package/package.json +62 -0
  367. package/prisma/backends/schema.sqlite.prisma +215 -0
  368. package/prisma/backends/template.db +0 -0
  369. package/prisma/schema.prisma +303 -0
  370. package/scripts/backup.mjs +151 -0
  371. package/scripts/build-template-db.mjs +38 -0
  372. package/scripts/check-atm10.mjs +27 -0
  373. package/scripts/check-sync.mjs +13 -0
  374. package/scripts/create-fts-index.mjs +50 -0
  375. package/scripts/enable-pgvector.mjs +90 -0
  376. package/scripts/enable-sqlite-vec.mjs +158 -0
  377. package/scripts/migrate-backend.mjs +188 -0
  378. package/scripts/migrate-embed-provenance.mjs +80 -0
  379. package/scripts/migrate-metadata-source.mjs +62 -0
  380. package/scripts/migrate-mod-source-files.mjs +67 -0
  381. package/scripts/post-update.mjs +77 -0
  382. package/scripts/verify-atm10.mjs +63 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Repository layer for PackVersion and PackFile tables.
3
+ * Tracks which files (mods, configs, scripts, etc.) are present in each
4
+ * modpack version that has been synced or inspected via sync_pack_mods.
5
+ */
6
+ import { getDb } from "../db.js";
7
+ /** Upsert a pack version record and return its DB id. */
8
+ export async function upsertPackVersion(input) {
9
+ const db = await getDb();
10
+ const record = await db.packVersion.upsert({
11
+ where: {
12
+ namespace_packId_versionId: {
13
+ namespace: input.namespace,
14
+ packId: input.packId,
15
+ versionId: input.versionId,
16
+ },
17
+ },
18
+ create: {
19
+ namespace: input.namespace,
20
+ packId: input.packId,
21
+ versionId: input.versionId,
22
+ packName: input.packName,
23
+ versionName: input.versionName,
24
+ mcVersion: input.mcVersion ?? null,
25
+ modloader: input.modloader ?? null,
26
+ },
27
+ update: {
28
+ packName: input.packName,
29
+ versionName: input.versionName,
30
+ mcVersion: input.mcVersion ?? null,
31
+ modloader: input.modloader ?? null,
32
+ updatedAt: new Date(),
33
+ },
34
+ });
35
+ return record.id;
36
+ }
37
+ /** Upsert a single pack file record. Keyed on (packVersionId, manifestFileId). */
38
+ export async function upsertPackFile(input) {
39
+ const db = await getDb();
40
+ const data = {
41
+ packVersionId: input.packVersionId,
42
+ manifestFileId: input.manifestFileId ?? null,
43
+ fileType: input.fileType,
44
+ fileName: input.fileName,
45
+ filePath: input.filePath ?? null,
46
+ cfProject: input.cfProject ?? null,
47
+ cfFile: input.cfFile ?? null,
48
+ sha1: input.sha1 ?? null,
49
+ status: input.status,
50
+ modId: input.modId ?? null,
51
+ };
52
+ if (input.manifestFileId != null) {
53
+ await db.packFile.upsert({
54
+ where: {
55
+ packVersionId_manifestFileId: {
56
+ packVersionId: input.packVersionId,
57
+ manifestFileId: input.manifestFileId,
58
+ },
59
+ },
60
+ create: data,
61
+ update: {
62
+ fileType: data.fileType,
63
+ fileName: data.fileName,
64
+ filePath: data.filePath,
65
+ cfProject: data.cfProject,
66
+ cfFile: data.cfFile,
67
+ sha1: data.sha1,
68
+ status: data.status,
69
+ modId: data.modId,
70
+ },
71
+ });
72
+ }
73
+ else {
74
+ await db.packFile.create({ data }).catch(() => { });
75
+ }
76
+ }
77
+ // ── Queries ───────────────────────────────────────────────────────────────────
78
+ /** List all known pack versions, optionally filtered by namespace and/or packId. */
79
+ export async function listPackVersions(namespace, packId) {
80
+ const db = await getDb();
81
+ return db.packVersion.findMany({
82
+ where: {
83
+ ...(namespace !== undefined ? { namespace } : {}),
84
+ ...(packId !== undefined ? { packId } : {}),
85
+ },
86
+ orderBy: { syncedAt: "desc" },
87
+ });
88
+ }
89
+ /** List all files recorded for a specific pack version DB id. */
90
+ export async function listPackFiles(packVersionId) {
91
+ const db = await getDb();
92
+ return db.packFile.findMany({
93
+ where: { packVersionId },
94
+ orderBy: [{ fileType: "asc" }, { fileName: "asc" }],
95
+ });
96
+ }
97
+ /** Find every pack version that contains a specific Mod (by DB id). */
98
+ export async function findPacksForMod(modId) {
99
+ const db = await getDb();
100
+ const files = await db.packFile.findMany({
101
+ where: { modId },
102
+ include: { packVersion: true },
103
+ });
104
+ return files.map((f) => ({
105
+ ...f.packVersion,
106
+ fileName: f.fileName,
107
+ fileType: f.fileType,
108
+ status: f.status,
109
+ cfProject: f.cfProject,
110
+ cfFile: f.cfFile,
111
+ }));
112
+ }
113
+ /** Find every pack version that contains a file with a given CurseForge project id. */
114
+ export async function findPacksForCfProject(cfProject) {
115
+ const db = await getDb();
116
+ const files = await db.packFile.findMany({
117
+ where: { cfProject },
118
+ include: { packVersion: true },
119
+ });
120
+ return files.map((f) => ({
121
+ ...f.packVersion,
122
+ fileName: f.fileName,
123
+ fileType: f.fileType,
124
+ status: f.status,
125
+ cfProject: f.cfProject,
126
+ cfFile: f.cfFile,
127
+ }));
128
+ }
129
+ /** Resolve a PackVersion record by namespace + packId + versionId. */
130
+ export async function findPackVersion(namespace, packId, versionId) {
131
+ const db = await getDb();
132
+ return db.packVersion.findUnique({
133
+ where: {
134
+ namespace_packId_versionId: { namespace, packId, versionId },
135
+ },
136
+ });
137
+ }
138
+ //# sourceMappingURL=packs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packs.js","sourceRoot":"","sources":["../../src/repositories/packs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface FtsSourceResult {
2
+ className: string;
3
+ snippet: string;
4
+ }
5
+ export interface FtsDocResult {
6
+ id: number;
7
+ class_name: string | null;
8
+ title: string;
9
+ summary: string | null;
10
+ url: string;
11
+ category: string;
12
+ namespace: string;
13
+ tags: string[];
14
+ }
15
+ export interface FtsPrimerResult {
16
+ id: number;
17
+ title: string;
18
+ summary: string | null;
19
+ from_version: string;
20
+ to_version: string;
21
+ modloader: string | null;
22
+ url: string;
23
+ }
24
+ export declare function ftsSearchSource(mcVersionId: number, query: string, limit: number): Promise<FtsSourceResult[]>;
25
+ /**
26
+ * BM25-ranked FTS search over mod source files.
27
+ * SQLite: fts_mod_source FTS5 table (ORDER BY rank = BM25).
28
+ * PostgreSQL: to_tsvector GIN index + ts_rank.
29
+ * Mod source must be indexed first (mod index_fts or index_semantic action).
30
+ */
31
+ export declare function ftsSearchModSource(modId: number, query: string, limit: number): Promise<FtsSourceResult[]>;
32
+ export declare function ftsSearchDocs(query: string, limit?: number): Promise<FtsDocResult[]>;
33
+ export declare function ftsSearchPrimers(query: string, modloader?: string, limit?: number): Promise<FtsPrimerResult[]>;
34
+ //# sourceMappingURL=search-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-adapter.d.ts","sourceRoot":"","sources":["../src/search-adapter.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,eAAe,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CA2C5B;AAID;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CA2C5B;AAID,wBAAsB,aAAa,CAC/B,KAAK,EAAE,MAAM,EACb,KAAK,SAAK,GACX,OAAO,CAAC,YAAY,EAAE,CAAC,CA4CzB;AAID,wBAAsB,gBAAgB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,KAAK,SAAK,GACX,OAAO,CAAC,eAAe,EAAE,CAAC,CA+D5B"}
@@ -0,0 +1,195 @@
1
+ // src/search-adapter.ts
2
+ /**
3
+ * Backend-agnostic FTS adapter.
4
+ *
5
+ * Postgres/PGlite: uses native tsvector (mc_source_files) or
6
+ * case-insensitive LIKE via Prisma's mode:"insensitive".
7
+ * SQLite: uses FTS5 MATCH (mc_source_files) or raw LIKE (docs/primers).
8
+ * SQLite paths throw until P2 wires them.
9
+ */
10
+ import { detectBackend } from "./db-backend.js";
11
+ import { getDb } from "./db.js";
12
+ /** Escape LIKE metacharacters so user input is matched literally. */
13
+ function escapeLike(s) {
14
+ return s.replace(/[%_\\]/g, c => "\\" + c);
15
+ }
16
+ // ── mc_source_files FTS ───────────────────────────────────────────────────────
17
+ export async function ftsSearchSource(mcVersionId, query, limit) {
18
+ const backend = detectBackend();
19
+ if (backend === "sqlite") {
20
+ const url = process.env.DATABASE_URL ?? "";
21
+ const path = url.replace(/^file:\/\//, "").replace(/^file:/, "");
22
+ const Database = (await import("better-sqlite3")).default;
23
+ const db = new Database(path, { readonly: true });
24
+ try {
25
+ const rows = db.prepare(`SELECT s.id, s.class_name, s.content FROM fts_mc_source f
26
+ JOIN mc_source_files s ON s.id = f.rowid
27
+ WHERE f.fts_mc_source MATCH ? AND s.mc_version_id = ?
28
+ ORDER BY rank
29
+ LIMIT ?`).all(query, mcVersionId, limit);
30
+ return rows.map(r => ({
31
+ className: r.class_name,
32
+ snippet: r.content.slice(0, 300),
33
+ }));
34
+ }
35
+ finally {
36
+ db.close();
37
+ }
38
+ }
39
+ // Postgres / PGlite — existing tsvector query
40
+ const db = await getDb();
41
+ const rows = await db.$queryRaw `
42
+ SELECT
43
+ class_name,
44
+ ts_headline('simple', content,
45
+ plainto_tsquery('simple', ${query}),
46
+ 'MaxWords=25, MinWords=15, StartSel="", StopSel=""'
47
+ ) AS snippet
48
+ FROM mc_source_files
49
+ WHERE mc_version_id = ${mcVersionId}
50
+ AND to_tsvector('simple', content) @@ plainto_tsquery('simple', ${query})
51
+ ORDER BY ts_rank(to_tsvector('simple', content), plainto_tsquery('simple', ${query})) DESC
52
+ LIMIT ${limit}
53
+ `;
54
+ return rows.map(r => ({ className: r.class_name, snippet: r.snippet }));
55
+ }
56
+ // ── mod_source_files FTS (fabric / neoforge / forge / quilt) ─────────────────
57
+ /**
58
+ * BM25-ranked FTS search over mod source files.
59
+ * SQLite: fts_mod_source FTS5 table (ORDER BY rank = BM25).
60
+ * PostgreSQL: to_tsvector GIN index + ts_rank.
61
+ * Mod source must be indexed first (mod index_fts or index_semantic action).
62
+ */
63
+ export async function ftsSearchModSource(modId, query, limit) {
64
+ const backend = detectBackend();
65
+ if (backend === "sqlite") {
66
+ const url = process.env.DATABASE_URL ?? "";
67
+ const path = url.replace(/^file:\/\//, "").replace(/^file:/, "");
68
+ const Database = (await import("better-sqlite3")).default;
69
+ const db = new Database(path, { readonly: true });
70
+ try {
71
+ const rows = db.prepare(`SELECT s.id, s.class_name, s.content FROM fts_mod_source f
72
+ JOIN mod_source_files s ON s.id = f.rowid
73
+ WHERE f.fts_mod_source MATCH ? AND s.mod_id = ?
74
+ ORDER BY rank
75
+ LIMIT ?`).all(query, modId, limit);
76
+ return rows.map(r => ({
77
+ className: r.class_name,
78
+ snippet: r.content.slice(0, 300),
79
+ }));
80
+ }
81
+ finally {
82
+ db.close();
83
+ }
84
+ }
85
+ // PostgreSQL — GIN index on to_tsvector('simple', content)
86
+ const db = await getDb();
87
+ const rows = await db.$queryRaw `
88
+ SELECT
89
+ class_name,
90
+ ts_headline('simple', content,
91
+ plainto_tsquery('simple', ${query}),
92
+ 'MaxWords=25, MinWords=15, StartSel="", StopSel=""'
93
+ ) AS snippet
94
+ FROM mod_source_files
95
+ WHERE mod_id = ${modId}
96
+ AND to_tsvector('simple', content) @@ plainto_tsquery('simple', ${query})
97
+ ORDER BY ts_rank(to_tsvector('simple', content), plainto_tsquery('simple', ${query})) DESC
98
+ LIMIT ${limit}
99
+ `;
100
+ return rows.map(r => ({ className: r.class_name, snippet: r.snippet }));
101
+ }
102
+ // ── doc_entries FTS ───────────────────────────────────────────────────────────
103
+ export async function ftsSearchDocs(query, limit = 20) {
104
+ const backend = detectBackend();
105
+ if (backend === "sqlite") {
106
+ const url = process.env.DATABASE_URL ?? "";
107
+ const path = url.replace(/^file:\/\//, "").replace(/^file:/, "");
108
+ const Database = (await import("better-sqlite3")).default;
109
+ const db = new Database(path, { readonly: true });
110
+ try {
111
+ const rows = db.prepare(`SELECT d.id, d.class_name, d.title, d.summary, d.url, d.category, d.namespace, d.tags
112
+ FROM fts_doc_entries f
113
+ JOIN doc_entries d ON d.id = f.rowid
114
+ WHERE f.fts_doc_entries MATCH ?
115
+ ORDER BY rank
116
+ LIMIT ?`).all(query, limit);
117
+ return rows.map(r => ({ ...r, tags: JSON.parse(r.tags ?? "[]") }));
118
+ }
119
+ finally {
120
+ db.close();
121
+ }
122
+ }
123
+ // Postgres / PGlite — raw LIKE (case-insensitive via lower())
124
+ const db = await getDb();
125
+ const kw = escapeLike(query.toLowerCase());
126
+ const rows = await db.$queryRaw `
127
+ SELECT id, class_name, title, summary, url, category, namespace, tags
128
+ FROM doc_entries
129
+ WHERE lower(title) LIKE ${"%" + kw + "%"}
130
+ OR lower(summary) LIKE ${"%" + kw + "%"}
131
+ OR lower(class_name) LIKE ${"%" + kw + "%"}
132
+ ORDER BY id
133
+ LIMIT ${limit}
134
+ `;
135
+ return rows;
136
+ }
137
+ // ── primers FTS ───────────────────────────────────────────────────────────────
138
+ export async function ftsSearchPrimers(query, modloader, limit = 20) {
139
+ const backend = detectBackend();
140
+ if (backend === "sqlite") {
141
+ const url = process.env.DATABASE_URL ?? "";
142
+ const path = url.replace(/^file:\/\//, "").replace(/^file:/, "");
143
+ const Database = (await import("better-sqlite3")).default;
144
+ const db = new Database(path, { readonly: true });
145
+ try {
146
+ const rows = db.prepare(`SELECT p.id, p.title, p.summary, p.from_version, p.to_version, p.modloader, p.url
147
+ FROM fts_primers f
148
+ JOIN primers p ON p.id = f.rowid
149
+ WHERE f.fts_primers MATCH ?
150
+ ${modloader ? "AND p.modloader = ?" : ""}
151
+ ORDER BY rank
152
+ LIMIT ?`).all(...[query, ...(modloader ? [modloader] : []), limit]);
153
+ return rows.map(r => ({
154
+ id: r.id, title: r.title, summary: r.summary,
155
+ from_version: r.from_version, to_version: r.to_version,
156
+ modloader: r.modloader ?? null, url: r.url,
157
+ }));
158
+ }
159
+ finally {
160
+ db.close();
161
+ }
162
+ }
163
+ // Postgres / PGlite — Prisma case-insensitive contains
164
+ const db = await getDb();
165
+ const rows = await db.primer.findMany({
166
+ where: {
167
+ AND: [
168
+ {
169
+ OR: [
170
+ { title: { contains: query, mode: "insensitive" } },
171
+ { summary: { contains: query, mode: "insensitive" } },
172
+ { content: { contains: query, mode: "insensitive" } },
173
+ { tags: { has: query } },
174
+ ],
175
+ },
176
+ ...(modloader ? [{ modloader }] : []),
177
+ ],
178
+ },
179
+ select: {
180
+ id: true, title: true, summary: true,
181
+ fromVersion: true, toVersion: true, modloader: true, url: true,
182
+ },
183
+ take: limit,
184
+ });
185
+ return rows.map(r => ({
186
+ id: r.id,
187
+ title: r.title,
188
+ summary: r.summary,
189
+ from_version: r.fromVersion,
190
+ to_version: r.toVersion,
191
+ modloader: r.modloader ?? null,
192
+ url: r.url,
193
+ }));
194
+ }
195
+ //# sourceMappingURL=search-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-adapter.js","sourceRoot":"","sources":["../src/search-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Class name search — CamelCase acronym, prefix, and substring matching.
3
+ * Ported from the mcsrc web app search algorithm.
4
+ */
5
+ export declare function searchClasses(classes: string[], query: string): string[];
6
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA+CxE"}
package/dist/search.js ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Class name search — CamelCase acronym, prefix, and substring matching.
3
+ * Ported from the mcsrc web app search algorithm.
4
+ */
5
+ export function searchClasses(classes, query) {
6
+ const q = query.trim();
7
+ if (!q)
8
+ return [];
9
+ const simpleNames = classes.map((c) => {
10
+ const parts = c.split("/");
11
+ return parts[parts.length - 1];
12
+ });
13
+ const results = [];
14
+ const upperQ = q.toUpperCase();
15
+ const lowerQ = q.toLowerCase();
16
+ for (let i = 0; i < classes.length; i++) {
17
+ const simple = simpleNames[i];
18
+ const simpleUpper = simple.toUpperCase();
19
+ if (simple === q) {
20
+ results.push({ score: 0, name: classes[i] });
21
+ continue;
22
+ }
23
+ if (simple.startsWith(q)) {
24
+ results.push({ score: 1, name: classes[i] });
25
+ continue;
26
+ }
27
+ // CamelCase acronym match
28
+ if (camelMatch(simple, q)) {
29
+ results.push({ score: 2, name: classes[i] });
30
+ continue;
31
+ }
32
+ // Case-insensitive prefix
33
+ if (simpleUpper.startsWith(upperQ)) {
34
+ results.push({ score: 3, name: classes[i] });
35
+ continue;
36
+ }
37
+ // Substring
38
+ if (simple.toLowerCase().includes(lowerQ)) {
39
+ results.push({ score: 4 + simple.toLowerCase().indexOf(lowerQ), name: classes[i] });
40
+ }
41
+ }
42
+ return results
43
+ .sort((a, b) => a.score - b.score || a.name.localeCompare(b.name))
44
+ .slice(0, 100)
45
+ .map((r) => r.name);
46
+ }
47
+ function camelMatch(className, query) {
48
+ const uppers = className.match(/[A-Z]/g);
49
+ if (!uppers)
50
+ return false;
51
+ const acronym = uppers.join("");
52
+ return acronym.toUpperCase().includes(query.toUpperCase());
53
+ }
54
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../src/search.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { searchClasses } from "./search.js";
3
+ const CLASSES = [
4
+ "net/minecraft/world/entity/LivingEntity",
5
+ "net/minecraft/world/entity/player/Player",
6
+ "net/minecraft/world/level/block/Block",
7
+ "net/minecraft/world/level/block/entity/BlockEntity",
8
+ "net/minecraft/world/item/Item",
9
+ "net/minecraft/world/item/ItemStack",
10
+ "com/example/mod/EnergyStorage",
11
+ "com/example/mod/EnergyStorageBlockEntity",
12
+ "com/example/mod/ExampleMod",
13
+ "com/example/mod/integration/jei/JEIPlugin",
14
+ ];
15
+ describe("searchClasses", () => {
16
+ it("returns empty array for empty query", () => {
17
+ expect(searchClasses(CLASSES, "")).toHaveLength(0);
18
+ expect(searchClasses(CLASSES, " ")).toHaveLength(0);
19
+ });
20
+ it("exact simple name match ranks first", () => {
21
+ const results = searchClasses(CLASSES, "Block");
22
+ expect(results[0]).toBe("net/minecraft/world/level/block/Block");
23
+ });
24
+ it("prefix match ranks before substring match", () => {
25
+ const results = searchClasses(CLASSES, "Item");
26
+ // "Item" exact match before "ItemStack" prefix match
27
+ expect(results[0]).toBe("net/minecraft/world/item/Item");
28
+ expect(results[1]).toBe("net/minecraft/world/item/ItemStack");
29
+ });
30
+ it("CamelCase acronym match works", () => {
31
+ const results = searchClasses(CLASSES, "LE");
32
+ expect(results).toContain("net/minecraft/world/entity/LivingEntity");
33
+ });
34
+ it("CamelCase acronym is case-insensitive", () => {
35
+ const results = searchClasses(CLASSES, "le");
36
+ expect(results).toContain("net/minecraft/world/entity/LivingEntity");
37
+ });
38
+ it("case-insensitive prefix match works", () => {
39
+ const results = searchClasses(CLASSES, "block");
40
+ expect(results).toContain("net/minecraft/world/level/block/Block");
41
+ expect(results).toContain("net/minecraft/world/level/block/entity/BlockEntity");
42
+ });
43
+ it("substring match works", () => {
44
+ const results = searchClasses(CLASSES, "Storage");
45
+ expect(results).toContain("com/example/mod/EnergyStorage");
46
+ expect(results).toContain("com/example/mod/EnergyStorageBlockEntity");
47
+ });
48
+ it("substring match on full internal path works", () => {
49
+ const results = searchClasses(CLASSES, "jei");
50
+ expect(results).toContain("com/example/mod/integration/jei/JEIPlugin");
51
+ });
52
+ it("returns at most 100 results", () => {
53
+ const many = Array.from({ length: 200 }, (_, i) => `com/example/Foo${i}`);
54
+ const results = searchClasses(many, "Foo");
55
+ expect(results.length).toBeLessThanOrEqual(100);
56
+ });
57
+ it("returns empty array when nothing matches", () => {
58
+ expect(searchClasses(CLASSES, "Zzzzz")).toHaveLength(0);
59
+ });
60
+ it("results are sorted — lower score before higher score", () => {
61
+ // "ES" is a CamelCase match for EnergyStorage — should appear before a pure substring match
62
+ const results = searchClasses(CLASSES, "ES");
63
+ const esIdx = results.findIndex(r => r.includes("EnergyStorage"));
64
+ const exIdx = results.findIndex(r => r.includes("ExampleMod"));
65
+ // EnergyStorage "ES" acronym should rank before ExampleMod "EM" — which shouldn't match at all
66
+ expect(esIdx).toBeGreaterThanOrEqual(0);
67
+ if (exIdx !== -1)
68
+ expect(esIdx).toBeLessThan(exIdx);
69
+ });
70
+ });
71
+ //# sourceMappingURL=search.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.js","sourceRoot":"","sources":["../src/search.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Normalizes a path that may have been typed from a WSL shell or a Windows
3
+ * shell so both work transparently.
4
+ *
5
+ * On Windows:
6
+ * /mnt/c/foo/bar.jar → C:/foo/bar.jar
7
+ * /mnt/wsl/foo.jar → left as-is (no drive letter, unlikely to be valid Win path)
8
+ * C:\foo\bar.jar → left as-is (already Windows)
9
+ *
10
+ * On Linux/macOS: returned unchanged (WSL paths are native there).
11
+ */
12
+ export declare function normalizeJarPath(p: string): string;
13
+ /**
14
+ * Validate that `untrusted` resolves to a path inside `base`.
15
+ * Throws if it would escape (path traversal attempt).
16
+ * Returns the resolved absolute path on success.
17
+ */
18
+ export declare function validatePath(untrusted: string, base: string): string;
19
+ /**
20
+ * Assert that `p` is an absolute path ending in `.jar`.
21
+ * Use on paths sourced from the DB or other semi-trusted boundaries
22
+ * to prevent filesystem access to arbitrary files.
23
+ */
24
+ export declare function assertJarPath(p: string): void;
25
+ /**
26
+ * Compile a user-supplied regex string safely.
27
+ * Throws if the pattern is too long or fails to compile.
28
+ */
29
+ export declare function safeRegex(pattern: string, flags?: string): RegExp;
30
+ /**
31
+ * Compute the SHA-512 hex digest of a file on disk.
32
+ */
33
+ export declare function fileSha512(filePath: string): Promise<string>;
34
+ /**
35
+ * Verify a file's SHA-512 against an expected value.
36
+ * Throws `HashMismatchError` if they differ.
37
+ */
38
+ export declare class HashMismatchError extends Error {
39
+ constructor(filePath: string, expected: string, actual: string);
40
+ }
41
+ export declare function verifyFileHash(filePath: string, expectedSha512: string): Promise<void>;
42
+ /**
43
+ * Decode Unicode Tag characters (U+E0000-E007F) back to their ASCII equivalents.
44
+ * This is the technique used by tools like HideTextTool to embed invisible text
45
+ * within visible strings. Returns the hidden ASCII payload (empty if none).
46
+ */
47
+ export declare function decodeTagChars(text: string): string;
48
+ /**
49
+ * Strip all invisible / zero-width Unicode characters from a string.
50
+ * Covers: Unicode Tag block (U+E0000-E007F), zero-width chars (U+200B-200D,
51
+ * U+FEFF, U+2060), bidi overrides (U+200E-200F, U+202A-202E, U+2066-2069),
52
+ * interlinear annotations (U+FFF9-FFFB), and variation selectors (U+FE00-FE0F).
53
+ */
54
+ export declare function stripInvisibleUnicode(text: string): string;
55
+ /**
56
+ * Check whether a string contains any invisible Unicode characters
57
+ * (Tag block, zero-width, bidi overrides, etc.).
58
+ */
59
+ export declare function containsInvisibleUnicode(text: string): boolean;
60
+ interface ValidationResult {
61
+ valid: boolean;
62
+ reason?: string;
63
+ flaggedEntries?: string[];
64
+ }
65
+ /**
66
+ * Validate a graph.json bundle for security issues.
67
+ * Checks schema, string lengths, prompt injection, and size limits.
68
+ */
69
+ export declare function validateGraphBundle(graph: unknown): ValidationResult;
70
+ /**
71
+ * Validate nodes/edges submitted by the chat agent during enrichment.
72
+ * Same checks as validateGraphBundle but on individual arrays.
73
+ */
74
+ export declare function validateGraphEntries(nodes: Array<{
75
+ id: string;
76
+ [k: string]: unknown;
77
+ }>, edges: Array<{
78
+ source: string;
79
+ target: string;
80
+ relation: string;
81
+ [k: string]: unknown;
82
+ }>): ValidationResult;
83
+ /**
84
+ * Validate an embedding bundle for security issues.
85
+ */
86
+ export declare function validateEmbeddingBundle(bundle: unknown): ValidationResult;
87
+ /**
88
+ * Validate an embedding registry index (index.json) returned from a remote server.
89
+ * Ensures each bundle entry has the expected field types to prevent TypeErrors
90
+ * from malformed/malicious registry responses.
91
+ */
92
+ export declare function validateEmbedRegistryIndex(data: unknown): ValidationResult;
93
+ /**
94
+ * Validate a graph registry index (index.json) returned from a remote server.
95
+ */
96
+ export declare function validateGraphRegistryIndex(data: unknown): ValidationResult;
97
+ export {};
98
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CASlD;AAID;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAYpE;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAI7C;AAMD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAM,GAAG,MAAM,CAS9D;AAID;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlE;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC5B,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAIjE;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5F;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBnD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmC1D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAYD,UAAU,gBAAgB;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAoBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAwFpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,EAClD,KAAK,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,GACzF,gBAAgB,CAElB;AAkBD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAwEzE;AAID;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAuB1E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAsB1E"}