repopo 0.12.0 → 0.14.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 (345) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +57 -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 +66 -1
  10. package/esm/api.d.ts.map +1 -1
  11. package/esm/api.js +18 -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 +5 -3
  17. package/esm/commands/check-native.d.ts.map +1 -1
  18. package/esm/commands/check-native.js +35 -7
  19. package/esm/commands/check-native.js.map +1 -1
  20. package/esm/commands/check.d.ts +8 -21
  21. package/esm/commands/check.d.ts.map +1 -1
  22. package/esm/commands/check.js +98 -154
  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 +1 -0
  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 +10 -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 +10 -1
  36. package/esm/context.d.ts.map +1 -1
  37. package/esm/context.js +19 -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 +46 -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/MaxChangedFiles.d.ts +17 -0
  163. package/esm/policies/MaxChangedFiles.d.ts.map +1 -0
  164. package/esm/policies/MaxChangedFiles.js +22 -0
  165. package/esm/policies/MaxChangedFiles.js.map +1 -0
  166. package/esm/policies/MutuallyExclusiveScripts.d.ts +8 -6
  167. package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -1
  168. package/esm/policies/MutuallyExclusiveScripts.js +9 -13
  169. package/esm/policies/MutuallyExclusiveScripts.js.map +1 -1
  170. package/esm/policies/NoBuildDirectory.d.ts +9 -3
  171. package/esm/policies/NoBuildDirectory.d.ts.map +1 -1
  172. package/esm/policies/NoBuildDirectory.js +8 -13
  173. package/esm/policies/NoBuildDirectory.js.map +1 -1
  174. package/esm/policies/NoJsFileExtensions.d.ts +9 -3
  175. package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
  176. package/esm/policies/NoJsFileExtensions.js +9 -14
  177. package/esm/policies/NoJsFileExtensions.js.map +1 -1
  178. package/esm/policies/NoLargeBinaryFiles.d.ts +9 -4
  179. package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
  180. package/esm/policies/NoLargeBinaryFiles.js +10 -16
  181. package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
  182. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +10 -6
  183. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  184. package/esm/policies/NoPrivateWorkspaceDependencies.js +12 -14
  185. package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
  186. package/esm/policies/NoTargetArtifacts.d.ts +9 -3
  187. package/esm/policies/NoTargetArtifacts.d.ts.map +1 -1
  188. package/esm/policies/NoTargetArtifacts.js +9 -14
  189. package/esm/policies/NoTargetArtifacts.js.map +1 -1
  190. package/esm/policies/NoUnsafeWithoutJustification.d.ts +11 -4
  191. package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -1
  192. package/esm/policies/NoUnsafeWithoutJustification.js +8 -9
  193. package/esm/policies/NoUnsafeWithoutJustification.js.map +1 -1
  194. package/esm/policies/NoWildcardDependencies.d.ts +5 -5
  195. package/esm/policies/NoWildcardDependencies.d.ts.map +1 -1
  196. package/esm/policies/NoWildcardDependencies.js +6 -6
  197. package/esm/policies/NoWildcardDependencies.js.map +1 -1
  198. package/esm/policies/PackageAllowedScopes.d.ts +9 -5
  199. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  200. package/esm/policies/PackageAllowedScopes.js +15 -16
  201. package/esm/policies/PackageAllowedScopes.js.map +1 -1
  202. package/esm/policies/PackageEsmType.d.ts +7 -5
  203. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  204. package/esm/policies/PackageEsmType.js +31 -31
  205. package/esm/policies/PackageEsmType.js.map +1 -1
  206. package/esm/policies/PackageFolderName.d.ts +8 -6
  207. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  208. package/esm/policies/PackageFolderName.js +13 -16
  209. package/esm/policies/PackageFolderName.js.map +1 -1
  210. package/esm/policies/PackageJsonProperties.d.ts +5 -3
  211. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  212. package/esm/policies/PackageJsonProperties.js +6 -17
  213. package/esm/policies/PackageJsonProperties.js.map +1 -1
  214. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +2 -7
  215. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  216. package/esm/policies/PackageJsonRepoDirectoryProperty.js +28 -42
  217. package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
  218. package/esm/policies/PackageJsonSorted.d.ts +2 -2
  219. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  220. package/esm/policies/PackageJsonSorted.js +15 -30
  221. package/esm/policies/PackageJsonSorted.js.map +1 -1
  222. package/esm/policies/PackageLicense.d.ts +4 -4
  223. package/esm/policies/PackageLicense.d.ts.map +1 -1
  224. package/esm/policies/PackageLicense.js +31 -52
  225. package/esm/policies/PackageLicense.js.map +1 -1
  226. package/esm/policies/PackagePrivateField.d.ts +12 -8
  227. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  228. package/esm/policies/PackagePrivateField.js +31 -23
  229. package/esm/policies/PackagePrivateField.js.map +1 -1
  230. package/esm/policies/PackageReadme.d.ts +6 -5
  231. package/esm/policies/PackageReadme.d.ts.map +1 -1
  232. package/esm/policies/PackageReadme.js +22 -59
  233. package/esm/policies/PackageReadme.js.map +1 -1
  234. package/esm/policies/PackageScripts.d.ts +26 -22
  235. package/esm/policies/PackageScripts.d.ts.map +1 -1
  236. package/esm/policies/PackageScripts.js +39 -36
  237. package/esm/policies/PackageScripts.js.map +1 -1
  238. package/esm/policies/PackageTestScripts.d.ts +10 -6
  239. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  240. package/esm/policies/PackageTestScripts.js +14 -16
  241. package/esm/policies/PackageTestScripts.js.map +1 -1
  242. package/esm/policies/PublicApiDocumented.d.ts +4 -4
  243. package/esm/policies/PublicApiDocumented.d.ts.map +1 -1
  244. package/esm/policies/PublicApiDocumented.js +10 -8
  245. package/esm/policies/PublicApiDocumented.js.map +1 -1
  246. package/esm/policies/RequireCompanionChanges.d.ts +16 -0
  247. package/esm/policies/RequireCompanionChanges.d.ts.map +1 -0
  248. package/esm/policies/RequireCompanionChanges.js +42 -0
  249. package/esm/policies/RequireCompanionChanges.js.map +1 -0
  250. package/esm/policies/RequiredGitignorePatterns.d.ts +11 -4
  251. package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
  252. package/esm/policies/RequiredGitignorePatterns.js +29 -36
  253. package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
  254. package/esm/policies/RequiredScripts.d.ts +9 -7
  255. package/esm/policies/RequiredScripts.d.ts.map +1 -1
  256. package/esm/policies/RequiredScripts.js +24 -24
  257. package/esm/policies/RequiredScripts.js.map +1 -1
  258. package/esm/policies/RustDocExists.d.ts +4 -4
  259. package/esm/policies/RustDocExists.d.ts.map +1 -1
  260. package/esm/policies/RustDocExists.js +6 -6
  261. package/esm/policies/RustDocExists.js.map +1 -1
  262. package/esm/policies/RustToolchainExists.d.ts +11 -4
  263. package/esm/policies/RustToolchainExists.d.ts.map +1 -1
  264. package/esm/policies/RustToolchainExists.js +10 -9
  265. package/esm/policies/RustToolchainExists.js.map +1 -1
  266. package/esm/policies/RustfmtConfigExists.d.ts +11 -4
  267. package/esm/policies/RustfmtConfigExists.d.ts.map +1 -1
  268. package/esm/policies/RustfmtConfigExists.js +10 -9
  269. package/esm/policies/RustfmtConfigExists.js.map +1 -1
  270. package/esm/policies/ScriptContains.d.ts +9 -7
  271. package/esm/policies/ScriptContains.d.ts.map +1 -1
  272. package/esm/policies/ScriptContains.js +9 -13
  273. package/esm/policies/ScriptContains.js.map +1 -1
  274. package/esm/policies/SharedDependencyVersions.d.ts +9 -4
  275. package/esm/policies/SharedDependencyVersions.d.ts.map +1 -1
  276. package/esm/policies/SharedDependencyVersions.js +28 -20
  277. package/esm/policies/SharedDependencyVersions.js.map +1 -1
  278. package/esm/policies/WorkspaceInheritance.d.ts +11 -4
  279. package/esm/policies/WorkspaceInheritance.d.ts.map +1 -1
  280. package/esm/policies/WorkspaceInheritance.js +10 -11
  281. package/esm/policies/WorkspaceInheritance.js.map +1 -1
  282. package/esm/policies/WorkspaceMembersValid.d.ts +11 -4
  283. package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -1
  284. package/esm/policies/WorkspaceMembersValid.js +10 -11
  285. package/esm/policies/WorkspaceMembersValid.js.map +1 -1
  286. package/esm/policies/constants.d.ts.map +1 -1
  287. package/esm/policies/constants.js +1 -1
  288. package/esm/policies/constants.js.map +1 -1
  289. package/esm/policies.d.ts +15 -5
  290. package/esm/policies.d.ts.map +1 -1
  291. package/esm/policies.js +14 -5
  292. package/esm/policies.js.map +1 -1
  293. package/esm/policy.d.ts +67 -289
  294. package/esm/policy.d.ts.map +1 -1
  295. package/esm/policy.js +1 -122
  296. package/esm/policy.js.map +1 -1
  297. package/esm/policyDefiners/defineCargoPolicy.d.ts +25 -9
  298. package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -1
  299. package/esm/policyDefiners/defineCargoPolicy.js +10 -28
  300. package/esm/policyDefiners/defineCargoPolicy.js.map +1 -1
  301. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +27 -14
  302. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  303. package/esm/policyDefiners/defineFileHeaderPolicy.js +16 -35
  304. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  305. package/esm/policyDefiners/defineGleamPolicy.d.ts +25 -9
  306. package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -1
  307. package/esm/policyDefiners/defineGleamPolicy.js +10 -27
  308. package/esm/policyDefiners/defineGleamPolicy.js.map +1 -1
  309. package/esm/policyDefiners/definePackagePolicy.d.ts +24 -13
  310. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  311. package/esm/policyDefiners/definePackagePolicy.js +9 -32
  312. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  313. package/esm/policyDefiners/spdxValidator.d.ts +4 -12
  314. package/esm/policyDefiners/spdxValidator.d.ts.map +1 -1
  315. package/esm/policyDefiners/spdxValidator.js +26 -14
  316. package/esm/policyDefiners/spdxValidator.js.map +1 -1
  317. package/esm/policyExecution.d.ts +20 -0
  318. package/esm/policyExecution.d.ts.map +1 -0
  319. package/esm/policyExecution.js +234 -0
  320. package/esm/policyExecution.js.map +1 -0
  321. package/esm/repositoryChanges.d.ts +26 -0
  322. package/esm/repositoryChanges.d.ts.map +1 -0
  323. package/esm/repositoryChanges.js +172 -0
  324. package/esm/repositoryChanges.js.map +1 -0
  325. package/esm/repositoryFiles.d.ts +6 -0
  326. package/esm/repositoryFiles.d.ts.map +1 -0
  327. package/esm/repositoryFiles.js +11 -0
  328. package/esm/repositoryFiles.js.map +1 -0
  329. package/esm/runner.d.ts +73 -47
  330. package/esm/runner.d.ts.map +1 -1
  331. package/esm/runner.js +158 -144
  332. package/esm/runner.js.map +1 -1
  333. package/esm/settlePolicyPromise.d.ts +4 -0
  334. package/esm/settlePolicyPromise.d.ts.map +1 -0
  335. package/esm/settlePolicyPromise.js +10 -0
  336. package/esm/settlePolicyPromise.js.map +1 -0
  337. package/esm/tsdoc-metadata.json +1 -1
  338. package/esm/utils/safePaths.d.ts +9 -0
  339. package/esm/utils/safePaths.d.ts.map +1 -0
  340. package/esm/utils/safePaths.js +40 -0
  341. package/esm/utils/safePaths.js.map +1 -0
  342. package/oclif.manifest.json +57 -2
  343. package/package.json +42 -27
  344. package/scripts/benchmark.mjs +341 -0
  345. package/sidecar/sidecar.mjs +388 -417
@@ -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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PackageEsmType.js","sourceRoot":"","sources":["../../src/policies/PackageEsmType.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport { resolve as resolvePath } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\nimport { detectIndentation } from \"../utils/indentation.js\";\n\nconst { writeFile: writeJson } = jsonfile;\n\n/**\n * Configuration for the PackageEsmType policy.\n *\n * This policy ensures the `type` field in package.json is correctly set\n * to indicate whether the package is an ESM or CommonJS module.\n *\n * @example\n * ```typescript\n * const config: PackageEsmTypeConfig = {\n * // Require ESM type field for all packages\n * requiredType: \"module\",\n * // Or detect based on exports/main field\n * detectFromExports: true,\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackageEsmTypeConfig {\n\t/**\n\t * The required `type` field value for all packages.\n\t *\n\t * - `\"module\"` - All packages must be ESM (use import/export)\n\t * - `\"commonjs\"` - All packages must be CommonJS (use require)\n\t * - `undefined` - Use detection logic based on exports/main\n\t *\n\t * @remarks\n\t *\n\t * If set, this overrides automatic detection. Use `detectFromExports`\n\t * for more flexible per-package type detection.\n\t */\n\trequiredType?: \"module\" | \"commonjs\";\n\n\t/**\n\t * Detect the expected `type` field from the exports or main field.\n\t *\n\t * When enabled, the policy analyzes the package's entry points:\n\t * - If exports use `.mjs` or have `import` conditions → `\"module\"`\n\t * - If exports use `.cjs` or have `require` conditions → `\"commonjs\"`\n\t * - If main field uses `.mjs` → `\"module\"`\n\t * - If main field uses `.cjs` → `\"commonjs\"`\n\t *\n\t * @defaultValue false\n\t */\n\tdetectFromExports?: boolean;\n\n\t/**\n\t * Package names or scopes to exclude from validation.\n\t *\n\t * @example\n\t * ```typescript\n\t * excludePackages: [\"@myorg/legacy-package\", \"old-cjs-lib\"]\n\t * ```\n\t */\n\texcludePackages?: string[];\n\n\t/**\n\t * Behavior when module type cannot be detected from exports/main.\n\t *\n\t * - `\"skip\"` (default) - Skip validation for packages where type cannot be detected\n\t * - `\"warn\"` - Pass validation but include a warning in the output\n\t * - `\"fail\"` - Fail validation when type cannot be detected\n\t *\n\t * This only applies when `detectFromExports` is true and no `requiredType` is set.\n\t *\n\t * @defaultValue \"skip\"\n\t */\n\tonDetectionFailure?: \"skip\" | \"warn\" | \"fail\";\n}\n\n/**\n * Result of detecting the module type from a package.\n */\ninterface DetectionResult {\n\t/**\n\t * The detected type, if any.\n\t */\n\ttype: \"module\" | \"commonjs\" | undefined;\n\n\t/**\n\t * Whether the package appears to be dual-format (both ESM and CommonJS).\n\t * When true, the `type` field should typically match the package's default format.\n\t */\n\tisDualFormat: boolean;\n\n\t/**\n\t * Human-readable reason for the detection result.\n\t */\n\treason: string;\n}\n\n/**\n * Detect module type from the exports field.\n */\nfunction detectTypeFromExports(\n\texports: PackageJson[\"exports\"],\n): DetectionResult | undefined {\n\tif (exports === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst exportsStr = JSON.stringify(exports);\n\tconst hasEsm = exportsStr.includes(\".mjs\") || exportsStr.includes('\"import\"');\n\tconst hasCjs =\n\t\texportsStr.includes(\".cjs\") || exportsStr.includes('\"require\"');\n\n\t// Dual format packages have both ESM and CJS exports\n\tif (hasEsm && hasCjs) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: true,\n\t\t\treason:\n\t\t\t\t\"Package has both ESM and CommonJS exports (dual format). Defaulting to ESM.\",\n\t\t};\n\t}\n\n\tif (hasEsm) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected ESM from exports field (.mjs or import condition)\",\n\t\t};\n\t}\n\n\tif (hasCjs) {\n\t\treturn {\n\t\t\ttype: \"commonjs\",\n\t\t\tisDualFormat: false,\n\t\t\treason:\n\t\t\t\t\"Detected CommonJS from exports field (.cjs or require condition)\",\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Detect module type from the main field.\n */\nfunction detectTypeFromMain(main: unknown): DetectionResult | undefined {\n\tif (typeof main !== \"string\") {\n\t\treturn undefined;\n\t}\n\n\tif (main.endsWith(\".mjs\")) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected ESM from main field (.mjs extension)\",\n\t\t};\n\t}\n\n\tif (main.endsWith(\".cjs\")) {\n\t\treturn {\n\t\t\ttype: \"commonjs\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected CommonJS from main field (.cjs extension)\",\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Detect the expected type field from the package's exports or main field.\n *\n * @param json - The package.json content\n * @returns Detection result with type, dual-format indicator, and reason\n */\nfunction detectTypeFromPackage(json: PackageJson): DetectionResult {\n\t// Check exports field for type hints\n\tconst exportsResult = detectTypeFromExports(json.exports);\n\tif (exportsResult !== undefined) {\n\t\treturn exportsResult;\n\t}\n\n\t// Check main field\n\tconst mainResult = detectTypeFromMain(json.main);\n\tif (mainResult !== undefined) {\n\t\treturn mainResult;\n\t}\n\n\t// Check module field (ESM entry point)\n\tif (json.module !== undefined) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected ESM from module field presence\",\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: undefined,\n\t\tisDualFormat: false,\n\t\treason: \"Could not detect module type from exports, main, or module fields\",\n\t};\n}\n\n/**\n * Check if a package matches an exclusion pattern.\n *\n * @param packageName - The package name\n * @param excludePackages - List of patterns to exclude\n * @returns true if the package should be excluded\n */\nfunction isExcluded(\n\tpackageName: string,\n\texcludePackages: string[] | undefined,\n): boolean {\n\tif (excludePackages === undefined || excludePackages.length === 0) {\n\t\treturn false;\n\t}\n\n\tfor (const pattern of excludePackages) {\n\t\t// Scope matching\n\t\tif (pattern.startsWith(\"@\") && packageName.startsWith(`${pattern}/`)) {\n\t\t\treturn true;\n\t\t}\n\t\t// Exact match\n\t\tif (packageName === pattern) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if the package should be skipped from validation.\n */\nfunction shouldSkipPackage(\n\tpackageName: string | undefined,\n\tconfig: PackageEsmTypeConfig,\n): boolean {\n\t// Skip packages without a name\n\tif (packageName === undefined) {\n\t\treturn true;\n\t}\n\n\t// Skip the root package\n\tif (packageName === \"root\") {\n\t\treturn true;\n\t}\n\n\t// Check exclusions\n\treturn isExcluded(packageName, config.excludePackages);\n}\n\n/**\n * Determine the expected type and reason from the config and package.\n */\nfunction determineExpectedType(\n\tjson: PackageJson,\n\tconfig: PackageEsmTypeConfig,\n): {\n\texpectedType: \"module\" | \"commonjs\" | undefined;\n\tdetectionReason: string | undefined;\n} {\n\tif (config.requiredType !== undefined) {\n\t\treturn {\n\t\t\texpectedType: config.requiredType,\n\t\t\tdetectionReason: `Required type: ${config.requiredType}`,\n\t\t};\n\t}\n\n\tif (config.detectFromExports === true) {\n\t\tconst detection = detectTypeFromPackage(json);\n\t\treturn {\n\t\t\texpectedType: detection.type,\n\t\t\tdetectionReason: detection.reason,\n\t\t};\n\t}\n\n\treturn { expectedType: undefined, detectionReason: undefined };\n}\n\n/**\n * Build the error message for a type mismatch.\n */\nfunction buildErrorMessage(\n\tpackageName: string,\n\tcurrentType: string | undefined,\n\texpectedType: string,\n): string {\n\tif (currentType === undefined) {\n\t\treturn `Package \"${packageName}\" is missing the \"type\" field. Expected: \"type\": \"${expectedType}\"`;\n\t}\n\treturn `Package \"${packageName}\" has \"type\": \"${currentType}\" but expected \"type\": \"${expectedType}\"`;\n}\n\n/**\n * Apply the auto-fix for the type field.\n */\nasync function applyFix(\n\tjson: PackageJson,\n\tfile: string,\n\troot: string,\n\texpectedType: \"module\" | \"commonjs\",\n\tfailResult: PolicyFailure,\n): Promise<PolicyFixResult> {\n\tconst fixResult: PolicyFixResult = {\n\t\t...failResult,\n\t\tresolved: false,\n\t};\n\n\ttry {\n\t\tjson.type = expectedType;\n\t\tconst filePath = resolvePath(root, file);\n\t\tconst indent = await detectIndentation(filePath);\n\t\tawait writeJson(filePath, json, { spaces: indent });\n\t\tfixResult.resolved = true;\n\t} catch {\n\t\tfixResult.resolved = false;\n\t\tfixResult.errorMessages = [`Failed to update ${file}`];\n\t}\n\n\treturn fixResult;\n}\n\n/**\n * A policy that ensures the `type` field in package.json is correctly set.\n *\n * This policy helps maintain consistency in how packages declare their module format,\n * which is essential for proper module resolution in Node.js and bundlers.\n *\n * @remarks\n *\n * The policy can operate in two modes:\n *\n * 1. **Required Type**: Set `requiredType` to enforce a specific type for all packages\n * 2. **Detection**: Set `detectFromExports: true` to detect the expected type from\n * the package's exports or main field\n *\n * When `detectFromExports` is enabled, the policy looks for:\n * - `.mjs` extensions or `\"import\"` conditions → expects `\"module\"`\n * - `.cjs` extensions or `\"require\"` conditions → expects `\"commonjs\"`\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageEsmType } from \"repopo/policies\";\n *\n * // Require all packages to be ESM\n * makePolicy(PackageEsmType, { requiredType: \"module\" })\n *\n * // Or detect based on exports\n * makePolicy(PackageEsmType, { detectFromExports: true })\n * ```\n *\n * @alpha\n */\nexport const PackageEsmType = definePackagePolicy<\n\tPackageJson,\n\tPackageEsmTypeConfig | undefined\n>({\n\tname: \"PackageEsmType\",\n\tdescription:\n\t\t\"Ensures the type field in package.json correctly indicates ESM or CommonJS module format.\",\n\thandler: async (json, { file, root, config, resolve }) => {\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// Check if package should be skipped\n\t\tif (shouldSkipPackage(packageName, config)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Determine the expected type\n\t\tconst { expectedType, detectionReason } = determineExpectedType(\n\t\t\tjson,\n\t\t\tconfig,\n\t\t);\n\n\t\t// Handle case where type cannot be detected\n\t\tif (expectedType === undefined) {\n\t\t\tif (config.onDetectionFailure === \"fail\") {\n\t\t\t\treturn {\n\t\t\t\t\tname: \"PackageEsmType\",\n\t\t\t\t\tfile,\n\t\t\t\t\tautoFixable: false,\n\t\t\t\t\terrorMessages: [\n\t\t\t\t\t\t`Package \"${packageName}\": ${detectionReason ?? \"Could not detect module type\"}. Set \"type\" field explicitly or use \"requiredType\" config.`,\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t\t// \"skip\" and \"warn\" both pass validation\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if current type matches expected\n\t\tif (json.type === expectedType) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Build failure result\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageEsmType.name,\n\t\t\tfile,\n\t\t\tautoFixable: true,\n\t\t\t// packageName is guaranteed to be defined here due to shouldSkipPackage check\n\t\t\terrorMessages: [\n\t\t\t\tbuildErrorMessage(packageName as string, json.type, expectedType),\n\t\t\t],\n\t\t};\n\n\t\tif (resolve) {\n\t\t\treturn applyFix(json, file, root, expectedType, failResult);\n\t\t}\n\n\t\treturn failResult;\n\t},\n});\n"]}
1
+ {"version":3,"file":"PackageEsmType.js","sourceRoot":"","sources":["../../src/policies/PackageEsmType.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport { resolve as resolvePath } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFinding } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\nimport { detectIndentation } from \"../utils/indentation.js\";\n\nconst { writeFile: writeJson } = jsonfile;\n\n/**\n * Configuration for the PackageEsmType policy.\n *\n * This policy ensures the `type` field in package.json is correctly set\n * to indicate whether the package is an ESM or CommonJS module.\n *\n * @example\n * ```typescript\n * const config: PackageEsmTypeConfig = {\n * // Require ESM type field for all packages\n * requiredType: \"module\",\n * // Or detect based on exports/main field\n * detectFromExports: true,\n * };\n * ```\n *\n * @public\n */\nexport interface PackageEsmTypeConfig {\n\t/**\n\t * The required `type` field value for all packages.\n\t *\n\t * - `\"module\"` - All packages must be ESM (use import/export)\n\t * - `\"commonjs\"` - All packages must be CommonJS (use require)\n\t * - `undefined` - Use detection logic based on exports/main\n\t *\n\t * @remarks\n\t *\n\t * If set, this overrides automatic detection. Use `detectFromExports`\n\t * for more flexible per-package type detection.\n\t */\n\trequiredType?: \"module\" | \"commonjs\";\n\n\t/**\n\t * Detect the expected `type` field from the exports or main field.\n\t *\n\t * When enabled, the policy analyzes the package's entry points:\n\t * - If exports use `.mjs` or have `import` conditions → `\"module\"`\n\t * - If exports use `.cjs` or have `require` conditions → `\"commonjs\"`\n\t * - If main field uses `.mjs` → `\"module\"`\n\t * - If main field uses `.cjs` → `\"commonjs\"`\n\t *\n\t * @defaultValue false\n\t */\n\tdetectFromExports?: boolean;\n\n\t/**\n\t * Package names or scopes to exclude from validation.\n\t *\n\t * @example\n\t * ```typescript\n\t * excludePackages: [\"@myorg/legacy-package\", \"old-cjs-lib\"]\n\t * ```\n\t */\n\texcludePackages?: string[];\n\n\t/**\n\t * Behavior when module type cannot be detected from exports/main.\n\t *\n\t * - `\"skip\"` (default) - Skip validation for packages where type cannot be detected\n\t * - `\"warn\"` - Pass validation but include a warning in the output\n\t * - `\"fail\"` - Fail validation when type cannot be detected\n\t *\n\t * This only applies when `detectFromExports` is true and no `requiredType` is set.\n\t *\n\t * @defaultValue \"skip\"\n\t */\n\tonDetectionFailure?: \"skip\" | \"warn\" | \"fail\";\n}\n\n/**\n * Result of detecting the module type from a package.\n */\ninterface DetectionResult {\n\t/**\n\t * The detected type, if any.\n\t */\n\ttype: \"module\" | \"commonjs\" | undefined;\n\n\t/**\n\t * Whether the package appears to be dual-format (both ESM and CommonJS).\n\t * When true, the `type` field should typically match the package's default format.\n\t */\n\tisDualFormat: boolean;\n\n\t/**\n\t * Human-readable reason for the detection result.\n\t */\n\treason: string;\n}\n\n/**\n * Detect module type from the exports field.\n */\nfunction detectTypeFromExports(\n\texports: PackageJson[\"exports\"],\n): DetectionResult | undefined {\n\tif (exports === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst exportsStr = JSON.stringify(exports);\n\tconst hasEsm = exportsStr.includes(\".mjs\") || exportsStr.includes('\"import\"');\n\tconst hasCjs =\n\t\texportsStr.includes(\".cjs\") || exportsStr.includes('\"require\"');\n\n\t// Dual format packages have both ESM and CJS exports\n\tif (hasEsm && hasCjs) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: true,\n\t\t\treason:\n\t\t\t\t\"Package has both ESM and CommonJS exports (dual format). Defaulting to ESM.\",\n\t\t};\n\t}\n\n\tif (hasEsm) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected ESM from exports field (.mjs or import condition)\",\n\t\t};\n\t}\n\n\tif (hasCjs) {\n\t\treturn {\n\t\t\ttype: \"commonjs\",\n\t\t\tisDualFormat: false,\n\t\t\treason:\n\t\t\t\t\"Detected CommonJS from exports field (.cjs or require condition)\",\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Detect module type from the main field.\n */\nfunction detectTypeFromMain(main: unknown): DetectionResult | undefined {\n\tif (typeof main !== \"string\") {\n\t\treturn undefined;\n\t}\n\n\tif (main.endsWith(\".mjs\")) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected ESM from main field (.mjs extension)\",\n\t\t};\n\t}\n\n\tif (main.endsWith(\".cjs\")) {\n\t\treturn {\n\t\t\ttype: \"commonjs\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected CommonJS from main field (.cjs extension)\",\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Detect the expected type field from the package's exports or main field.\n *\n * @param json - The package.json content\n * @returns Detection result with type, dual-format indicator, and reason\n */\nfunction detectTypeFromPackage(json: PackageJson): DetectionResult {\n\t// Check exports field for type hints\n\tconst exportsResult = detectTypeFromExports(json.exports);\n\tif (exportsResult !== undefined) {\n\t\treturn exportsResult;\n\t}\n\n\t// Check main field\n\tconst mainResult = detectTypeFromMain(json.main);\n\tif (mainResult !== undefined) {\n\t\treturn mainResult;\n\t}\n\n\t// Check module field (ESM entry point)\n\tif (json.module !== undefined) {\n\t\treturn {\n\t\t\ttype: \"module\",\n\t\t\tisDualFormat: false,\n\t\t\treason: \"Detected ESM from module field presence\",\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: undefined,\n\t\tisDualFormat: false,\n\t\treason: \"Could not detect module type from exports, main, or module fields\",\n\t};\n}\n\n/**\n * Check if a package matches an exclusion pattern.\n *\n * @param packageName - The package name\n * @param excludePackages - List of patterns to exclude\n * @returns true if the package should be excluded\n */\nfunction isExcluded(\n\tpackageName: string,\n\texcludePackages: string[] | undefined,\n): boolean {\n\tif (excludePackages === undefined || excludePackages.length === 0) {\n\t\treturn false;\n\t}\n\n\tfor (const pattern of excludePackages) {\n\t\t// Scope matching\n\t\tif (pattern.startsWith(\"@\") && packageName.startsWith(`${pattern}/`)) {\n\t\t\treturn true;\n\t\t}\n\t\t// Exact match\n\t\tif (packageName === pattern) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if the package should be skipped from validation.\n */\nfunction shouldSkipPackage(\n\tpackageName: string | undefined,\n\tconfig: PackageEsmTypeConfig,\n): boolean {\n\t// Skip packages without a name\n\tif (packageName === undefined) {\n\t\treturn true;\n\t}\n\n\t// Skip the root package\n\tif (packageName === \"root\") {\n\t\treturn true;\n\t}\n\n\t// Check exclusions\n\treturn isExcluded(packageName, config.excludePackages);\n}\n\n/**\n * Determine the expected type and reason from the config and package.\n */\nfunction determineExpectedType(\n\tjson: PackageJson,\n\tconfig: PackageEsmTypeConfig,\n): {\n\texpectedType: \"module\" | \"commonjs\" | undefined;\n\tdetectionReason: string | undefined;\n} {\n\tif (config.requiredType !== undefined) {\n\t\treturn {\n\t\t\texpectedType: config.requiredType,\n\t\t\tdetectionReason: `Required type: ${config.requiredType}`,\n\t\t};\n\t}\n\n\tif (config.detectFromExports === true) {\n\t\tconst detection = detectTypeFromPackage(json);\n\t\treturn {\n\t\t\texpectedType: detection.type,\n\t\t\tdetectionReason: detection.reason,\n\t\t};\n\t}\n\n\treturn { expectedType: undefined, detectionReason: undefined };\n}\n\n/**\n * Build the error message for a type mismatch.\n */\nfunction buildErrorMessage(\n\tpackageName: string,\n\tcurrentType: string | undefined,\n\texpectedType: string,\n): string {\n\tif (currentType === undefined) {\n\t\treturn `Package \"${packageName}\" is missing the \"type\" field. Expected: \"type\": \"${expectedType}\"`;\n\t}\n\treturn `Package \"${packageName}\" has \"type\": \"${currentType}\" but expected \"type\": \"${expectedType}\"`;\n}\n\n/**\n * Apply the auto-fix for the type field.\n */\nasync function applyFix(\n\tjson: PackageJson,\n\tfile: string,\n\troot: string,\n\texpectedType: \"module\" | \"commonjs\",\n\tfailResult: PolicyFinding[],\n): Promise<PolicyFinding[]> {\n\tconst fixResult: PolicyFinding[] = failResult.map((finding) => ({\n\t\t...finding,\n\t\tfixStatus: \"failed\",\n\t}));\n\ttry {\n\t\tjson.type = expectedType;\n\t\tconst filePath = resolvePath(root, file);\n\t\tconst indent = await detectIndentation(filePath);\n\t\tawait writeJson(filePath, json, { spaces: indent });\n\t\tfor (const finding of fixResult) {\n\t\t\tfinding.fixStatus = \"fixed\";\n\t\t}\n\t} catch {\n\t\tfor (const finding of fixResult) {\n\t\t\tfinding.fixStatus = \"failed\";\n\t\t}\n\t\tfixResult.splice(\n\t\t\t0,\n\t\t\tfixResult.length,\n\t\t\t...[`Failed to update ${file}`].map((message) => ({\n\t\t\t\t...fixResult[0],\n\t\t\t\tmessage,\n\t\t\t})),\n\t\t);\n\t}\n\n\treturn fixResult;\n}\n\n/**\n * A policy that ensures the `type` field in package.json is correctly set.\n *\n * This policy helps maintain consistency in how packages declare their module format,\n * which is essential for proper module resolution in Node.js and bundlers.\n *\n * @remarks\n *\n * The policy can operate in two modes:\n *\n * 1. **Required Type**: Set `requiredType` to enforce a specific type for all packages\n * 2. **Detection**: Set `detectFromExports: true` to detect the expected type from\n * the package's exports or main field\n *\n * When `detectFromExports` is enabled, the policy looks for:\n * - `.mjs` extensions or `\"import\"` conditions → expects `\"module\"`\n * - `.cjs` extensions or `\"require\"` conditions → expects `\"commonjs\"`\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageEsmType } from \"repopo/policies\";\n *\n * // Require all packages to be ESM\n * makePolicy(PackageEsmType, { config: { requiredType: \"module\" } })\n *\n * // Or detect based on exports\n * makePolicy(PackageEsmType, { config: { detectFromExports: true } })\n * ```\n *\n * @public\n */\nexport const PackageEsmType = definePackagePolicy<\n\tPackageJson,\n\tPackageEsmTypeConfig | undefined\n>({\n\tname: \"PackageEsmType\",\n\trequiresConfig: true,\n\tdescription:\n\t\t\"Ensures the type field in package.json correctly indicates ESM or CommonJS module format.\",\n\thandler: async (json, { file, root, config, resolve }) => {\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// Check if package should be skipped\n\t\tif (shouldSkipPackage(packageName, config)) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Determine the expected type\n\t\tconst { expectedType, detectionReason } = determineExpectedType(\n\t\t\tjson,\n\t\t\tconfig,\n\t\t);\n\n\t\t// Handle case where type cannot be detected\n\t\tif (expectedType === undefined) {\n\t\t\tif (config.onDetectionFailure === \"fail\") {\n\t\t\t\treturn [\n\t\t\t\t\t`Package \"${packageName}\": ${detectionReason ?? \"Could not detect module type\"}. Set \"type\" field explicitly or use \"requiredType\" config.`,\n\t\t\t\t].map((message) => ({ message }));\n\t\t\t}\n\t\t\t// \"skip\" and \"warn\" both pass validation\n\t\t\treturn [];\n\t\t}\n\n\t\t// Check if current type matches expected\n\t\tif (json.type === expectedType) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Build failure result\n\t\tconst failResult: PolicyFinding[] = [\n\t\t\tbuildErrorMessage(packageName as string, json.type, expectedType),\n\t\t].map((message) => ({\n\t\t\tmessage,\n\t\t\tfixStatus: \"available\",\n\t\t}));\n\t\tif (resolve) {\n\t\t\treturn applyFix(json, file, root, expectedType, failResult);\n\t\t}\n\n\t\treturn failResult;\n\t},\n});\n"]}
@@ -16,7 +16,7 @@
16
16
  * };
17
17
  * ```
18
18
  *
19
- * @alpha
19
+ * @public
20
20
  */
21
21
  export interface PackageFolderNameConfig {
22
22
  /**
@@ -73,7 +73,7 @@ export interface PackageFolderNameConfig {
73
73
  *
74
74
  * For example:
75
75
  * - `packages/my-lib/package.json` with name `my-lib` ✓
76
- * - `packages/my-lib/package.json` with name `@myorg/my-lib` ✓ (if @myorg in stripScopes)
76
+ * - `packages/my-lib/package.json` with name `@myorg/my-lib` ✓ (if `@myorg` is in `stripScopes`)
77
77
  * - `packages/wrong-name/package.json` with name `my-lib` ✗
78
78
  *
79
79
  * @example
@@ -84,14 +84,16 @@ export interface PackageFolderNameConfig {
84
84
  * const config: RepopoConfig = {
85
85
  * policies: [
86
86
  * makePolicy(PackageFolderName, {
87
- * stripScopes: ["@myorg", "@internal"],
88
- * excludePackages: ["@myorg/special-case"],
87
+ * config: {
88
+ * stripScopes: ["@myorg", "@internal"],
89
+ * excludePackages: ["@myorg/special-case"],
90
+ * },
89
91
  * }),
90
92
  * ],
91
93
  * };
92
94
  * ```
93
95
  *
94
- * @alpha
96
+ * @public
95
97
  */
96
- export declare const PackageFolderName: import("../policy.js").PolicyShape<PackageFolderNameConfig | undefined>;
98
+ export declare const PackageFolderName: import("../policy.js").FilePolicyDefinition<PackageFolderNameConfig | undefined>;
97
99
  //# sourceMappingURL=PackageFolderName.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageFolderName.d.ts","sourceRoot":"","sources":["../../src/policies/PackageFolderName.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,iBAAiB,yEAqD5B,CAAC"}
1
+ {"version":3,"file":"PackageFolderName.d.ts","sourceRoot":"","sources":["../../src/policies/PackageFolderName.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,iBAAiB,kFAgD5B,CAAC"}
@@ -46,7 +46,7 @@ function getExpectedFolderName(packageName, stripScopes) {
46
46
  *
47
47
  * For example:
48
48
  * - `packages/my-lib/package.json` with name `my-lib` ✓
49
- * - `packages/my-lib/package.json` with name `@myorg/my-lib` ✓ (if @myorg in stripScopes)
49
+ * - `packages/my-lib/package.json` with name `@myorg/my-lib` ✓ (if `@myorg` is in `stripScopes`)
50
50
  * - `packages/wrong-name/package.json` with name `my-lib` ✗
51
51
  *
52
52
  * @example
@@ -57,14 +57,16 @@ function getExpectedFolderName(packageName, stripScopes) {
57
57
  * const config: RepopoConfig = {
58
58
  * policies: [
59
59
  * makePolicy(PackageFolderName, {
60
- * stripScopes: ["@myorg", "@internal"],
61
- * excludePackages: ["@myorg/special-case"],
60
+ * config: {
61
+ * stripScopes: ["@myorg", "@internal"],
62
+ * excludePackages: ["@myorg/special-case"],
63
+ * },
62
64
  * }),
63
65
  * ],
64
66
  * };
65
67
  * ```
66
68
  *
67
- * @alpha
69
+ * @public
68
70
  */
69
71
  export const PackageFolderName = definePackagePolicy({
70
72
  name: "PackageFolderName",
@@ -75,15 +77,15 @@ export const PackageFolderName = definePackagePolicy({
75
77
  const packageName = json.name;
76
78
  // Skip packages without a name
77
79
  if (packageName === undefined) {
78
- return true;
80
+ return [];
79
81
  }
80
82
  // Skip the root package (common in monorepos)
81
83
  if (packageName === "root") {
82
- return true;
84
+ return [];
83
85
  }
84
86
  // Skip explicitly excluded packages
85
87
  if (effectiveConfig.excludePackages?.includes(packageName)) {
86
- return true;
88
+ return [];
87
89
  }
88
90
  // Get the folder name (parent directory of package.json)
89
91
  const folderName = path.basename(path.dirname(file));
@@ -91,17 +93,12 @@ export const PackageFolderName = definePackagePolicy({
91
93
  const expectedFolderName = getExpectedFolderName(packageName, effectiveConfig.stripScopes ?? []);
92
94
  // Compare folder name to expected name
93
95
  if (folderName === expectedFolderName) {
94
- return true;
96
+ return [];
95
97
  }
96
98
  // Mismatch - build error message
97
- const failResult = {
98
- name: PackageFolderName.name,
99
- file,
100
- autoFixable: false, // Can't auto-fix folder names
101
- errorMessages: [
102
- `Package folder "${folderName}" does not match package name "${packageName}". Expected folder name: "${expectedFolderName}"`,
103
- ],
104
- };
99
+ const failResult = [
100
+ `Package folder "${folderName}" does not match package name "${packageName}". Expected folder name: "${expectedFolderName}"`,
101
+ ].map((message) => ({ message }));
105
102
  return failResult;
106
103
  },
107
104
  });
@@ -1 +1 @@
1
- {"version":3,"file":"PackageFolderName.js","sourceRoot":"","sources":["../../src/policies/PackageFolderName.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,SAAS,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgE3D;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,KAAa,EAAE,WAAqB;IAC7D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAC7B,WAAmB,EACnB,WAAqB;IAErB,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAE9D,gEAAgE;IAChE,IAAI,KAAK,KAAK,SAAS,IAAI,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC;QACjE,OAAO,YAAY,CAAC;IACrB,CAAC;IAED,8EAA8E;IAC9E,OAAO,WAAW,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAGlD;IACD,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,iFAAiF;IAClF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzC,2DAA2D;QAC3D,MAAM,eAAe,GAAG,MAAM,IAAI,EAAE,CAAC;QAErC,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,oCAAoC;QACpC,IAAI,eAAe,CAAC,eAAe,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC;QACb,CAAC;QAED,yDAAyD;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAErD,+BAA+B;QAC/B,MAAM,kBAAkB,GAAG,qBAAqB,CAC/C,WAAW,EACX,eAAe,CAAC,WAAW,IAAI,EAAE,CACjC,CAAC;QAEF,uCAAuC;QACvC,IAAI,UAAU,KAAK,kBAAkB,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,iCAAiC;QACjC,MAAM,UAAU,GAAkB;YACjC,IAAI,EAAE,iBAAiB,CAAC,IAAI;YAC5B,IAAI;YACJ,WAAW,EAAE,KAAK,EAAE,8BAA8B;YAClD,aAAa,EAAE;gBACd,mBAAmB,UAAU,kCAAkC,WAAW,6BAA6B,kBAAkB,GAAG;aAC5H;SACD,CAAC;QACF,OAAO,UAAU,CAAC;IACnB,CAAC;CACD,CAAC,CAAC","sourcesContent":["import path from \"pathe\";\nimport picomatch from \"picomatch\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\nimport { parsePackageName } from \"../utils/packageName.js\";\n\n/**\n * Configuration for the PackageFolderName policy.\n *\n * This policy ensures that package folder names match their package names,\n * promoting consistency and making packages easier to find in the file system.\n *\n * @example\n * ```typescript\n * const config: PackageFolderNameConfig = {\n * // Strip all scopes when matching folder names\n * stripScopes: [\"@*\"],\n * // Or strip specific scopes\n * stripScopes: [\"@myorg\", \"@internal\"],\n * // These packages are exempt from the check\n * excludePackages: [\"@myorg/special-name\"],\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackageFolderNameConfig {\n\t/**\n\t * A list of npm scope patterns to strip when comparing folder names to package names.\n\t *\n\t * For scoped packages like `@myorg/my-package`, if `@myorg` matches a pattern in this list,\n\t * the policy will expect the folder to be named `my-package` (not `@myorg/my-package`).\n\t *\n\t * @remarks\n\t *\n\t * Supports glob patterns:\n\t * - `@*` - matches all scopes\n\t * - `@myorg` - matches exactly `@myorg`\n\t * - `@my*` - matches scopes starting with `@my`\n\t *\n\t * @example\n\t * ```typescript\n\t * // Strip all scopes - @anything/my-package → folder \"my-package\"\n\t * stripScopes: [\"@*\"]\n\t *\n\t * // Strip specific scopes only\n\t * stripScopes: [\"@myorg\", \"@internal\"]\n\t *\n\t * // Strip scopes matching a pattern\n\t * stripScopes: [\"@fluid*\"]\n\t * ```\n\t */\n\tstripScopes?: string[];\n\n\t/**\n\t * A list of package names that are exempt from folder name matching.\n\t *\n\t * Use this for packages that intentionally have different folder names,\n\t * such as legacy packages or packages with special naming requirements.\n\t *\n\t * @example\n\t * ```typescript\n\t * excludePackages: [\"@myorg/cli\", \"legacy-package\"]\n\t * ```\n\t */\n\texcludePackages?: string[];\n}\n\n/**\n * Check if a scope should be stripped based on the patterns.\n *\n * @param scope - The scope to check (e.g., `@myorg`)\n * @param stripScopes - List of scope patterns to match (supports glob patterns via picomatch)\n * @returns `true` if the scope matches any pattern\n */\nfunction shouldStripScope(scope: string, stripScopes: string[]): boolean {\n\tif (stripScopes.length === 0) {\n\t\treturn false;\n\t}\n\n\treturn picomatch.isMatch(scope, stripScopes);\n}\n\n/**\n * Get the expected folder name from a package name.\n *\n * @param packageName - The package name (e.g., `@myorg/my-package`)\n * @param stripScopes - Scope patterns to strip from the package name\n * @returns The expected folder name\n */\nfunction getExpectedFolderName(\n\tpackageName: string,\n\tstripScopes: string[],\n): string {\n\tconst { scope, unscopedName } = parsePackageName(packageName);\n\n\t// Check if the package is scoped and should have scope stripped\n\tif (scope !== undefined && shouldStripScope(scope, stripScopes)) {\n\t\treturn unscopedName;\n\t}\n\n\t// Return full package name for unscoped packages or scopes not in stripScopes\n\treturn packageName;\n}\n\n/**\n * A policy that ensures package folder names match package names.\n *\n * This policy helps maintain a consistent and predictable file structure\n * in monorepos by ensuring that folder names correspond to package names.\n * This makes it easier to locate packages in the file system.\n *\n * @remarks\n *\n * The policy compares the immediate parent folder name of the package.json\n * against the package name. For scoped packages, the scope can optionally\n * be stripped based on the `stripScopes` configuration.\n *\n * For example:\n * - `packages/my-lib/package.json` with name `my-lib` ✓\n * - `packages/my-lib/package.json` with name `@myorg/my-lib` ✓ (if @myorg in stripScopes)\n * - `packages/wrong-name/package.json` with name `my-lib` ✗\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageFolderName } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackageFolderName, {\n * stripScopes: [\"@myorg\", \"@internal\"],\n * excludePackages: [\"@myorg/special-case\"],\n * }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackageFolderName = definePackagePolicy<\n\tPackageJson,\n\tPackageFolderNameConfig | undefined\n>({\n\tname: \"PackageFolderName\",\n\tdescription:\n\t\t\"Ensures package folder names match package names for consistent file structure.\",\n\thandler: async (json, { file, config }) => {\n\t\t// If no config provided, use defaults (check all packages)\n\t\tconst effectiveConfig = config ?? {};\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// Skip explicitly excluded packages\n\t\tif (effectiveConfig.excludePackages?.includes(packageName)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Get the folder name (parent directory of package.json)\n\t\tconst folderName = path.basename(path.dirname(file));\n\n\t\t// Get the expected folder name\n\t\tconst expectedFolderName = getExpectedFolderName(\n\t\t\tpackageName,\n\t\t\teffectiveConfig.stripScopes ?? [],\n\t\t);\n\n\t\t// Compare folder name to expected name\n\t\tif (folderName === expectedFolderName) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Mismatch - build error message\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageFolderName.name,\n\t\t\tfile,\n\t\t\tautoFixable: false, // Can't auto-fix folder names\n\t\t\terrorMessages: [\n\t\t\t\t`Package folder \"${folderName}\" does not match package name \"${packageName}\". Expected folder name: \"${expectedFolderName}\"`,\n\t\t\t],\n\t\t};\n\t\treturn failResult;\n\t},\n});\n"]}
1
+ {"version":3,"file":"PackageFolderName.js","sourceRoot":"","sources":["../../src/policies/PackageFolderName.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,SAAS,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgE3D;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,KAAa,EAAE,WAAqB;IAC7D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAC7B,WAAmB,EACnB,WAAqB;IAErB,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAE9D,gEAAgE;IAChE,IAAI,KAAK,KAAK,SAAS,IAAI,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC;QACjE,OAAO,YAAY,CAAC;IACrB,CAAC;IAED,8EAA8E;IAC9E,OAAO,WAAW,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAGlD;IACD,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,iFAAiF;IAClF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzC,2DAA2D;QAC3D,MAAM,eAAe,GAAG,MAAM,IAAI,EAAE,CAAC;QAErC,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,oCAAoC;QACpC,IAAI,eAAe,CAAC,eAAe,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,CAAC;QACX,CAAC;QAED,yDAAyD;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAErD,+BAA+B;QAC/B,MAAM,kBAAkB,GAAG,qBAAqB,CAC/C,WAAW,EACX,eAAe,CAAC,WAAW,IAAI,EAAE,CACjC,CAAC;QAEF,uCAAuC;QACvC,IAAI,UAAU,KAAK,kBAAkB,EAAE,CAAC;YACvC,OAAO,EAAE,CAAC;QACX,CAAC;QAED,iCAAiC;QACjC,MAAM,UAAU,GAAoB;YACnC,mBAAmB,UAAU,kCAAkC,WAAW,6BAA6B,kBAAkB,GAAG;SAC5H,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAClC,OAAO,UAAU,CAAC;IACnB,CAAC;CACD,CAAC,CAAC","sourcesContent":["import path from \"pathe\";\nimport picomatch from \"picomatch\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFinding } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\nimport { parsePackageName } from \"../utils/packageName.js\";\n\n/**\n * Configuration for the PackageFolderName policy.\n *\n * This policy ensures that package folder names match their package names,\n * promoting consistency and making packages easier to find in the file system.\n *\n * @example\n * ```typescript\n * const config: PackageFolderNameConfig = {\n * // Strip all scopes when matching folder names\n * stripScopes: [\"@*\"],\n * // Or strip specific scopes\n * stripScopes: [\"@myorg\", \"@internal\"],\n * // These packages are exempt from the check\n * excludePackages: [\"@myorg/special-name\"],\n * };\n * ```\n *\n * @public\n */\nexport interface PackageFolderNameConfig {\n\t/**\n\t * A list of npm scope patterns to strip when comparing folder names to package names.\n\t *\n\t * For scoped packages like `@myorg/my-package`, if `@myorg` matches a pattern in this list,\n\t * the policy will expect the folder to be named `my-package` (not `@myorg/my-package`).\n\t *\n\t * @remarks\n\t *\n\t * Supports glob patterns:\n\t * - `@*` - matches all scopes\n\t * - `@myorg` - matches exactly `@myorg`\n\t * - `@my*` - matches scopes starting with `@my`\n\t *\n\t * @example\n\t * ```typescript\n\t * // Strip all scopes - @anything/my-package → folder \"my-package\"\n\t * stripScopes: [\"@*\"]\n\t *\n\t * // Strip specific scopes only\n\t * stripScopes: [\"@myorg\", \"@internal\"]\n\t *\n\t * // Strip scopes matching a pattern\n\t * stripScopes: [\"@fluid*\"]\n\t * ```\n\t */\n\tstripScopes?: string[];\n\n\t/**\n\t * A list of package names that are exempt from folder name matching.\n\t *\n\t * Use this for packages that intentionally have different folder names,\n\t * such as legacy packages or packages with special naming requirements.\n\t *\n\t * @example\n\t * ```typescript\n\t * excludePackages: [\"@myorg/cli\", \"legacy-package\"]\n\t * ```\n\t */\n\texcludePackages?: string[];\n}\n\n/**\n * Check if a scope should be stripped based on the patterns.\n *\n * @param scope - The scope to check (e.g., `@myorg`)\n * @param stripScopes - List of scope patterns to match (supports glob patterns via picomatch)\n * @returns `true` if the scope matches any pattern\n */\nfunction shouldStripScope(scope: string, stripScopes: string[]): boolean {\n\tif (stripScopes.length === 0) {\n\t\treturn false;\n\t}\n\n\treturn picomatch.isMatch(scope, stripScopes);\n}\n\n/**\n * Get the expected folder name from a package name.\n *\n * @param packageName - The package name (e.g., `@myorg/my-package`)\n * @param stripScopes - Scope patterns to strip from the package name\n * @returns The expected folder name\n */\nfunction getExpectedFolderName(\n\tpackageName: string,\n\tstripScopes: string[],\n): string {\n\tconst { scope, unscopedName } = parsePackageName(packageName);\n\n\t// Check if the package is scoped and should have scope stripped\n\tif (scope !== undefined && shouldStripScope(scope, stripScopes)) {\n\t\treturn unscopedName;\n\t}\n\n\t// Return full package name for unscoped packages or scopes not in stripScopes\n\treturn packageName;\n}\n\n/**\n * A policy that ensures package folder names match package names.\n *\n * This policy helps maintain a consistent and predictable file structure\n * in monorepos by ensuring that folder names correspond to package names.\n * This makes it easier to locate packages in the file system.\n *\n * @remarks\n *\n * The policy compares the immediate parent folder name of the package.json\n * against the package name. For scoped packages, the scope can optionally\n * be stripped based on the `stripScopes` configuration.\n *\n * For example:\n * - `packages/my-lib/package.json` with name `my-lib` ✓\n * - `packages/my-lib/package.json` with name `@myorg/my-lib` ✓ (if `@myorg` is in `stripScopes`)\n * - `packages/wrong-name/package.json` with name `my-lib` ✗\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageFolderName } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackageFolderName, {\n * config: {\n * stripScopes: [\"@myorg\", \"@internal\"],\n * excludePackages: [\"@myorg/special-case\"],\n * },\n * }),\n * ],\n * };\n * ```\n *\n * @public\n */\nexport const PackageFolderName = definePackagePolicy<\n\tPackageJson,\n\tPackageFolderNameConfig | undefined\n>({\n\tname: \"PackageFolderName\",\n\tdescription:\n\t\t\"Ensures package folder names match package names for consistent file structure.\",\n\thandler: async (json, { file, config }) => {\n\t\t// If no config provided, use defaults (check all packages)\n\t\tconst effectiveConfig = config ?? {};\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// Skip explicitly excluded packages\n\t\tif (effectiveConfig.excludePackages?.includes(packageName)) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Get the folder name (parent directory of package.json)\n\t\tconst folderName = path.basename(path.dirname(file));\n\n\t\t// Get the expected folder name\n\t\tconst expectedFolderName = getExpectedFolderName(\n\t\t\tpackageName,\n\t\t\teffectiveConfig.stripScopes ?? [],\n\t\t);\n\n\t\t// Compare folder name to expected name\n\t\tif (folderName === expectedFolderName) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Mismatch - build error message\n\t\tconst failResult: PolicyFinding[] = [\n\t\t\t`Package folder \"${folderName}\" does not match package name \"${packageName}\". Expected folder name: \"${expectedFolderName}\"`,\n\t\t].map((message) => ({ message }));\n\t\treturn failResult;\n\t},\n});\n"]}
@@ -2,7 +2,7 @@ import type { PackageJson } from "type-fest";
2
2
  /**
3
3
  * Policy settings for the PackageJsonProperties repo policy.
4
4
  *
5
- * @alpha
5
+ * @public
6
6
  */
7
7
  export interface PackageJsonPropertiesSettings {
8
8
  /**
@@ -13,7 +13,9 @@ export interface PackageJsonPropertiesSettings {
13
13
  /**
14
14
  * A RepoPolicy that checks that package.json properties in packages match expected values.
15
15
  *
16
- * @alpha
16
+ * @public
17
17
  */
18
- export declare const PackageJsonProperties: import("../policy.js").PolicyShape<PackageJsonPropertiesSettings | undefined>;
18
+ export declare const PackageJsonProperties: import("../policy.js").FilePolicyDefinition<PackageJsonPropertiesSettings> & {
19
+ requiresConfig: true;
20
+ };
19
21
  //# sourceMappingURL=PackageJsonProperties.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageJsonProperties.d.ts","sourceRoot":"","sources":["../../src/policies/PackageJsonProperties.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAc7C;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC7C;;OAEG;IACH,QAAQ,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,+EAoDhC,CAAC"}
1
+ {"version":3,"file":"PackageJsonProperties.d.ts","sourceRoot":"","sources":["../../src/policies/PackageJsonProperties.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAa7C;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC7C;;OAEG;IACH,QAAQ,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;CAoChC,CAAC"}
@@ -15,22 +15,17 @@ const mergeProperties = createDefu((object, key, value) => {
15
15
  /**
16
16
  * A RepoPolicy that checks that package.json properties in packages match expected values.
17
17
  *
18
- * @alpha
18
+ * @public
19
19
  */
20
20
  export const PackageJsonProperties = definePackagePolicy({
21
21
  name: "PackageJsonProperties",
22
22
  description: "Ensures package.json files contain required properties with correct values.",
23
+ requiresConfig: true,
23
24
  handler: function* (json, { file, root, config, resolve }) {
24
25
  if (config === undefined) {
25
- return true;
26
+ throw new TypeError("PackageJsonProperties requires config.");
26
27
  }
27
28
  const { verbatim } = config;
28
- const failResult = {
29
- name: PackageJsonProperties.name,
30
- file,
31
- autoFixable: true,
32
- errorMessages: [],
33
- };
34
29
  const merged = mergeProperties(verbatim, json);
35
30
  const result = diff(merged, json);
36
31
  const messages = [];
@@ -39,19 +34,13 @@ export const PackageJsonProperties = definePackagePolicy({
39
34
  }
40
35
  if (messages.length > 0) {
41
36
  if (resolve) {
42
- const fixResult = {
43
- ...failResult,
44
- resolved: false,
45
- };
46
37
  yield* call(() => writeJson(resolvePath(root, file), merged, { spaces: "\t" }));
47
- fixResult.resolved = true;
48
- return fixResult;
38
+ return messages.map((message) => ({ message, fixStatus: "fixed" }));
49
39
  }
50
40
  // There were errors, and we're not resolving them, so return a fail result
51
- failResult.errorMessages = messages;
52
- return failResult;
41
+ return messages.map((message) => ({ message, fixStatus: "available" }));
53
42
  }
54
- return true;
43
+ return [];
55
44
  },
56
45
  });
57
46
  //# sourceMappingURL=PackageJsonProperties.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageJsonProperties.js","sourceRoot":"","sources":["../../src/policies/PackageJsonProperties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAG/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;AAE1C,MAAM,eAAe,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC,CAAC;AAcH;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAGtD;IACD,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACV,6EAA6E;IAC9E,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;QAE5B,MAAM,UAAU,GAAkB;YACjC,IAAI,EAAE,qBAAqB,CAAC,IAAI;YAChC,IAAI;YACJ,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,EAAE;SACjB,CAAC;QAEF,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CACZ,2CAA2C,UAAU,CAAC,IAAI,IAAI,CAC9D,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,OAAO,EAAE,CAAC;gBACb,MAAM,SAAS,GAAoB;oBAClC,GAAG,UAAU;oBACb,QAAQ,EAAE,KAAK;iBACf,CAAC;gBAEF,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAChB,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAC5D,CAAC;gBAEF,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC;gBAC1B,OAAO,SAAS,CAAC;YAClB,CAAC;YAED,2EAA2E;YAC3E,UAAU,CAAC,aAAa,GAAG,QAAQ,CAAC;YACpC,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { createDefu } from \"defu\";\nimport { call } from \"effection\";\nimport jsonfile from \"jsonfile\";\nimport diff from \"microdiff\";\nimport { resolve as resolvePath } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\nconst { writeFile: writeJson } = jsonfile;\n\nconst mergeProperties = createDefu((object, key, value) => {\n\tif (Array.isArray(value)) {\n\t\tobject[key] = value;\n\t\treturn true;\n\t}\n\treturn false;\n});\n\n/**\n * Policy settings for the PackageJsonProperties repo policy.\n *\n * @alpha\n */\nexport interface PackageJsonPropertiesSettings {\n\t/**\n\t * Sets a package.json property to the value provided. The value will be used verbatim.\n\t */\n\tverbatim: PackageJson;\n}\n\n/**\n * A RepoPolicy that checks that package.json properties in packages match expected values.\n *\n * @alpha\n */\nexport const PackageJsonProperties = definePackagePolicy<\n\tPackageJson,\n\tPackageJsonPropertiesSettings | undefined\n>({\n\tname: \"PackageJsonProperties\",\n\tdescription:\n\t\t\"Ensures package.json files contain required properties with correct values.\",\n\thandler: function* (json, { file, root, config, resolve }) {\n\t\tif (config === undefined) {\n\t\t\treturn true;\n\t\t}\n\t\tconst { verbatim } = config;\n\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageJsonProperties.name,\n\t\t\tfile,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [],\n\t\t};\n\n\t\tconst merged = mergeProperties(verbatim, json);\n\t\tconst result = diff(merged, json);\n\n\t\tconst messages: string[] = [];\n\t\tfor (const diffResult of result) {\n\t\t\tmessages.push(\n\t\t\t\t`Incorrect package.json field value for '${diffResult.path}'.`,\n\t\t\t);\n\t\t}\n\n\t\tif (messages.length > 0) {\n\t\t\tif (resolve) {\n\t\t\t\tconst fixResult: PolicyFixResult = {\n\t\t\t\t\t...failResult,\n\t\t\t\t\tresolved: false,\n\t\t\t\t};\n\n\t\t\t\tyield* call(() =>\n\t\t\t\t\twriteJson(resolvePath(root, file), merged, { spaces: \"\\t\" }),\n\t\t\t\t);\n\n\t\t\t\tfixResult.resolved = true;\n\t\t\t\treturn fixResult;\n\t\t\t}\n\n\t\t\t// There were errors, and we're not resolving them, so return a fail result\n\t\t\tfailResult.errorMessages = messages;\n\t\t\treturn failResult;\n\t\t}\n\n\t\treturn true;\n\t},\n});\n"]}
1
+ {"version":3,"file":"PackageJsonProperties.js","sourceRoot":"","sources":["../../src/policies/PackageJsonProperties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;AAE1C,MAAM,eAAe,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC,CAAC;AAcH;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAGtD;IACD,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACV,6EAA6E;IAC9E,cAAc,EAAE,IAAI;IACpB,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;QAC5B,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CACZ,2CAA2C,UAAU,CAAC,IAAI,IAAI,CAC9D,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,OAAO,EAAE,CAAC;gBACb,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAChB,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAC5D,CAAC;gBACF,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;YAED,2EAA2E;YAC3E,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,EAAE,CAAC;IACX,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { createDefu } from \"defu\";\nimport { call } from \"effection\";\nimport jsonfile from \"jsonfile\";\nimport diff from \"microdiff\";\nimport { resolve as resolvePath } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\nconst { writeFile: writeJson } = jsonfile;\n\nconst mergeProperties = createDefu((object, key, value) => {\n\tif (Array.isArray(value)) {\n\t\tobject[key] = value;\n\t\treturn true;\n\t}\n\treturn false;\n});\n\n/**\n * Policy settings for the PackageJsonProperties repo policy.\n *\n * @public\n */\nexport interface PackageJsonPropertiesSettings {\n\t/**\n\t * Sets a package.json property to the value provided. The value will be used verbatim.\n\t */\n\tverbatim: PackageJson;\n}\n\n/**\n * A RepoPolicy that checks that package.json properties in packages match expected values.\n *\n * @public\n */\nexport const PackageJsonProperties = definePackagePolicy<\n\tPackageJson,\n\tPackageJsonPropertiesSettings\n>({\n\tname: \"PackageJsonProperties\",\n\tdescription:\n\t\t\"Ensures package.json files contain required properties with correct values.\",\n\trequiresConfig: true,\n\thandler: function* (json, { file, root, config, resolve }) {\n\t\tif (config === undefined) {\n\t\t\tthrow new TypeError(\"PackageJsonProperties requires config.\");\n\t\t}\n\t\tconst { verbatim } = config;\n\t\tconst merged = mergeProperties(verbatim, json);\n\t\tconst result = diff(merged, json);\n\n\t\tconst messages: string[] = [];\n\t\tfor (const diffResult of result) {\n\t\t\tmessages.push(\n\t\t\t\t`Incorrect package.json field value for '${diffResult.path}'.`,\n\t\t\t);\n\t\t}\n\n\t\tif (messages.length > 0) {\n\t\t\tif (resolve) {\n\t\t\t\tyield* call(() =>\n\t\t\t\t\twriteJson(resolvePath(root, file), merged, { spaces: \"\\t\" }),\n\t\t\t\t);\n\t\t\t\treturn messages.map((message) => ({ message, fixStatus: \"fixed\" }));\n\t\t\t}\n\n\t\t\t// There were errors, and we're not resolving them, so return a fail result\n\t\t\treturn messages.map((message) => ({ message, fixStatus: \"available\" }));\n\t\t}\n\t\treturn [];\n\t},\n});\n"]}
@@ -1,8 +1,3 @@
1
- /**
2
- * A RepoPolicy that checks that the repository.directory property in package.json is set correctly. If the repository
3
- * field is a string instead of an object the package will be ignored.
4
- *
5
- * @alpha
6
- */
7
- export declare const PackageJsonRepoDirectoryProperty: import("../policy.js").PolicyShape<undefined>;
1
+ /** Ensures repository.directory matches each package's repository-relative directory. @public */
2
+ export declare const PackageJsonRepoDirectoryProperty: import("../policy.js").FilePolicyDefinition<void>;
8
3
  //# sourceMappingURL=PackageJsonRepoDirectoryProperty.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageJsonRepoDirectoryProperty.d.ts","sourceRoot":"","sources":["../../src/policies/PackageJsonRepoDirectoryProperty.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,+CAwD3C,CAAC"}
1
+ {"version":3,"file":"PackageJsonRepoDirectoryProperty.d.ts","sourceRoot":"","sources":["../../src/policies/PackageJsonRepoDirectoryProperty.ts"],"names":[],"mappings":"AAKA,iGAAiG;AACjG,eAAO,MAAM,gCAAgC,mDAqC3C,CAAC"}
@@ -2,55 +2,41 @@ import assert from "node:assert/strict";
2
2
  import { updatePackageJsonFile } from "@fluid-tools/build-infrastructure";
3
3
  import path from "pathe";
4
4
  import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
5
- /**
6
- * A RepoPolicy that checks that the repository.directory property in package.json is set correctly. If the repository
7
- * field is a string instead of an object the package will be ignored.
8
- *
9
- * @alpha
10
- */
5
+ /** Ensures repository.directory matches each package's repository-relative directory. @public */
11
6
  export const PackageJsonRepoDirectoryProperty = definePackagePolicy({
12
7
  name: "PackageJsonRepoDirectoryProperty",
13
8
  description: "Ensures the repository.directory property in package.json is set correctly for monorepo packages.",
14
- handler: function* (json, { file, root, resolve }) {
15
- const failResult = {
16
- name: PackageJsonRepoDirectoryProperty.name,
17
- file,
18
- autoFixable: true,
19
- errorMessages: [],
20
- };
21
- const fixResult = {
22
- ...failResult,
23
- resolved: false,
24
- };
9
+ handler: async (json, { file, root, resolve }) => {
25
10
  const packageJsonPath = path.resolve(root, file);
26
- const pkgDir = path.dirname(packageJsonPath);
27
- const maybeDir = path.relative(root, pkgDir);
28
- const relativePkgDir = maybeDir === "" ? undefined : maybeDir;
29
- if (typeof json.repository === "object" &&
30
- json.repository.directory !== relativePkgDir) {
31
- if (resolve) {
32
- try {
33
- updatePackageJsonFile(packageJsonPath, (pkgJson) => {
34
- assert(typeof pkgJson.repository === "object");
35
- if (relativePkgDir === undefined) {
36
- delete pkgJson.repository.directory;
37
- }
38
- else {
39
- pkgJson.repository.directory = relativePkgDir;
40
- }
41
- });
42
- fixResult.resolved = true;
11
+ const directory = path.relative(root, path.dirname(packageJsonPath)) || undefined;
12
+ if (typeof json.repository !== "object" ||
13
+ json.repository.directory === directory) {
14
+ return [];
15
+ }
16
+ const message = `repository.directory value is wrong. Expected '${directory}', got '${json.repository.directory}'`;
17
+ if (!resolve) {
18
+ return [{ message, fixStatus: "available" }];
19
+ }
20
+ try {
21
+ updatePackageJsonFile(packageJsonPath, (pkg) => {
22
+ assert(typeof pkg.repository === "object");
23
+ if (directory === undefined) {
24
+ delete pkg.repository.directory;
43
25
  }
44
- catch (error) {
45
- fixResult.resolved = false;
46
- fixResult.errorMessages.push(`${error.message}\n${error.stack}`);
26
+ else {
27
+ pkg.repository.directory = directory;
47
28
  }
48
- return fixResult;
49
- }
50
- failResult.errorMessages.push(`repository.directory value is wrong. Expected '${relativePkgDir}', got '${json.repository.directory}'`);
51
- return failResult;
29
+ });
30
+ }
31
+ catch (error) {
32
+ return [
33
+ {
34
+ message: `${message}: ${error instanceof Error ? error.message : String(error)}`,
35
+ fixStatus: "failed",
36
+ },
37
+ ];
52
38
  }
53
- return true;
39
+ return [{ message, fixStatus: "fixed" }];
54
40
  },
55
41
  });
56
42
  //# sourceMappingURL=PackageJsonRepoDirectoryProperty.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageJsonRepoDirectoryProperty.js","sourceRoot":"","sources":["../../src/policies/PackageJsonRepoDirectoryProperty.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,IAAI,MAAM,OAAO,CAAC;AAGzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,mBAAmB,CAGjE;IACD,IAAI,EAAE,kCAAkC;IACxC,WAAW,EACV,mGAAmG;IACpG,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;QAChD,MAAM,UAAU,GAAkB;YACjC,IAAI,EAAE,gCAAgC,CAAC,IAAI;YAC3C,IAAI;YACJ,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,EAAE;SACjB,CAAC;QAEF,MAAM,SAAS,GAAoB;YAClC,GAAG,UAAU;YACb,QAAQ,EAAE,KAAK;SACf,CAAC;QAEF,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;QAE9D,IACC,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;YACnC,IAAI,CAAC,UAAU,CAAC,SAAS,KAAK,cAAc,EAC3C,CAAC;YACF,IAAI,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC;oBACJ,qBAAqB,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE;wBAClD,MAAM,CAAC,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC;wBAC/C,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;4BAClC,OAAO,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC;wBACrC,CAAC;6BAAM,CAAC;4BACP,OAAO,CAAC,UAAU,CAAC,SAAS,GAAG,cAAc,CAAC;wBAC/C,CAAC;oBACF,CAAC,CAAC,CAAC;oBACH,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC;gBAC3B,CAAC;gBAAC,OAAO,KAAc,EAAE,CAAC;oBACzB,SAAS,CAAC,QAAQ,GAAG,KAAK,CAAC;oBAC3B,SAAS,CAAC,aAAa,CAAC,IAAI,CAC3B,GAAI,KAAe,CAAC,OAAO,KAAM,KAAe,CAAC,KAAK,EAAE,CACxD,CAAC;gBACH,CAAC;gBACD,OAAO,SAAS,CAAC;YAClB,CAAC;YACD,UAAU,CAAC,aAAa,CAAC,IAAI,CAC5B,kDAAkD,cAAc,WAAW,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG,CACvG,CAAC;YACF,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport { updatePackageJsonFile } from \"@fluid-tools/build-infrastructure\";\nimport path from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * A RepoPolicy that checks that the repository.directory property in package.json is set correctly. If the repository\n * field is a string instead of an object the package will be ignored.\n *\n * @alpha\n */\nexport const PackageJsonRepoDirectoryProperty = definePackagePolicy<\n\tPackageJson,\n\tundefined\n>({\n\tname: \"PackageJsonRepoDirectoryProperty\",\n\tdescription:\n\t\t\"Ensures the repository.directory property in package.json is set correctly for monorepo packages.\",\n\thandler: function* (json, { file, root, resolve }) {\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageJsonRepoDirectoryProperty.name,\n\t\t\tfile,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [],\n\t\t};\n\n\t\tconst fixResult: PolicyFixResult = {\n\t\t\t...failResult,\n\t\t\tresolved: false,\n\t\t};\n\n\t\tconst packageJsonPath = path.resolve(root, file);\n\t\tconst pkgDir = path.dirname(packageJsonPath);\n\t\tconst maybeDir = path.relative(root, pkgDir);\n\t\tconst relativePkgDir = maybeDir === \"\" ? undefined : maybeDir;\n\n\t\tif (\n\t\t\ttypeof json.repository === \"object\" &&\n\t\t\tjson.repository.directory !== relativePkgDir\n\t\t) {\n\t\t\tif (resolve) {\n\t\t\t\ttry {\n\t\t\t\t\tupdatePackageJsonFile(packageJsonPath, (pkgJson) => {\n\t\t\t\t\t\tassert(typeof pkgJson.repository === \"object\");\n\t\t\t\t\t\tif (relativePkgDir === undefined) {\n\t\t\t\t\t\t\tdelete pkgJson.repository.directory;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tpkgJson.repository.directory = relativePkgDir;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tfixResult.resolved = true;\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tfixResult.resolved = false;\n\t\t\t\t\tfixResult.errorMessages.push(\n\t\t\t\t\t\t`${(error as Error).message}\\n${(error as Error).stack}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn fixResult;\n\t\t\t}\n\t\t\tfailResult.errorMessages.push(\n\t\t\t\t`repository.directory value is wrong. Expected '${relativePkgDir}', got '${json.repository.directory}'`,\n\t\t\t);\n\t\t\treturn failResult;\n\t\t}\n\n\t\treturn true;\n\t},\n});\n"]}
1
+ {"version":3,"file":"PackageJsonRepoDirectoryProperty.js","sourceRoot":"","sources":["../../src/policies/PackageJsonRepoDirectoryProperty.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E,iGAAiG;AACjG,MAAM,CAAC,MAAM,gCAAgC,GAAG,mBAAmB,CAAC;IACnE,IAAI,EAAE,kCAAkC;IACxC,WAAW,EACV,mGAAmG;IACpG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QAChD,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,SAAS,GACd,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,IAAI,SAAS,CAAC;QACjE,IACC,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;YACnC,IAAI,CAAC,UAAU,CAAC,SAAS,KAAK,SAAS,EACtC,CAAC;YACF,OAAO,EAAE,CAAC;QACX,CAAC;QACD,MAAM,OAAO,GAAG,kDAAkD,SAAS,WAAW,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG,CAAC;QACnH,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC;YACJ,qBAAqB,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC9C,MAAM,CAAC,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC;gBAC3C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;oBAC7B,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;gBACjC,CAAC;qBAAM,CAAC;oBACP,GAAG,CAAC,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC;gBACtC,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,OAAO;gBACN;oBACC,OAAO,EAAE,GAAG,OAAO,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;oBAChF,SAAS,EAAE,QAAQ;iBACnB;aACD,CAAC;QACH,CAAC;QACD,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;CACD,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport { updatePackageJsonFile } from \"@fluid-tools/build-infrastructure\";\nimport path from \"pathe\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/** Ensures repository.directory matches each package's repository-relative directory. @public */\nexport const PackageJsonRepoDirectoryProperty = definePackagePolicy({\n\tname: \"PackageJsonRepoDirectoryProperty\",\n\tdescription:\n\t\t\"Ensures the repository.directory property in package.json is set correctly for monorepo packages.\",\n\thandler: async (json, { file, root, resolve }) => {\n\t\tconst packageJsonPath = path.resolve(root, file);\n\t\tconst directory =\n\t\t\tpath.relative(root, path.dirname(packageJsonPath)) || undefined;\n\t\tif (\n\t\t\ttypeof json.repository !== \"object\" ||\n\t\t\tjson.repository.directory === directory\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\tconst message = `repository.directory value is wrong. Expected '${directory}', got '${json.repository.directory}'`;\n\t\tif (!resolve) {\n\t\t\treturn [{ message, fixStatus: \"available\" }];\n\t\t}\n\t\ttry {\n\t\t\tupdatePackageJsonFile(packageJsonPath, (pkg) => {\n\t\t\t\tassert(typeof pkg.repository === \"object\");\n\t\t\t\tif (directory === undefined) {\n\t\t\t\t\tdelete pkg.repository.directory;\n\t\t\t\t} else {\n\t\t\t\t\tpkg.repository.directory = directory;\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error: unknown) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tmessage: `${message}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tfixStatus: \"failed\",\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn [{ message, fixStatus: \"fixed\" }];\n\t},\n});\n"]}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * A repo policy that checks if package.json files in the repo are sorted using sort-package-json.
3
3
  *
4
- * @alpha
4
+ * @public
5
5
  */
6
- export declare const PackageJsonSorted: import("../policy.js").PolicyShape<undefined>;
6
+ export declare const PackageJsonSorted: import("../policy.js").FilePolicyDefinition<void>;
7
7
  //# sourceMappingURL=PackageJsonSorted.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageJsonSorted.d.ts","sourceRoot":"","sources":["../../src/policies/PackageJsonSorted.ts"],"names":[],"mappings":"AAwCA;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,+CA0D5B,CAAC"}
1
+ {"version":3,"file":"PackageJsonSorted.d.ts","sourceRoot":"","sources":["../../src/policies/PackageJsonSorted.ts"],"names":[],"mappings":"AAwCA;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,mDA6C5B,CAAC"}