@flaid/devmap 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -0
  3. package/dist/ai/completion.d.ts +7 -0
  4. package/dist/ai/completion.d.ts.map +1 -0
  5. package/dist/ai/completion.js +27 -0
  6. package/dist/ai/completion.js.map +1 -0
  7. package/dist/ai/contextBuilder.d.ts +42 -0
  8. package/dist/ai/contextBuilder.d.ts.map +1 -0
  9. package/dist/ai/contextBuilder.js +632 -0
  10. package/dist/ai/contextBuilder.js.map +1 -0
  11. package/dist/ai/groq.d.ts +36 -0
  12. package/dist/ai/groq.d.ts.map +1 -0
  13. package/dist/ai/groq.js +368 -0
  14. package/dist/ai/groq.js.map +1 -0
  15. package/dist/ai/openrouter.d.ts +20 -0
  16. package/dist/ai/openrouter.d.ts.map +1 -0
  17. package/dist/ai/openrouter.js +187 -0
  18. package/dist/ai/openrouter.js.map +1 -0
  19. package/dist/ai/prompts.d.ts +7 -0
  20. package/dist/ai/prompts.d.ts.map +1 -0
  21. package/dist/ai/prompts.js +88 -0
  22. package/dist/ai/prompts.js.map +1 -0
  23. package/dist/ai/provider.d.ts +15 -0
  24. package/dist/ai/provider.d.ts.map +1 -0
  25. package/dist/ai/provider.js +28 -0
  26. package/dist/ai/provider.js.map +1 -0
  27. package/dist/ai/snapshotEnrichment.d.ts +4 -0
  28. package/dist/ai/snapshotEnrichment.d.ts.map +1 -0
  29. package/dist/ai/snapshotEnrichment.js +188 -0
  30. package/dist/ai/snapshotEnrichment.js.map +1 -0
  31. package/dist/ai/types.d.ts +29 -0
  32. package/dist/ai/types.d.ts.map +1 -0
  33. package/dist/ai/types.js +2 -0
  34. package/dist/ai/types.js.map +1 -0
  35. package/dist/analyzers/analysis/extractors/fallbackExtractor.d.ts +30 -0
  36. package/dist/analyzers/analysis/extractors/fallbackExtractor.d.ts.map +1 -0
  37. package/dist/analyzers/analysis/extractors/fallbackExtractor.js +114 -0
  38. package/dist/analyzers/analysis/extractors/fallbackExtractor.js.map +1 -0
  39. package/dist/analyzers/analysis/extractors/index.d.ts +16 -0
  40. package/dist/analyzers/analysis/extractors/index.d.ts.map +1 -0
  41. package/dist/analyzers/analysis/extractors/index.js +135 -0
  42. package/dist/analyzers/analysis/extractors/index.js.map +1 -0
  43. package/dist/analyzers/analysis/extractors/prismaExtractor.d.ts +15 -0
  44. package/dist/analyzers/analysis/extractors/prismaExtractor.d.ts.map +1 -0
  45. package/dist/analyzers/analysis/extractors/prismaExtractor.js +183 -0
  46. package/dist/analyzers/analysis/extractors/prismaExtractor.js.map +1 -0
  47. package/dist/analyzers/analysis/extractors/sqlExtractor.d.ts +14 -0
  48. package/dist/analyzers/analysis/extractors/sqlExtractor.d.ts.map +1 -0
  49. package/dist/analyzers/analysis/extractors/sqlExtractor.js +163 -0
  50. package/dist/analyzers/analysis/extractors/sqlExtractor.js.map +1 -0
  51. package/dist/analyzers/analysis/extractors/types.d.ts +76 -0
  52. package/dist/analyzers/analysis/extractors/types.d.ts.map +1 -0
  53. package/dist/analyzers/analysis/extractors/types.js +2 -0
  54. package/dist/analyzers/analysis/extractors/types.js.map +1 -0
  55. package/dist/analyzers/analysis/fileAnalysis.d.ts +36 -0
  56. package/dist/analyzers/analysis/fileAnalysis.d.ts.map +1 -0
  57. package/dist/analyzers/analysis/fileAnalysis.js +2 -0
  58. package/dist/analyzers/analysis/fileAnalysis.js.map +1 -0
  59. package/dist/analyzers/analysis/fileRole.d.ts +30 -0
  60. package/dist/analyzers/analysis/fileRole.d.ts.map +1 -0
  61. package/dist/analyzers/analysis/fileRole.js +242 -0
  62. package/dist/analyzers/analysis/fileRole.js.map +1 -0
  63. package/dist/analyzers/analysis/fileScanner.d.ts +10 -0
  64. package/dist/analyzers/analysis/fileScanner.d.ts.map +1 -0
  65. package/dist/analyzers/analysis/fileScanner.js +44 -0
  66. package/dist/analyzers/analysis/fileScanner.js.map +1 -0
  67. package/dist/analyzers/analysis/filterEngine.d.ts +2 -0
  68. package/dist/analyzers/analysis/filterEngine.d.ts.map +1 -0
  69. package/dist/analyzers/analysis/filterEngine.js +110 -0
  70. package/dist/analyzers/analysis/filterEngine.js.map +1 -0
  71. package/dist/analyzers/analysis/index.d.ts +12 -0
  72. package/dist/analyzers/analysis/index.d.ts.map +1 -0
  73. package/dist/analyzers/analysis/index.js +8 -0
  74. package/dist/analyzers/analysis/index.js.map +1 -0
  75. package/dist/analyzers/analysis/preprocessors/astroPreprocessor.d.ts +23 -0
  76. package/dist/analyzers/analysis/preprocessors/astroPreprocessor.d.ts.map +1 -0
  77. package/dist/analyzers/analysis/preprocessors/astroPreprocessor.js +40 -0
  78. package/dist/analyzers/analysis/preprocessors/astroPreprocessor.js.map +1 -0
  79. package/dist/analyzers/analysis/preprocessors/index.d.ts +5 -0
  80. package/dist/analyzers/analysis/preprocessors/index.d.ts.map +1 -0
  81. package/dist/analyzers/analysis/preprocessors/index.js +4 -0
  82. package/dist/analyzers/analysis/preprocessors/index.js.map +1 -0
  83. package/dist/analyzers/analysis/preprocessors/sveltePreprocessor.d.ts +27 -0
  84. package/dist/analyzers/analysis/preprocessors/sveltePreprocessor.d.ts.map +1 -0
  85. package/dist/analyzers/analysis/preprocessors/sveltePreprocessor.js +50 -0
  86. package/dist/analyzers/analysis/preprocessors/sveltePreprocessor.js.map +1 -0
  87. package/dist/analyzers/analysis/preprocessors/types.d.ts +45 -0
  88. package/dist/analyzers/analysis/preprocessors/types.d.ts.map +1 -0
  89. package/dist/analyzers/analysis/preprocessors/types.js +2 -0
  90. package/dist/analyzers/analysis/preprocessors/types.js.map +1 -0
  91. package/dist/analyzers/analysis/preprocessors/vuePreprocessor.d.ts +21 -0
  92. package/dist/analyzers/analysis/preprocessors/vuePreprocessor.d.ts.map +1 -0
  93. package/dist/analyzers/analysis/preprocessors/vuePreprocessor.js +44 -0
  94. package/dist/analyzers/analysis/preprocessors/vuePreprocessor.js.map +1 -0
  95. package/dist/analyzers/analysis/tsMorphAnalyzer.d.ts +10 -0
  96. package/dist/analyzers/analysis/tsMorphAnalyzer.d.ts.map +1 -0
  97. package/dist/analyzers/analysis/tsMorphAnalyzer.js +190 -0
  98. package/dist/analyzers/analysis/tsMorphAnalyzer.js.map +1 -0
  99. package/dist/analyzers/detectors/capabilityDetector.d.ts +28 -0
  100. package/dist/analyzers/detectors/capabilityDetector.d.ts.map +1 -0
  101. package/dist/analyzers/detectors/capabilityDetector.js +288 -0
  102. package/dist/analyzers/detectors/capabilityDetector.js.map +1 -0
  103. package/dist/analyzers/detectors/databaseDetector.d.ts +7 -0
  104. package/dist/analyzers/detectors/databaseDetector.d.ts.map +1 -0
  105. package/dist/analyzers/detectors/databaseDetector.js +71 -0
  106. package/dist/analyzers/detectors/databaseDetector.js.map +1 -0
  107. package/dist/analyzers/detectors/frameworkDetector.d.ts +22 -0
  108. package/dist/analyzers/detectors/frameworkDetector.d.ts.map +1 -0
  109. package/dist/analyzers/detectors/frameworkDetector.js +160 -0
  110. package/dist/analyzers/detectors/frameworkDetector.js.map +1 -0
  111. package/dist/analyzers/detectors/frontendFeatureDetector.d.ts +26 -0
  112. package/dist/analyzers/detectors/frontendFeatureDetector.d.ts.map +1 -0
  113. package/dist/analyzers/detectors/frontendFeatureDetector.js +269 -0
  114. package/dist/analyzers/detectors/frontendFeatureDetector.js.map +1 -0
  115. package/dist/analyzers/detectors/index.d.ts +11 -0
  116. package/dist/analyzers/detectors/index.d.ts.map +1 -0
  117. package/dist/analyzers/detectors/index.js +7 -0
  118. package/dist/analyzers/detectors/index.js.map +1 -0
  119. package/dist/analyzers/detectors/nestRouteDetector.d.ts +13 -0
  120. package/dist/analyzers/detectors/nestRouteDetector.d.ts.map +1 -0
  121. package/dist/analyzers/detectors/nestRouteDetector.js +69 -0
  122. package/dist/analyzers/detectors/nestRouteDetector.js.map +1 -0
  123. package/dist/analyzers/detectors/routeDetector.d.ts +22 -0
  124. package/dist/analyzers/detectors/routeDetector.d.ts.map +1 -0
  125. package/dist/analyzers/detectors/routeDetector.js +368 -0
  126. package/dist/analyzers/detectors/routeDetector.js.map +1 -0
  127. package/dist/analyzers/detectors/serviceDetector.d.ts +3 -0
  128. package/dist/analyzers/detectors/serviceDetector.d.ts.map +1 -0
  129. package/dist/analyzers/detectors/serviceDetector.js +81 -0
  130. package/dist/analyzers/detectors/serviceDetector.js.map +1 -0
  131. package/dist/analyzers/features/featureDetector.d.ts +22 -0
  132. package/dist/analyzers/features/featureDetector.d.ts.map +1 -0
  133. package/dist/analyzers/features/featureDetector.js +821 -0
  134. package/dist/analyzers/features/featureDetector.js.map +1 -0
  135. package/dist/analyzers/features/featureMerge.d.ts +65 -0
  136. package/dist/analyzers/features/featureMerge.d.ts.map +1 -0
  137. package/dist/analyzers/features/featureMerge.js +168 -0
  138. package/dist/analyzers/features/featureMerge.js.map +1 -0
  139. package/dist/analyzers/features/featureSimilarity.d.ts +152 -0
  140. package/dist/analyzers/features/featureSimilarity.d.ts.map +1 -0
  141. package/dist/analyzers/features/featureSimilarity.js +264 -0
  142. package/dist/analyzers/features/featureSimilarity.js.map +1 -0
  143. package/dist/analyzers/features/index.d.ts +6 -0
  144. package/dist/analyzers/features/index.d.ts.map +1 -0
  145. package/dist/analyzers/features/index.js +4 -0
  146. package/dist/analyzers/features/index.js.map +1 -0
  147. package/dist/analyzers/graph/dependencyGraph.d.ts +5 -0
  148. package/dist/analyzers/graph/dependencyGraph.d.ts.map +1 -0
  149. package/dist/analyzers/graph/dependencyGraph.js +88 -0
  150. package/dist/analyzers/graph/dependencyGraph.js.map +1 -0
  151. package/dist/analyzers/graph/dependencyMap.d.ts +43 -0
  152. package/dist/analyzers/graph/dependencyMap.d.ts.map +1 -0
  153. package/dist/analyzers/graph/dependencyMap.js +85 -0
  154. package/dist/analyzers/graph/dependencyMap.js.map +1 -0
  155. package/dist/analyzers/graph/entryPoints.d.ts +3 -0
  156. package/dist/analyzers/graph/entryPoints.d.ts.map +1 -0
  157. package/dist/analyzers/graph/entryPoints.js +21 -0
  158. package/dist/analyzers/graph/entryPoints.js.map +1 -0
  159. package/dist/analyzers/graph/index.d.ts +7 -0
  160. package/dist/analyzers/graph/index.d.ts.map +1 -0
  161. package/dist/analyzers/graph/index.js +5 -0
  162. package/dist/analyzers/graph/index.js.map +1 -0
  163. package/dist/analyzers/graph/sourceScope.d.ts +2 -0
  164. package/dist/analyzers/graph/sourceScope.d.ts.map +1 -0
  165. package/dist/analyzers/graph/sourceScope.js +30 -0
  166. package/dist/analyzers/graph/sourceScope.js.map +1 -0
  167. package/dist/analyzers/inference/domainInference.d.ts +58 -0
  168. package/dist/analyzers/inference/domainInference.d.ts.map +1 -0
  169. package/dist/analyzers/inference/domainInference.js +234 -0
  170. package/dist/analyzers/inference/domainInference.js.map +1 -0
  171. package/dist/analyzers/inference/index.d.ts +5 -0
  172. package/dist/analyzers/inference/index.d.ts.map +1 -0
  173. package/dist/analyzers/inference/index.js +3 -0
  174. package/dist/analyzers/inference/index.js.map +1 -0
  175. package/dist/analyzers/inference/ownershipTopology.d.ts +8 -0
  176. package/dist/analyzers/inference/ownershipTopology.d.ts.map +1 -0
  177. package/dist/analyzers/inference/ownershipTopology.js +65 -0
  178. package/dist/analyzers/inference/ownershipTopology.js.map +1 -0
  179. package/dist/analyzers/pipeline/analyzerRegistry.d.ts +9 -0
  180. package/dist/analyzers/pipeline/analyzerRegistry.d.ts.map +1 -0
  181. package/dist/analyzers/pipeline/analyzerRegistry.js +35 -0
  182. package/dist/analyzers/pipeline/analyzerRegistry.js.map +1 -0
  183. package/dist/analyzers/pipeline/heuristicAnalyzer.d.ts +12 -0
  184. package/dist/analyzers/pipeline/heuristicAnalyzer.d.ts.map +1 -0
  185. package/dist/analyzers/pipeline/heuristicAnalyzer.js +150 -0
  186. package/dist/analyzers/pipeline/heuristicAnalyzer.js.map +1 -0
  187. package/dist/analyzers/pipeline/index.d.ts +7 -0
  188. package/dist/analyzers/pipeline/index.d.ts.map +1 -0
  189. package/dist/analyzers/pipeline/index.js +5 -0
  190. package/dist/analyzers/pipeline/index.js.map +1 -0
  191. package/dist/analyzers/pipeline/projectMap.d.ts +120 -0
  192. package/dist/analyzers/pipeline/projectMap.d.ts.map +1 -0
  193. package/dist/analyzers/pipeline/projectMap.js +726 -0
  194. package/dist/analyzers/pipeline/projectMap.js.map +1 -0
  195. package/dist/analyzers/pipeline/projectMetadata.d.ts +19 -0
  196. package/dist/analyzers/pipeline/projectMetadata.d.ts.map +1 -0
  197. package/dist/analyzers/pipeline/projectMetadata.js +149 -0
  198. package/dist/analyzers/pipeline/projectMetadata.js.map +1 -0
  199. package/dist/analyzers/pipeline/reasonTags.d.ts +6 -0
  200. package/dist/analyzers/pipeline/reasonTags.d.ts.map +1 -0
  201. package/dist/analyzers/pipeline/reasonTags.js +6 -0
  202. package/dist/analyzers/pipeline/reasonTags.js.map +1 -0
  203. package/dist/analyzers/registry/ai-providers.d.ts +3 -0
  204. package/dist/analyzers/registry/ai-providers.d.ts.map +1 -0
  205. package/dist/analyzers/registry/ai-providers.js +94 -0
  206. package/dist/analyzers/registry/ai-providers.js.map +1 -0
  207. package/dist/analyzers/registry/analytics.d.ts +3 -0
  208. package/dist/analyzers/registry/analytics.d.ts.map +1 -0
  209. package/dist/analyzers/registry/analytics.js +15 -0
  210. package/dist/analyzers/registry/analytics.js.map +1 -0
  211. package/dist/analyzers/registry/auth.d.ts +3 -0
  212. package/dist/analyzers/registry/auth.d.ts.map +1 -0
  213. package/dist/analyzers/registry/auth.js +18 -0
  214. package/dist/analyzers/registry/auth.js.map +1 -0
  215. package/dist/analyzers/registry/background-jobs.d.ts +3 -0
  216. package/dist/analyzers/registry/background-jobs.d.ts.map +1 -0
  217. package/dist/analyzers/registry/background-jobs.js +14 -0
  218. package/dist/analyzers/registry/background-jobs.js.map +1 -0
  219. package/dist/analyzers/registry/caching.d.ts +3 -0
  220. package/dist/analyzers/registry/caching.d.ts.map +1 -0
  221. package/dist/analyzers/registry/caching.js +13 -0
  222. package/dist/analyzers/registry/caching.js.map +1 -0
  223. package/dist/analyzers/registry/cms-content.d.ts +3 -0
  224. package/dist/analyzers/registry/cms-content.d.ts.map +1 -0
  225. package/dist/analyzers/registry/cms-content.js +15 -0
  226. package/dist/analyzers/registry/cms-content.js.map +1 -0
  227. package/dist/analyzers/registry/database.d.ts +3 -0
  228. package/dist/analyzers/registry/database.d.ts.map +1 -0
  229. package/dist/analyzers/registry/database.js +13 -0
  230. package/dist/analyzers/registry/database.js.map +1 -0
  231. package/dist/analyzers/registry/email.d.ts +3 -0
  232. package/dist/analyzers/registry/email.d.ts.map +1 -0
  233. package/dist/analyzers/registry/email.js +19 -0
  234. package/dist/analyzers/registry/email.js.map +1 -0
  235. package/dist/analyzers/registry/file-upload.d.ts +3 -0
  236. package/dist/analyzers/registry/file-upload.d.ts.map +1 -0
  237. package/dist/analyzers/registry/file-upload.js +19 -0
  238. package/dist/analyzers/registry/file-upload.js.map +1 -0
  239. package/dist/analyzers/registry/firebase.d.ts +3 -0
  240. package/dist/analyzers/registry/firebase.d.ts.map +1 -0
  241. package/dist/analyzers/registry/firebase.js +8 -0
  242. package/dist/analyzers/registry/firebase.js.map +1 -0
  243. package/dist/analyzers/registry/index.d.ts +16 -0
  244. package/dist/analyzers/registry/index.d.ts.map +1 -0
  245. package/dist/analyzers/registry/index.js +88 -0
  246. package/dist/analyzers/registry/index.js.map +1 -0
  247. package/dist/analyzers/registry/internationalization.d.ts +3 -0
  248. package/dist/analyzers/registry/internationalization.d.ts.map +1 -0
  249. package/dist/analyzers/registry/internationalization.js +13 -0
  250. package/dist/analyzers/registry/internationalization.js.map +1 -0
  251. package/dist/analyzers/registry/logging-monitoring.d.ts +3 -0
  252. package/dist/analyzers/registry/logging-monitoring.d.ts.map +1 -0
  253. package/dist/analyzers/registry/logging-monitoring.js +14 -0
  254. package/dist/analyzers/registry/logging-monitoring.js.map +1 -0
  255. package/dist/analyzers/registry/notifications.d.ts +3 -0
  256. package/dist/analyzers/registry/notifications.d.ts.map +1 -0
  257. package/dist/analyzers/registry/notifications.js +14 -0
  258. package/dist/analyzers/registry/notifications.js.map +1 -0
  259. package/dist/analyzers/registry/payments.d.ts +3 -0
  260. package/dist/analyzers/registry/payments.d.ts.map +1 -0
  261. package/dist/analyzers/registry/payments.js +23 -0
  262. package/dist/analyzers/registry/payments.js.map +1 -0
  263. package/dist/analyzers/registry/rate-limiting.d.ts +3 -0
  264. package/dist/analyzers/registry/rate-limiting.d.ts.map +1 -0
  265. package/dist/analyzers/registry/rate-limiting.js +13 -0
  266. package/dist/analyzers/registry/rate-limiting.js.map +1 -0
  267. package/dist/analyzers/registry/search.d.ts +3 -0
  268. package/dist/analyzers/registry/search.d.ts.map +1 -0
  269. package/dist/analyzers/registry/search.js +15 -0
  270. package/dist/analyzers/registry/search.js.map +1 -0
  271. package/dist/analyzers/registry/testing.d.ts +3 -0
  272. package/dist/analyzers/registry/testing.d.ts.map +1 -0
  273. package/dist/analyzers/registry/testing.js +13 -0
  274. package/dist/analyzers/registry/testing.js.map +1 -0
  275. package/dist/analyzers/registry/types.d.ts +14 -0
  276. package/dist/analyzers/registry/types.d.ts.map +1 -0
  277. package/dist/analyzers/registry/types.js +2 -0
  278. package/dist/analyzers/registry/types.js.map +1 -0
  279. package/dist/cache/agentNavigation.d.ts +7 -0
  280. package/dist/cache/agentNavigation.d.ts.map +1 -0
  281. package/dist/cache/agentNavigation.js +253 -0
  282. package/dist/cache/agentNavigation.js.map +1 -0
  283. package/dist/cache/fileHash.d.ts +2 -0
  284. package/dist/cache/fileHash.d.ts.map +1 -0
  285. package/dist/cache/fileHash.js +5 -0
  286. package/dist/cache/fileHash.js.map +1 -0
  287. package/dist/cache/snapshot.d.ts +20 -0
  288. package/dist/cache/snapshot.d.ts.map +1 -0
  289. package/dist/cache/snapshot.js +184 -0
  290. package/dist/cache/snapshot.js.map +1 -0
  291. package/dist/commands/analyze.d.ts +12 -0
  292. package/dist/commands/analyze.d.ts.map +1 -0
  293. package/dist/commands/analyze.js +201 -0
  294. package/dist/commands/analyze.js.map +1 -0
  295. package/dist/commands/config.d.ts +10 -0
  296. package/dist/commands/config.d.ts.map +1 -0
  297. package/dist/commands/config.js +65 -0
  298. package/dist/commands/config.js.map +1 -0
  299. package/dist/commands/doctor.d.ts +11 -0
  300. package/dist/commands/doctor.d.ts.map +1 -0
  301. package/dist/commands/doctor.js +141 -0
  302. package/dist/commands/doctor.js.map +1 -0
  303. package/dist/commands/explain.d.ts +37 -0
  304. package/dist/commands/explain.d.ts.map +1 -0
  305. package/dist/commands/explain.js +101 -0
  306. package/dist/commands/explain.js.map +1 -0
  307. package/dist/commands/flow.d.ts +34 -0
  308. package/dist/commands/flow.d.ts.map +1 -0
  309. package/dist/commands/flow.js +151 -0
  310. package/dist/commands/flow.js.map +1 -0
  311. package/dist/commands/init.d.ts +16 -0
  312. package/dist/commands/init.d.ts.map +1 -0
  313. package/dist/commands/init.js +197 -0
  314. package/dist/commands/init.js.map +1 -0
  315. package/dist/commands/map.d.ts +24 -0
  316. package/dist/commands/map.d.ts.map +1 -0
  317. package/dist/commands/map.js +282 -0
  318. package/dist/commands/map.js.map +1 -0
  319. package/dist/commands/onboarding.d.ts +36 -0
  320. package/dist/commands/onboarding.d.ts.map +1 -0
  321. package/dist/commands/onboarding.js +226 -0
  322. package/dist/commands/onboarding.js.map +1 -0
  323. package/dist/index.d.ts +3 -0
  324. package/dist/index.d.ts.map +1 -0
  325. package/dist/index.js +104 -0
  326. package/dist/index.js.map +1 -0
  327. package/dist/onboarding/model.d.ts +27 -0
  328. package/dist/onboarding/model.d.ts.map +1 -0
  329. package/dist/onboarding/model.js +2 -0
  330. package/dist/onboarding/model.js.map +1 -0
  331. package/dist/onboarding/modelBuilder.d.ts +4 -0
  332. package/dist/onboarding/modelBuilder.d.ts.map +1 -0
  333. package/dist/onboarding/modelBuilder.js +330 -0
  334. package/dist/onboarding/modelBuilder.js.map +1 -0
  335. package/dist/utils/agentsFile.d.ts +6 -0
  336. package/dist/utils/agentsFile.d.ts.map +1 -0
  337. package/dist/utils/agentsFile.js +85 -0
  338. package/dist/utils/agentsFile.js.map +1 -0
  339. package/dist/utils/config.d.ts +20 -0
  340. package/dist/utils/config.d.ts.map +1 -0
  341. package/dist/utils/config.js +88 -0
  342. package/dist/utils/config.js.map +1 -0
  343. package/dist/utils/devmapFile.d.ts +3 -0
  344. package/dist/utils/devmapFile.d.ts.map +1 -0
  345. package/dist/utils/devmapFile.js +43 -0
  346. package/dist/utils/devmapFile.js.map +1 -0
  347. package/dist/utils/errors.d.ts +8 -0
  348. package/dist/utils/errors.d.ts.map +1 -0
  349. package/dist/utils/errors.js +92 -0
  350. package/dist/utils/errors.js.map +1 -0
  351. package/dist/utils/gitignore.d.ts +2 -0
  352. package/dist/utils/gitignore.d.ts.map +1 -0
  353. package/dist/utils/gitignore.js +22 -0
  354. package/dist/utils/gitignore.js.map +1 -0
  355. package/dist/utils/help.d.ts +3 -0
  356. package/dist/utils/help.d.ts.map +1 -0
  357. package/dist/utils/help.js +19 -0
  358. package/dist/utils/help.js.map +1 -0
  359. package/dist/utils/mapRenderer.d.ts +39 -0
  360. package/dist/utils/mapRenderer.d.ts.map +1 -0
  361. package/dist/utils/mapRenderer.js +90 -0
  362. package/dist/utils/mapRenderer.js.map +1 -0
  363. package/dist/utils/markdownTerminal.d.ts +6 -0
  364. package/dist/utils/markdownTerminal.d.ts.map +1 -0
  365. package/dist/utils/markdownTerminal.js +153 -0
  366. package/dist/utils/markdownTerminal.js.map +1 -0
  367. package/dist/utils/output.d.ts +29 -0
  368. package/dist/utils/output.d.ts.map +1 -0
  369. package/dist/utils/output.js +108 -0
  370. package/dist/utils/output.js.map +1 -0
  371. package/dist/utils/packageMetadata.d.ts +2 -0
  372. package/dist/utils/packageMetadata.d.ts.map +1 -0
  373. package/dist/utils/packageMetadata.js +5 -0
  374. package/dist/utils/packageMetadata.js.map +1 -0
  375. package/dist/utils/prompt.d.ts +11 -0
  376. package/dist/utils/prompt.d.ts.map +1 -0
  377. package/dist/utils/prompt.js +81 -0
  378. package/dist/utils/prompt.js.map +1 -0
  379. package/dist/utils/slug.d.ts +2 -0
  380. package/dist/utils/slug.d.ts.map +1 -0
  381. package/dist/utils/slug.js +8 -0
  382. package/dist/utils/slug.js.map +1 -0
  383. package/dist/utils/targetResolver.d.ts +7 -0
  384. package/dist/utils/targetResolver.d.ts.map +1 -0
  385. package/dist/utils/targetResolver.js +15 -0
  386. package/dist/utils/targetResolver.js.map +1 -0
  387. package/dist/utils/welcome.d.ts +10 -0
  388. package/dist/utils/welcome.d.ts.map +1 -0
  389. package/dist/utils/welcome.js +80 -0
  390. package/dist/utils/welcome.js.map +1 -0
  391. package/package.json +61 -0
@@ -0,0 +1,821 @@
1
+ import { classifyFileRole, isTechnicalFeatureSource, isDocumentationMeta } from "../analysis/index.js";
2
+ import { detectFrontendPageFeatures, detectClientRouteFeatures } from "../detectors/index.js";
3
+ import { isArchitectureSource } from "../graph/index.js";
4
+ import { mergeIntoFeatureList } from "./featureMerge.js";
5
+ import { FEATURE_SIGNALS, hasAiProviderUrl, isAiProviderImport } from "../registry/index.js";
6
+ // ---------------------------------------------------------------------------
7
+ // ROLE_FEATURES — only user-visible features, not architectural layers.
8
+ //
9
+ // Excluded intentionally:
10
+ // "api-handler", "service", "middleware", "repository", "ui-component"
11
+ // → architectural implementation concerns, not domain features
12
+ // "ai-integration"
13
+ // → detected via FEATURE_SIGNALS (import-based), role-based too noisy
14
+ // "documentation"
15
+ // → re-added with strict meta-file filtering via isDocumentationEvidence()
16
+ //
17
+ // FEATURE_SIGNALS (vocabulary-driven feature detection) lives in
18
+ // ../registry/index.js — one file per domain under ../registry/.
19
+ // ---------------------------------------------------------------------------
20
+ const ROLE_FEATURES = [
21
+ {
22
+ role: "documentation",
23
+ name: "Documentation",
24
+ purpose: "Contains project documentation, API references, and developer guides.",
25
+ terms: ["documentation", "docs", "guide", "reference", "api", "wiki"]
26
+ },
27
+ {
28
+ role: "landing-ui",
29
+ name: "Web Landing",
30
+ purpose: "Contains public-facing landing page and marketing UI components.",
31
+ terms: ["web", "landing", "marketing", "hero", "ui", "homepage"]
32
+ },
33
+ {
34
+ role: "cli-command",
35
+ name: "CLI Commands",
36
+ purpose: "Contains CLI entry points and command handlers.",
37
+ terms: ["cli", "command", "bin", "argv", "commander", "yargs"]
38
+ },
39
+ ];
40
+ // ---------------------------------------------------------------------------
41
+ // Infrastructure entity names — auth provider internals and ORM bookkeeping
42
+ // entities that should never appear as standalone domain features.
43
+ //
44
+ // These are excluded from entityGraphToFeatures regardless of their relations.
45
+ //
46
+ // Rule: an entity is infrastructure if it exists solely to support an
47
+ // external system (auth provider, ORM, payment processor) and has no
48
+ // business logic of its own visible to the application domain.
49
+ //
50
+ // "Account" is excluded here because in NextAuth / Lucia schemas it
51
+ // represents an OAuth provider link record, not a user-facing account.
52
+ // Projects that genuinely use "Account" as a domain entity (e.g. billing
53
+ // accounts, bank accounts) will still detect it via FEATURE_SIGNALS or
54
+ // capabilitiesToFeatures — so excluding it here is safe.
55
+ // ---------------------------------------------------------------------------
56
+ const INFRASTRUCTURE_ENTITY_NAMES = new Set([
57
+ // NextAuth / Lucia / Better-Auth internals
58
+ "Account",
59
+ "Session",
60
+ "VerificationToken",
61
+ "VerificationCode",
62
+ "Authenticator",
63
+ // Generic auth infrastructure
64
+ "PasswordResetToken",
65
+ "RefreshToken",
66
+ "OAuthToken",
67
+ "OAuthAccount",
68
+ // Audit / system tables
69
+ "AuditLog",
70
+ "ActivityLog",
71
+ "EventLog",
72
+ ]);
73
+ // ---------------------------------------------------------------------------
74
+ // Documentation evidence filter
75
+ // ---------------------------------------------------------------------------
76
+ function isDocumentationEvidence(filePath) {
77
+ const normalized = filePath.toLowerCase();
78
+ const filename = normalized.split("/").at(-1) ?? normalized;
79
+ if (/(^|\/)\.github(\/|$)/.test(normalized))
80
+ return false;
81
+ if (isDocumentationMeta(filename))
82
+ return false;
83
+ return (/(^|\/)docs?(\/|$)/.test(normalized)
84
+ || /(^|\/)wiki(\/|$)/.test(normalized)
85
+ || filename === "readme.md"
86
+ || /\.(guide|tutorial|reference)\.(md|mdx)$/.test(filename)
87
+ || /(openapi|swagger)\.(json|yaml|yml)$/.test(filename));
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Feature evidence file filter
91
+ //
92
+ // Excludes files that are generated artifacts or migration history —
93
+ // these contain domain keywords (table/column names) that cause false
94
+ // positive feature detection without representing actual implementation.
95
+ // ---------------------------------------------------------------------------
96
+ function isFeatureEvidenceFile(path) {
97
+ const lower = path.toLowerCase();
98
+ return !(/\/prisma\/migrations\//.test(lower)
99
+ || /\/migrations\//.test(lower)
100
+ || /\.sql$/.test(lower)
101
+ || /\/generated\//.test(lower)
102
+ || /\.generated\./.test(lower)
103
+ || /\/prisma\/schema\.prisma$/.test(lower)
104
+ || /^prisma\/schema\.prisma$/.test(lower));
105
+ }
106
+ // ---------------------------------------------------------------------------
107
+ // Registry self-exclusion
108
+ //
109
+ // Files under ../registry/ *define* the detection vocabulary. They are not
110
+ // evidence of a real feature in the scanned project — without this check a
111
+ // file like registry/email.ts would self-match the "email" term it describes.
112
+ // ---------------------------------------------------------------------------
113
+ function isRegistryFile(path) {
114
+ return /\/analyzers\/registry\//.test(path.toLowerCase());
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // FEATURE_FILE_PRIORITIES
118
+ // ---------------------------------------------------------------------------
119
+ const FEATURE_FILE_PRIORITIES = {
120
+ Documentation: [
121
+ /(^|\/)readme\.md$/,
122
+ /(^|\/)contributing\.md$/,
123
+ /(^|\/)changelog\.md$/,
124
+ /(^|\/)license(\.md)?$/,
125
+ /(^|\/)docs\/index\.md$/,
126
+ /(^|\/)docs\//,
127
+ ],
128
+ Authentication: [
129
+ /(^|\/)src\/auth\.[cm]?[jt]sx?$/,
130
+ /(^|\/)auth\.[cm]?[jt]sx?$/,
131
+ /\/auth\/config\.[cm]?[jt]sx?$/,
132
+ /(^|\/)middleware\.[cm]?[jt]sx?$/,
133
+ /\/auth\/middleware\.[cm]?[jt]sx?$/,
134
+ /\/api\/auth\//,
135
+ /\/api\/.*\/(login|register|logout)\.[cm]?[jt]sx?$/,
136
+ /\/providers?\/auth[^/]*\.[cm]?[jt]sx?$/,
137
+ /\/context\/auth[^/]*\.[cm]?[jt]sx?$/,
138
+ ],
139
+ Payments: [
140
+ /\/lib\/stripe\.[cm]?[jt]sx?$/,
141
+ /\/lib\/payment[^/]*\.[cm]?[jt]sx?$/,
142
+ /\/api\/.*webhook[^/]*\.[cm]?[jt]sx?$/,
143
+ /\/api\/.*checkout[^/]*\.[cm]?[jt]sx?$/,
144
+ /\/api\/.*payment[^/]*\.[cm]?[jt]sx?$/,
145
+ ],
146
+ "AI Integration": [
147
+ /\/lib\/ai\.[cm]?[jt]sx?$/,
148
+ /\/ai\/provider\.[cm]?[jt]sx?$/,
149
+ /\/ai\/client\.[cm]?[jt]sx?$/,
150
+ /\/lib\/openai\.[cm]?[jt]sx?$/,
151
+ /\/lib\/groq\.[cm]?[jt]sx?$/,
152
+ /\/ai\/prompts?\.[cm]?[jt]sx?$/,
153
+ /\/ai\/completion\.[cm]?[jt]sx?$/,
154
+ ],
155
+ Email: [
156
+ /\/lib\/email[^/]*\.[cm]?[jt]sx?$/,
157
+ /\/lib\/mailer[^/]*\.[cm]?[jt]sx?$/,
158
+ /\/emails?\//,
159
+ /\/templates?\//,
160
+ ],
161
+ "File Upload": [
162
+ /\/lib\/upload[^/]*\.[cm]?[jt]sx?$/,
163
+ /\/lib\/storage[^/]*\.[cm]?[jt]sx?$/,
164
+ /\/lib\/cloudinary[^/]*\.[cm]?[jt]sx?$/,
165
+ /\/api\/.*upload[^/]*\.[cm]?[jt]sx?$/,
166
+ ],
167
+ "Background Jobs": [
168
+ /\/lib\/queue[^/]*\.[cm]?[jt]sx?$/,
169
+ /\/lib\/worker[^/]*\.[cm]?[jt]sx?$/,
170
+ /\/workers?\//,
171
+ /\/jobs?\//,
172
+ /\/queues?\//,
173
+ ],
174
+ Caching: [
175
+ /\/lib\/redis\.[cm]?[jt]sx?$/,
176
+ /\/lib\/cache[^/]*\.[cm]?[jt]sx?$/,
177
+ /\/cache\//,
178
+ ],
179
+ "CLI Commands": [
180
+ /\/src\/index\.[cm]?[jt]sx?$/,
181
+ /\/bin\//,
182
+ /\/commands?\/index\.[cm]?[jt]sx?$/,
183
+ /\/commands?\//,
184
+ ],
185
+ "Web Landing": [
186
+ /\/pages\/index\.(astro|tsx?|jsx?)$/,
187
+ /\/app\/page\.(tsx?|jsx?)$/,
188
+ /\/landing\//,
189
+ /(hero|pricing|features?section)[^/]*\.(astro|tsx?|jsx?|vue|svelte)$/,
190
+ ],
191
+ Testing: [
192
+ /\/(vitest|jest)\.config\.[cm]?[jt]sx?$/,
193
+ /\/test-utils?\.[cm]?[jt]sx?$/,
194
+ /\/setup\.(test|spec)\.[cm]?[jt]sx?$/,
195
+ ],
196
+ Search: [
197
+ /\/lib\/search[^/]*\.[cm]?[jt]sx?$/,
198
+ /\/lib\/meilisearch[^/]*\.[cm]?[jt]sx?$/,
199
+ /\/lib\/algolia[^/]*\.[cm]?[jt]sx?$/,
200
+ ],
201
+ "Logging & Monitoring": [
202
+ /\/lib\/logger[^/]*\.[cm]?[jt]sx?$/,
203
+ /\/lib\/sentry[^/]*\.[cm]?[jt]sx?$/,
204
+ /\/instrumentation\.[cm]?[jt]sx?$/,
205
+ /\/sentry\.(client|server|edge)\.[cm]?[jt]sx?$/,
206
+ ],
207
+ };
208
+ // ---------------------------------------------------------------------------
209
+ // Entry point scoring
210
+ //
211
+ // Lower score = better entry point candidate.
212
+ // Generic utility/helper files score >= ENTRY_POINT_EXCLUDE_THRESHOLD (excluded).
213
+ // ---------------------------------------------------------------------------
214
+ const ENTRY_POINT_EXCLUDE_THRESHOLD = 90;
215
+ export function classifyFileTier(path) {
216
+ const lower = path.toLowerCase();
217
+ if (/\/(prisma\/)?migrations?\//.test(lower))
218
+ return "excluded";
219
+ if (/\.sql$/.test(lower))
220
+ return "excluded";
221
+ if (/\/generated\//.test(lower) || /\.generated\./.test(lower))
222
+ return "excluded";
223
+ if (/\.(lock|log|map)$/.test(lower))
224
+ return "excluded";
225
+ if (/(^|\/)schema\.prisma$/.test(lower))
226
+ return "reference";
227
+ if (/\.(config|conf)\.[cm]?[jt]s$/.test(lower))
228
+ return "reference";
229
+ if (/\/(api|routes?)\//.test(lower))
230
+ return "primary";
231
+ if (/\.(service|usecase|action|route|handler)\.[cm]?[jt]sx?$/.test(lower))
232
+ return "primary";
233
+ if (/\/(hooks?|stores?)\//.test(lower))
234
+ return "primary";
235
+ if (/\.[cm]?[jt]sx?$/.test(lower))
236
+ return "supporting";
237
+ return "reference";
238
+ }
239
+ function scoreEntryPointRelevance(file, _context) {
240
+ const lower = file.toLowerCase();
241
+ if (/\/(utils?|helpers?|constants?|types?|shared)\.[cm]?[jt]sx?$/.test(lower))
242
+ return 100;
243
+ if (/\/(index)\.[cm]?[jt]sx?$/.test(lower) && !/\/(api|routes?|commands?)\//.test(lower))
244
+ return 95;
245
+ if (/\.(d\.ts)$/.test(lower))
246
+ return 100;
247
+ if (/\/(route|handler)\.[cm]?[jt]sx?$/.test(lower))
248
+ return 5;
249
+ if (/\/api\//.test(lower))
250
+ return 10;
251
+ if (/\.(service|usecase|action)\.[cm]?[jt]sx?$/.test(lower))
252
+ return 20;
253
+ if (/\/services?\//.test(lower))
254
+ return 25;
255
+ if (/\/(commands?|bin)\//.test(lower))
256
+ return 15;
257
+ if (/\/(pages?|app)\/.+\/(page|layout)\.[cm]?[jt]sx?$/.test(lower))
258
+ return 30;
259
+ if (/\/components?\//.test(lower))
260
+ return 50;
261
+ if (/\/lib\//.test(lower))
262
+ return 60;
263
+ return 70;
264
+ }
265
+ // ---------------------------------------------------------------------------
266
+ // Main entry
267
+ // ---------------------------------------------------------------------------
268
+ export function detectFeatures(files, analyses, routes, database, entityGraph, capabilities, fileGraph) {
269
+ const features = [];
270
+ const scopedFiles = files.filter((file) => isArchitectureSource(file.path));
271
+ // --- ROLE_FEATURES ---
272
+ for (const definition of ROLE_FEATURES) {
273
+ const evidence = scopedFiles
274
+ .filter((file) => classifyFileRole(file.path) === definition.role
275
+ || (definition.name === "CLI Commands"
276
+ && /(^|\/)src\/index\.[cm]?[jt]s$/.test(file.path.toLowerCase())))
277
+ .filter((file) => isFeatureEvidenceFile(file.path))
278
+ .filter((file) => definition.role !== "documentation" || isDocumentationEvidence(file.path))
279
+ .map((file) => file.path)
280
+ .sort((left, right) => featureFilePriority(definition.name, left) - featureFilePriority(definition.name, right)
281
+ || left.localeCompare(right))
282
+ .slice(0, 12);
283
+ if (evidence.length > 0) {
284
+ features.push(createFeatureInfo(definition.name, evidence, definition.terms, definition.purpose, analyses));
285
+ }
286
+ }
287
+ // --- FEATURE_SIGNALS ---
288
+ // Pre-filter once here — avoids redundant isFeatureEvidenceFile calls inside each signal loop
289
+ // Registry files (../registry/**) are excluded: they *define* the vocabulary,
290
+ // so their paths/content would otherwise self-match every signal they describe.
291
+ const technicalFiles = scopedFiles
292
+ .filter((file) => isTechnicalFeatureSource(file.path))
293
+ .filter((file) => isFeatureEvidenceFile(file.path))
294
+ .filter((file) => !isRegistryFile(file.path));
295
+ for (const signal of FEATURE_SIGNALS) {
296
+ const evidence = technicalFiles
297
+ .filter((file) => matchesSignal(file, analyses[file.path], signal.terms, signal.importOnly))
298
+ .map((file) => file.path)
299
+ .sort((left, right) => featureFilePriority(signal.name, left) - featureFilePriority(signal.name, right)
300
+ || left.localeCompare(right))
301
+ .slice(0, 5);
302
+ const primaryEvidence = evidence.filter((f) => classifyFileTier(f) === "primary" || classifyFileTier(f) === "supporting");
303
+ if (signal.minimumDistinctFiles && primaryEvidence.length < signal.minimumDistinctFiles) {
304
+ continue;
305
+ }
306
+ if (evidence.length > 0) {
307
+ mergeFeature(features, createFeatureInfo(signal.name, evidence, signal.terms, signal.purpose, analyses));
308
+ }
309
+ }
310
+ // Database and API Routes are architectural concerns, not domain features.
311
+ // Database info lives in snapshot.database, routes in snapshot.routes.
312
+ if (capabilities && capabilities.length > 0) {
313
+ for (const feature of capabilitiesToFeatures(capabilities)) {
314
+ if (feature !== null)
315
+ mergeFeature(features, feature);
316
+ }
317
+ }
318
+ if (entityGraph && entityGraph.entityNames.length > 0) {
319
+ for (const feature of entityGraphToFeatures(entityGraph, scopedFiles)) {
320
+ mergeFeature(features, feature);
321
+ }
322
+ }
323
+ if (fileGraph) {
324
+ for (const feature of detectFrontendPageFeatures(routes, fileGraph)) {
325
+ mergeFeature(features, feature);
326
+ }
327
+ for (const feature of detectClientRouteFeatures(scopedFiles, fileGraph)) {
328
+ mergeFeature(features, feature);
329
+ }
330
+ }
331
+ return enrichAuthenticationFeature(features, scopedFiles, analyses)
332
+ .sort((left, right) => left.name.localeCompare(right.name));
333
+ }
334
+ // ---------------------------------------------------------------------------
335
+ // capabilitiesToFeatures
336
+ //
337
+ // Capabilities with no resolvable entry points are dropped — they represent
338
+ // route patterns detected without backing implementation files, which
339
+ // produces low-quality features (empty criticalFiles, misleading names).
340
+ // ---------------------------------------------------------------------------
341
+ function capabilitiesToFeatures(capabilities) {
342
+ return capabilities.map((cap) => {
343
+ const terms = [cap.kind, ...cap.entities.map((e) => e.toLowerCase())];
344
+ const scoredEvidence = cap.evidence
345
+ .map((file) => ({ file, score: scoreEntryPointRelevance(file, cap.kind) }))
346
+ .sort((a, b) => a.score - b.score);
347
+ const entryPoints = scoredEvidence
348
+ .filter((e) => e.score < ENTRY_POINT_EXCLUDE_THRESHOLD)
349
+ .filter((e) => {
350
+ const tier = classifyFileTier(e.file);
351
+ return tier === "primary" || tier === "supporting";
352
+ })
353
+ .slice(0, 2)
354
+ .map((e) => e.file);
355
+ // Drop capabilities with no resolvable entry points and non-high confidence.
356
+ // These are weak detections: route pattern matched but no backing file found.
357
+ if (entryPoints.length === 0 && cap.confidence !== "high")
358
+ return null;
359
+ return {
360
+ name: cap.name,
361
+ purpose: purposeFromCapability(cap),
362
+ files: cap.evidence,
363
+ entryPoints,
364
+ businessFlow: [],
365
+ searchTerms: [...new Set(terms)],
366
+ confidence: cap.confidence,
367
+ evidence: cap.evidence
368
+ };
369
+ });
370
+ }
371
+ function purposeFromCapability(cap) {
372
+ const entityList = cap.entities.length > 0 ? cap.entities.join(", ") : "resources";
373
+ switch (cap.kind) {
374
+ case "crud": return `Handles create, read, update, and delete operations for ${entityList}.`;
375
+ case "sharing": return `Handles content sharing via public links and share tokens.`;
376
+ case "collaboration": return `Handles team collaboration, workspaces, and member management.`;
377
+ case "discovery": return `Handles public content discovery and browsing.`;
378
+ case "publishing": return `Handles content publishing and visibility management.`;
379
+ case "social": return `Handles social interactions like likes, favorites, and reactions.`;
380
+ case "file-management": return `Handles file uploads, storage, and media management.`;
381
+ case "real-time": return `Handles real-time events, websockets, and live updates.`;
382
+ case "search": return `Handles full-text search and content filtering.`;
383
+ case "reporting": return `Handles usage statistics, analytics, and reporting.`;
384
+ default: return `Handles ${cap.kind} operations for ${entityList}.`;
385
+ }
386
+ }
387
+ // ---------------------------------------------------------------------------
388
+ // entityGraphToFeatures
389
+ //
390
+ // Entity ownership model:
391
+ //
392
+ // TRUE CHILD — entity with a single parent via one-to-many AND no own
393
+ // children (leaf node), OR has a child-like name suffix.
394
+ // Skipped as standalone feature; mentioned in parent's purpose.
395
+ // Example: ChecklistItem (owned by Message, no children, suffix "Item")
396
+ //
397
+ // STANDALONE — entity with multiple parents, or entity that itself owns
398
+ // other entities (intermediate node). Gets its own feature.
399
+ // Example: Room (owned by User, but owns Message[])
400
+ // Example: Message (owned by User+Room, but owns ChecklistItem[])
401
+ //
402
+ // OWNED — non-infra, non-true-child entities this entity owns via
403
+ // one-to-many. Shown in purpose string.
404
+ //
405
+ // PEER — many-to-many associations. Shown as "associates with X".
406
+ //
407
+ // Infrastructure entities (auth provider internals, ORM bookkeeping) are
408
+ // excluded entirely via INFRASTRUCTURE_ENTITY_NAMES.
409
+ // ---------------------------------------------------------------------------
410
+ // Suffixes that semantically indicate a sub-item of a parent entity.
411
+ // Used as a tiebreaker when an entity has a single parent and no children.
412
+ const TRUE_CHILD_SUFFIXES = /(?:Item|Entry|Detail|Line|Row|Part|Step|Variant|Option)$/;
413
+ /**
414
+ * isTrueChildEntity — determines if an entity should be skipped as standalone.
415
+ *
416
+ * An entity is a true child if ALL of:
417
+ * 1. Exactly ONE parent owns it via one-to-many (single exclusive owner)
418
+ * 2. It has NO outgoing one-to-many of its own (leaf node)
419
+ * OR its name has a child-like suffix (Item, Entry, Detail, etc.)
420
+ */
421
+ function isTrueChildEntity(entityName, relations) {
422
+ const parents = relations.filter((r) => r.to === entityName && r.kind === "one-to-many");
423
+ if (parents.length === 0)
424
+ return false;
425
+ if (parents.length > 1)
426
+ return false;
427
+ const hasOwnChildren = relations.some((r) => r.from === entityName && r.kind === "one-to-many");
428
+ if (!hasOwnChildren)
429
+ return true;
430
+ if (TRUE_CHILD_SUFFIXES.test(entityName))
431
+ return true;
432
+ return false;
433
+ }
434
+ function entityFileTierScore(path) {
435
+ if (/\.(prisma)$/.test(path))
436
+ return 50;
437
+ if (/\/(migrations?)\//.test(path))
438
+ return 100;
439
+ return 0;
440
+ }
441
+ function findEntityFiles(entityName, files) {
442
+ const lowerName = entityName.toLowerCase();
443
+ const nameSegments = splitNameToSegments(lowerName);
444
+ const EXCLUDED_EXTS = /\.(sql|lock|log)(\.[^/]+)?$/i;
445
+ const isNonSourceDoc = (p) => /\.md$/i.test(p) && !/\/docs\//.test(p.toLowerCase());
446
+ return files
447
+ .filter((f) => isFeatureEvidenceFile(f.path))
448
+ .filter((f) => {
449
+ const lowerPath = f.path.toLowerCase();
450
+ return !EXCLUDED_EXTS.test(lowerPath) && !isNonSourceDoc(lowerPath);
451
+ })
452
+ .filter((f) => {
453
+ const lowerPath = f.path.toLowerCase();
454
+ const pathSegments = lowerPath.split(/[/\\]/);
455
+ return pathSegments.some((segment) => {
456
+ const fileStem = segment.replace(/\.[^/.]+$/, "");
457
+ if (fileStem === lowerName)
458
+ return true;
459
+ const segParts = splitNameToSegments(fileStem);
460
+ return nameSegments.some((ns) => segParts.includes(ns));
461
+ });
462
+ })
463
+ .map((f) => f.path)
464
+ .sort((a, b) => {
465
+ const tierDiff = entityFileTierScore(a) - entityFileTierScore(b);
466
+ if (tierDiff !== 0)
467
+ return tierDiff;
468
+ return a.localeCompare(b);
469
+ })
470
+ .slice(0, 5);
471
+ }
472
+ function splitNameToSegments(name) {
473
+ return name
474
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
475
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
476
+ .toLowerCase()
477
+ .split(/[^a-z0-9]+/)
478
+ .filter(Boolean);
479
+ }
480
+ function entityGraphToFeatures(entityGraph, files = []) {
481
+ if (entityGraph.source === "empty")
482
+ return [];
483
+ // Deduplicate relations across the graph
484
+ const relations = [];
485
+ const seenRelKeys = new Set();
486
+ for (const entity of entityGraph.entities) {
487
+ for (const r of entity.relations) {
488
+ const key = `${r.from}→${r.to}:${r.kind}`;
489
+ if (!seenRelKeys.has(key)) {
490
+ seenRelKeys.add(key);
491
+ relations.push(r);
492
+ }
493
+ }
494
+ }
495
+ const trueChildNames = new Set(entityGraph.entities
496
+ .map((e) => e.name)
497
+ .filter((name) => isTrueChildEntity(name, relations)));
498
+ const features = [];
499
+ const meaningfulEntities = entityGraph.source === "prisma"
500
+ ? entityGraph.entities.filter((e) => relations.some((r) => r.from === e.name || r.to === e.name))
501
+ : entityGraph.entities;
502
+ for (const entity of meaningfulEntities.slice(0, 8)) {
503
+ if (trueChildNames.has(entity.name))
504
+ continue;
505
+ if (INFRASTRUCTURE_ENTITY_NAMES.has(entity.name))
506
+ continue;
507
+ const ownedNames = relations
508
+ .filter((r) => r.from === entity.name && r.kind === "one-to-many")
509
+ .map((r) => r.to)
510
+ .filter((n) => !INFRASTRUCTURE_ENTITY_NAMES.has(n) && !trueChildNames.has(n));
511
+ const oneToOneOwned = relations
512
+ .filter((r) => r.from === entity.name && r.kind === "one-to-one")
513
+ .map((r) => r.to)
514
+ .filter((n) => !INFRASTRUCTURE_ENTITY_NAMES.has(n) && !trueChildNames.has(n));
515
+ const allOwned = [...new Set([...ownedNames, ...oneToOneOwned])];
516
+ const peerNames = relations
517
+ .filter((r) => r.kind === "many-to-many"
518
+ && (r.from === entity.name || r.to === entity.name))
519
+ .map((r) => r.from === entity.name ? r.to : r.from)
520
+ .filter((n) => !INFRASTRUCTURE_ENTITY_NAMES.has(n) && !trueChildNames.has(n) && n !== entity.name);
521
+ const purpose = buildEntityPurpose(entity.name, allOwned, peerNames);
522
+ const searchTerms = [
523
+ entity.name.toLowerCase(),
524
+ ...allOwned.map((n) => n.toLowerCase()),
525
+ ...peerNames.map((n) => n.toLowerCase()),
526
+ "management", "crud"
527
+ ].filter((v, i, arr) => arr.indexOf(v) === i);
528
+ const entityFiles = entity.sourceFiles ?? findEntityFiles(entity.name, files);
529
+ if (entityFiles.length === 0)
530
+ continue;
531
+ const entryPoints = entityFiles
532
+ .map((file) => ({ file, score: scoreEntryPointRelevance(file, entity.name.toLowerCase()) }))
533
+ .sort((a, b) => a.score - b.score)
534
+ .filter((e) => e.score < ENTRY_POINT_EXCLUDE_THRESHOLD)
535
+ .filter((e) => {
536
+ const tier = classifyFileTier(e.file);
537
+ return tier === "primary" || tier === "supporting";
538
+ })
539
+ .slice(0, 2)
540
+ .map((e) => e.file);
541
+ let confidence = entityGraph.source === "prisma" ? "high" : "medium";
542
+ if (entityFiles.length === 1) {
543
+ const tier = classifyFileTier(entityFiles[0]);
544
+ if (tier === "reference")
545
+ confidence = "low";
546
+ }
547
+ features.push({
548
+ name: `${entity.name} Management`,
549
+ purpose,
550
+ files: entityFiles,
551
+ entryPoints,
552
+ businessFlow: [],
553
+ searchTerms,
554
+ confidence,
555
+ evidence: entityFiles
556
+ });
557
+ }
558
+ return features;
559
+ }
560
+ function buildEntityPurpose(entityName, owned, peers) {
561
+ if (owned.length > 0 && peers.length > 0) {
562
+ return `Manages ${entityName} (including ${owned.join(", ")}) and its associations with ${peers.join(", ")}.`;
563
+ }
564
+ if (owned.length > 0) {
565
+ return `Manages ${entityName} and its owned items: ${owned.join(", ")}.`;
566
+ }
567
+ if (peers.length > 0) {
568
+ return `Manages ${entityName} and its associations with ${peers.join(", ")}.`;
569
+ }
570
+ return `Manages ${entityName} data and operations.`;
571
+ }
572
+ // ---------------------------------------------------------------------------
573
+ // Confidence calculation
574
+ // ---------------------------------------------------------------------------
575
+ function calculateFeatureConfidence(evidence, analyses) {
576
+ if (evidence.length === 0)
577
+ return "low";
578
+ const highQualityCount = evidence.filter((path) => analyses[path]?.confidence === "high").length;
579
+ if (highQualityCount >= 2)
580
+ return "high";
581
+ if (highQualityCount >= 1 || evidence.length >= 2)
582
+ return "medium";
583
+ return "low";
584
+ }
585
+ function createFeatureInfo(name, evidence, terms, purpose = `Identifies ${name.toLowerCase()} capability in the project.`, analyses = {}) {
586
+ const files = evidence.filter((item) => item.includes("/") || /\.[A-Za-z0-9]+$/.test(item));
587
+ const entryPoints = files
588
+ .map((file) => ({ file, score: scoreEntryPointRelevance(file, name.toLowerCase()) }))
589
+ .sort((a, b) => a.score - b.score)
590
+ .filter((e) => e.score < ENTRY_POINT_EXCLUDE_THRESHOLD)
591
+ .filter((e) => {
592
+ const tier = classifyFileTier(e.file);
593
+ return tier === "primary" || tier === "supporting";
594
+ })
595
+ .slice(0, 2)
596
+ .map((e) => e.file);
597
+ return {
598
+ name,
599
+ purpose,
600
+ files,
601
+ businessFlow: [],
602
+ entryPoints,
603
+ searchTerms: [...new Set(terms.map((term) => term.toLowerCase()))],
604
+ confidence: calculateFeatureConfidence(evidence, analyses),
605
+ evidence
606
+ };
607
+ }
608
+ /**
609
+ * mergeFeature — wrapper untuk backward compat internal usage.
610
+ * Delegasi ke similarity-based mergeIntoFeatureList dari featureMerge.ts.
611
+ *
612
+ * Alasan tidak hapus function ini: masih dipanggil di beberapa tempat di file ini.
613
+ * mergeIntoFeatureList menggantikan logika lama yang pakai normalizeFeatureName.
614
+ */
615
+ function mergeFeature(features, addition) {
616
+ mergeIntoFeatureList(features, addition);
617
+ }
618
+ // ---------------------------------------------------------------------------
619
+ // matchesSignal
620
+ //
621
+ // AI Integration: import-only by default — see ../registry/ai-providers.ts for the
622
+ // provider vocabulary and the fetch()-URL fallback rules.
623
+ //
624
+ // All other signals: path matching first, then import matching.
625
+ // ---------------------------------------------------------------------------
626
+ function matchesSignal(file, analysis, terms, importOnly) {
627
+ if (importOnly) {
628
+ if (analysis?.imports.some(isAiProviderImport))
629
+ return true;
630
+ if (hasAiProviderUrl(file.content))
631
+ return true;
632
+ return classifyFileRole(file.path) === "ai-integration";
633
+ }
634
+ const path = file.path.toLowerCase();
635
+ if (terms.some((term) => matchesPathTerm(path, term)))
636
+ return true;
637
+ if (analysis) {
638
+ return terms.some((term) => analysis.imports.some((specifier) => specifier.toLowerCase().includes(term)));
639
+ }
640
+ return false;
641
+ }
642
+ const regexCache = new Map();
643
+ function getOrCompilePattern(term) {
644
+ if (regexCache.has(term))
645
+ return regexCache.get(term);
646
+ const pattern = new RegExp(`(?:^|[/._-])${escapeRegex(term)}(?:[/._-]|$)`);
647
+ regexCache.set(term, pattern);
648
+ return pattern;
649
+ }
650
+ function matchesPathTerm(path, term) {
651
+ // All terms ≤7 chars use word-boundary matching to prevent partial matches.
652
+ //
653
+ // ≤3 chars: "ai" must not match "detail", "tailwind", "email"
654
+ // 4-7 chars: "search" must not match "SearchSurah.tsx" (component name, not a path segment)
655
+ // "upload" must not match "LoginUploadWidget.tsx"
656
+ // ≥8 chars: substring is fine — long terms are specific enough (e.g. "elasticsearch")
657
+ if (term.length <= 7) {
658
+ return getOrCompilePattern(term).test(path);
659
+ }
660
+ return path.includes(term);
661
+ }
662
+ function escapeRegex(str) {
663
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
664
+ }
665
+ // ---------------------------------------------------------------------------
666
+ // Authentication enrichment
667
+ // ---------------------------------------------------------------------------
668
+ function enrichAuthenticationFeature(features, files, analyses) {
669
+ const authFiles = collectAuthenticationFeatureFiles(files, analyses);
670
+ if (authFiles.length === 0)
671
+ return features;
672
+ const existingAuth = features.find((f) => f.name === "Authentication");
673
+ if (existingAuth) {
674
+ return features.map((feature) => feature.name === "Authentication"
675
+ ? {
676
+ ...feature,
677
+ files: orderAuthenticationFiles([...new Set([...feature.files, ...authFiles])]),
678
+ evidence: orderAuthenticationFiles([...new Set([...feature.evidence, ...authFiles])]),
679
+ confidence: calculateFeatureConfidence([...new Set([...feature.evidence, ...authFiles])], analyses)
680
+ }
681
+ : feature);
682
+ }
683
+ return [
684
+ ...features,
685
+ createFeatureInfo("Authentication", authFiles, [
686
+ "auth", "authentication", "login", "session", "jwt", "next-auth"
687
+ ], undefined, analyses)
688
+ ];
689
+ }
690
+ function collectAuthenticationFeatureFiles(files, analyses) {
691
+ return orderAuthenticationFiles(files
692
+ .filter((file) => isArchitectureSource(file.path))
693
+ .filter((file) => isTechnicalFeatureSource(file.path))
694
+ .filter((file) => isFeatureEvidenceFile(file.path))
695
+ .filter((file) => !isAnalyzerImplementationFile(file.path))
696
+ .filter((file) => classifyFileRole(file.path) !== "ai-integration")
697
+ .filter((file) => {
698
+ const analysis = analyses[file.path];
699
+ const imports = analysis?.imports ?? extractImportsFallback(file.content);
700
+ const symbols = analysis
701
+ ? analysis.symbols.map((s) => s.name)
702
+ : extractSymbolsFallback(file.content);
703
+ return detectAuthenticationSemanticRole(file.path, symbols, imports, file.content) !== null;
704
+ })
705
+ .map((file) => file.path));
706
+ }
707
+ function isAnalyzerImplementationFile(path) {
708
+ const normalized = path.toLowerCase();
709
+ return (/(^|\/)(analyzers?|detectors?)\//.test(normalized)
710
+ || /(^|\/)[^/]+(?:analyzer|detector)\.[cm]?[jt]sx?$/.test(normalized));
711
+ }
712
+ export function detectAuthenticationSemanticRole(path, symbols, imports, content = "") {
713
+ const normalizedPath = path.toLowerCase();
714
+ const text = `${normalizedPath} ${symbols.join(" ")} ${imports.join(" ")} ${content}`.toLowerCase();
715
+ const normalizedImports = imports.map((s) => s.toLowerCase());
716
+ const hasAuthImport = normalizedImports.some((s) => /(^|[/@-])(auth|next-auth|auth0|clerk|lucia|better-auth|passport|kinde)([/.-]|$)/.test(s)
717
+ || /supabase.*auth/.test(s)
718
+ || /firebase\/auth/.test(s));
719
+ const hasAuthSymbol = symbols.some((s) => /(auth|session|login|register|signin|signout|jwt|token|credential)/i.test(s));
720
+ const hasAuthPath = /(^|[/._-])(auth|session|login|register|signin|signout)([/._-]|$)/.test(normalizedPath);
721
+ const hasGuardPath = /(^|[/._-])(guard|middleware|proxy|protected)([/._-]|$)/.test(normalizedPath);
722
+ const hasGuardSymbol = symbols.some((s) => /(guard|middleware|proxy|protected)/i.test(s));
723
+ if (/(^|\/)src\/auth\.[cm]?[jt]sx?$/.test(normalizedPath)
724
+ || /(^|\/)auth\.[cm]?[jt]sx?$/.test(normalizedPath)
725
+ || (hasSymbol(symbols, "auth") && hasSymbol(symbols, "handlers"))
726
+ || (hasAuthImport && /\b(nextauth|getserversession|getsession|credentials|authconfig)\b/.test(text)))
727
+ return "auth-config";
728
+ if (/(^|\/)(src\/)?(proxy|middleware)\.[cm]?[jt]sx?$/.test(normalizedPath)
729
+ || ((hasAuthPath || hasAuthImport || hasAuthSymbol) && (hasGuardPath || hasGuardSymbol)))
730
+ return "guard";
731
+ if (/providers?\.[cm]?[jt]sx?$/.test(normalizedPath) && (hasAuthImport || hasAuthSymbol))
732
+ return "provider";
733
+ if (/(app-shell|layout)\.[cm]?[jt]sx?$/.test(normalizedPath)
734
+ && /\b(signout|handlesignout|usesession|sessionprovider|useauth)\b/.test(text))
735
+ return "consumer";
736
+ if (hasAuthPath || hasAuthImport || hasAuthSymbol)
737
+ return "consumer";
738
+ return null;
739
+ }
740
+ // ---------------------------------------------------------------------------
741
+ // File priority helpers
742
+ // ---------------------------------------------------------------------------
743
+ function featureFilePriority(featureName, path) {
744
+ const normalized = path.toLowerCase();
745
+ if (featureName === "Documentation") {
746
+ if (normalized === "readme.md")
747
+ return 0;
748
+ if (normalized === "contributing.md")
749
+ return 1;
750
+ if (normalized === "changelog.md")
751
+ return 2;
752
+ if (/^packages\/[^/]+\/readme\.md$/.test(normalized))
753
+ return 10;
754
+ if (/^docs\//.test(normalized))
755
+ return 20;
756
+ return 30 + normalized.split("/").length;
757
+ }
758
+ const index = FEATURE_FILE_PRIORITIES[featureName]
759
+ ?.findIndex((pattern) => pattern.test(normalized)) ?? -1;
760
+ return index === -1 ? 100 : index;
761
+ }
762
+ export function orderAuthenticationFiles(files) {
763
+ return [...new Set(files)].sort((left, right) => authenticationFilePriority(left) - authenticationFilePriority(right)
764
+ || left.localeCompare(right));
765
+ }
766
+ export function authenticationFilePriority(path) {
767
+ const normalized = path.toLowerCase();
768
+ if (/(^|\/)(src\/)?(proxy|middleware)\.[cm]?[jt]sx?$/.test(normalized))
769
+ return 10;
770
+ if (/(^|\/)(src\/)?auth\.[cm]?[jt]sx?$/.test(normalized))
771
+ return 20;
772
+ if (/\/auth\/config\.[cm]?[jt]sx?$/.test(normalized))
773
+ return 25;
774
+ if (/\/api\/auth\//.test(normalized))
775
+ return 30;
776
+ if (/\/api\/.*\/(login|register|logout)\.[cm]?[jt]s$/.test(normalized))
777
+ return 35;
778
+ if (/login.*(page|form)\.[cm]?[jt]sx?$/.test(normalized))
779
+ return 40;
780
+ if (/register.*(page|form)\.[cm]?[jt]sx?$/.test(normalized))
781
+ return 45;
782
+ if (/providers?\.[cm]?[jt]sx?$/.test(normalized))
783
+ return 50;
784
+ if (/(dashboard|app-shell|layout)\.[cm]?[jt]sx?$/.test(normalized))
785
+ return 60;
786
+ return 80;
787
+ }
788
+ // ---------------------------------------------------------------------------
789
+ // Fallback helpers (used when ts-morph analysis unavailable)
790
+ // ---------------------------------------------------------------------------
791
+ function extractImportsFallback(content) {
792
+ const imports = [];
793
+ const pattern = /(?:import\s+(?:[^'"]+\s+from\s+)?|require\()\s*['"]([^'"]+)['"]/g;
794
+ let match = pattern.exec(content);
795
+ while (match) {
796
+ imports.push(match[1].toLowerCase());
797
+ match = pattern.exec(content);
798
+ }
799
+ return imports;
800
+ }
801
+ function extractSymbolsFallback(content) {
802
+ const symbols = new Set();
803
+ const patterns = [
804
+ /export\s+(?:async\s+)?function\s+([A-Za-z_$][A-Za-z0-9_$]*)/g,
805
+ /export\s+const\s+([A-Za-z_$][A-Za-z0-9_$]*)/g,
806
+ /export\s+class\s+([A-Za-z_$][A-Za-z0-9_$]*)/g,
807
+ /(?:function|const)\s+([A-Za-z_$][A-Za-z0-9_$]*(?:Auth|Session|Login|Register|SignOut|Provider|Guard)[A-Za-z0-9_$]*)/g
808
+ ];
809
+ for (const pattern of patterns) {
810
+ let match = pattern.exec(content);
811
+ while (match) {
812
+ symbols.add(match[1]);
813
+ match = pattern.exec(content);
814
+ }
815
+ }
816
+ return [...symbols];
817
+ }
818
+ function hasSymbol(symbols, name) {
819
+ return symbols.some((s) => s.toLowerCase() === name);
820
+ }
821
+ //# sourceMappingURL=featureDetector.js.map