@featurevisor/core 2.26.1 → 3.0.1

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 (390) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/coverage/clover.xml +4991 -3130
  3. package/coverage/coverage-final.json +63 -39
  4. package/coverage/lcov-report/block-navigation.js +1 -1
  5. package/coverage/lcov-report/index.html +248 -98
  6. package/coverage/lcov-report/sorter.js +21 -7
  7. package/coverage/lcov-report/src/assess-distribution/index.html +116 -0
  8. package/coverage/lcov-report/src/assess-distribution/index.ts.html +754 -0
  9. package/coverage/lcov-report/{list → src/benchmark}/index.html +30 -30
  10. package/coverage/lcov-report/src/benchmark/index.ts.html +793 -0
  11. package/coverage/lcov-report/{builder → src/builder}/allocator.ts.html +38 -38
  12. package/coverage/lcov-report/{builder/buildScopedConditions.ts.html → src/builder/applyContextToConditions.ts.html} +80 -65
  13. package/coverage/lcov-report/{builder/buildScopedDatafile.ts.html → src/builder/applyContextToDatafile.ts.html} +92 -92
  14. package/coverage/lcov-report/{builder/buildScopedSegments.ts.html → src/builder/applyContextToSegments.ts.html} +103 -67
  15. package/coverage/lcov-report/{builder → src/builder}/buildDatafile.ts.html +336 -306
  16. package/coverage/lcov-report/src/builder/buildProject.ts.html +1117 -0
  17. package/coverage/lcov-report/src/builder/buildRuntimeDatafiles.ts.html +256 -0
  18. package/coverage/lcov-report/{builder → src/builder}/getFeatureRanges.ts.html +22 -22
  19. package/coverage/lcov-report/{builder → src/builder}/hashes.ts.html +50 -50
  20. package/coverage/lcov-report/{builder → src/builder}/index.html +114 -84
  21. package/coverage/lcov-report/{tester/cliFormat.ts.html → src/builder/index.ts.html} +17 -29
  22. package/coverage/lcov-report/{builder → src/builder}/mutateVariables.ts.html +55 -55
  23. package/coverage/lcov-report/{builder → src/builder}/mutator.ts.html +118 -118
  24. package/coverage/lcov-report/{builder → src/builder}/revision.ts.html +15 -15
  25. package/coverage/lcov-report/{builder → src/builder}/traffic.ts.html +86 -86
  26. package/coverage/lcov-report/src/cli/cli.ts.html +400 -0
  27. package/coverage/lcov-report/{tester → src/cli}/index.html +41 -41
  28. package/coverage/lcov-report/src/cli/plugins.ts.html +214 -0
  29. package/coverage/lcov-report/{config → src/config}/index.html +31 -31
  30. package/coverage/lcov-report/{config → src/config}/index.ts.html +12 -12
  31. package/coverage/lcov-report/{config → src/config}/projectConfig.ts.html +312 -96
  32. package/coverage/lcov-report/{datasource → src/datasource}/adapter.ts.html +28 -73
  33. package/coverage/lcov-report/{datasource → src/datasource}/datasource.ts.html +191 -104
  34. package/coverage/lcov-report/{datasource → src/datasource}/filesystemAdapter.ts.html +233 -635
  35. package/coverage/lcov-report/{datasource → src/datasource}/index.html +48 -48
  36. package/coverage/lcov-report/{datasource → src/datasource}/index.ts.html +14 -14
  37. package/coverage/lcov-report/src/evaluate/index.html +116 -0
  38. package/coverage/lcov-report/src/evaluate/index.ts.html +814 -0
  39. package/coverage/lcov-report/src/find-duplicate-segments/findDuplicateSegments.ts.html +313 -0
  40. package/coverage/lcov-report/src/find-duplicate-segments/index.html +131 -0
  41. package/coverage/lcov-report/src/find-duplicate-segments/index.ts.html +307 -0
  42. package/coverage/lcov-report/src/find-usage/index.html +116 -0
  43. package/coverage/lcov-report/src/find-usage/index.ts.html +1780 -0
  44. package/coverage/lcov-report/src/generate-code/index.html +131 -0
  45. package/coverage/lcov-report/src/generate-code/index.ts.html +403 -0
  46. package/coverage/lcov-report/{generate-code → src/generate-code}/typescript.ts.html +266 -1361
  47. package/coverage/lcov-report/{generate-code → src}/index.html +38 -23
  48. package/coverage/lcov-report/src/info/index.html +116 -0
  49. package/coverage/lcov-report/src/info/index.ts.html +472 -0
  50. package/coverage/lcov-report/src/init/index.html +116 -0
  51. package/coverage/lcov-report/src/init/index.ts.html +280 -0
  52. package/coverage/lcov-report/{linter → src/linter}/attributeSchema.ts.html +160 -157
  53. package/coverage/lcov-report/{linter → src/linter}/checkCircularDependency.ts.html +25 -25
  54. package/coverage/lcov-report/{linter → src/linter}/checkPercentageExceedingSlot.ts.html +42 -42
  55. package/coverage/lcov-report/{linter → src/linter}/conditionSchema.ts.html +207 -207
  56. package/coverage/lcov-report/{linter → src/linter}/featureSchema.ts.html +462 -471
  57. package/coverage/lcov-report/{linter → src/linter}/groupSchema.ts.html +25 -22
  58. package/coverage/lcov-report/{linter → src/linter}/index.html +129 -99
  59. package/coverage/lcov-report/src/linter/index.ts.html +88 -0
  60. package/coverage/lcov-report/{linter → src/linter}/lintProject.ts.html +740 -332
  61. package/coverage/lcov-report/{linter → src/linter}/mutationNotation.ts.html +130 -130
  62. package/coverage/lcov-report/{linter → src/linter}/printError.ts.html +27 -27
  63. package/coverage/lcov-report/{linter → src/linter}/schema.ts.html +153 -150
  64. package/coverage/lcov-report/{linter → src/linter}/segmentSchema.ts.html +18 -15
  65. package/coverage/lcov-report/src/linter/targetSchema.ts.html +223 -0
  66. package/coverage/lcov-report/{linter → src/linter}/testSchema.ts.html +54 -48
  67. package/coverage/lcov-report/{linter → src/linter}/zodHelpers.ts.html +17 -17
  68. package/coverage/lcov-report/src/list/index.html +131 -0
  69. package/coverage/lcov-report/src/list/index.ts.html +2065 -0
  70. package/coverage/lcov-report/{list → src/list}/matrix.ts.html +43 -58
  71. package/coverage/lcov-report/src/promoter/index.html +116 -0
  72. package/coverage/lcov-report/src/promoter/index.ts.html +3883 -0
  73. package/coverage/lcov-report/src/sets.ts.html +313 -0
  74. package/coverage/lcov-report/src/targeting.ts.html +403 -0
  75. package/coverage/lcov-report/src/tester/cliFormat.ts.html +133 -0
  76. package/coverage/lcov-report/{tester → src/tester}/helpers.ts.html +15 -15
  77. package/coverage/lcov-report/src/tester/index.html +206 -0
  78. package/coverage/lcov-report/src/tester/prettyDuration.ts.html +187 -0
  79. package/coverage/lcov-report/src/tester/printTestResult.ts.html +337 -0
  80. package/coverage/lcov-report/src/tester/testFeature.ts.html +1186 -0
  81. package/coverage/lcov-report/src/tester/testProject.ts.html +1018 -0
  82. package/coverage/lcov-report/src/tester/testSegment.ts.html +316 -0
  83. package/coverage/lcov-report/{utils → src/utils}/extractKeys.ts.html +68 -68
  84. package/coverage/lcov-report/{utils → src/utils}/git.ts.html +44 -68
  85. package/coverage/lcov-report/{utils → src/utils}/index.html +44 -44
  86. package/coverage/lcov-report/{utils → src/utils}/index.ts.html +14 -14
  87. package/coverage/lcov-report/{utils → src/utils}/pretty.ts.html +20 -20
  88. package/coverage/lcov.info +10121 -5723
  89. package/jest.config.js +13 -4
  90. package/lib/assess-distribution/index.d.ts +1 -1
  91. package/lib/assess-distribution/index.js +59 -40
  92. package/lib/assess-distribution/index.js.map +1 -1
  93. package/lib/benchmark/index.d.ts +8 -5
  94. package/lib/benchmark/index.js +82 -65
  95. package/lib/benchmark/index.js.map +1 -1
  96. package/lib/builder/applyContextToConditions.d.ts +5 -0
  97. package/lib/builder/{buildScopedConditions.js → applyContextToConditions.js} +19 -14
  98. package/lib/builder/applyContextToConditions.js.map +1 -0
  99. package/lib/builder/applyContextToDatafile.d.ts +2 -0
  100. package/lib/builder/{buildScopedDatafile.js → applyContextToDatafile.js} +26 -26
  101. package/lib/builder/applyContextToDatafile.js.map +1 -0
  102. package/lib/builder/applyContextToSegments.d.ts +5 -0
  103. package/lib/builder/{buildScopedSegments.js → applyContextToSegments.js} +19 -14
  104. package/lib/builder/applyContextToSegments.js.map +1 -0
  105. package/lib/builder/buildDatafile.d.ts +9 -6
  106. package/lib/builder/buildDatafile.js +86 -51
  107. package/lib/builder/buildDatafile.js.map +1 -1
  108. package/lib/builder/buildProject.d.ts +17 -3
  109. package/lib/builder/buildProject.js +151 -59
  110. package/lib/builder/buildProject.js.map +1 -1
  111. package/lib/builder/buildRuntimeDatafiles.d.ts +12 -0
  112. package/lib/builder/buildRuntimeDatafiles.js +35 -0
  113. package/lib/builder/buildRuntimeDatafiles.js.map +1 -0
  114. package/lib/builder/getFeatureRanges.js +34 -1
  115. package/lib/builder/getFeatureRanges.js.map +1 -1
  116. package/lib/builder/hashes.js +34 -1
  117. package/lib/builder/hashes.js.map +1 -1
  118. package/lib/builder/index.d.ts +0 -1
  119. package/lib/builder/index.js +0 -1
  120. package/lib/builder/index.js.map +1 -1
  121. package/lib/cli/cli.js +0 -4
  122. package/lib/cli/cli.js.map +1 -1
  123. package/lib/cli/plugins.js +7 -2
  124. package/lib/cli/plugins.js.map +1 -1
  125. package/lib/config/projectConfig.d.ts +17 -17
  126. package/lib/config/projectConfig.js +101 -15
  127. package/lib/config/projectConfig.js.map +1 -1
  128. package/lib/datasource/adapter.d.ts +7 -9
  129. package/lib/datasource/adapter.js +0 -7
  130. package/lib/datasource/adapter.js.map +1 -1
  131. package/lib/datasource/datasource.d.ts +15 -5
  132. package/lib/datasource/datasource.js +37 -9
  133. package/lib/datasource/datasource.js.map +1 -1
  134. package/lib/datasource/filesystemAdapter.d.ts +4 -10
  135. package/lib/datasource/filesystemAdapter.js +111 -149
  136. package/lib/datasource/filesystemAdapter.js.map +1 -1
  137. package/lib/evaluate/index.d.ts +1 -7
  138. package/lib/evaluate/index.js +81 -67
  139. package/lib/evaluate/index.js.map +1 -1
  140. package/lib/find-duplicate-segments/findDuplicateSegments.js +34 -1
  141. package/lib/find-duplicate-segments/findDuplicateSegments.js.map +1 -1
  142. package/lib/find-duplicate-segments/index.js +21 -13
  143. package/lib/find-duplicate-segments/index.js.map +1 -1
  144. package/lib/find-usage/index.js +57 -41
  145. package/lib/find-usage/index.js.map +1 -1
  146. package/lib/generate-code/index.d.ts +1 -1
  147. package/lib/generate-code/index.js +64 -21
  148. package/lib/generate-code/index.js.map +1 -1
  149. package/lib/generate-code/typescript.d.ts +1 -1
  150. package/lib/generate-code/typescript.js +59 -333
  151. package/lib/generate-code/typescript.js.map +1 -1
  152. package/lib/index.d.ts +2 -1
  153. package/lib/index.js +2 -1
  154. package/lib/index.js.map +1 -1
  155. package/lib/info/index.js +57 -16
  156. package/lib/info/index.js.map +1 -1
  157. package/lib/init/index.d.ts +2 -2
  158. package/lib/init/index.js +39 -3
  159. package/lib/init/index.js.map +1 -1
  160. package/lib/linter/attributeSchema.d.ts +1 -0
  161. package/lib/linter/attributeSchema.js +1 -0
  162. package/lib/linter/attributeSchema.js.map +1 -1
  163. package/lib/linter/conditionSchema.js +5 -5
  164. package/lib/linter/conditionSchema.js.map +1 -1
  165. package/lib/linter/featureSchema.d.ts +4 -1
  166. package/lib/linter/featureSchema.js +15 -13
  167. package/lib/linter/featureSchema.js.map +1 -1
  168. package/lib/linter/groupSchema.d.ts +1 -0
  169. package/lib/linter/groupSchema.js +1 -0
  170. package/lib/linter/groupSchema.js.map +1 -1
  171. package/lib/linter/lintProject.d.ts +1 -3
  172. package/lib/linter/lintProject.js +198 -68
  173. package/lib/linter/lintProject.js.map +1 -1
  174. package/lib/linter/schema.js +1 -0
  175. package/lib/linter/schema.js.map +1 -1
  176. package/lib/linter/segmentSchema.d.ts +1 -0
  177. package/lib/linter/segmentSchema.js +1 -0
  178. package/lib/linter/segmentSchema.js.map +1 -1
  179. package/lib/linter/targetSchema.d.ts +16 -0
  180. package/lib/linter/targetSchema.js +40 -0
  181. package/lib/linter/targetSchema.js.map +1 -0
  182. package/lib/linter/testSchema.d.ts +4 -3
  183. package/lib/linter/testSchema.js +9 -4
  184. package/lib/linter/testSchema.js.map +1 -1
  185. package/lib/list/index.d.ts +1 -0
  186. package/lib/list/index.js +131 -12
  187. package/lib/list/index.js.map +1 -1
  188. package/lib/list/matrix.js +3 -7
  189. package/lib/list/matrix.js.map +1 -1
  190. package/lib/promoter/index.d.ts +50 -0
  191. package/lib/promoter/index.js +880 -0
  192. package/lib/promoter/index.js.map +1 -0
  193. package/lib/sets.d.ts +11 -0
  194. package/lib/sets.js +81 -0
  195. package/lib/sets.js.map +1 -0
  196. package/lib/targeting.d.ts +14 -0
  197. package/lib/targeting.js +82 -0
  198. package/lib/targeting.js.map +1 -0
  199. package/lib/tester/cliFormat.d.ts +7 -1
  200. package/lib/tester/cliFormat.js +11 -2
  201. package/lib/tester/cliFormat.js.map +1 -1
  202. package/lib/tester/printTestResult.js +2 -2
  203. package/lib/tester/printTestResult.js.map +1 -1
  204. package/lib/tester/testFeature.d.ts +0 -1
  205. package/lib/tester/testFeature.js +8 -25
  206. package/lib/tester/testFeature.js.map +1 -1
  207. package/lib/tester/testProject.d.ts +2 -3
  208. package/lib/tester/testProject.js +93 -86
  209. package/lib/tester/testProject.js.map +1 -1
  210. package/lib/tester/testSegment.d.ts +1 -1
  211. package/lib/tester/testSegment.js +3 -21
  212. package/lib/tester/testSegment.js.map +1 -1
  213. package/lib/utils/git.js +45 -19
  214. package/lib/utils/git.js.map +1 -1
  215. package/package.json +12 -12
  216. package/src/assess-distribution/index.ts +72 -52
  217. package/src/benchmark/index.ts +124 -91
  218. package/src/builder/{buildScopedConditions.spec.ts → applyContextToConditions.spec.ts} +160 -142
  219. package/src/builder/{buildScopedConditions.ts → applyContextToConditions.ts} +19 -14
  220. package/src/builder/{buildScopedDatafile.spec.ts → applyContextToDatafile.spec.ts} +141 -81
  221. package/src/builder/{buildScopedDatafile.ts → applyContextToDatafile.ts} +33 -33
  222. package/src/builder/{buildScopedSegments.spec.ts → applyContextToSegments.spec.ts} +171 -151
  223. package/src/builder/{buildScopedSegments.ts → applyContextToSegments.ts} +26 -14
  224. package/src/builder/buildDatafile.spec.ts +192 -14
  225. package/src/builder/buildDatafile.ts +74 -64
  226. package/src/builder/buildProject.ts +171 -86
  227. package/src/builder/buildRuntimeDatafiles.ts +57 -0
  228. package/src/builder/index.ts +0 -1
  229. package/src/cli/cli.ts +0 -5
  230. package/src/cli/plugins.ts +7 -2
  231. package/src/config/projectConfig.spec.ts +171 -8
  232. package/src/config/projectConfig.ts +100 -28
  233. package/src/datasource/adapter.ts +8 -23
  234. package/src/datasource/datasource.ts +50 -21
  235. package/src/datasource/filesystemAdapter.spec.ts +133 -74
  236. package/src/datasource/filesystemAdapter.ts +93 -227
  237. package/src/evaluate/index.ts +109 -97
  238. package/src/find-duplicate-segments/index.ts +34 -16
  239. package/src/find-usage/index.ts +89 -44
  240. package/src/generate-code/index.ts +36 -24
  241. package/src/generate-code/typescript.spec.ts +106 -0
  242. package/src/generate-code/typescript.ts +33 -398
  243. package/src/index.ts +2 -1
  244. package/src/info/index.ts +72 -16
  245. package/src/init/index.ts +1 -1
  246. package/src/linter/attributeSchema.ts +1 -0
  247. package/src/linter/conditionSchema.spec.ts +23 -3
  248. package/src/linter/conditionSchema.ts +5 -5
  249. package/src/linter/featureSchema.spec.ts +107 -18
  250. package/src/linter/featureSchema.ts +25 -28
  251. package/src/linter/groupSchema.ts +1 -0
  252. package/src/linter/lintProject.spec.ts +131 -92
  253. package/src/linter/lintProject.ts +233 -97
  254. package/src/linter/schema.ts +1 -0
  255. package/src/linter/segmentSchema.spec.ts +5 -3
  256. package/src/linter/segmentSchema.ts +1 -0
  257. package/src/linter/targetSchema.spec.ts +159 -0
  258. package/src/linter/targetSchema.ts +46 -0
  259. package/src/linter/testSchema.spec.ts +70 -5
  260. package/src/linter/testSchema.ts +12 -10
  261. package/src/list/index.spec.ts +135 -0
  262. package/src/list/index.ts +188 -12
  263. package/src/list/matrix.ts +3 -8
  264. package/src/promoter/index.spec.ts +617 -0
  265. package/src/promoter/index.ts +1266 -0
  266. package/src/sets.ts +76 -0
  267. package/src/targeting.spec.ts +74 -0
  268. package/src/targeting.ts +106 -0
  269. package/src/tester/cliFormat.ts +11 -1
  270. package/src/tester/printTestResult.ts +12 -3
  271. package/src/tester/testFeature.ts +10 -36
  272. package/src/tester/testProject.spec.ts +50 -0
  273. package/src/tester/testProject.ts +89 -140
  274. package/src/tester/testSegment.ts +5 -22
  275. package/src/utils/git.ts +13 -21
  276. package/tsconfig.cjs.json +5 -1
  277. package/tsconfig.typecheck.json +9 -0
  278. package/coverage/lcov-report/builder/convertToV1.ts.html +0 -583
  279. package/lib/builder/allocator.spec.d.ts +0 -1
  280. package/lib/builder/allocator.spec.js +0 -85
  281. package/lib/builder/allocator.spec.js.map +0 -1
  282. package/lib/builder/buildDatafile.spec.d.ts +0 -1
  283. package/lib/builder/buildDatafile.spec.js +0 -233
  284. package/lib/builder/buildDatafile.spec.js.map +0 -1
  285. package/lib/builder/buildScopedConditions.d.ts +0 -5
  286. package/lib/builder/buildScopedConditions.js.map +0 -1
  287. package/lib/builder/buildScopedConditions.spec.d.ts +0 -1
  288. package/lib/builder/buildScopedConditions.spec.js +0 -2167
  289. package/lib/builder/buildScopedConditions.spec.js.map +0 -1
  290. package/lib/builder/buildScopedDatafile.d.ts +0 -2
  291. package/lib/builder/buildScopedDatafile.js.map +0 -1
  292. package/lib/builder/buildScopedDatafile.spec.d.ts +0 -1
  293. package/lib/builder/buildScopedDatafile.spec.js +0 -2277
  294. package/lib/builder/buildScopedDatafile.spec.js.map +0 -1
  295. package/lib/builder/buildScopedSegments.d.ts +0 -5
  296. package/lib/builder/buildScopedSegments.js.map +0 -1
  297. package/lib/builder/buildScopedSegments.spec.d.ts +0 -1
  298. package/lib/builder/buildScopedSegments.spec.js +0 -1062
  299. package/lib/builder/buildScopedSegments.spec.js.map +0 -1
  300. package/lib/builder/convertToV1.d.ts +0 -10
  301. package/lib/builder/convertToV1.js +0 -119
  302. package/lib/builder/convertToV1.js.map +0 -1
  303. package/lib/builder/mutateVariables.spec.d.ts +0 -1
  304. package/lib/builder/mutateVariables.spec.js +0 -1074
  305. package/lib/builder/mutateVariables.spec.js.map +0 -1
  306. package/lib/builder/mutator.spec.d.ts +0 -1
  307. package/lib/builder/mutator.spec.js +0 -368
  308. package/lib/builder/mutator.spec.js.map +0 -1
  309. package/lib/builder/revision.spec.d.ts +0 -1
  310. package/lib/builder/revision.spec.js +0 -21
  311. package/lib/builder/revision.spec.js.map +0 -1
  312. package/lib/builder/traffic.spec.d.ts +0 -1
  313. package/lib/builder/traffic.spec.js +0 -872
  314. package/lib/builder/traffic.spec.js.map +0 -1
  315. package/lib/config/projectConfig.spec.d.ts +0 -1
  316. package/lib/config/projectConfig.spec.js +0 -24
  317. package/lib/config/projectConfig.spec.js.map +0 -1
  318. package/lib/datasource/filesystemAdapter.spec.d.ts +0 -1
  319. package/lib/datasource/filesystemAdapter.spec.js +0 -88
  320. package/lib/datasource/filesystemAdapter.spec.js.map +0 -1
  321. package/lib/generate-code/typescript.spec.d.ts +0 -1
  322. package/lib/generate-code/typescript.spec.js +0 -78
  323. package/lib/generate-code/typescript.spec.js.map +0 -1
  324. package/lib/linter/attributeSchema.spec.d.ts +0 -1
  325. package/lib/linter/attributeSchema.spec.js +0 -266
  326. package/lib/linter/attributeSchema.spec.js.map +0 -1
  327. package/lib/linter/conditionSchema.spec.d.ts +0 -1
  328. package/lib/linter/conditionSchema.spec.js +0 -380
  329. package/lib/linter/conditionSchema.spec.js.map +0 -1
  330. package/lib/linter/featureSchema.spec.d.ts +0 -1
  331. package/lib/linter/featureSchema.spec.js +0 -1552
  332. package/lib/linter/featureSchema.spec.js.map +0 -1
  333. package/lib/linter/lintProject.spec.d.ts +0 -1
  334. package/lib/linter/lintProject.spec.js +0 -211
  335. package/lib/linter/lintProject.spec.js.map +0 -1
  336. package/lib/linter/mutationNotation.spec.d.ts +0 -1
  337. package/lib/linter/mutationNotation.spec.js +0 -598
  338. package/lib/linter/mutationNotation.spec.js.map +0 -1
  339. package/lib/linter/schema.spec.d.ts +0 -1
  340. package/lib/linter/schema.spec.js +0 -535
  341. package/lib/linter/schema.spec.js.map +0 -1
  342. package/lib/linter/segmentSchema.spec.d.ts +0 -1
  343. package/lib/linter/segmentSchema.spec.js +0 -303
  344. package/lib/linter/segmentSchema.spec.js.map +0 -1
  345. package/lib/linter/testSchema.spec.d.ts +0 -1
  346. package/lib/linter/testSchema.spec.js +0 -162
  347. package/lib/linter/testSchema.spec.js.map +0 -1
  348. package/lib/list/matrix.spec.d.ts +0 -1
  349. package/lib/list/matrix.spec.js +0 -42
  350. package/lib/list/matrix.spec.js.map +0 -1
  351. package/lib/site/exportSite.d.ts +0 -2
  352. package/lib/site/exportSite.js +0 -30
  353. package/lib/site/exportSite.js.map +0 -1
  354. package/lib/site/generateHistory.d.ts +0 -3
  355. package/lib/site/generateHistory.js +0 -31
  356. package/lib/site/generateHistory.js.map +0 -1
  357. package/lib/site/generateSiteSearchIndex.d.ts +0 -4
  358. package/lib/site/generateSiteSearchIndex.js +0 -195
  359. package/lib/site/generateSiteSearchIndex.js.map +0 -1
  360. package/lib/site/getLastModifiedFromHistory.d.ts +0 -2
  361. package/lib/site/getLastModifiedFromHistory.js +0 -18
  362. package/lib/site/getLastModifiedFromHistory.js.map +0 -1
  363. package/lib/site/getOwnerAndRepoFromUrl.d.ts +0 -4
  364. package/lib/site/getOwnerAndRepoFromUrl.js +0 -20
  365. package/lib/site/getOwnerAndRepoFromUrl.js.map +0 -1
  366. package/lib/site/getRelativePaths.d.ts +0 -6
  367. package/lib/site/getRelativePaths.js +0 -15
  368. package/lib/site/getRelativePaths.js.map +0 -1
  369. package/lib/site/getRepoDetails.d.ts +0 -8
  370. package/lib/site/getRepoDetails.js +0 -48
  371. package/lib/site/getRepoDetails.js.map +0 -1
  372. package/lib/site/index.d.ts +0 -2
  373. package/lib/site/index.js +0 -43
  374. package/lib/site/index.js.map +0 -1
  375. package/lib/site/serveSite.d.ts +0 -2
  376. package/lib/site/serveSite.js +0 -54
  377. package/lib/site/serveSite.js.map +0 -1
  378. package/lib/tester/helpers.spec.d.ts +0 -1
  379. package/lib/tester/helpers.spec.js +0 -115
  380. package/lib/tester/helpers.spec.js.map +0 -1
  381. package/src/builder/convertToV1.ts +0 -166
  382. package/src/site/exportSite.ts +0 -42
  383. package/src/site/generateHistory.ts +0 -40
  384. package/src/site/generateSiteSearchIndex.ts +0 -258
  385. package/src/site/getLastModifiedFromHistory.ts +0 -21
  386. package/src/site/getOwnerAndRepoFromUrl.ts +0 -17
  387. package/src/site/getRelativePaths.ts +0 -24
  388. package/src/site/getRepoDetails.ts +0 -62
  389. package/src/site/index.ts +0 -46
  390. package/src/site/serveSite.ts +0 -58
@@ -1,17 +1,18 @@
1
1
  import type { Context, DatafileContent } from "@featurevisor/types";
2
- import {
3
- Evaluation,
4
- createInstance,
5
- createLogger,
6
- LogLevel,
7
- LogMessage,
8
- LogDetails,
9
- } from "@featurevisor/sdk";
2
+ import { createFeaturevisor } from "@featurevisor/sdk";
3
+ import type { Evaluation, FeaturevisorDiagnostic } from "@featurevisor/sdk";
10
4
 
11
5
  import { Dependencies } from "../dependencies";
12
- import { SCHEMA_VERSION } from "../config";
13
- import { buildDatafile } from "../builder";
6
+ import { buildRuntimeDatafiles } from "../builder/buildRuntimeDatafiles";
14
7
  import { Plugin } from "../cli";
8
+ import { assertProjectSetJsonSelection, getProjectSetExecutions, printSetHeader } from "../sets";
9
+ import {
10
+ CLI_COLOR_CYAN,
11
+ CLI_FORMAT_BOLD,
12
+ CLI_FORMAT_GREEN,
13
+ CLI_FORMAT_YELLOW,
14
+ colorize,
15
+ } from "../tester/cliFormat";
15
16
 
16
17
  function printEvaluationDetails(evaluation: Evaluation) {
17
18
  const ignoreKeys = ["featureKey", "variableKey", "traffic", "force"];
@@ -22,31 +23,35 @@ function printEvaluationDetails(evaluation: Evaluation) {
22
23
  }
23
24
 
24
25
  if (key === "variation") {
25
- console.log(`-`, `${key}:`, value?.value);
26
+ console.log(` ${colorize(key, CLI_COLOR_CYAN)}:`, value?.value);
26
27
  continue;
27
28
  }
28
29
 
29
30
  if (key === "variableSchema") {
30
- console.log(`-`, `variableType:`, value.type);
31
- console.log(`-`, `defaultValue:`, value.defaultValue);
31
+ console.log(` ${colorize("variableType", CLI_COLOR_CYAN)}:`, value.type);
32
+ console.log(` ${colorize("defaultValue", CLI_COLOR_CYAN)}:`, value.defaultValue);
32
33
  continue;
33
34
  }
34
35
 
35
- console.log(`-`, `${key}:`, value);
36
+ console.log(` ${colorize(key, CLI_COLOR_CYAN)}:`, value);
36
37
  }
37
38
  }
38
39
 
39
- function printLogs(logs: Log[]) {
40
- logs.forEach((log) => {
41
- console.log(`[${log.level}] ${log.message}`, log.details);
40
+ function printDiagnostics(diagnostics: FeaturevisorDiagnostic[]) {
41
+ diagnostics.forEach((diagnostic) => {
42
+ const levelColor = diagnostic.level === "error" ? 31 : diagnostic.level === "warn" ? 33 : 2;
43
+ console.log(
44
+ `${colorize(`[${diagnostic.level}]`, levelColor)} ${diagnostic.message}`,
45
+ diagnostic,
46
+ );
42
47
  console.log("");
43
48
  });
44
49
  }
45
50
 
46
51
  function printHeader(message: string) {
47
- console.log("\n\n###############");
48
- console.log(`# ${message}`);
49
- console.log("###############\n");
52
+ console.log("");
53
+ console.log(CLI_FORMAT_BOLD, message);
54
+ console.log("");
50
55
  }
51
56
 
52
57
  export interface EvaluateOptions {
@@ -56,57 +61,32 @@ export interface EvaluateOptions {
56
61
  json?: boolean;
57
62
  pretty?: boolean;
58
63
  verbose?: boolean;
59
- schemaVersion?: string;
60
64
  inflate?: number;
65
+ target?: string | string[];
61
66
  }
62
67
 
63
- export interface Log {
64
- level: LogLevel;
65
- message: LogMessage;
66
- details?: LogDetails;
67
- }
68
-
69
- export async function evaluateFeature(deps: Dependencies, options: EvaluateOptions) {
70
- const { datasource, projectConfig } = deps;
71
-
72
- const existingState = await datasource.readState(options.environment || false);
73
- const datafileContent = await buildDatafile(
74
- projectConfig,
75
- datasource,
76
- {
77
- schemaVersion: options.schemaVersion || SCHEMA_VERSION,
78
- revision: "include-all-features",
79
- environment: options.environment || false,
80
- inflate: options.inflate,
81
- },
82
- existingState,
83
- );
84
-
85
- let logs: Log[] = [];
86
- const f = createInstance({
68
+ async function evaluateFeatureWithDatafile(
69
+ datafileContent: DatafileContent,
70
+ options: EvaluateOptions,
71
+ target?: string,
72
+ ) {
73
+ let diagnostics: FeaturevisorDiagnostic[] = [];
74
+ const f = createFeaturevisor({
87
75
  datafile: datafileContent as DatafileContent,
88
- logger: createLogger({
89
- level: "debug",
90
- handler: (level, message, details) => {
91
- logs.push({
92
- level,
93
- message,
94
- details,
95
- });
96
- },
97
- }),
76
+ logLevel: "debug",
77
+ onDiagnostic: (diagnostic) => diagnostics.push(diagnostic),
98
78
  });
99
79
 
100
80
  const flagEvaluation = f.evaluateFlag(options.feature, options.context as Context);
101
- const flagEvaluationLogs = [...logs];
102
- logs = [];
81
+ const flagEvaluationDiagnostics = [...diagnostics];
82
+ diagnostics = [];
103
83
 
104
84
  const variationEvaluation = f.evaluateVariation(options.feature, options.context as Context);
105
- const variationEvaluationLogs = [...logs];
106
- logs = [];
85
+ const variationEvaluationDiagnostics = [...diagnostics];
86
+ diagnostics = [];
107
87
 
108
88
  const variableEvaluations: Record<string, Evaluation> = {};
109
- const variableEvaluationLogs: Record<string, Log[]> = {};
89
+ const variableEvaluationDiagnostics: Record<string, FeaturevisorDiagnostic[]> = {};
110
90
 
111
91
  const feature = f.getFeature(options.feature);
112
92
  if (feature?.variablesSchema) {
@@ -121,8 +101,8 @@ export async function evaluateFeature(deps: Dependencies, options: EvaluateOptio
121
101
  options.context as Context,
122
102
  );
123
103
 
124
- variableEvaluationLogs[variableKey] = [...logs];
125
- logs = [];
104
+ variableEvaluationDiagnostics[variableKey] = [...diagnostics];
105
+ diagnostics = [];
126
106
 
127
107
  variableEvaluations[variableKey] = variableEvaluation;
128
108
  });
@@ -135,25 +115,27 @@ export async function evaluateFeature(deps: Dependencies, options: EvaluateOptio
135
115
  };
136
116
 
137
117
  if (options.json) {
138
- console.log(
139
- options.pretty ? JSON.stringify(allEvaluations, null, 2) : JSON.stringify(allEvaluations),
140
- );
141
-
142
- return;
118
+ return allEvaluations;
143
119
  }
144
120
 
145
121
  console.log("");
146
- console.log(`Evaluating feature "${options.feature}" in environment "${options.environment}"...`);
147
- console.log(`Against context: ${JSON.stringify(options.context)}`);
122
+ console.log(CLI_FORMAT_BOLD, "Evaluating Featurevisor feature");
123
+ console.log(` ${colorize("Feature", CLI_COLOR_CYAN)}: ${options.feature}`);
124
+ console.log(` ${colorize("Environment", CLI_COLOR_CYAN)}: ${options.environment || false}`);
125
+ if (target) console.log(` ${colorize("Target", CLI_COLOR_CYAN)}: ${target}`);
126
+ console.log(` ${colorize("Context", CLI_COLOR_CYAN)}: ${JSON.stringify(options.context)}`);
148
127
 
149
128
  // flag
150
129
  printHeader("Is enabled?");
151
130
 
152
131
  if (options.verbose) {
153
- printLogs(flagEvaluationLogs);
132
+ printDiagnostics(flagEvaluationDiagnostics);
154
133
  }
155
134
 
156
- console.log("Value:", flagEvaluation.enabled);
135
+ console.log(
136
+ flagEvaluation.enabled ? CLI_FORMAT_GREEN : CLI_FORMAT_YELLOW,
137
+ `Value: ${flagEvaluation.enabled}`,
138
+ );
157
139
  console.log("\nDetails:\n");
158
140
 
159
141
  printEvaluationDetails(flagEvaluation);
@@ -163,15 +145,15 @@ export async function evaluateFeature(deps: Dependencies, options: EvaluateOptio
163
145
 
164
146
  if (feature?.variations) {
165
147
  if (options.verbose) {
166
- printLogs(variationEvaluationLogs);
148
+ printDiagnostics(variationEvaluationDiagnostics);
167
149
  }
168
150
 
169
- console.log("Value:", JSON.stringify(variationEvaluation.variation?.value));
151
+ console.log(CLI_FORMAT_GREEN, `Value: ${JSON.stringify(variationEvaluation.variation?.value)}`);
170
152
  console.log("\nDetails:\n");
171
153
 
172
154
  printEvaluationDetails(variationEvaluation);
173
155
  } else {
174
- console.log("No variations defined.");
156
+ console.log(CLI_FORMAT_YELLOW, "No variations defined.");
175
157
  }
176
158
 
177
159
  // variables
@@ -180,15 +162,14 @@ export async function evaluateFeature(deps: Dependencies, options: EvaluateOptio
180
162
  printHeader(`Variable: ${key}`);
181
163
 
182
164
  if (options.verbose) {
183
- printLogs(variableEvaluationLogs[key]);
165
+ printDiagnostics(variableEvaluationDiagnostics[key]);
184
166
  }
185
167
 
186
- console.log(
187
- "Value:",
168
+ const variableValue =
188
169
  typeof value.variableValue !== "undefined"
189
170
  ? JSON.stringify(value.variableValue)
190
- : value.variableValue,
191
- );
171
+ : value.variableValue;
172
+ console.log(CLI_FORMAT_GREEN, `Value: ${variableValue}`);
192
173
  console.log("\nDetails:\n");
193
174
 
194
175
  printEvaluationDetails(value);
@@ -196,30 +177,61 @@ export async function evaluateFeature(deps: Dependencies, options: EvaluateOptio
196
177
  } else {
197
178
  printHeader("Variables");
198
179
 
199
- console.log("No variables defined.");
180
+ console.log(CLI_FORMAT_YELLOW, "No variables defined.");
181
+ }
182
+
183
+ return allEvaluations;
184
+ }
185
+
186
+ export async function evaluateFeature(deps: Dependencies, options: EvaluateOptions) {
187
+ const datafiles = await buildRuntimeDatafiles(deps, {
188
+ environment: options.environment || false,
189
+ target: options.target,
190
+ revision: "include-all-features",
191
+ inflate: options.inflate,
192
+ });
193
+
194
+ const results = [];
195
+ for (const entry of datafiles) {
196
+ const evaluations = await evaluateFeatureWithDatafile(entry.datafile, options, entry.target);
197
+ results.push({ target: entry.target, evaluations });
198
+ }
199
+
200
+ if (options.json) {
201
+ const output = results.length === 1 ? results[0].evaluations : results;
202
+ console.log(options.pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output));
200
203
  }
201
204
  }
202
205
 
203
206
  export const evaluatePlugin: Plugin = {
204
207
  command: "evaluate",
205
208
  handler: async ({ rootDirectoryPath, projectConfig, datasource, parsed }) => {
206
- await evaluateFeature(
207
- {
208
- rootDirectoryPath,
209
- projectConfig,
210
- datasource,
211
- options: parsed,
212
- },
213
- {
214
- environment: parsed.environment,
215
- feature: parsed.feature,
216
- context: parsed.context ? JSON.parse(parsed.context) : {},
217
- // @NOTE: introduce optional --at?
218
- json: parsed.json,
219
- pretty: parsed.pretty,
220
- verbose: parsed.verbose,
221
- },
222
- );
209
+ assertProjectSetJsonSelection(projectConfig, parsed.set, parsed.json);
210
+
211
+ const executions = await getProjectSetExecutions(projectConfig, datasource, parsed.set);
212
+
213
+ for (const execution of executions) {
214
+ printSetHeader(projectConfig, execution.set, parsed.json);
215
+
216
+ await evaluateFeature(
217
+ {
218
+ rootDirectoryPath,
219
+ projectConfig: execution.projectConfig,
220
+ datasource: execution.datasource,
221
+ options: parsed,
222
+ },
223
+ {
224
+ environment: parsed.environment,
225
+ feature: parsed.feature,
226
+ context: parsed.context ? JSON.parse(parsed.context) : {},
227
+ // @NOTE: introduce optional --at?
228
+ json: parsed.json,
229
+ pretty: parsed.pretty,
230
+ verbose: parsed.verbose,
231
+ target: parsed.target,
232
+ },
233
+ );
234
+ }
223
235
  },
224
236
  examples: [
225
237
  {
@@ -1,6 +1,14 @@
1
1
  import { findDuplicateSegments, DuplicateSegmentsOptions } from "./findDuplicateSegments";
2
2
  import { Dependencies } from "../dependencies";
3
3
  import { Plugin } from "../cli";
4
+ import { getProjectSetExecutions, printSetHeader } from "../sets";
5
+ import {
6
+ CLI_COLOR_CYAN,
7
+ CLI_FORMAT_BOLD,
8
+ CLI_FORMAT_GREEN,
9
+ CLI_FORMAT_YELLOW,
10
+ colorize,
11
+ } from "../tester/cliFormat";
4
12
 
5
13
  export async function findDuplicateSegmentsInProject(
6
14
  deps: Dependencies,
@@ -9,21 +17,25 @@ export async function findDuplicateSegmentsInProject(
9
17
  const duplicates = await findDuplicateSegments(deps, options);
10
18
 
11
19
  console.log("");
20
+ console.log(CLI_FORMAT_BOLD, "Finding duplicate Featurevisor segments");
12
21
 
13
22
  if (duplicates.length === 0) {
14
- console.log("No duplicate segments found");
23
+ console.log(CLI_FORMAT_GREEN, "No duplicate segments found");
15
24
  return;
16
25
  }
17
26
 
18
- console.log(`Found ${duplicates.length} duplicate(s):\n`);
27
+ console.log(CLI_FORMAT_YELLOW, `Found ${duplicates.length} duplicate(s):`);
28
+ console.log("");
19
29
 
20
30
  duplicates.forEach((entry) => {
21
31
  if (options.authors) {
22
- console.log(` - Segments: ${entry.segments.join(", ")}`);
23
- console.log(` Authors: ${entry.authors && entry.authors.join(", ")}`);
32
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} Segments: ${entry.segments.join(", ")}`);
33
+ console.log(
34
+ ` ${colorize("Authors", CLI_COLOR_CYAN)}: ${entry.authors && entry.authors.join(", ")}`,
35
+ );
24
36
  console.log("");
25
37
  } else {
26
- console.log(` - ${entry.segments.join(", ")}`);
38
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${entry.segments.join(", ")}`);
27
39
  }
28
40
  });
29
41
  }
@@ -31,17 +43,23 @@ export async function findDuplicateSegmentsInProject(
31
43
  export const findDuplicateSegmentsPlugin: Plugin = {
32
44
  command: "find-duplicate-segments",
33
45
  handler: async ({ rootDirectoryPath, projectConfig, datasource, parsed }) => {
34
- await findDuplicateSegmentsInProject(
35
- {
36
- rootDirectoryPath,
37
- projectConfig,
38
- datasource,
39
- options: parsed,
40
- },
41
- {
42
- authors: parsed.authors,
43
- },
44
- );
46
+ const executions = await getProjectSetExecutions(projectConfig, datasource, parsed.set);
47
+
48
+ for (const execution of executions) {
49
+ printSetHeader(projectConfig, execution.set);
50
+
51
+ await findDuplicateSegmentsInProject(
52
+ {
53
+ rootDirectoryPath,
54
+ projectConfig: execution.projectConfig,
55
+ datasource: execution.datasource,
56
+ options: parsed,
57
+ },
58
+ {
59
+ authors: parsed.authors,
60
+ },
61
+ );
62
+ }
45
63
  },
46
64
  examples: [
47
65
  {
@@ -6,6 +6,15 @@ import {
6
6
  extractAttributeKeysFromConditions,
7
7
  extractSegmentKeysFromGroupSegments,
8
8
  } from "../utils/extractKeys";
9
+ import { getProjectSetExecutions, printSetHeader } from "../sets";
10
+ import {
11
+ CLI_COLOR_CYAN,
12
+ CLI_COLOR_DIM,
13
+ CLI_FORMAT_BOLD,
14
+ CLI_FORMAT_GREEN,
15
+ CLI_FORMAT_YELLOW,
16
+ colorize,
17
+ } from "../tester/cliFormat";
9
18
 
10
19
  export interface UsageInFeatures {
11
20
  [featureKey: string]: {
@@ -110,7 +119,7 @@ export async function findAllUsageInFeatures(deps: Dependencies): Promise<UsageI
110
119
  }
111
120
 
112
121
  // no environments
113
- if (projectConfig.environments === false) {
122
+ if (!Array.isArray(projectConfig.environments)) {
114
123
  // force
115
124
  if (Array.isArray(feature.force)) {
116
125
  feature.force.forEach((force) => {
@@ -301,6 +310,8 @@ export interface FindUsageOptions {
301
310
  export async function findUsageInProject(deps: Dependencies, options: FindUsageOptions) {
302
311
  const { datasource } = deps;
303
312
 
313
+ console.log("");
314
+ console.log(CLI_FORMAT_BOLD, "Finding Featurevisor usage");
304
315
  console.log("");
305
316
 
306
317
  const usageInFeatures = await findAllUsageInFeatures(deps);
@@ -311,18 +322,21 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
311
322
  const usedInFeatures = await findFeatureUsage(usageInFeatures, options.feature);
312
323
 
313
324
  if (usedInFeatures.size === 0) {
314
- console.log(`Feature "${options.feature}" is not used in any features.`);
325
+ console.log(CLI_FORMAT_GREEN, `Feature "${options.feature}" is not used in any features.`);
315
326
  } else {
316
- console.log(`Feature "${options.feature}" is used in the following features:\n`);
327
+ console.log(CLI_FORMAT_BOLD, `Feature "${options.feature}" is used in these features`);
328
+ console.log("");
317
329
 
318
330
  for (const featureKey of Array.from(usedInFeatures)) {
319
331
  if (options.authors) {
320
332
  const entries = await datasource.listHistoryEntries("feature", featureKey);
321
333
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
322
334
 
323
- console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
335
+ console.log(
336
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
337
+ );
324
338
  } else {
325
- console.log(` - ${featureKey}`);
339
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey}`);
326
340
  }
327
341
  }
328
342
  }
@@ -335,18 +349,21 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
335
349
  const usedInFeatures = await findSegmentUsage(usageInFeatures, options.segment);
336
350
 
337
351
  if (usedInFeatures.size === 0) {
338
- console.log(`Segment "${options.segment}" is not used in any features.`);
352
+ console.log(CLI_FORMAT_GREEN, `Segment "${options.segment}" is not used in any features.`);
339
353
  } else {
340
- console.log(`Segment "${options.segment}" is used in the following features:\n`);
354
+ console.log(CLI_FORMAT_BOLD, `Segment "${options.segment}" is used in these features`);
355
+ console.log("");
341
356
 
342
357
  for (const featureKey of Array.from(usedInFeatures)) {
343
358
  if (options.authors) {
344
359
  const entries = await datasource.listHistoryEntries("feature", featureKey);
345
360
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
346
361
 
347
- console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
362
+ console.log(
363
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
364
+ );
348
365
  } else {
349
- console.log(` - ${featureKey}`);
366
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey}`);
350
367
  }
351
368
  }
352
369
  }
@@ -359,22 +376,28 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
359
376
  const usedIn = await findAttributeUsage(usageInFeatures, usageInSegments, options.attribute);
360
377
 
361
378
  if (usedIn.features.size === 0 && usedIn.segments.size === 0) {
362
- console.log(`Attribute "${options.attribute}" is not used in any features or segments.`);
379
+ console.log(
380
+ CLI_FORMAT_GREEN,
381
+ `Attribute "${options.attribute}" is not used in any features or segments.`,
382
+ );
363
383
 
364
384
  return;
365
385
  }
366
386
 
367
387
  if (usedIn.segments.size > 0) {
368
- console.log(`Attribute "${options.attribute}" is used in the following segments:\n`);
388
+ console.log(CLI_FORMAT_BOLD, `Attribute "${options.attribute}" is used in these segments`);
389
+ console.log("");
369
390
 
370
391
  for (const segmentKey of Array.from(usedIn.segments)) {
371
392
  if (options.authors) {
372
393
  const entries = await datasource.listHistoryEntries("segment", segmentKey);
373
394
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
374
395
 
375
- console.log(` - ${segmentKey} (Authors: ${authors.join(", ")})`);
396
+ console.log(
397
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${segmentKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
398
+ );
376
399
  } else {
377
- console.log(` - ${segmentKey}`);
400
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${segmentKey}`);
378
401
  }
379
402
  }
380
403
 
@@ -387,16 +410,20 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
387
410
  }
388
411
 
389
412
  if (affectedFeatures.size > 0) {
390
- console.log(`\nSegments above are used in the following features:\n`);
413
+ console.log("");
414
+ console.log(CLI_FORMAT_BOLD, "Segments above are used in these features");
415
+ console.log("");
391
416
 
392
417
  for (const featureKey of Array.from(affectedFeatures)) {
393
418
  if (options.authors) {
394
419
  const entries = await datasource.listHistoryEntries("feature", featureKey);
395
420
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
396
421
 
397
- console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
422
+ console.log(
423
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
424
+ );
398
425
  } else {
399
- console.log(` - ${featureKey}`);
426
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey}`);
400
427
  }
401
428
  }
402
429
 
@@ -405,16 +432,22 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
405
432
  }
406
433
 
407
434
  if (usedIn.features.size > 0) {
408
- console.log(`Attribute "${options.attribute}" is used directly in the following features:\n`);
435
+ console.log(
436
+ CLI_FORMAT_BOLD,
437
+ `Attribute "${options.attribute}" is used directly in these features`,
438
+ );
439
+ console.log("");
409
440
 
410
441
  for (const featureKey of Array.from(usedIn.features)) {
411
442
  if (options.authors) {
412
443
  const entries = await datasource.listHistoryEntries("feature", featureKey);
413
444
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
414
445
 
415
- console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
446
+ console.log(
447
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
448
+ );
416
449
  } else {
417
- console.log(` - ${featureKey}`);
450
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${featureKey}`);
418
451
  }
419
452
  }
420
453
 
@@ -429,18 +462,21 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
429
462
  const unusedSegments = await findUnusedSegments(deps, usageInFeatures);
430
463
 
431
464
  if (unusedSegments.size === 0) {
432
- console.log("No unused segments found.");
465
+ console.log(CLI_FORMAT_GREEN, "No unused segments found.");
433
466
  } else {
434
- console.log("Unused segments:\n");
467
+ console.log(CLI_FORMAT_YELLOW, "Unused segments");
468
+ console.log("");
435
469
 
436
470
  for (const segmentKey of Array.from(unusedSegments)) {
437
471
  if (options.authors) {
438
472
  const entries = await datasource.listHistoryEntries("segment", segmentKey);
439
473
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
440
474
 
441
- console.log(` - ${segmentKey} (Authors: ${authors.join(", ")})`);
475
+ console.log(
476
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${segmentKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
477
+ );
442
478
  } else {
443
- console.log(` - ${segmentKey}`);
479
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${segmentKey}`);
444
480
  }
445
481
  }
446
482
  }
@@ -453,18 +489,21 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
453
489
  const unusedAttributes = await findUnusedAttributes(deps, usageInFeatures, usageInSegments);
454
490
 
455
491
  if (unusedAttributes.size === 0) {
456
- console.log("No unused attributes found.");
492
+ console.log(CLI_FORMAT_GREEN, "No unused attributes found.");
457
493
  } else {
458
- console.log("Unused attributes:\n");
494
+ console.log(CLI_FORMAT_YELLOW, "Unused attributes");
495
+ console.log("");
459
496
 
460
497
  for (const attributeKey of Array.from(unusedAttributes)) {
461
498
  if (options.authors) {
462
499
  const entries = await datasource.listHistoryEntries("attribute", attributeKey);
463
500
  const authors = Array.from(new Set(entries.map((entry) => entry.author)));
464
501
 
465
- console.log(` - ${attributeKey} (Authors: ${authors.join(", ")})`);
502
+ console.log(
503
+ ` ${colorize("•", CLI_COLOR_CYAN)} ${attributeKey} ${colorize(`(Authors: ${authors.join(", ")})`, CLI_COLOR_DIM)}`,
504
+ );
466
505
  } else {
467
- console.log(` - ${attributeKey}`);
506
+ console.log(` ${colorize("•", CLI_COLOR_CYAN)} ${attributeKey}`);
468
507
  }
469
508
  }
470
509
  }
@@ -472,28 +511,34 @@ export async function findUsageInProject(deps: Dependencies, options: FindUsageO
472
511
  return;
473
512
  }
474
513
 
475
- console.log("Please specify a segment or attribute.");
514
+ console.log(CLI_FORMAT_YELLOW, "Please specify a feature, segment, attribute, or unused query.");
476
515
  }
477
516
 
478
517
  export const findUsagePlugin: Plugin = {
479
518
  command: "find-usage",
480
519
  handler: async ({ rootDirectoryPath, projectConfig, datasource, parsed }) => {
481
- await findUsageInProject(
482
- {
483
- rootDirectoryPath,
484
- projectConfig,
485
- datasource,
486
- options: parsed,
487
- },
488
- {
489
- feature: parsed.feature,
490
- segment: parsed.segment,
491
- attribute: parsed.attribute,
492
- unusedSegments: parsed.unusedSegments,
493
- unusedAttributes: parsed.unusedAttributes,
494
- authors: parsed.authors,
495
- },
496
- );
520
+ const executions = await getProjectSetExecutions(projectConfig, datasource, parsed.set);
521
+
522
+ for (const execution of executions) {
523
+ printSetHeader(projectConfig, execution.set);
524
+
525
+ await findUsageInProject(
526
+ {
527
+ rootDirectoryPath,
528
+ projectConfig: execution.projectConfig,
529
+ datasource: execution.datasource,
530
+ options: parsed,
531
+ },
532
+ {
533
+ feature: parsed.feature,
534
+ segment: parsed.segment,
535
+ attribute: parsed.attribute,
536
+ unusedSegments: parsed.unusedSegments,
537
+ unusedAttributes: parsed.unusedAttributes,
538
+ authors: parsed.authors,
539
+ },
540
+ );
541
+ }
497
542
  },
498
543
  examples: [
499
544
  {