repopo 0.12.0 → 0.13.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 (333) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +50 -90
  3. package/THIRD-PARTY-LICENSES.txt +169 -11
  4. package/bin/dev.js +0 -0
  5. package/esm/adapters/fluidFramework.d.ts +13 -9
  6. package/esm/adapters/fluidFramework.d.ts.map +1 -1
  7. package/esm/adapters/fluidFramework.js +20 -43
  8. package/esm/adapters/fluidFramework.js.map +1 -1
  9. package/esm/api.d.ts +64 -1
  10. package/esm/api.d.ts.map +1 -1
  11. package/esm/api.js +17 -1
  12. package/esm/api.js.map +1 -1
  13. package/esm/baseCommand.d.ts.map +1 -1
  14. package/esm/baseCommand.js +2 -2
  15. package/esm/baseCommand.js.map +1 -1
  16. package/esm/commands/check-native.d.ts +3 -3
  17. package/esm/commands/check-native.d.ts.map +1 -1
  18. package/esm/commands/check-native.js +26 -7
  19. package/esm/commands/check-native.js.map +1 -1
  20. package/esm/commands/check.d.ts +6 -21
  21. package/esm/commands/check.d.ts.map +1 -1
  22. package/esm/commands/check.js +73 -153
  23. package/esm/commands/check.js.map +1 -1
  24. package/esm/commands/list.d.ts.map +1 -1
  25. package/esm/commands/list.js +2 -1
  26. package/esm/commands/list.js.map +1 -1
  27. package/esm/concurrency.d.ts +3 -0
  28. package/esm/concurrency.d.ts.map +1 -0
  29. package/esm/concurrency.js +8 -0
  30. package/esm/concurrency.js.map +1 -0
  31. package/esm/config.d.ts +5 -39
  32. package/esm/config.d.ts.map +1 -1
  33. package/esm/config.js +3 -7
  34. package/esm/config.js.map +1 -1
  35. package/esm/context.d.ts +8 -1
  36. package/esm/context.d.ts.map +1 -1
  37. package/esm/context.js +8 -1
  38. package/esm/context.js.map +1 -1
  39. package/esm/executionContractError.d.ts +4 -0
  40. package/esm/executionContractError.d.ts.map +1 -0
  41. package/esm/executionContractError.js +4 -0
  42. package/esm/executionContractError.js.map +1 -0
  43. package/esm/fileCache.d.ts +12 -0
  44. package/esm/fileCache.d.ts.map +1 -0
  45. package/esm/fileCache.js +37 -0
  46. package/esm/fileCache.js.map +1 -0
  47. package/esm/filePaths.d.ts +2 -0
  48. package/esm/filePaths.d.ts.map +1 -0
  49. package/esm/filePaths.js +9 -0
  50. package/esm/filePaths.js.map +1 -0
  51. package/esm/generators.d.ts +0 -20
  52. package/esm/generators.d.ts.map +1 -1
  53. package/esm/generators.js.map +1 -1
  54. package/esm/index.d.ts +3 -16
  55. package/esm/index.d.ts.map +1 -1
  56. package/esm/index.js +3 -17
  57. package/esm/index.js.map +1 -1
  58. package/esm/makePolicy.d.ts +20 -100
  59. package/esm/makePolicy.d.ts.map +1 -1
  60. package/esm/makePolicy.js +44 -132
  61. package/esm/makePolicy.js.map +1 -1
  62. package/esm/perf.d.ts +5 -2
  63. package/esm/perf.d.ts.map +1 -1
  64. package/esm/perf.js +10 -9
  65. package/esm/perf.js.map +1 -1
  66. package/esm/policies/CargoLicenceValidated.d.ts +4 -4
  67. package/esm/policies/CargoLicenceValidated.d.ts.map +1 -1
  68. package/esm/policies/CargoLicenceValidated.js +9 -7
  69. package/esm/policies/CargoLicenceValidated.js.map +1 -1
  70. package/esm/policies/CargoLintsConfigured.d.ts +4 -4
  71. package/esm/policies/CargoLintsConfigured.d.ts.map +1 -1
  72. package/esm/policies/CargoLintsConfigured.js +19 -15
  73. package/esm/policies/CargoLintsConfigured.js.map +1 -1
  74. package/esm/policies/CargoLockPolicy.d.ts +4 -4
  75. package/esm/policies/CargoLockPolicy.d.ts.map +1 -1
  76. package/esm/policies/CargoLockPolicy.js +15 -11
  77. package/esm/policies/CargoLockPolicy.js.map +1 -1
  78. package/esm/policies/CargoTomlRequired.d.ts +5 -5
  79. package/esm/policies/CargoTomlRequired.d.ts.map +1 -1
  80. package/esm/policies/CargoTomlRequired.js +7 -7
  81. package/esm/policies/CargoTomlRequired.js.map +1 -1
  82. package/esm/policies/CargoTomlSorted.d.ts +4 -4
  83. package/esm/policies/CargoTomlSorted.d.ts.map +1 -1
  84. package/esm/policies/CargoTomlSorted.js +21 -17
  85. package/esm/policies/CargoTomlSorted.js.map +1 -1
  86. package/esm/policies/ConditionalScripts.d.ts +10 -8
  87. package/esm/policies/ConditionalScripts.d.ts.map +1 -1
  88. package/esm/policies/ConditionalScripts.js +24 -22
  89. package/esm/policies/ConditionalScripts.js.map +1 -1
  90. package/esm/policies/ExactScripts.d.ts +8 -6
  91. package/esm/policies/ExactScripts.d.ts.map +1 -1
  92. package/esm/policies/ExactScripts.js +15 -18
  93. package/esm/policies/ExactScripts.js.map +1 -1
  94. package/esm/policies/GleamDepVersions.d.ts +5 -5
  95. package/esm/policies/GleamDepVersions.d.ts.map +1 -1
  96. package/esm/policies/GleamDepVersions.js +5 -5
  97. package/esm/policies/GleamDepVersions.js.map +1 -1
  98. package/esm/policies/GleamDocExists.d.ts +4 -4
  99. package/esm/policies/GleamDocExists.d.ts.map +1 -1
  100. package/esm/policies/GleamDocExists.js +6 -6
  101. package/esm/policies/GleamDocExists.js.map +1 -1
  102. package/esm/policies/GleamInternalModulesConfigured.d.ts +4 -4
  103. package/esm/policies/GleamInternalModulesConfigured.d.ts.map +1 -1
  104. package/esm/policies/GleamInternalModulesConfigured.js +8 -6
  105. package/esm/policies/GleamInternalModulesConfigured.js.map +1 -1
  106. package/esm/policies/GleamLicenceConfigured.d.ts +4 -4
  107. package/esm/policies/GleamLicenceConfigured.d.ts.map +1 -1
  108. package/esm/policies/GleamLicenceConfigured.js +8 -6
  109. package/esm/policies/GleamLicenceConfigured.js.map +1 -1
  110. package/esm/policies/GleamManifestCommitted.d.ts +10 -3
  111. package/esm/policies/GleamManifestCommitted.d.ts.map +1 -1
  112. package/esm/policies/GleamManifestCommitted.js +10 -9
  113. package/esm/policies/GleamManifestCommitted.js.map +1 -1
  114. package/esm/policies/GleamMonorepoConsistency.d.ts +13 -5
  115. package/esm/policies/GleamMonorepoConsistency.d.ts.map +1 -1
  116. package/esm/policies/GleamMonorepoConsistency.js +10 -10
  117. package/esm/policies/GleamMonorepoConsistency.js.map +1 -1
  118. package/esm/policies/GleamNameRestrictions.d.ts +4 -4
  119. package/esm/policies/GleamNameRestrictions.d.ts.map +1 -1
  120. package/esm/policies/GleamNameRestrictions.js +6 -6
  121. package/esm/policies/GleamNameRestrictions.js.map +1 -1
  122. package/esm/policies/GleamNoPathDepsInPublished.d.ts +4 -4
  123. package/esm/policies/GleamNoPathDepsInPublished.d.ts.map +1 -1
  124. package/esm/policies/GleamNoPathDepsInPublished.js +6 -6
  125. package/esm/policies/GleamNoPathDepsInPublished.js.map +1 -1
  126. package/esm/policies/GleamPathDepsValid.d.ts +3 -3
  127. package/esm/policies/GleamPathDepsValid.d.ts.map +1 -1
  128. package/esm/policies/GleamPathDepsValid.js +5 -5
  129. package/esm/policies/GleamPathDepsValid.js.map +1 -1
  130. package/esm/policies/GleamProjectStructure.d.ts +11 -4
  131. package/esm/policies/GleamProjectStructure.d.ts.map +1 -1
  132. package/esm/policies/GleamProjectStructure.js +7 -8
  133. package/esm/policies/GleamProjectStructure.js.map +1 -1
  134. package/esm/policies/GleamSharedDependencyVersions.d.ts +12 -4
  135. package/esm/policies/GleamSharedDependencyVersions.d.ts.map +1 -1
  136. package/esm/policies/GleamSharedDependencyVersions.js +10 -10
  137. package/esm/policies/GleamSharedDependencyVersions.js.map +1 -1
  138. package/esm/policies/GleamTomlRequired.d.ts +4 -4
  139. package/esm/policies/GleamTomlRequired.d.ts.map +1 -1
  140. package/esm/policies/GleamTomlRequired.js +5 -5
  141. package/esm/policies/GleamTomlRequired.js.map +1 -1
  142. package/esm/policies/GleamTomlSorted.d.ts +4 -4
  143. package/esm/policies/GleamTomlSorted.d.ts.map +1 -1
  144. package/esm/policies/GleamTomlSorted.js +21 -17
  145. package/esm/policies/GleamTomlSorted.js.map +1 -1
  146. package/esm/policies/GleamVersionConstraint.d.ts +4 -4
  147. package/esm/policies/GleamVersionConstraint.d.ts.map +1 -1
  148. package/esm/policies/GleamVersionConstraint.js +14 -10
  149. package/esm/policies/GleamVersionConstraint.js.map +1 -1
  150. package/esm/policies/HtmlFileHeaders.d.ts +4 -2
  151. package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
  152. package/esm/policies/HtmlFileHeaders.js +1 -1
  153. package/esm/policies/HtmlFileHeaders.js.map +1 -1
  154. package/esm/policies/JsTsFileHeaders.d.ts +4 -2
  155. package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
  156. package/esm/policies/JsTsFileHeaders.js +1 -1
  157. package/esm/policies/JsTsFileHeaders.js.map +1 -1
  158. package/esm/policies/LicenseFileExists.d.ts +10 -4
  159. package/esm/policies/LicenseFileExists.d.ts.map +1 -1
  160. package/esm/policies/LicenseFileExists.js +27 -20
  161. package/esm/policies/LicenseFileExists.js.map +1 -1
  162. package/esm/policies/MutuallyExclusiveScripts.d.ts +8 -6
  163. package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -1
  164. package/esm/policies/MutuallyExclusiveScripts.js +9 -13
  165. package/esm/policies/MutuallyExclusiveScripts.js.map +1 -1
  166. package/esm/policies/NoBuildDirectory.d.ts +9 -3
  167. package/esm/policies/NoBuildDirectory.d.ts.map +1 -1
  168. package/esm/policies/NoBuildDirectory.js +8 -13
  169. package/esm/policies/NoBuildDirectory.js.map +1 -1
  170. package/esm/policies/NoJsFileExtensions.d.ts +9 -3
  171. package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
  172. package/esm/policies/NoJsFileExtensions.js +9 -14
  173. package/esm/policies/NoJsFileExtensions.js.map +1 -1
  174. package/esm/policies/NoLargeBinaryFiles.d.ts +9 -4
  175. package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
  176. package/esm/policies/NoLargeBinaryFiles.js +10 -16
  177. package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
  178. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +10 -6
  179. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  180. package/esm/policies/NoPrivateWorkspaceDependencies.js +12 -14
  181. package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
  182. package/esm/policies/NoTargetArtifacts.d.ts +9 -3
  183. package/esm/policies/NoTargetArtifacts.d.ts.map +1 -1
  184. package/esm/policies/NoTargetArtifacts.js +9 -14
  185. package/esm/policies/NoTargetArtifacts.js.map +1 -1
  186. package/esm/policies/NoUnsafeWithoutJustification.d.ts +11 -4
  187. package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -1
  188. package/esm/policies/NoUnsafeWithoutJustification.js +8 -9
  189. package/esm/policies/NoUnsafeWithoutJustification.js.map +1 -1
  190. package/esm/policies/NoWildcardDependencies.d.ts +5 -5
  191. package/esm/policies/NoWildcardDependencies.d.ts.map +1 -1
  192. package/esm/policies/NoWildcardDependencies.js +6 -6
  193. package/esm/policies/NoWildcardDependencies.js.map +1 -1
  194. package/esm/policies/PackageAllowedScopes.d.ts +9 -5
  195. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  196. package/esm/policies/PackageAllowedScopes.js +15 -16
  197. package/esm/policies/PackageAllowedScopes.js.map +1 -1
  198. package/esm/policies/PackageEsmType.d.ts +7 -5
  199. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  200. package/esm/policies/PackageEsmType.js +31 -31
  201. package/esm/policies/PackageEsmType.js.map +1 -1
  202. package/esm/policies/PackageFolderName.d.ts +8 -6
  203. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  204. package/esm/policies/PackageFolderName.js +13 -16
  205. package/esm/policies/PackageFolderName.js.map +1 -1
  206. package/esm/policies/PackageJsonProperties.d.ts +5 -3
  207. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  208. package/esm/policies/PackageJsonProperties.js +6 -17
  209. package/esm/policies/PackageJsonProperties.js.map +1 -1
  210. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +2 -7
  211. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  212. package/esm/policies/PackageJsonRepoDirectoryProperty.js +28 -42
  213. package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
  214. package/esm/policies/PackageJsonSorted.d.ts +2 -2
  215. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  216. package/esm/policies/PackageJsonSorted.js +15 -30
  217. package/esm/policies/PackageJsonSorted.js.map +1 -1
  218. package/esm/policies/PackageLicense.d.ts +4 -4
  219. package/esm/policies/PackageLicense.d.ts.map +1 -1
  220. package/esm/policies/PackageLicense.js +31 -52
  221. package/esm/policies/PackageLicense.js.map +1 -1
  222. package/esm/policies/PackagePrivateField.d.ts +12 -8
  223. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  224. package/esm/policies/PackagePrivateField.js +31 -23
  225. package/esm/policies/PackagePrivateField.js.map +1 -1
  226. package/esm/policies/PackageReadme.d.ts +6 -5
  227. package/esm/policies/PackageReadme.d.ts.map +1 -1
  228. package/esm/policies/PackageReadme.js +22 -59
  229. package/esm/policies/PackageReadme.js.map +1 -1
  230. package/esm/policies/PackageScripts.d.ts +26 -22
  231. package/esm/policies/PackageScripts.d.ts.map +1 -1
  232. package/esm/policies/PackageScripts.js +39 -36
  233. package/esm/policies/PackageScripts.js.map +1 -1
  234. package/esm/policies/PackageTestScripts.d.ts +10 -6
  235. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  236. package/esm/policies/PackageTestScripts.js +14 -16
  237. package/esm/policies/PackageTestScripts.js.map +1 -1
  238. package/esm/policies/PublicApiDocumented.d.ts +4 -4
  239. package/esm/policies/PublicApiDocumented.d.ts.map +1 -1
  240. package/esm/policies/PublicApiDocumented.js +10 -8
  241. package/esm/policies/PublicApiDocumented.js.map +1 -1
  242. package/esm/policies/RequiredGitignorePatterns.d.ts +11 -4
  243. package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
  244. package/esm/policies/RequiredGitignorePatterns.js +29 -36
  245. package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
  246. package/esm/policies/RequiredScripts.d.ts +9 -7
  247. package/esm/policies/RequiredScripts.d.ts.map +1 -1
  248. package/esm/policies/RequiredScripts.js +24 -24
  249. package/esm/policies/RequiredScripts.js.map +1 -1
  250. package/esm/policies/RustDocExists.d.ts +4 -4
  251. package/esm/policies/RustDocExists.d.ts.map +1 -1
  252. package/esm/policies/RustDocExists.js +6 -6
  253. package/esm/policies/RustDocExists.js.map +1 -1
  254. package/esm/policies/RustToolchainExists.d.ts +11 -4
  255. package/esm/policies/RustToolchainExists.d.ts.map +1 -1
  256. package/esm/policies/RustToolchainExists.js +10 -9
  257. package/esm/policies/RustToolchainExists.js.map +1 -1
  258. package/esm/policies/RustfmtConfigExists.d.ts +11 -4
  259. package/esm/policies/RustfmtConfigExists.d.ts.map +1 -1
  260. package/esm/policies/RustfmtConfigExists.js +10 -9
  261. package/esm/policies/RustfmtConfigExists.js.map +1 -1
  262. package/esm/policies/ScriptContains.d.ts +9 -7
  263. package/esm/policies/ScriptContains.d.ts.map +1 -1
  264. package/esm/policies/ScriptContains.js +9 -13
  265. package/esm/policies/ScriptContains.js.map +1 -1
  266. package/esm/policies/SharedDependencyVersions.d.ts +9 -4
  267. package/esm/policies/SharedDependencyVersions.d.ts.map +1 -1
  268. package/esm/policies/SharedDependencyVersions.js +28 -20
  269. package/esm/policies/SharedDependencyVersions.js.map +1 -1
  270. package/esm/policies/WorkspaceInheritance.d.ts +11 -4
  271. package/esm/policies/WorkspaceInheritance.d.ts.map +1 -1
  272. package/esm/policies/WorkspaceInheritance.js +10 -11
  273. package/esm/policies/WorkspaceInheritance.js.map +1 -1
  274. package/esm/policies/WorkspaceMembersValid.d.ts +11 -4
  275. package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -1
  276. package/esm/policies/WorkspaceMembersValid.js +10 -11
  277. package/esm/policies/WorkspaceMembersValid.js.map +1 -1
  278. package/esm/policies/constants.d.ts.map +1 -1
  279. package/esm/policies/constants.js +1 -1
  280. package/esm/policies/constants.js.map +1 -1
  281. package/esm/policies.d.ts +13 -5
  282. package/esm/policies.d.ts.map +1 -1
  283. package/esm/policies.js +12 -5
  284. package/esm/policies.js.map +1 -1
  285. package/esm/policy.d.ts +61 -289
  286. package/esm/policy.d.ts.map +1 -1
  287. package/esm/policy.js +1 -122
  288. package/esm/policy.js.map +1 -1
  289. package/esm/policyDefiners/defineCargoPolicy.d.ts +25 -9
  290. package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -1
  291. package/esm/policyDefiners/defineCargoPolicy.js +10 -28
  292. package/esm/policyDefiners/defineCargoPolicy.js.map +1 -1
  293. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +27 -14
  294. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  295. package/esm/policyDefiners/defineFileHeaderPolicy.js +16 -35
  296. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  297. package/esm/policyDefiners/defineGleamPolicy.d.ts +25 -9
  298. package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -1
  299. package/esm/policyDefiners/defineGleamPolicy.js +10 -27
  300. package/esm/policyDefiners/defineGleamPolicy.js.map +1 -1
  301. package/esm/policyDefiners/definePackagePolicy.d.ts +24 -13
  302. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  303. package/esm/policyDefiners/definePackagePolicy.js +9 -32
  304. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  305. package/esm/policyDefiners/spdxValidator.d.ts +4 -12
  306. package/esm/policyDefiners/spdxValidator.d.ts.map +1 -1
  307. package/esm/policyDefiners/spdxValidator.js +26 -14
  308. package/esm/policyDefiners/spdxValidator.js.map +1 -1
  309. package/esm/policyExecution.d.ts +19 -0
  310. package/esm/policyExecution.d.ts.map +1 -0
  311. package/esm/policyExecution.js +224 -0
  312. package/esm/policyExecution.js.map +1 -0
  313. package/esm/repositoryFiles.d.ts +4 -0
  314. package/esm/repositoryFiles.d.ts.map +1 -0
  315. package/esm/repositoryFiles.js +8 -0
  316. package/esm/repositoryFiles.js.map +1 -0
  317. package/esm/runner.d.ts +72 -47
  318. package/esm/runner.d.ts.map +1 -1
  319. package/esm/runner.js +153 -138
  320. package/esm/runner.js.map +1 -1
  321. package/esm/settlePolicyPromise.d.ts +4 -0
  322. package/esm/settlePolicyPromise.d.ts.map +1 -0
  323. package/esm/settlePolicyPromise.js +10 -0
  324. package/esm/settlePolicyPromise.js.map +1 -0
  325. package/esm/tsdoc-metadata.json +1 -1
  326. package/esm/utils/safePaths.d.ts +9 -0
  327. package/esm/utils/safePaths.d.ts.map +1 -0
  328. package/esm/utils/safePaths.js +40 -0
  329. package/esm/utils/safePaths.js.map +1 -0
  330. package/oclif.manifest.json +19 -2
  331. package/package.json +42 -27
  332. package/scripts/benchmark.mjs +341 -0
  333. package/sidecar/sidecar.mjs +348 -417
@@ -1,4 +1,3 @@
1
- import { makePolicyDefinition } from "../makePolicy.js";
2
1
  /**
3
2
  * Build artifact extensions that should not be committed to source control.
4
3
  */
@@ -16,27 +15,23 @@ const ARTIFACT_REGEX = new RegExp(`(${ARTIFACT_EXTENSIONS.map((ext) => ext.repla
16
15
  /**
17
16
  * A policy that prevents accidental commits of Rust build artifacts.
18
17
  *
19
- * @alpha
18
+ * @public
20
19
  */
21
- export const NoTargetArtifacts = makePolicyDefinition({
20
+ export const NoTargetArtifacts = {
22
21
  name: "NoTargetArtifacts",
23
22
  description: "Prevents accidental commits of Rust build artifacts (.rlib, .rmeta, .so, .dylib, etc.).",
24
23
  match: ARTIFACT_REGEX,
25
- // biome-ignore lint/correctness/useYield: no yield needed
26
24
  handler: function* ({ file }) {
27
25
  // Allow files inside test/fixture directories
28
26
  if (file.includes("test/") || file.includes("fixture")) {
29
- return true;
27
+ return [];
30
28
  }
31
- return {
32
- name: NoTargetArtifacts.name,
33
- file,
34
- autoFixable: false,
35
- errorMessages: [
36
- `Build artifact detected: ${file}. Rust build artifacts should not be committed to source control.`,
37
- ],
29
+ return [
30
+ `Build artifact detected: ${file}. Rust build artifacts should not be committed to source control.`,
31
+ ].map((message) => ({
32
+ message,
38
33
  manualFix: "Remove the file from source control and ensure /target/ is in .gitignore.",
39
- };
34
+ }));
40
35
  },
41
- });
36
+ };
42
37
  //# sourceMappingURL=NoTargetArtifacts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoTargetArtifacts.js","sourceRoot":"","sources":["../../src/policies/NoTargetArtifacts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;GAEG;AACH,MAAM,mBAAmB,GAAG;IAC3B,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;CACN,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,MAAM,CAChC,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAC3E,GAAG,CACH,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqB,oBAAoB,CAAC;IACvE,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,yFAAyF;IAC1F,KAAK,EAAE,cAAc;IACrB,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE;QAC3B,8CAA8C;QAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,OAAO,IAAgC,CAAC;QACzC,CAAC;QAED,OAAO;YACN,IAAI,EAAE,iBAAiB,CAAC,IAAI;YAC5B,IAAI;YACJ,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE;gBACd,4BAA4B,IAAI,mEAAmE;aACnG;YACD,SAAS,EACR,2EAA2E;SAC5E,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { Operation } from \"effection\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition, PolicyFailure } from \"../policy.js\";\n\n/**\n * Build artifact extensions that should not be committed to source control.\n */\nconst ARTIFACT_EXTENSIONS = [\n\t\".rlib\",\n\t\".rmeta\",\n\t\".d\",\n\t\".so\",\n\t\".dylib\",\n\t\".dll\",\n\t\".exe\",\n\t\".pdb\",\n];\n\nconst ARTIFACT_REGEX = new RegExp(\n\t`(${ARTIFACT_EXTENSIONS.map((ext) => ext.replace(\".\", \"\\\\.\")).join(\"|\")})$`,\n\t\"i\",\n);\n\n/**\n * A policy that prevents accidental commits of Rust build artifacts.\n *\n * @alpha\n */\nexport const NoTargetArtifacts: PolicyDefinition = makePolicyDefinition({\n\tname: \"NoTargetArtifacts\",\n\tdescription:\n\t\t\"Prevents accidental commits of Rust build artifacts (.rlib, .rmeta, .so, .dylib, etc.).\",\n\tmatch: ARTIFACT_REGEX,\n\t// biome-ignore lint/correctness/useYield: no yield needed\n\thandler: function* ({ file }): Operation<PolicyFailure> {\n\t\t// Allow files inside test/fixture directories\n\t\tif (file.includes(\"test/\") || file.includes(\"fixture\")) {\n\t\t\treturn true as unknown as PolicyFailure;\n\t\t}\n\n\t\treturn {\n\t\t\tname: NoTargetArtifacts.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t`Build artifact detected: ${file}. Rust build artifacts should not be committed to source control.`,\n\t\t\t],\n\t\t\tmanualFix:\n\t\t\t\t\"Remove the file from source control and ensure /target/ is in .gitignore.\",\n\t\t};\n\t},\n});\n"]}
1
+ {"version":3,"file":"NoTargetArtifacts.js","sourceRoot":"","sources":["../../src/policies/NoTargetArtifacts.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,mBAAmB,GAAG;IAC3B,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;CACN,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,MAAM,CAChC,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAC3E,GAAG,CACH,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,yFAAyF;IAC1F,KAAK,EAAE,cAAc;IACrB,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE;QAC3B,8CAA8C;QAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,OAAO,EAAE,CAAC;QACX,CAAC;QACD,OAAO;YACN,4BAA4B,IAAI,mEAAmE;SACnG,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACnB,OAAO;YACP,SAAS,EACR,2EAA2E;SAC5E,CAAC,CAAC,CAAC;IACL,CAAC;CAC8B,CAAC","sourcesContent":["import type { Operation } from \"effection\";\nimport type { FilePolicyDefinition, PolicyFinding } from \"../policy.js\";\n\n/**\n * Build artifact extensions that should not be committed to source control.\n */\nconst ARTIFACT_EXTENSIONS = [\n\t\".rlib\",\n\t\".rmeta\",\n\t\".d\",\n\t\".so\",\n\t\".dylib\",\n\t\".dll\",\n\t\".exe\",\n\t\".pdb\",\n];\n\nconst ARTIFACT_REGEX = new RegExp(\n\t`(${ARTIFACT_EXTENSIONS.map((ext) => ext.replace(\".\", \"\\\\.\")).join(\"|\")})$`,\n\t\"i\",\n);\n\n/**\n * A policy that prevents accidental commits of Rust build artifacts.\n *\n * @public\n */\nexport const NoTargetArtifacts = {\n\tname: \"NoTargetArtifacts\",\n\tdescription:\n\t\t\"Prevents accidental commits of Rust build artifacts (.rlib, .rmeta, .so, .dylib, etc.).\",\n\tmatch: ARTIFACT_REGEX,\n\thandler: function* ({ file }): Operation<PolicyFinding[]> {\n\t\t// Allow files inside test/fixture directories\n\t\tif (file.includes(\"test/\") || file.includes(\"fixture\")) {\n\t\t\treturn [];\n\t\t}\n\t\treturn [\n\t\t\t`Build artifact detected: ${file}. Rust build artifacts should not be committed to source control.`,\n\t\t].map((message) => ({\n\t\t\tmessage,\n\t\t\tmanualFix:\n\t\t\t\t\"Remove the file from source control and ensure /target/ is in .gitignore.\",\n\t\t}));\n\t},\n} satisfies FilePolicyDefinition;\n"]}
@@ -1,8 +1,7 @@
1
- import type { PolicyDefinition } from "../policy.js";
2
1
  /**
3
2
  * Configuration for the NoUnsafeWithoutJustification policy.
4
3
  *
5
- * @alpha
4
+ * @public
6
5
  */
7
6
  export interface NoUnsafeWithoutJustificationConfig {
8
7
  /**
@@ -18,7 +17,15 @@ export interface NoUnsafeWithoutJustificationConfig {
18
17
  /**
19
18
  * A policy that requires SAFETY comments on unsafe blocks in Rust source files.
20
19
  *
21
- * @alpha
20
+ * @public
22
21
  */
23
- export declare const NoUnsafeWithoutJustification: PolicyDefinition<NoUnsafeWithoutJustificationConfig>;
22
+ export declare const NoUnsafeWithoutJustification: {
23
+ name: string;
24
+ description: string;
25
+ match: RegExp;
26
+ handler: ({ file, root, config }: import("../policy.js").PolicyArgs<NoUnsafeWithoutJustificationConfig>) => Promise<{
27
+ message: string;
28
+ manualFix: string;
29
+ }[]>;
30
+ };
24
31
  //# sourceMappingURL=NoUnsafeWithoutJustification.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoUnsafeWithoutJustification.d.ts","sourceRoot":"","sources":["../../src/policies/NoUnsafeWithoutJustification.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,kCAAkC;IAClD;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AA+CD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,gBAAgB,CAAC,kCAAkC,CA4C3F,CAAC"}
1
+ {"version":3,"file":"NoUnsafeWithoutJustification.d.ts","sourceRoot":"","sources":["../../src/policies/NoUnsafeWithoutJustification.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,kCAAkC;IAClD;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AA+CD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;CA0C2B,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "pathe";
3
- import { makePolicyDefinition } from "../makePolicy.js";
4
3
  const UNSAFE_PATTERN = /\bunsafe\s*\{|\bunsafe\s+fn\b|\bunsafe\s+impl\b/;
5
4
  /**
6
5
  * Check whether the lines preceding an unsafe block contain the required safety comment.
@@ -42,16 +41,16 @@ function isExcluded(file, excludePaths) {
42
41
  /**
43
42
  * A policy that requires SAFETY comments on unsafe blocks in Rust source files.
44
43
  *
45
- * @alpha
44
+ * @public
46
45
  */
47
- export const NoUnsafeWithoutJustification = makePolicyDefinition({
46
+ export const NoUnsafeWithoutJustification = {
48
47
  name: "NoUnsafeWithoutJustification",
49
48
  description: "Requires safety justification comments on unsafe blocks in Rust source files.",
50
49
  match: /\.rs$/,
51
50
  handler: async ({ file, root, config }) => {
52
51
  const requiredComment = config?.requireComment ?? "// SAFETY:";
53
52
  if (isExcluded(file, config?.excludePaths)) {
54
- return true;
53
+ return [];
55
54
  }
56
55
  const content = await readFile(resolve(root, file), "utf-8");
57
56
  const lines = content.split("\n");
@@ -69,12 +68,12 @@ export const NoUnsafeWithoutJustification = makePolicyDefinition({
69
68
  }
70
69
  }
71
70
  if (violations.length > 0) {
72
- return {
73
- error: violations.join("; "),
71
+ return violations.map((message) => ({
72
+ message,
74
73
  manualFix: `Add a "${requiredComment}" comment above each unsafe block explaining why it is safe.`,
75
- };
74
+ }));
76
75
  }
77
- return true;
76
+ return [];
78
77
  },
79
- });
78
+ };
80
79
  //# sourceMappingURL=NoUnsafeWithoutJustification.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoUnsafeWithoutJustification.js","sourceRoot":"","sources":["../../src/policies/NoUnsafeWithoutJustification.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition } from \"../policy.js\";\n\n/**\n * Configuration for the NoUnsafeWithoutJustification policy.\n *\n * @alpha\n */\nexport interface NoUnsafeWithoutJustificationConfig {\n\t/**\n\t * The comment prefix to look for before unsafe blocks.\n\t * @defaultValue \"// SAFETY:\"\n\t */\n\trequireComment?: string;\n\n\t/**\n\t * Paths to exclude from this check (e.g., FFI modules).\n\t */\n\texcludePaths?: string[];\n}\n\nconst UNSAFE_PATTERN = /\\bunsafe\\s*\\{|\\bunsafe\\s+fn\\b|\\bunsafe\\s+impl\\b/;\n\n/**\n * Check whether the lines preceding an unsafe block contain the required safety comment.\n */\nfunction hasJustificationComment(\n\tlines: string[],\n\tlineIndex: number,\n\trequiredComment: string,\n): boolean {\n\tfor (let j = lineIndex - 1; j >= Math.max(0, lineIndex - 5); j--) {\n\t\tconst prevLine = lines[j];\n\t\tif (prevLine === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst trimmedPrev = prevLine.trim();\n\t\tif (trimmedPrev === \"\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (trimmedPrev.toUpperCase().includes(requiredComment.toUpperCase())) {\n\t\t\treturn true;\n\t\t}\n\t\t// Stop if we hit a non-comment, non-attribute line\n\t\tif (!(trimmedPrev.startsWith(\"//\") || trimmedPrev.startsWith(\"#[\"))) {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if a file path should be excluded from the unsafe check.\n */\nfunction isExcluded(file: string, excludePaths: string[] | undefined): boolean {\n\tif (!excludePaths) {\n\t\treturn false;\n\t}\n\tfor (const excludePath of excludePaths) {\n\t\tif (file.includes(excludePath)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * A policy that requires SAFETY comments on unsafe blocks in Rust source files.\n *\n * @alpha\n */\nexport const NoUnsafeWithoutJustification: PolicyDefinition<NoUnsafeWithoutJustificationConfig> =\n\tmakePolicyDefinition({\n\t\tname: \"NoUnsafeWithoutJustification\",\n\t\tdescription:\n\t\t\t\"Requires safety justification comments on unsafe blocks in Rust source files.\",\n\t\tmatch: /\\.rs$/,\n\t\thandler: async ({ file, root, config }) => {\n\t\t\tconst requiredComment = config?.requireComment ?? \"// SAFETY:\";\n\n\t\t\tif (isExcluded(file, config?.excludePaths)) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst content = await readFile(resolve(root, file), \"utf-8\");\n\t\t\tconst lines = content.split(\"\\n\");\n\t\t\tconst violations: string[] = [];\n\n\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\tconst line = lines[i];\n\t\t\t\tif (line === undefined) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst trimmed = line.trim();\n\n\t\t\t\t// Look for `unsafe` keyword usage (blocks, functions, impls)\n\t\t\t\tif (\n\t\t\t\t\tUNSAFE_PATTERN.test(trimmed) &&\n\t\t\t\t\t!hasJustificationComment(lines, i, requiredComment)\n\t\t\t\t) {\n\t\t\t\t\tviolations.push(\n\t\t\t\t\t\t`Line ${i + 1}: unsafe block without ${requiredComment} comment`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (violations.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: violations.join(\"; \"),\n\t\t\t\t\tmanualFix: `Add a \"${requiredComment}\" comment above each unsafe block explaining why it is safe.`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
1
+ {"version":3,"file":"NoUnsafeWithoutJustification.js","sourceRoot":"","sources":["../../src/policies/NoUnsafeWithoutJustification.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"pathe\";\nimport type { FilePolicyDefinition } from \"../policy.js\";\n/**\n * Configuration for the NoUnsafeWithoutJustification policy.\n *\n * @public\n */\nexport interface NoUnsafeWithoutJustificationConfig {\n\t/**\n\t * The comment prefix to look for before unsafe blocks.\n\t * @defaultValue \"// SAFETY:\"\n\t */\n\trequireComment?: string;\n\n\t/**\n\t * Paths to exclude from this check (e.g., FFI modules).\n\t */\n\texcludePaths?: string[];\n}\n\nconst UNSAFE_PATTERN = /\\bunsafe\\s*\\{|\\bunsafe\\s+fn\\b|\\bunsafe\\s+impl\\b/;\n\n/**\n * Check whether the lines preceding an unsafe block contain the required safety comment.\n */\nfunction hasJustificationComment(\n\tlines: string[],\n\tlineIndex: number,\n\trequiredComment: string,\n): boolean {\n\tfor (let j = lineIndex - 1; j >= Math.max(0, lineIndex - 5); j--) {\n\t\tconst prevLine = lines[j];\n\t\tif (prevLine === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst trimmedPrev = prevLine.trim();\n\t\tif (trimmedPrev === \"\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (trimmedPrev.toUpperCase().includes(requiredComment.toUpperCase())) {\n\t\t\treturn true;\n\t\t}\n\t\t// Stop if we hit a non-comment, non-attribute line\n\t\tif (!(trimmedPrev.startsWith(\"//\") || trimmedPrev.startsWith(\"#[\"))) {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if a file path should be excluded from the unsafe check.\n */\nfunction isExcluded(file: string, excludePaths: string[] | undefined): boolean {\n\tif (!excludePaths) {\n\t\treturn false;\n\t}\n\tfor (const excludePath of excludePaths) {\n\t\tif (file.includes(excludePath)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * A policy that requires SAFETY comments on unsafe blocks in Rust source files.\n *\n * @public\n */\nexport const NoUnsafeWithoutJustification = {\n\tname: \"NoUnsafeWithoutJustification\",\n\tdescription:\n\t\t\"Requires safety justification comments on unsafe blocks in Rust source files.\",\n\tmatch: /\\.rs$/,\n\thandler: async ({ file, root, config }) => {\n\t\tconst requiredComment = config?.requireComment ?? \"// SAFETY:\";\n\n\t\tif (isExcluded(file, config?.excludePaths)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst content = await readFile(resolve(root, file), \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst violations: string[] = [];\n\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i];\n\t\t\tif (line === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst trimmed = line.trim();\n\n\t\t\t// Look for `unsafe` keyword usage (blocks, functions, impls)\n\t\t\tif (\n\t\t\t\tUNSAFE_PATTERN.test(trimmed) &&\n\t\t\t\t!hasJustificationComment(lines, i, requiredComment)\n\t\t\t) {\n\t\t\t\tviolations.push(\n\t\t\t\t\t`Line ${i + 1}: unsafe block without ${requiredComment} comment`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (violations.length > 0) {\n\t\t\treturn violations.map((message) => ({\n\t\t\t\tmessage,\n\t\t\t\tmanualFix: `Add a \"${requiredComment}\" comment above each unsafe block explaining why it is safe.`,\n\t\t\t}));\n\t\t}\n\t\treturn [];\n\t},\n} satisfies FilePolicyDefinition<NoUnsafeWithoutJustificationConfig>;\n"]}
@@ -1,8 +1,8 @@
1
- import type { PolicyShape } from "../policy.js";
1
+ import type { FilePolicyDefinition } from "../policy.js";
2
2
  /**
3
3
  * Configuration for the NoWildcardDependencies policy.
4
4
  *
5
- * @alpha
5
+ * @public
6
6
  */
7
7
  export interface NoWildcardDependenciesConfig {
8
8
  /**
@@ -12,7 +12,7 @@ export interface NoWildcardDependenciesConfig {
12
12
  deny?: string[];
13
13
  /**
14
14
  * Version patterns to warn about.
15
- * @defaultValue [">="]
15
+ * @defaultValue `[">="]`
16
16
  */
17
17
  warn?: string[];
18
18
  /**
@@ -24,7 +24,7 @@ export interface NoWildcardDependenciesConfig {
24
24
  /**
25
25
  * A policy that prevents wildcard or overly permissive version specifications in Cargo.toml.
26
26
  *
27
- * @alpha
27
+ * @public
28
28
  */
29
- export declare const NoWildcardDependencies: PolicyShape<NoWildcardDependenciesConfig>;
29
+ export declare const NoWildcardDependencies: FilePolicyDefinition<NoWildcardDependenciesConfig>;
30
30
  //# sourceMappingURL=NoWildcardDependencies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoWildcardDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoWildcardDependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAkED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,4BAA4B,CAiD1E,CAAC"}
1
+ {"version":3,"file":"NoWildcardDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoWildcardDependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAMzD;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAkED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,oDA+C4B,CAAC"}
@@ -45,7 +45,7 @@ function checkSectionDeps(deps, sectionName, isDev, allowDev, denyPatterns, warn
45
45
  /**
46
46
  * A policy that prevents wildcard or overly permissive version specifications in Cargo.toml.
47
47
  *
48
- * @alpha
48
+ * @public
49
49
  */
50
50
  export const NoWildcardDependencies = defineCargoPolicy({
51
51
  name: "NoWildcardDependencies",
@@ -53,7 +53,7 @@ export const NoWildcardDependencies = defineCargoPolicy({
53
53
  handler: async (toml, { config }) => {
54
54
  // Skip workspace root
55
55
  if (toml.workspace !== undefined && toml.package === undefined) {
56
- return true;
56
+ return [];
57
57
  }
58
58
  const denyPatterns = config?.deny ?? DEFAULT_DENY;
59
59
  const warnPatterns = config?.warn ?? DEFAULT_WARN;
@@ -72,12 +72,12 @@ export const NoWildcardDependencies = defineCargoPolicy({
72
72
  checkSectionDeps(deps, name, isDev, allowDev, denyPatterns, warnPatterns, errors);
73
73
  }
74
74
  if (errors.length > 0) {
75
- return {
76
- error: errors.join("; "),
75
+ return errors.map((message) => ({
76
+ message,
77
77
  manualFix: 'Use specific version ranges (e.g., "1.0", "^1.0", "~1.0") instead of wildcards.',
78
- };
78
+ }));
79
79
  }
80
- return true;
80
+ return [];
81
81
  },
82
82
  });
83
83
  //# sourceMappingURL=NoWildcardDependencies.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoWildcardDependencies.js","sourceRoot":"","sources":["../../src/policies/NoWildcardDependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AA2BhD,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3B,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,CAAC;AAE5B,SAAS,gBAAgB,CACxB,OAAe,EACf,YAAsB,EACtB,YAAsB;IAEtB,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACpC,IAAI,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,OAAO,MAAM,CAAC;QACf,CAAC;IACF,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACpC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACjC,OAAO,MAAM,CAAC;QACf,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,cAAc,CAAC,GAAY;IACnC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACZ,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,GAA8B,CAAC;QAC9C,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACxC,OAAO,MAAM,CAAC,OAAO,CAAC;QACvB,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CACxB,IAA6B,EAC7B,WAAmB,EACnB,KAAc,EACd,QAAiB,EACjB,YAAsB,EACtB,YAAsB,EACtB,MAAgB;IAEhB,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QAED,MAAM,aAAa,GAAG,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC5D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;QAEtE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CACV,IAAI,WAAW,KAAK,OAAO,OAAO,OAAO,iCAAiC,CAC1E,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CACV,IAAI,WAAW,KAAK,OAAO,OAAO,OAAO,2CAA2C,CACpF,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAClC,iBAAiB,CAAC;IACjB,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACV,yFAAyF;IAC1F,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,sBAAsB;QACtB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,EAAE,IAAI,IAAI,YAAY,CAAC;QAClD,MAAM,YAAY,GAAG,MAAM,EAAE,IAAI,IAAI,YAAY,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC;QAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG;YAChB,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE;YACtC,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE;YAC5C,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE;SACzC,CAAC;QAEF,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;YACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAwC,CAAC;YAC/D,IAAI,CAAC,IAAI,EAAE,CAAC;gBACX,SAAS;YACV,CAAC;YAED,gBAAgB,CACf,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,MAAM,CACN,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EACR,iFAAiF;aAClF,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PolicyShape } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\n\n/**\n * Configuration for the NoWildcardDependencies policy.\n *\n * @alpha\n */\nexport interface NoWildcardDependenciesConfig {\n\t/**\n\t * Version patterns to deny outright.\n\t * @defaultValue [\"*\"]\n\t */\n\tdeny?: string[];\n\n\t/**\n\t * Version patterns to warn about.\n\t * @defaultValue [\">=\"]\n\t */\n\twarn?: string[];\n\n\t/**\n\t * If true, dev-dependencies are checked more leniently (only deny, not warn).\n\t * @defaultValue true\n\t */\n\tallowDev?: boolean;\n}\n\nconst DEFAULT_DENY = [\"*\"];\nconst DEFAULT_WARN = [\">=\"];\n\nfunction checkVersionSpec(\n\tversion: string,\n\tdenyPatterns: string[],\n\twarnPatterns: string[],\n): \"deny\" | \"warn\" | \"ok\" {\n\tfor (const pattern of denyPatterns) {\n\t\tif (version === pattern || version.startsWith(pattern)) {\n\t\t\treturn \"deny\";\n\t\t}\n\t}\n\tfor (const pattern of warnPatterns) {\n\t\tif (version.startsWith(pattern)) {\n\t\t\treturn \"warn\";\n\t\t}\n\t}\n\treturn \"ok\";\n}\n\nfunction extractVersion(dep: unknown): string | undefined {\n\tif (typeof dep === \"string\") {\n\t\treturn dep;\n\t}\n\tif (typeof dep === \"object\" && dep !== null) {\n\t\tconst record = dep as Record<string, unknown>;\n\t\tif (typeof record.version === \"string\") {\n\t\t\treturn record.version;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction checkSectionDeps(\n\tdeps: Record<string, unknown>,\n\tsectionName: string,\n\tisDev: boolean,\n\tallowDev: boolean,\n\tdenyPatterns: string[],\n\twarnPatterns: string[],\n\terrors: string[],\n): void {\n\tfor (const [depName, depValue] of Object.entries(deps)) {\n\t\tconst version = extractVersion(depValue);\n\t\tif (!version) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst effectiveWarn = isDev && allowDev ? [] : warnPatterns;\n\t\tconst result = checkVersionSpec(version, denyPatterns, effectiveWarn);\n\n\t\tif (result === \"deny\") {\n\t\t\terrors.push(\n\t\t\t\t`[${sectionName}] ${depName} = \"${version}\" uses a denied version pattern`,\n\t\t\t);\n\t\t} else if (result === \"warn\") {\n\t\t\terrors.push(\n\t\t\t\t`[${sectionName}] ${depName} = \"${version}\" uses an overly permissive version range`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * A policy that prevents wildcard or overly permissive version specifications in Cargo.toml.\n *\n * @alpha\n */\nexport const NoWildcardDependencies: PolicyShape<NoWildcardDependenciesConfig> =\n\tdefineCargoPolicy({\n\t\tname: \"NoWildcardDependencies\",\n\t\tdescription:\n\t\t\t\"Prevents wildcard or overly permissive dependency version specifications in Cargo.toml.\",\n\t\thandler: async (toml: CargoToml, { config }) => {\n\t\t\t// Skip workspace root\n\t\t\tif (toml.workspace !== undefined && toml.package === undefined) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst denyPatterns = config?.deny ?? DEFAULT_DENY;\n\t\t\tconst warnPatterns = config?.warn ?? DEFAULT_WARN;\n\t\t\tconst allowDev = config?.allowDev ?? true;\n\t\t\tconst errors: string[] = [];\n\n\t\t\tconst sections = [\n\t\t\t\t{ name: \"dependencies\", isDev: false },\n\t\t\t\t{ name: \"build-dependencies\", isDev: false },\n\t\t\t\t{ name: \"dev-dependencies\", isDev: true },\n\t\t\t];\n\n\t\t\tfor (const { name, isDev } of sections) {\n\t\t\t\tconst deps = toml[name] as Record<string, unknown> | undefined;\n\t\t\t\tif (!deps) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcheckSectionDeps(\n\t\t\t\t\tdeps,\n\t\t\t\t\tname,\n\t\t\t\t\tisDev,\n\t\t\t\t\tallowDev,\n\t\t\t\t\tdenyPatterns,\n\t\t\t\t\twarnPatterns,\n\t\t\t\t\terrors,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t'Use specific version ranges (e.g., \"1.0\", \"^1.0\", \"~1.0\") instead of wildcards.',\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
1
+ {"version":3,"file":"NoWildcardDependencies.js","sourceRoot":"","sources":["../../src/policies/NoWildcardDependencies.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FilePolicyDefinition } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\n\n/**\n * Configuration for the NoWildcardDependencies policy.\n *\n * @public\n */\nexport interface NoWildcardDependenciesConfig {\n\t/**\n\t * Version patterns to deny outright.\n\t * @defaultValue [\"*\"]\n\t */\n\tdeny?: string[];\n\n\t/**\n\t * Version patterns to warn about.\n\t * @defaultValue `[\">=\"]`\n\t */\n\twarn?: string[];\n\n\t/**\n\t * If true, dev-dependencies are checked more leniently (only deny, not warn).\n\t * @defaultValue true\n\t */\n\tallowDev?: boolean;\n}\n\nconst DEFAULT_DENY = [\"*\"];\nconst DEFAULT_WARN = [\">=\"];\n\nfunction checkVersionSpec(\n\tversion: string,\n\tdenyPatterns: string[],\n\twarnPatterns: string[],\n): \"deny\" | \"warn\" | \"ok\" {\n\tfor (const pattern of denyPatterns) {\n\t\tif (version === pattern || version.startsWith(pattern)) {\n\t\t\treturn \"deny\";\n\t\t}\n\t}\n\tfor (const pattern of warnPatterns) {\n\t\tif (version.startsWith(pattern)) {\n\t\t\treturn \"warn\";\n\t\t}\n\t}\n\treturn \"ok\";\n}\n\nfunction extractVersion(dep: unknown): string | undefined {\n\tif (typeof dep === \"string\") {\n\t\treturn dep;\n\t}\n\tif (typeof dep === \"object\" && dep !== null) {\n\t\tconst record = dep as Record<string, unknown>;\n\t\tif (typeof record.version === \"string\") {\n\t\t\treturn record.version;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction checkSectionDeps(\n\tdeps: Record<string, unknown>,\n\tsectionName: string,\n\tisDev: boolean,\n\tallowDev: boolean,\n\tdenyPatterns: string[],\n\twarnPatterns: string[],\n\terrors: string[],\n): void {\n\tfor (const [depName, depValue] of Object.entries(deps)) {\n\t\tconst version = extractVersion(depValue);\n\t\tif (!version) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst effectiveWarn = isDev && allowDev ? [] : warnPatterns;\n\t\tconst result = checkVersionSpec(version, denyPatterns, effectiveWarn);\n\n\t\tif (result === \"deny\") {\n\t\t\terrors.push(\n\t\t\t\t`[${sectionName}] ${depName} = \"${version}\" uses a denied version pattern`,\n\t\t\t);\n\t\t} else if (result === \"warn\") {\n\t\t\terrors.push(\n\t\t\t\t`[${sectionName}] ${depName} = \"${version}\" uses an overly permissive version range`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * A policy that prevents wildcard or overly permissive version specifications in Cargo.toml.\n *\n * @public\n */\nexport const NoWildcardDependencies = defineCargoPolicy({\n\tname: \"NoWildcardDependencies\",\n\tdescription:\n\t\t\"Prevents wildcard or overly permissive dependency version specifications in Cargo.toml.\",\n\thandler: async (toml: CargoToml, { config }) => {\n\t\t// Skip workspace root\n\t\tif (toml.workspace !== undefined && toml.package === undefined) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst denyPatterns = config?.deny ?? DEFAULT_DENY;\n\t\tconst warnPatterns = config?.warn ?? DEFAULT_WARN;\n\t\tconst allowDev = config?.allowDev ?? true;\n\t\tconst errors: string[] = [];\n\n\t\tconst sections = [\n\t\t\t{ name: \"dependencies\", isDev: false },\n\t\t\t{ name: \"build-dependencies\", isDev: false },\n\t\t\t{ name: \"dev-dependencies\", isDev: true },\n\t\t];\n\n\t\tfor (const { name, isDev } of sections) {\n\t\t\tconst deps = toml[name] as Record<string, unknown> | undefined;\n\t\t\tif (!deps) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcheckSectionDeps(\n\t\t\t\tdeps,\n\t\t\t\tname,\n\t\t\t\tisDev,\n\t\t\t\tallowDev,\n\t\t\t\tdenyPatterns,\n\t\t\t\twarnPatterns,\n\t\t\t\terrors,\n\t\t\t);\n\t\t}\n\n\t\tif (errors.length > 0) {\n\t\t\treturn errors.map((message) => ({\n\t\t\t\tmessage,\n\t\t\t\tmanualFix:\n\t\t\t\t\t'Use specific version ranges (e.g., \"1.0\", \"^1.0\", \"~1.0\") instead of wildcards.',\n\t\t\t}));\n\t\t}\n\t\treturn [];\n\t},\n}) satisfies FilePolicyDefinition<NoWildcardDependenciesConfig>;\n"]}
@@ -14,7 +14,7 @@
14
14
  * };
15
15
  * ```
16
16
  *
17
- * @alpha
17
+ * @public
18
18
  */
19
19
  export interface PackageAllowedScopesConfig {
20
20
  /**
@@ -75,14 +75,18 @@ export interface PackageAllowedScopesConfig {
75
75
  * const config: RepopoConfig = {
76
76
  * policies: [
77
77
  * makePolicy(PackageAllowedScopes, {
78
- * allowedScopes: ["@myorg", "@internal"],
79
- * unscopedPackages: ["legacy-package"],
78
+ * config: {
79
+ * allowedScopes: ["@myorg", "@internal"],
80
+ * unscopedPackages: ["legacy-package"],
81
+ * },
80
82
  * }),
81
83
  * ],
82
84
  * };
83
85
  * ```
84
86
  *
85
- * @alpha
87
+ * @public
86
88
  */
87
- export declare const PackageAllowedScopes: import("../policy.js").PolicyShape<PackageAllowedScopesConfig | undefined>;
89
+ export declare const PackageAllowedScopes: import("../policy.js").FilePolicyDefinition<PackageAllowedScopesConfig | undefined> & {
90
+ requiresConfig: true;
91
+ };
88
92
  //# sourceMappingURL=PackageAllowedScopes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageAllowedScopes.d.ts","sourceRoot":"","sources":["../../src/policies/PackageAllowedScopes.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAiDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,oBAAoB,4EAuD/B,CAAC"}
1
+ {"version":3,"file":"PackageAllowedScopes.d.ts","sourceRoot":"","sources":["../../src/policies/PackageAllowedScopes.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAiDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,oBAAoB;;CAmD/B,CAAC"}
@@ -60,40 +60,42 @@ function isUnscopedPackageAllowed(packageName, unscopedPackages) {
60
60
  * const config: RepopoConfig = {
61
61
  * policies: [
62
62
  * makePolicy(PackageAllowedScopes, {
63
- * allowedScopes: ["@myorg", "@internal"],
64
- * unscopedPackages: ["legacy-package"],
63
+ * config: {
64
+ * allowedScopes: ["@myorg", "@internal"],
65
+ * unscopedPackages: ["legacy-package"],
66
+ * },
65
67
  * }),
66
68
  * ],
67
69
  * };
68
70
  * ```
69
71
  *
70
- * @alpha
72
+ * @public
71
73
  */
72
74
  export const PackageAllowedScopes = definePackagePolicy({
73
75
  name: "PackageAllowedScopes",
76
+ requiresConfig: true,
74
77
  description: "Ensures packages use only allowed npm scopes and package names.",
75
- // biome-ignore lint/correctness/useYield: no yield needed
76
- handler: function* (json, { file, config }) {
78
+ handler: function* (json, { config }) {
77
79
  // If no config provided, skip validation
78
80
  if (config === undefined) {
79
- return true;
81
+ return [];
80
82
  }
81
83
  const packageName = json.name;
82
84
  // Skip packages without a name
83
85
  if (packageName === undefined) {
84
- return true;
86
+ return [];
85
87
  }
86
88
  // Skip the root package (common in monorepos)
87
89
  if (packageName === "root") {
88
- return true;
90
+ return [];
89
91
  }
90
92
  // Check if the package uses an allowed scope
91
93
  if (isScopeAllowed(packageName, config.allowedScopes)) {
92
- return true;
94
+ return [];
93
95
  }
94
96
  // Check if the package is an allowed unscoped package
95
97
  if (isUnscopedPackageAllowed(packageName, config.unscopedPackages)) {
96
- return true;
98
+ return [];
97
99
  }
98
100
  // Package doesn't match any allowed pattern - build error message
99
101
  const scope = getPackageScope(packageName);
@@ -106,12 +108,9 @@ export const PackageAllowedScopes = definePackagePolicy({
106
108
  // Package is unscoped but not in the allowed list
107
109
  errorMessage = `Package "${packageName}" is an unscoped package that is not in the allowed unscoped packages list. Allowed unscoped packages: ${config.unscopedPackages?.join(", ") ?? "(none)"}`;
108
110
  }
109
- const failResult = {
110
- name: PackageAllowedScopes.name,
111
- file,
112
- autoFixable: false, // Can't auto-fix package names
113
- errorMessages: [errorMessage],
114
- };
111
+ const failResult = [errorMessage].map((message) => ({
112
+ message,
113
+ }));
115
114
  return failResult;
116
115
  },
117
116
  });
@@ -1 +1 @@
1
- {"version":3,"file":"PackageAllowedScopes.js","sourceRoot":"","sources":["../../src/policies/PackageAllowedScopes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAwDpE;;;;;;GAMG;AACH,SAAS,cAAc,CACtB,WAAmB,EACnB,aAAmC;IAEnC,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,oDAAoD;QACpD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAChC,WAAmB,EACnB,gBAAsC;IAEtC,IAAI,gBAAgB,KAAK,SAAS,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,oCAAoC;IACpC,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAGrD;IACD,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACV,iEAAiE;IAClE,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACzC,yCAAyC;QACzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC;QAE9B,+BAA+B;QAC/B,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,8CAA8C;QAC9C,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,6CAA6C;QAC7C,IAAI,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACb,CAAC;QAED,sDAAsD;QACtD,IAAI,wBAAwB,CAAC,WAAW,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,CAAC;QACb,CAAC;QAED,kEAAkE;QAClE,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,YAAoB,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,kCAAkC;YAClC,YAAY,GAAG,YAAY,WAAW,iBAAiB,KAAK,8DAA8D,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1K,CAAC;aAAM,CAAC;YACP,kDAAkD;YAClD,YAAY,GAAG,YAAY,WAAW,0GAA0G,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QACnM,CAAC;QAED,MAAM,UAAU,GAAkB;YACjC,IAAI,EAAE,oBAAoB,CAAC,IAAI;YAC/B,IAAI;YACJ,WAAW,EAAE,KAAK,EAAE,+BAA+B;YACnD,aAAa,EAAE,CAAC,YAAY,CAAC;SAC7B,CAAC;QACF,OAAO,UAAU,CAAC;IACnB,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\nimport { getPackageScope, isScoped } from \"../utils/packageName.js\";\n\n/**\n * Configuration for the PackageAllowedScopes policy.\n *\n * This policy ensures packages in a monorepo use only approved scopes or package names.\n * This prevents accidental introduction of new scopes and ensures naming consistency.\n *\n * @example\n * ```typescript\n * const config: PackageAllowedScopesConfig = {\n * // Only packages in these scopes are allowed\n * allowedScopes: [\"@myorg\", \"@internal\", \"@experimental\"],\n * // These specific unscoped packages are also allowed\n * unscopedPackages: [\"my-legacy-tool\", \"special-package\"],\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackageAllowedScopesConfig {\n\t/**\n\t * A list of npm scopes that are allowed for packages in this repository.\n\t *\n\t * Scopes should start with `@` (e.g., `@myorg`). A package like `@myorg/foo`\n\t * would match the scope `@myorg`.\n\t *\n\t * @remarks\n\t *\n\t * If a package's scope is not in this list and the package is not in\n\t * `unscopedPackages`, the policy will fail.\n\t *\n\t * @example\n\t * ```typescript\n\t * allowedScopes: [\"@myorg\", \"@myorg-tools\", \"@myorg-internal\"]\n\t * ```\n\t */\n\tallowedScopes?: string[];\n\n\t/**\n\t * A list of unscoped package names that are explicitly allowed.\n\t *\n\t * Use this for legacy packages or special cases where an unscoped name is needed.\n\t *\n\t * @remarks\n\t *\n\t * Unscoped packages not in this list will cause the policy to fail.\n\t *\n\t * @example\n\t * ```typescript\n\t * unscopedPackages: [\"my-legacy-tool\", \"special-package\"]\n\t * ```\n\t */\n\tunscopedPackages?: string[];\n}\n\n/**\n * Check if a package's scope is in the allowed list.\n *\n * @param packageName - The package name to check\n * @param allowedScopes - List of allowed scopes\n * @returns `true` if the package's scope is allowed\n */\nfunction isScopeAllowed(\n\tpackageName: string,\n\tallowedScopes: string[] | undefined,\n): boolean {\n\tif (allowedScopes === undefined || allowedScopes.length === 0) {\n\t\treturn false;\n\t}\n\n\tconst scope = getPackageScope(packageName);\n\tif (scope === undefined) {\n\t\t// Package is unscoped, so scope check doesn't apply\n\t\treturn false;\n\t}\n\n\treturn allowedScopes.includes(scope);\n}\n\n/**\n * Check if an unscoped package name is in the allowed list.\n *\n * @param packageName - The package name to check\n * @param unscopedPackages - List of allowed unscoped package names\n * @returns `true` if the unscoped package is allowed\n */\nfunction isUnscopedPackageAllowed(\n\tpackageName: string,\n\tunscopedPackages: string[] | undefined,\n): boolean {\n\tif (unscopedPackages === undefined || unscopedPackages.length === 0) {\n\t\treturn false;\n\t}\n\n\t// Only applies to unscoped packages\n\tif (isScoped(packageName)) {\n\t\treturn false;\n\t}\n\n\treturn unscopedPackages.includes(packageName);\n}\n\n/**\n * A policy that ensures packages use only allowed scopes and package names.\n *\n * This policy prevents accidental introduction of new npm scopes or unscoped packages\n * in a monorepo. It helps maintain naming consistency and prevents typos or mistakes\n * when creating new packages.\n *\n * @remarks\n *\n * The policy checks packages in the following order:\n *\n * 1. If the package is scoped (starts with `@`), check if its scope is in `allowedScopes`\n * 2. If the package is unscoped, check if it's in `unscopedPackages`\n * 3. If neither check passes, the policy fails\n *\n * The \"root\" package (common in monorepos) is automatically skipped.\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageAllowedScopes } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackageAllowedScopes, {\n * allowedScopes: [\"@myorg\", \"@internal\"],\n * unscopedPackages: [\"legacy-package\"],\n * }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackageAllowedScopes = definePackagePolicy<\n\tPackageJson,\n\tPackageAllowedScopesConfig | undefined\n>({\n\tname: \"PackageAllowedScopes\",\n\tdescription:\n\t\t\"Ensures packages use only allowed npm scopes and package names.\",\n\t// biome-ignore lint/correctness/useYield: no yield needed\n\thandler: function* (json, { file, config }) {\n\t\t// If no config provided, skip validation\n\t\tif (config === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst packageName = json.name;\n\n\t\t// Skip packages without a name\n\t\tif (packageName === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Skip the root package (common in monorepos)\n\t\tif (packageName === \"root\") {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if the package uses an allowed scope\n\t\tif (isScopeAllowed(packageName, config.allowedScopes)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if the package is an allowed unscoped package\n\t\tif (isUnscopedPackageAllowed(packageName, config.unscopedPackages)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Package doesn't match any allowed pattern - build error message\n\t\tconst scope = getPackageScope(packageName);\n\t\tlet errorMessage: string;\n\t\tif (scope !== undefined) {\n\t\t\t// Package has an unexpected scope\n\t\t\terrorMessage = `Package \"${packageName}\" uses scope \"${scope}\" which is not in the allowed scopes list. Allowed scopes: ${config.allowedScopes?.join(\", \") ?? \"(none)\"}`;\n\t\t} else {\n\t\t\t// Package is unscoped but not in the allowed list\n\t\t\terrorMessage = `Package \"${packageName}\" is an unscoped package that is not in the allowed unscoped packages list. Allowed unscoped packages: ${config.unscopedPackages?.join(\", \") ?? \"(none)\"}`;\n\t\t}\n\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageAllowedScopes.name,\n\t\t\tfile,\n\t\t\tautoFixable: false, // Can't auto-fix package names\n\t\t\terrorMessages: [errorMessage],\n\t\t};\n\t\treturn failResult;\n\t},\n});\n"]}
1
+ {"version":3,"file":"PackageAllowedScopes.js","sourceRoot":"","sources":["../../src/policies/PackageAllowedScopes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAwDpE;;;;;;GAMG;AACH,SAAS,cAAc,CACtB,WAAmB,EACnB,aAAmC;IAEnC,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,oDAAoD;QACpD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAChC,WAAmB,EACnB,gBAAsC;IAEtC,IAAI,gBAAgB,KAAK,SAAS,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,oCAAoC;IACpC,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAGrD;IACD,IAAI,EAAE,sBAAsB;IAC5B,cAAc,EAAE,IAAI;IACpB,WAAW,EACV,iEAAiE;IAClE,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE;QACnC,yCAAyC;QACzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACX,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC;QAE9B,+BAA+B;QAC/B,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,EAAE,CAAC;QACX,CAAC;QAED,8CAA8C;QAC9C,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC;QACX,CAAC;QAED,6CAA6C;QAC7C,IAAI,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC;QACX,CAAC;QAED,sDAAsD;QACtD,IAAI,wBAAwB,CAAC,WAAW,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpE,OAAO,EAAE,CAAC;QACX,CAAC;QAED,kEAAkE;QAClE,MAAM,KAAK,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,YAAoB,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,kCAAkC;YAClC,YAAY,GAAG,YAAY,WAAW,iBAAiB,KAAK,8DAA8D,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1K,CAAC;aAAM,CAAC;YACP,kDAAkD;YAClD,YAAY,GAAG,YAAY,WAAW,0GAA0G,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QACnM,CAAC;QACD,MAAM,UAAU,GAAoB,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACpE,OAAO;SACP,CAAC,CAAC,CAAC;QACJ,OAAO,UAAU,CAAC;IACnB,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PackageJson } from \"type-fest\";\nimport type { PolicyFinding } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\nimport { getPackageScope, isScoped } from \"../utils/packageName.js\";\n\n/**\n * Configuration for the PackageAllowedScopes policy.\n *\n * This policy ensures packages in a monorepo use only approved scopes or package names.\n * This prevents accidental introduction of new scopes and ensures naming consistency.\n *\n * @example\n * ```typescript\n * const config: PackageAllowedScopesConfig = {\n * // Only packages in these scopes are allowed\n * allowedScopes: [\"@myorg\", \"@internal\", \"@experimental\"],\n * // These specific unscoped packages are also allowed\n * unscopedPackages: [\"my-legacy-tool\", \"special-package\"],\n * };\n * ```\n *\n * @public\n */\nexport interface PackageAllowedScopesConfig {\n\t/**\n\t * A list of npm scopes that are allowed for packages in this repository.\n\t *\n\t * Scopes should start with `@` (e.g., `@myorg`). A package like `@myorg/foo`\n\t * would match the scope `@myorg`.\n\t *\n\t * @remarks\n\t *\n\t * If a package's scope is not in this list and the package is not in\n\t * `unscopedPackages`, the policy will fail.\n\t *\n\t * @example\n\t * ```typescript\n\t * allowedScopes: [\"@myorg\", \"@myorg-tools\", \"@myorg-internal\"]\n\t * ```\n\t */\n\tallowedScopes?: string[];\n\n\t/**\n\t * A list of unscoped package names that are explicitly allowed.\n\t *\n\t * Use this for legacy packages or special cases where an unscoped name is needed.\n\t *\n\t * @remarks\n\t *\n\t * Unscoped packages not in this list will cause the policy to fail.\n\t *\n\t * @example\n\t * ```typescript\n\t * unscopedPackages: [\"my-legacy-tool\", \"special-package\"]\n\t * ```\n\t */\n\tunscopedPackages?: string[];\n}\n\n/**\n * Check if a package's scope is in the allowed list.\n *\n * @param packageName - The package name to check\n * @param allowedScopes - List of allowed scopes\n * @returns `true` if the package's scope is allowed\n */\nfunction isScopeAllowed(\n\tpackageName: string,\n\tallowedScopes: string[] | undefined,\n): boolean {\n\tif (allowedScopes === undefined || allowedScopes.length === 0) {\n\t\treturn false;\n\t}\n\n\tconst scope = getPackageScope(packageName);\n\tif (scope === undefined) {\n\t\t// Package is unscoped, so scope check doesn't apply\n\t\treturn false;\n\t}\n\n\treturn allowedScopes.includes(scope);\n}\n\n/**\n * Check if an unscoped package name is in the allowed list.\n *\n * @param packageName - The package name to check\n * @param unscopedPackages - List of allowed unscoped package names\n * @returns `true` if the unscoped package is allowed\n */\nfunction isUnscopedPackageAllowed(\n\tpackageName: string,\n\tunscopedPackages: string[] | undefined,\n): boolean {\n\tif (unscopedPackages === undefined || unscopedPackages.length === 0) {\n\t\treturn false;\n\t}\n\n\t// Only applies to unscoped packages\n\tif (isScoped(packageName)) {\n\t\treturn false;\n\t}\n\n\treturn unscopedPackages.includes(packageName);\n}\n\n/**\n * A policy that ensures packages use only allowed scopes and package names.\n *\n * This policy prevents accidental introduction of new npm scopes or unscoped packages\n * in a monorepo. It helps maintain naming consistency and prevents typos or mistakes\n * when creating new packages.\n *\n * @remarks\n *\n * The policy checks packages in the following order:\n *\n * 1. If the package is scoped (starts with `@`), check if its scope is in `allowedScopes`\n * 2. If the package is unscoped, check if it's in `unscopedPackages`\n * 3. If neither check passes, the policy fails\n *\n * The \"root\" package (common in monorepos) is automatically skipped.\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageAllowedScopes } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackageAllowedScopes, {\n * config: {\n * allowedScopes: [\"@myorg\", \"@internal\"],\n * unscopedPackages: [\"legacy-package\"],\n * },\n * }),\n * ],\n * };\n * ```\n *\n * @public\n */\nexport const PackageAllowedScopes = definePackagePolicy<\n\tPackageJson,\n\tPackageAllowedScopesConfig | undefined\n>({\n\tname: \"PackageAllowedScopes\",\n\trequiresConfig: true,\n\tdescription:\n\t\t\"Ensures packages use only allowed npm scopes and package names.\",\n\thandler: function* (json, { config }) {\n\t\t// If no config provided, skip validation\n\t\tif (config === undefined) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst packageName = json.name;\n\n\t\t// Skip packages without a name\n\t\tif (packageName === undefined) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Skip the root package (common in monorepos)\n\t\tif (packageName === \"root\") {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Check if the package uses an allowed scope\n\t\tif (isScopeAllowed(packageName, config.allowedScopes)) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Check if the package is an allowed unscoped package\n\t\tif (isUnscopedPackageAllowed(packageName, config.unscopedPackages)) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Package doesn't match any allowed pattern - build error message\n\t\tconst scope = getPackageScope(packageName);\n\t\tlet errorMessage: string;\n\t\tif (scope !== undefined) {\n\t\t\t// Package has an unexpected scope\n\t\t\terrorMessage = `Package \"${packageName}\" uses scope \"${scope}\" which is not in the allowed scopes list. Allowed scopes: ${config.allowedScopes?.join(\", \") ?? \"(none)\"}`;\n\t\t} else {\n\t\t\t// Package is unscoped but not in the allowed list\n\t\t\terrorMessage = `Package \"${packageName}\" is an unscoped package that is not in the allowed unscoped packages list. Allowed unscoped packages: ${config.unscopedPackages?.join(\", \") ?? \"(none)\"}`;\n\t\t}\n\t\tconst failResult: PolicyFinding[] = [errorMessage].map((message) => ({\n\t\t\tmessage,\n\t\t}));\n\t\treturn failResult;\n\t},\n});\n"]}
@@ -14,7 +14,7 @@
14
14
  * };
15
15
  * ```
16
16
  *
17
- * @alpha
17
+ * @public
18
18
  */
19
19
  export interface PackageEsmTypeConfig {
20
20
  /**
@@ -88,13 +88,15 @@ export interface PackageEsmTypeConfig {
88
88
  * import { PackageEsmType } from "repopo/policies";
89
89
  *
90
90
  * // Require all packages to be ESM
91
- * makePolicy(PackageEsmType, { requiredType: "module" })
91
+ * makePolicy(PackageEsmType, { config: { requiredType: "module" } })
92
92
  *
93
93
  * // Or detect based on exports
94
- * makePolicy(PackageEsmType, { detectFromExports: true })
94
+ * makePolicy(PackageEsmType, { config: { detectFromExports: true } })
95
95
  * ```
96
96
  *
97
- * @alpha
97
+ * @public
98
98
  */
99
- export declare const PackageEsmType: import("../policy.js").PolicyShape<PackageEsmTypeConfig | undefined>;
99
+ export declare const PackageEsmType: import("../policy.js").FilePolicyDefinition<PackageEsmTypeConfig | undefined> & {
100
+ requiresConfig: true;
101
+ };
100
102
  //# sourceMappingURL=PackageEsmType.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageEsmType.d.ts","sourceRoot":"","sources":["../../src/policies/PackageEsmType.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAErC;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9C;AA2PD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,cAAc,sEAgEzB,CAAC"}
1
+ {"version":3,"file":"PackageEsmType.d.ts","sourceRoot":"","sources":["../../src/policies/PackageEsmType.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAErC;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9C;AAqQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,cAAc;;CAwDzB,CAAC"}
@@ -161,20 +161,27 @@ function buildErrorMessage(packageName, currentType, expectedType) {
161
161
  * Apply the auto-fix for the type field.
162
162
  */
163
163
  async function applyFix(json, file, root, expectedType, failResult) {
164
- const fixResult = {
165
- ...failResult,
166
- resolved: false,
167
- };
164
+ const fixResult = failResult.map((finding) => ({
165
+ ...finding,
166
+ fixStatus: "failed",
167
+ }));
168
168
  try {
169
169
  json.type = expectedType;
170
170
  const filePath = resolvePath(root, file);
171
171
  const indent = await detectIndentation(filePath);
172
172
  await writeJson(filePath, json, { spaces: indent });
173
- fixResult.resolved = true;
173
+ for (const finding of fixResult) {
174
+ finding.fixStatus = "fixed";
175
+ }
174
176
  }
175
177
  catch {
176
- fixResult.resolved = false;
177
- fixResult.errorMessages = [`Failed to update ${file}`];
178
+ for (const finding of fixResult) {
179
+ finding.fixStatus = "failed";
180
+ }
181
+ fixResult.splice(0, fixResult.length, ...[`Failed to update ${file}`].map((message) => ({
182
+ ...fixResult[0],
183
+ message,
184
+ })));
178
185
  }
179
186
  return fixResult;
180
187
  }
@@ -202,58 +209,51 @@ async function applyFix(json, file, root, expectedType, failResult) {
202
209
  * import { PackageEsmType } from "repopo/policies";
203
210
  *
204
211
  * // Require all packages to be ESM
205
- * makePolicy(PackageEsmType, { requiredType: "module" })
212
+ * makePolicy(PackageEsmType, { config: { requiredType: "module" } })
206
213
  *
207
214
  * // Or detect based on exports
208
- * makePolicy(PackageEsmType, { detectFromExports: true })
215
+ * makePolicy(PackageEsmType, { config: { detectFromExports: true } })
209
216
  * ```
210
217
  *
211
- * @alpha
218
+ * @public
212
219
  */
213
220
  export const PackageEsmType = definePackagePolicy({
214
221
  name: "PackageEsmType",
222
+ requiresConfig: true,
215
223
  description: "Ensures the type field in package.json correctly indicates ESM or CommonJS module format.",
216
224
  handler: async (json, { file, root, config, resolve }) => {
217
225
  // If no config provided, skip validation
218
226
  if (config === undefined) {
219
- return true;
227
+ return [];
220
228
  }
221
229
  const packageName = json.name;
222
230
  // Check if package should be skipped
223
231
  if (shouldSkipPackage(packageName, config)) {
224
- return true;
232
+ return [];
225
233
  }
226
234
  // Determine the expected type
227
235
  const { expectedType, detectionReason } = determineExpectedType(json, config);
228
236
  // Handle case where type cannot be detected
229
237
  if (expectedType === undefined) {
230
238
  if (config.onDetectionFailure === "fail") {
231
- return {
232
- name: "PackageEsmType",
233
- file,
234
- autoFixable: false,
235
- errorMessages: [
236
- `Package "${packageName}": ${detectionReason ?? "Could not detect module type"}. Set "type" field explicitly or use "requiredType" config.`,
237
- ],
238
- };
239
+ return [
240
+ `Package "${packageName}": ${detectionReason ?? "Could not detect module type"}. Set "type" field explicitly or use "requiredType" config.`,
241
+ ].map((message) => ({ message }));
239
242
  }
240
243
  // "skip" and "warn" both pass validation
241
- return true;
244
+ return [];
242
245
  }
243
246
  // Check if current type matches expected
244
247
  if (json.type === expectedType) {
245
- return true;
248
+ return [];
246
249
  }
247
250
  // Build failure result
248
- const failResult = {
249
- name: PackageEsmType.name,
250
- file,
251
- autoFixable: true,
252
- // packageName is guaranteed to be defined here due to shouldSkipPackage check
253
- errorMessages: [
254
- buildErrorMessage(packageName, json.type, expectedType),
255
- ],
256
- };
251
+ const failResult = [
252
+ buildErrorMessage(packageName, json.type, expectedType),
253
+ ].map((message) => ({
254
+ message,
255
+ fixStatus: "available",
256
+ }));
257
257
  if (resolve) {
258
258
  return applyFix(json, file, root, expectedType, failResult);
259
259
  }