repopo 0.9.0 → 0.12.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 (271) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +41 -2
  3. package/THIRD-PARTY-LICENSES.txt +71 -11
  4. package/bin/dev.js +5 -1
  5. package/esm/baseCommand.d.ts +1 -1
  6. package/esm/baseCommand.d.ts.map +1 -1
  7. package/esm/baseCommand.js +6 -9
  8. package/esm/baseCommand.js.map +1 -1
  9. package/esm/commands/check-native.d.ts +25 -0
  10. package/esm/commands/check-native.d.ts.map +1 -0
  11. package/esm/commands/check-native.js +137 -0
  12. package/esm/commands/check-native.js.map +1 -0
  13. package/esm/commands/check.d.ts +8 -19
  14. package/esm/commands/check.d.ts.map +1 -1
  15. package/esm/commands/check.js +97 -169
  16. package/esm/commands/check.js.map +1 -1
  17. package/esm/commands/list.d.ts.map +1 -1
  18. package/esm/commands/list.js +5 -6
  19. package/esm/commands/list.js.map +1 -1
  20. package/esm/config.d.ts +19 -4
  21. package/esm/config.d.ts.map +1 -1
  22. package/esm/config.js +2 -3
  23. package/esm/config.js.map +1 -1
  24. package/esm/context.d.ts +13 -3
  25. package/esm/context.d.ts.map +1 -1
  26. package/esm/context.js +11 -1
  27. package/esm/context.js.map +1 -1
  28. package/esm/index.d.ts +7 -2
  29. package/esm/index.d.ts.map +1 -1
  30. package/esm/index.js +9 -1
  31. package/esm/index.js.map +1 -1
  32. package/esm/makePolicy.d.ts +77 -8
  33. package/esm/makePolicy.d.ts.map +1 -1
  34. package/esm/makePolicy.js +108 -4
  35. package/esm/makePolicy.js.map +1 -1
  36. package/esm/perf.d.ts +7 -2
  37. package/esm/perf.d.ts.map +1 -1
  38. package/esm/perf.js.map +1 -1
  39. package/esm/policies/CargoLicenceValidated.d.ts +41 -0
  40. package/esm/policies/CargoLicenceValidated.d.ts.map +1 -0
  41. package/esm/policies/CargoLicenceValidated.js +45 -0
  42. package/esm/policies/CargoLicenceValidated.js.map +1 -0
  43. package/esm/policies/CargoLintsConfigured.d.ts +30 -0
  44. package/esm/policies/CargoLintsConfigured.d.ts.map +1 -0
  45. package/esm/policies/CargoLintsConfigured.js +61 -0
  46. package/esm/policies/CargoLintsConfigured.js.map +1 -0
  47. package/esm/policies/CargoLockPolicy.d.ts +34 -0
  48. package/esm/policies/CargoLockPolicy.d.ts.map +1 -0
  49. package/esm/policies/CargoLockPolicy.js +57 -0
  50. package/esm/policies/CargoLockPolicy.js.map +1 -0
  51. package/esm/policies/CargoTomlRequired.d.ts +34 -0
  52. package/esm/policies/CargoTomlRequired.d.ts.map +1 -0
  53. package/esm/policies/CargoTomlRequired.js +77 -0
  54. package/esm/policies/CargoTomlRequired.js.map +1 -0
  55. package/esm/policies/CargoTomlSorted.d.ts +20 -0
  56. package/esm/policies/CargoTomlSorted.d.ts.map +1 -0
  57. package/esm/policies/CargoTomlSorted.js +164 -0
  58. package/esm/policies/CargoTomlSorted.js.map +1 -0
  59. package/esm/policies/ConditionalScripts.d.ts +94 -0
  60. package/esm/policies/ConditionalScripts.d.ts.map +1 -0
  61. package/esm/policies/ConditionalScripts.js +145 -0
  62. package/esm/policies/ConditionalScripts.js.map +1 -0
  63. package/esm/policies/ExactScripts.d.ts +51 -0
  64. package/esm/policies/ExactScripts.d.ts.map +1 -0
  65. package/esm/policies/ExactScripts.js +108 -0
  66. package/esm/policies/ExactScripts.js.map +1 -0
  67. package/esm/policies/GleamDepVersions.d.ts +25 -0
  68. package/esm/policies/GleamDepVersions.d.ts.map +1 -0
  69. package/esm/policies/GleamDepVersions.js +67 -0
  70. package/esm/policies/GleamDepVersions.js.map +1 -0
  71. package/esm/policies/GleamDocExists.d.ts +24 -0
  72. package/esm/policies/GleamDocExists.d.ts.map +1 -0
  73. package/esm/policies/GleamDocExists.js +39 -0
  74. package/esm/policies/GleamDocExists.js.map +1 -0
  75. package/esm/policies/GleamInternalModulesConfigured.d.ts +21 -0
  76. package/esm/policies/GleamInternalModulesConfigured.d.ts.map +1 -0
  77. package/esm/policies/GleamInternalModulesConfigured.js +30 -0
  78. package/esm/policies/GleamInternalModulesConfigured.js.map +1 -0
  79. package/esm/policies/GleamLicenceConfigured.d.ts +29 -0
  80. package/esm/policies/GleamLicenceConfigured.d.ts.map +1 -0
  81. package/esm/policies/GleamLicenceConfigured.js +34 -0
  82. package/esm/policies/GleamLicenceConfigured.js.map +1 -0
  83. package/esm/policies/GleamManifestCommitted.d.ts +9 -0
  84. package/esm/policies/GleamManifestCommitted.d.ts.map +1 -0
  85. package/esm/policies/GleamManifestCommitted.js +26 -0
  86. package/esm/policies/GleamManifestCommitted.js.map +1 -0
  87. package/esm/policies/GleamMonorepoConsistency.d.ts +30 -0
  88. package/esm/policies/GleamMonorepoConsistency.d.ts.map +1 -0
  89. package/esm/policies/GleamMonorepoConsistency.js +74 -0
  90. package/esm/policies/GleamMonorepoConsistency.js.map +1 -0
  91. package/esm/policies/GleamNameRestrictions.d.ts +25 -0
  92. package/esm/policies/GleamNameRestrictions.d.ts.map +1 -0
  93. package/esm/policies/GleamNameRestrictions.js +44 -0
  94. package/esm/policies/GleamNameRestrictions.js.map +1 -0
  95. package/esm/policies/GleamNoPathDepsInPublished.d.ts +22 -0
  96. package/esm/policies/GleamNoPathDepsInPublished.d.ts.map +1 -0
  97. package/esm/policies/GleamNoPathDepsInPublished.js +43 -0
  98. package/esm/policies/GleamNoPathDepsInPublished.js.map +1 -0
  99. package/esm/policies/GleamPathDepsValid.d.ts +9 -0
  100. package/esm/policies/GleamPathDepsValid.d.ts.map +1 -0
  101. package/esm/policies/GleamPathDepsValid.js +59 -0
  102. package/esm/policies/GleamPathDepsValid.js.map +1 -0
  103. package/esm/policies/GleamProjectStructure.d.ts +25 -0
  104. package/esm/policies/GleamProjectStructure.d.ts.map +1 -0
  105. package/esm/policies/GleamProjectStructure.js +33 -0
  106. package/esm/policies/GleamProjectStructure.js.map +1 -0
  107. package/esm/policies/GleamSharedDependencyVersions.d.ts +29 -0
  108. package/esm/policies/GleamSharedDependencyVersions.d.ts.map +1 -0
  109. package/esm/policies/GleamSharedDependencyVersions.js +101 -0
  110. package/esm/policies/GleamSharedDependencyVersions.js.map +1 -0
  111. package/esm/policies/GleamTomlRequired.d.ts +30 -0
  112. package/esm/policies/GleamTomlRequired.d.ts.map +1 -0
  113. package/esm/policies/GleamTomlRequired.js +37 -0
  114. package/esm/policies/GleamTomlRequired.js.map +1 -0
  115. package/esm/policies/GleamTomlSorted.d.ts +20 -0
  116. package/esm/policies/GleamTomlSorted.d.ts.map +1 -0
  117. package/esm/policies/GleamTomlSorted.js +153 -0
  118. package/esm/policies/GleamTomlSorted.js.map +1 -0
  119. package/esm/policies/GleamVersionConstraint.d.ts +20 -0
  120. package/esm/policies/GleamVersionConstraint.d.ts.map +1 -0
  121. package/esm/policies/GleamVersionConstraint.js +64 -0
  122. package/esm/policies/GleamVersionConstraint.js.map +1 -0
  123. package/esm/policies/HtmlFileHeaders.d.ts +1 -1
  124. package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
  125. package/esm/policies/HtmlFileHeaders.js +1 -1
  126. package/esm/policies/HtmlFileHeaders.js.map +1 -1
  127. package/esm/policies/JsTsFileHeaders.d.ts +1 -1
  128. package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
  129. package/esm/policies/MutuallyExclusiveScripts.d.ts +46 -0
  130. package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -0
  131. package/esm/policies/MutuallyExclusiveScripts.js +52 -0
  132. package/esm/policies/MutuallyExclusiveScripts.js.map +1 -0
  133. package/esm/policies/NoBuildDirectory.d.ts +9 -0
  134. package/esm/policies/NoBuildDirectory.d.ts.map +1 -0
  135. package/esm/policies/NoBuildDirectory.js +29 -0
  136. package/esm/policies/NoBuildDirectory.js.map +1 -0
  137. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +1 -1
  138. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  139. package/esm/policies/NoTargetArtifacts.d.ts +8 -0
  140. package/esm/policies/NoTargetArtifacts.d.ts.map +1 -0
  141. package/esm/policies/NoTargetArtifacts.js +42 -0
  142. package/esm/policies/NoTargetArtifacts.js.map +1 -0
  143. package/esm/policies/NoUnsafeWithoutJustification.d.ts +24 -0
  144. package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -0
  145. package/esm/policies/NoUnsafeWithoutJustification.js +80 -0
  146. package/esm/policies/NoUnsafeWithoutJustification.js.map +1 -0
  147. package/esm/policies/NoWildcardDependencies.d.ts +30 -0
  148. package/esm/policies/NoWildcardDependencies.d.ts.map +1 -0
  149. package/esm/policies/NoWildcardDependencies.js +83 -0
  150. package/esm/policies/NoWildcardDependencies.js.map +1 -0
  151. package/esm/policies/PackageAllowedScopes.d.ts +1 -1
  152. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  153. package/esm/policies/PackageEsmType.d.ts +1 -1
  154. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  155. package/esm/policies/PackageEsmType.js +7 -5
  156. package/esm/policies/PackageEsmType.js.map +1 -1
  157. package/esm/policies/PackageFolderName.d.ts +1 -1
  158. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  159. package/esm/policies/PackageJsonProperties.d.ts +1 -1
  160. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  161. package/esm/policies/PackageJsonProperties.js +12 -4
  162. package/esm/policies/PackageJsonProperties.js.map +1 -1
  163. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +1 -1
  164. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  165. package/esm/policies/PackageJsonRepoDirectoryProperty.js +3 -2
  166. package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
  167. package/esm/policies/PackageJsonSorted.d.ts +1 -1
  168. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  169. package/esm/policies/PackageJsonSorted.js +42 -7
  170. package/esm/policies/PackageJsonSorted.js.map +1 -1
  171. package/esm/policies/PackageLicense.d.ts +1 -1
  172. package/esm/policies/PackageLicense.d.ts.map +1 -1
  173. package/esm/policies/PackageLicense.js +1 -2
  174. package/esm/policies/PackageLicense.js.map +1 -1
  175. package/esm/policies/PackagePrivateField.d.ts +1 -1
  176. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  177. package/esm/policies/PackagePrivateField.js +3 -2
  178. package/esm/policies/PackagePrivateField.js.map +1 -1
  179. package/esm/policies/PackageReadme.d.ts +1 -1
  180. package/esm/policies/PackageReadme.d.ts.map +1 -1
  181. package/esm/policies/PackageReadme.js +2 -2
  182. package/esm/policies/PackageReadme.js.map +1 -1
  183. package/esm/policies/PackageScripts.d.ts +1 -1
  184. package/esm/policies/PackageScripts.d.ts.map +1 -1
  185. package/esm/policies/PackageScripts.js +3 -2
  186. package/esm/policies/PackageScripts.js.map +1 -1
  187. package/esm/policies/PackageTestScripts.d.ts +1 -1
  188. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  189. package/esm/policies/PackageTestScripts.js +3 -3
  190. package/esm/policies/PackageTestScripts.js.map +1 -1
  191. package/esm/policies/PublicApiDocumented.d.ts +21 -0
  192. package/esm/policies/PublicApiDocumented.d.ts.map +1 -0
  193. package/esm/policies/PublicApiDocumented.js +36 -0
  194. package/esm/policies/PublicApiDocumented.js.map +1 -0
  195. package/esm/policies/RequiredScripts.d.ts +71 -0
  196. package/esm/policies/RequiredScripts.d.ts.map +1 -0
  197. package/esm/policies/RequiredScripts.js +121 -0
  198. package/esm/policies/RequiredScripts.js.map +1 -0
  199. package/esm/policies/RustDocExists.d.ts +24 -0
  200. package/esm/policies/RustDocExists.d.ts.map +1 -0
  201. package/esm/policies/RustDocExists.js +49 -0
  202. package/esm/policies/RustDocExists.js.map +1 -0
  203. package/esm/policies/RustToolchainExists.d.ts +20 -0
  204. package/esm/policies/RustToolchainExists.d.ts.map +1 -0
  205. package/esm/policies/RustToolchainExists.js +27 -0
  206. package/esm/policies/RustToolchainExists.js.map +1 -0
  207. package/esm/policies/RustfmtConfigExists.d.ts +20 -0
  208. package/esm/policies/RustfmtConfigExists.d.ts.map +1 -0
  209. package/esm/policies/RustfmtConfigExists.js +27 -0
  210. package/esm/policies/RustfmtConfigExists.js.map +1 -0
  211. package/esm/policies/ScriptContains.d.ts +64 -0
  212. package/esm/policies/ScriptContains.d.ts.map +1 -0
  213. package/esm/policies/ScriptContains.js +62 -0
  214. package/esm/policies/ScriptContains.js.map +1 -0
  215. package/esm/policies/SharedDependencyVersions.d.ts +24 -0
  216. package/esm/policies/SharedDependencyVersions.d.ts.map +1 -0
  217. package/esm/policies/SharedDependencyVersions.js +135 -0
  218. package/esm/policies/SharedDependencyVersions.js.map +1 -0
  219. package/esm/policies/WorkspaceInheritance.d.ts +24 -0
  220. package/esm/policies/WorkspaceInheritance.d.ts.map +1 -0
  221. package/esm/policies/WorkspaceInheritance.js +94 -0
  222. package/esm/policies/WorkspaceInheritance.js.map +1 -0
  223. package/esm/policies/WorkspaceMembersValid.d.ts +20 -0
  224. package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -0
  225. package/esm/policies/WorkspaceMembersValid.js +88 -0
  226. package/esm/policies/WorkspaceMembersValid.js.map +1 -0
  227. package/esm/policies/constants.d.ts +8 -0
  228. package/esm/policies/constants.d.ts.map +1 -1
  229. package/esm/policies/constants.js +8 -0
  230. package/esm/policies/constants.js.map +1 -1
  231. package/esm/policies.d.ts +36 -1
  232. package/esm/policies.d.ts.map +1 -1
  233. package/esm/policies.js +68 -0
  234. package/esm/policies.js.map +1 -1
  235. package/esm/policy.d.ts +202 -84
  236. package/esm/policy.d.ts.map +1 -1
  237. package/esm/policy.js +103 -21
  238. package/esm/policy.js.map +1 -1
  239. package/esm/policyDefiners/defineCargoPolicy.d.ts +66 -0
  240. package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -0
  241. package/esm/policyDefiners/defineCargoPolicy.js +60 -0
  242. package/esm/policyDefiners/defineCargoPolicy.js.map +1 -0
  243. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +7 -2
  244. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  245. package/esm/policyDefiners/defineFileHeaderPolicy.js +11 -7
  246. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  247. package/esm/policyDefiners/defineGleamPolicy.d.ts +65 -0
  248. package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -0
  249. package/esm/policyDefiners/defineGleamPolicy.js +59 -0
  250. package/esm/policyDefiners/defineGleamPolicy.js.map +1 -0
  251. package/esm/policyDefiners/definePackagePolicy.d.ts +18 -5
  252. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  253. package/esm/policyDefiners/definePackagePolicy.js +14 -4
  254. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  255. package/esm/policyDefiners/spdxValidator.d.ts +74 -0
  256. package/esm/policyDefiners/spdxValidator.d.ts.map +1 -0
  257. package/esm/policyDefiners/spdxValidator.js +127 -0
  258. package/esm/policyDefiners/spdxValidator.js.map +1 -0
  259. package/esm/policyDefiners/tomlParser.d.ts +8 -0
  260. package/esm/policyDefiners/tomlParser.d.ts.map +1 -0
  261. package/esm/policyDefiners/tomlParser.js +17 -0
  262. package/esm/policyDefiners/tomlParser.js.map +1 -0
  263. package/esm/runner.d.ts +60 -0
  264. package/esm/runner.d.ts.map +1 -0
  265. package/esm/runner.js +174 -0
  266. package/esm/runner.js.map +1 -0
  267. package/esm/tsdoc-metadata.json +1 -1
  268. package/oclif.manifest.json +100 -3
  269. package/package.json +46 -31
  270. package/scripts/postinstall.mjs +154 -0
  271. package/sidecar/sidecar.mjs +468 -0
package/esm/index.js CHANGED
@@ -10,7 +10,15 @@
10
10
  */
11
11
  export { run } from "@oclif/core";
12
12
  export { fromFluidHandlers, } from "./adapters/fluidFramework.js";
13
- export { makePolicy, makePolicyDefinition, } from "./makePolicy.js";
13
+ export { makePolicy, makePolicyDefinition, policy, } from "./makePolicy.js";
14
+ export {
15
+ // Type guards
16
+ isPolicyError, isPolicyFailure, isPolicyFixResult,
17
+ // New types
18
+ Policy, } from "./policy.js";
19
+ export { defineCargoPolicy, } from "./policyDefiners/defineCargoPolicy.js";
14
20
  export { defineFileHeaderPolicy, } from "./policyDefiners/defineFileHeaderPolicy.js";
21
+ export { defineGleamPolicy, } from "./policyDefiners/defineGleamPolicy.js";
15
22
  export { definePackagePolicy as generatePackagePolicy, } from "./policyDefiners/definePackagePolicy.js";
23
+ export { PolicyRunner, } from "./runner.js";
16
24
  //# sourceMappingURL=index.js.map
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAGN,iBAAiB,GACjB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EACN,UAAU,EACV,oBAAoB,GAEpB,MAAM,iBAAiB,CAAC;AAazB,OAAO,EAEN,sBAAsB,GAGtB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAEN,mBAAmB,IAAI,qBAAqB,GAE5C,MAAM,yCAAyC,CAAC","sourcesContent":["/**\n * A tool for enforcing repository policies and standards across codebases.\n *\n * @remarks\n * Repopo provides a framework for defining and enforcing policies across repositories,\n * such as file headers, package.json consistency, and other code standards.\n * It can be used as a CLI tool or integrated into CI/CD pipelines.\n *\n * @packageDocumentation\n */\n\nexport { run } from \"@oclif/core\";\nexport {\n\ttype FluidAdapterOptions,\n\ttype FluidHandler,\n\tfromFluidHandlers,\n} from \"./adapters/fluidFramework.js\";\nexport type {\n\t// PolicyList,\n\tRepopoConfig,\n} from \"./config.js\";\nexport {\n\tmakePolicy,\n\tmakePolicyDefinition,\n\ttype PolicyDefinitionInput,\n} from \"./makePolicy.js\";\nexport type {\n\tPolicyDefinition,\n\tPolicyFailure,\n\tPolicyFixResult,\n\tPolicyFunctionArguments,\n\tPolicyHandler,\n\tPolicyHandlerResult,\n\tPolicyInstance,\n\tPolicyInstanceSettings,\n\tPolicyName,\n\tPolicyStandaloneResolver,\n} from \"./policy.js\";\nexport {\n\ttype DefineFileHeaderPolicyArgs,\n\tdefineFileHeaderPolicy,\n\ttype FileHeaderGeneratorConfig,\n\ttype FileHeaderPolicyConfig,\n} from \"./policyDefiners/defineFileHeaderPolicy.js\";\nexport {\n\ttype DefinePackagePolicyArgs,\n\tdefinePackagePolicy as generatePackagePolicy,\n\ttype PackageJsonHandler,\n} from \"./policyDefiners/definePackagePolicy.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAGN,iBAAiB,GACjB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACN,UAAU,EACV,oBAAoB,EAGpB,MAAM,GACN,MAAM,iBAAiB,CAAC;AAEzB,OAAO;AAGN,cAAc;AACd,aAAa,EACb,eAAe,EACf,iBAAiB;AACjB,YAAY;AACZ,MAAM,GAkBN,MAAM,aAAa,CAAC;AACrB,OAAO,EAIN,iBAAiB,GACjB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAEN,sBAAsB,GAGtB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAEN,iBAAiB,GAGjB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAEN,mBAAmB,IAAI,qBAAqB,GAE5C,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAEN,YAAY,GAGZ,MAAM,aAAa,CAAC","sourcesContent":["/**\n * A tool for enforcing repository policies and standards across codebases.\n *\n * @remarks\n * Repopo provides a framework for defining and enforcing policies across repositories,\n * such as file headers, package.json consistency, and other code standards.\n * It can be used as a CLI tool or integrated into CI/CD pipelines.\n *\n * @packageDocumentation\n */\n\nexport { run } from \"@oclif/core\";\nexport {\n\ttype FluidAdapterOptions,\n\ttype FluidHandler,\n\tfromFluidHandlers,\n} from \"./adapters/fluidFramework.js\";\nexport type {\n\t// PolicyList,\n\tRepopoConfig,\n} from \"./config.js\";\nexport type { ExcludedPolicyFileMap } from \"./context.js\";\nexport {\n\tmakePolicy,\n\tmakePolicyDefinition,\n\ttype PolicyDefinitionInput,\n\ttype PolicyOptions,\n\tpolicy,\n} from \"./makePolicy.js\";\nexport type { PolicyAction, PolicyHandlerPerfStats } from \"./perf.js\";\nexport {\n\ttype ConfiguredPolicy,\n\ttype IdentifiedPolicy,\n\t// Type guards\n\tisPolicyError,\n\tisPolicyFailure,\n\tisPolicyFixResult,\n\t// New types\n\tPolicy,\n\ttype PolicyArgs,\n\t// Legacy types (for backward compatibility)\n\ttype PolicyDefinition,\n\ttype PolicyError,\n\ttype PolicyFailure,\n\ttype PolicyFixResult,\n\ttype PolicyFunctionArguments,\n\ttype PolicyHandler,\n\ttype PolicyHandlerResult,\n\ttype PolicyInstance,\n\ttype PolicyInstanceId,\n\ttype PolicyInstanceSettings,\n\ttype PolicyName,\n\ttype PolicyResolver,\n\ttype PolicyResult,\n\ttype PolicyShape,\n\ttype PolicyStandaloneResolver,\n} from \"./policy.js\";\nexport {\n\ttype CargoToml,\n\ttype CargoTomlHandler,\n\ttype DefineCargoPolicyArgs,\n\tdefineCargoPolicy,\n} from \"./policyDefiners/defineCargoPolicy.js\";\nexport {\n\ttype DefineFileHeaderPolicyArgs,\n\tdefineFileHeaderPolicy,\n\ttype FileHeaderGeneratorConfig,\n\ttype FileHeaderPolicyConfig,\n} from \"./policyDefiners/defineFileHeaderPolicy.js\";\nexport {\n\ttype DefineGleamPolicyArgs,\n\tdefineGleamPolicy,\n\ttype GleamToml,\n\ttype GleamTomlHandler,\n} from \"./policyDefiners/defineGleamPolicy.js\";\nexport {\n\ttype DefinePackagePolicyArgs,\n\tdefinePackagePolicy as generatePackagePolicy,\n\ttype PackageJsonHandler,\n} from \"./policyDefiners/definePackagePolicy.js\";\nexport {\n\ttype PolicyFileResult,\n\tPolicyRunner,\n\ttype PolicyRunnerOptions,\n\ttype PolicyRunResults,\n} from \"./runner.js\";\n"]}
@@ -1,10 +1,74 @@
1
- import type { PolicyDefinition, PolicyInstance, PolicyInstanceSettings } from "./policy.js";
1
+ import type { ConfiguredPolicy, PolicyDefinition, PolicyInstance, PolicyInstanceId, PolicyInstanceSettings, PolicyName, PolicyShape } from "./policy.js";
2
2
  /**
3
- * Input arguments for creating a policy definition.
3
+ * Options for configuring a policy instance.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface PolicyOptions {
8
+ /**
9
+ * A stable identifier for this configured policy instance.
10
+ *
11
+ * This is required when the same policy definition is configured more than once.
12
+ */
13
+ instanceId?: PolicyInstanceId;
14
+ /**
15
+ * File paths matching these patterns will be excluded from this policy.
16
+ * Patterns are matched against repo-relative paths.
17
+ */
18
+ exclude?: (string | RegExp)[];
19
+ }
20
+ /**
21
+ * Configure a policy for use in repopo.
4
22
  *
5
23
  * @remarks
6
- * This type is identical to {@link PolicyDefinition} but is used as the input type
7
- * for {@link makePolicyDefinition} to make the API more explicit.
24
+ * This function takes a policy definition and returns a configured policy instance
25
+ * that can be added to the `policies` array in `repopo.config.ts`.
26
+ *
27
+ * Handlers are automatically normalized: async functions are wrapped for Effection
28
+ * compatibility, while generator functions are used directly.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Policy with no config, just options
33
+ * policy(NoJsFileExtensions, { exclude: ["bin/*"] })
34
+ *
35
+ * // Policy with config
36
+ * policy(PackageJsonProperties, { verbatim: { license: "MIT" } })
37
+ *
38
+ * // Policy with config and options
39
+ * policy(PackageJsonProperties, { verbatim: { license: "MIT" } }, { exclude: ["vendor/*"] })
40
+ *
41
+ * // Duplicate policies need stable instance IDs
42
+ * policy(PackageJsonProperties, sourceConfig, { instanceId: "source-packages" })
43
+ * policy(PackageJsonProperties, testConfig, { instanceId: "test-packages" })
44
+ * ```
45
+ *
46
+ * @alpha
47
+ */
48
+ export declare function policy<C = void>(policyDef: PolicyShape<C>, options?: PolicyOptions & {
49
+ exclude: (string | RegExp)[];
50
+ }): ConfiguredPolicy<C>;
51
+ /** @alpha */
52
+ export declare function policy<C>(policyDef: PolicyShape<C>, config: C, options?: PolicyOptions): ConfiguredPolicy<C>;
53
+ /**
54
+ * Assigns stable identities to configured policy instances.
55
+ *
56
+ * Single instances retain the policy name for compatibility. Duplicate instances
57
+ * must declare explicit identities so their identities remain stable across config
58
+ * reordering and policy renames.
59
+ *
60
+ * @internal
61
+ */
62
+ export declare function identifyPolicyInstances<T extends {
63
+ name: PolicyName;
64
+ instanceId?: PolicyInstanceId | undefined;
65
+ }>(policies: readonly T[]): (T & {
66
+ instanceId: PolicyInstanceId;
67
+ })[];
68
+ /**
69
+ * Input arguments for creating a policy definition.
70
+ *
71
+ * @deprecated Use {@link PolicyShape} directly instead.
8
72
  *
9
73
  * @alpha
10
74
  */
@@ -12,9 +76,7 @@ export type PolicyDefinitionInput<C = undefined> = PolicyDefinition<C>;
12
76
  /**
13
77
  * Creates a {@link PolicyDefinition} from the provided arguments.
14
78
  *
15
- * @remarks
16
- * This function accepts an object with all policy properties, making it easier
17
- * to add new optional properties in the future without breaking changes.
79
+ * @deprecated Define policies as object literals satisfying {@link PolicyShape} instead.
18
80
  *
19
81
  * @example
20
82
  * ```typescript
@@ -30,7 +92,14 @@ export type PolicyDefinitionInput<C = undefined> = PolicyDefinition<C>;
30
92
  */
31
93
  export declare function makePolicyDefinition<C = undefined>(args: PolicyDefinitionInput<C>): PolicyDefinition<C>;
32
94
  /**
33
- * Combine a {@link PolicyDefinition} with a policy-specific config and other settings to produce a {@link PolicyInstance}.
95
+ * Combine a {@link PolicyDefinition} with a policy-specific config and other settings.
96
+ *
97
+ * @deprecated Use the `policy` function instead, which has a simpler API.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * makePolicy(NoJsFileExtensions, undefined, { excludeFiles: ["bin/*"] })
102
+ * ```
34
103
  *
35
104
  * @alpha
36
105
  */
@@ -1 +1 @@
1
- {"version":3,"file":"makePolicy.d.ts","sourceRoot":"","sources":["../src/makePolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,SAAS,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,SAAS,EACjD,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC5B,gBAAgB,CAAC,CAAC,CAAC,CASrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC3B,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC/B,MAAM,CAAC,EAAE,CAAC,EACV,QAAQ,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAClC,cAAc,CAAC,CAAC,CAAC,CAMnB"}
1
+ {"version":3,"file":"makePolicy.d.ts","sourceRoot":"","sources":["../src/makePolicy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,gBAAgB,EAEhB,gBAAgB,EAGhB,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,WAAW,EACX,MAAM,aAAa,CAAC;AAMrB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC9B;AAuBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,IAAI,EAC9B,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CAAE,GACxD,gBAAgB,CAAC,CAAC,CAAC,CAAC;AACvB,aAAa;AACb,wBAAgB,MAAM,CAAC,CAAC,EACvB,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,EACzB,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,aAAa,GACrB,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAmDvB;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACtC,CAAC,SAAS;IACT,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;CAC1C,EACA,QAAQ,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG;IAAE,UAAU,EAAE,gBAAgB,CAAA;CAAE,CAAC,EAAE,CAgDlE;AAMD;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,SAAS,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,SAAS,EACjD,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC5B,gBAAgB,CAAC,CAAC,CAAC,CASrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC3B,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC/B,MAAM,CAAC,EAAE,CAAC,EACV,QAAQ,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAClC,cAAc,CAAC,CAAC,CAAC,CAMnB"}
package/esm/makePolicy.js CHANGED
@@ -1,9 +1,106 @@
1
+ import { call } from "effection";
2
+ import { isGeneratorFunction } from "./generators.js";
3
+ /**
4
+ * Normalizes a handler to always return an Effection Operation.
5
+ * Detection happens once at registration time, not per-invocation.
6
+ */
7
+ function normalizeHandler(handler) {
8
+ if (isGeneratorFunction(handler)) {
9
+ // Already a generator, return as-is
10
+ return handler;
11
+ }
12
+ // Async function - wrap with call()
13
+ return function* (args) {
14
+ const asyncHandler = handler;
15
+ return yield* call(() => asyncHandler(args));
16
+ };
17
+ }
18
+ /** @alpha */
19
+ export function policy(policyDef, configOrOptions, maybeOptions) {
20
+ // Determine if the second argument is config or options
21
+ let config;
22
+ let options;
23
+ if (maybeOptions !== undefined) {
24
+ // Three-argument form: policy(def, config, options)
25
+ config = configOrOptions;
26
+ options = maybeOptions;
27
+ }
28
+ else if (configOrOptions !== undefined) {
29
+ // Two-argument form: need to determine if it's config or options
30
+ // PolicyOptions has a specific shape with 'exclude' property
31
+ if (typeof configOrOptions === "object" &&
32
+ configOrOptions !== null &&
33
+ "exclude" in configOrOptions &&
34
+ !("name" in configOrOptions) &&
35
+ Object.keys(configOrOptions).every((k) => k === "exclude" || k === "instanceId")) {
36
+ // It's options (has 'exclude' and only option keys)
37
+ options = configOrOptions;
38
+ }
39
+ else {
40
+ // It's config
41
+ config = configOrOptions;
42
+ }
43
+ }
44
+ // Merge with default config if available
45
+ const effectiveConfig = config ?? policyDef.defaultConfig;
46
+ // Support both 'exclude' and 'excludeFiles' for backward compatibility
47
+ const excludePatterns = options?.exclude;
48
+ return {
49
+ ...policyDef,
50
+ config: effectiveConfig,
51
+ exclude: excludePatterns,
52
+ excludeFiles: excludePatterns,
53
+ instanceId: options?.instanceId,
54
+ _internalHandler: normalizeHandler(policyDef.handler),
55
+ };
56
+ }
57
+ /**
58
+ * Assigns stable identities to configured policy instances.
59
+ *
60
+ * Single instances retain the policy name for compatibility. Duplicate instances
61
+ * must declare explicit identities so their identities remain stable across config
62
+ * reordering and policy renames.
63
+ *
64
+ * @internal
65
+ */
66
+ export function identifyPolicyInstances(policies) {
67
+ const explicitIds = new Set();
68
+ const nameCounts = new Map();
69
+ for (const configuredPolicy of policies) {
70
+ nameCounts.set(configuredPolicy.name, (nameCounts.get(configuredPolicy.name) ?? 0) + 1);
71
+ if (configuredPolicy.instanceId !== undefined) {
72
+ if (explicitIds.has(configuredPolicy.instanceId)) {
73
+ throw new Error(`Duplicate policy instance ID: ${configuredPolicy.instanceId}`);
74
+ }
75
+ explicitIds.add(configuredPolicy.instanceId);
76
+ }
77
+ }
78
+ const usedIds = new Set(explicitIds);
79
+ return policies.map((configuredPolicy) => {
80
+ if (configuredPolicy.instanceId !== undefined) {
81
+ return {
82
+ ...configuredPolicy,
83
+ instanceId: configuredPolicy.instanceId,
84
+ };
85
+ }
86
+ if ((nameCounts.get(configuredPolicy.name) ?? 0) > 1) {
87
+ throw new Error(`Policy '${configuredPolicy.name}' is configured multiple times. Set a unique instanceId for each instance.`);
88
+ }
89
+ const instanceId = configuredPolicy.name;
90
+ if (usedIds.has(instanceId)) {
91
+ throw new Error(`Policy instance ID '${instanceId}' conflicts with another configured policy. Set an explicit unique instanceId.`);
92
+ }
93
+ usedIds.add(instanceId);
94
+ return {
95
+ ...configuredPolicy,
96
+ instanceId,
97
+ };
98
+ });
99
+ }
1
100
  /**
2
101
  * Creates a {@link PolicyDefinition} from the provided arguments.
3
102
  *
4
- * @remarks
5
- * This function accepts an object with all policy properties, making it easier
6
- * to add new optional properties in the future without breaking changes.
103
+ * @deprecated Define policies as object literals satisfying {@link PolicyShape} instead.
7
104
  *
8
105
  * @example
9
106
  * ```typescript
@@ -28,7 +125,14 @@ export function makePolicyDefinition(args) {
28
125
  };
29
126
  }
30
127
  /**
31
- * Combine a {@link PolicyDefinition} with a policy-specific config and other settings to produce a {@link PolicyInstance}.
128
+ * Combine a {@link PolicyDefinition} with a policy-specific config and other settings.
129
+ *
130
+ * @deprecated Use the `policy` function instead, which has a simpler API.
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * makePolicy(NoJsFileExtensions, undefined, { excludeFiles: ["bin/*"] })
135
+ * ```
32
136
  *
33
137
  * @alpha
34
138
  */
@@ -1 +1 @@
1
- {"version":3,"file":"makePolicy.js","sourceRoot":"","sources":["../src/makePolicy.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,oBAAoB,CACnC,IAA8B;IAE9B,OAAO;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACvB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACzB,UAA+B,EAC/B,MAAU,EACV,QAAoC;IAEpC,OAAO;QACN,GAAG,UAAU;QACb,GAAG,QAAQ;QACX,MAAM;KACsB,CAAC;AAC/B,CAAC","sourcesContent":["import type {\n\tPolicyDefinition,\n\tPolicyInstance,\n\tPolicyInstanceSettings,\n} from \"./policy.js\";\n\n/**\n * Input arguments for creating a policy definition.\n *\n * @remarks\n * This type is identical to {@link PolicyDefinition} but is used as the input type\n * for {@link makePolicyDefinition} to make the API more explicit.\n *\n * @alpha\n */\nexport type PolicyDefinitionInput<C = undefined> = PolicyDefinition<C>;\n\n/**\n * Creates a {@link PolicyDefinition} from the provided arguments.\n *\n * @remarks\n * This function accepts an object with all policy properties, making it easier\n * to add new optional properties in the future without breaking changes.\n *\n * @example\n * ```typescript\n * const MyPolicy = makePolicyDefinition({\n * name: \"MyPolicy\",\n * description: \"Ensures files follow conventions\",\n * match: /\\.ts$/,\n * handler: async ({ file }) => true,\n * });\n * ```\n *\n * @alpha\n */\nexport function makePolicyDefinition<C = undefined>(\n\targs: PolicyDefinitionInput<C>,\n): PolicyDefinition<C> {\n\treturn {\n\t\tname: args.name,\n\t\tdescription: args.description,\n\t\tmatch: args.match,\n\t\thandler: args.handler,\n\t\tdefaultConfig: args.defaultConfig,\n\t\tresolver: args.resolver,\n\t};\n}\n\n/**\n * Combine a {@link PolicyDefinition} with a policy-specific config and other settings to produce a {@link PolicyInstance}.\n *\n * @alpha\n */\nexport function makePolicy<C>(\n\tdefinition: PolicyDefinition<C>,\n\tconfig?: C,\n\tsettings?: PolicyInstanceSettings<C>,\n): PolicyInstance<C> {\n\treturn {\n\t\t...definition,\n\t\t...settings,\n\t\tconfig,\n\t} satisfies PolicyInstance<C>;\n}\n"]}
1
+ {"version":3,"file":"makePolicy.js","sourceRoot":"","sources":["../src/makePolicy.ts"],"names":[],"mappings":"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","sourcesContent":["import { call, type Operation } from \"effection\";\nimport { isGeneratorFunction } from \"./generators.js\";\nimport type {\n\tConfiguredPolicy,\n\tPolicyArgs,\n\tPolicyDefinition,\n\tPolicyHandler,\n\tPolicyHandlerResult,\n\tPolicyInstance,\n\tPolicyInstanceId,\n\tPolicyInstanceSettings,\n\tPolicyName,\n\tPolicyShape,\n} from \"./policy.js\";\n\n// ============================================================================\n// New API: policy() function\n// ============================================================================\n\n/**\n * Options for configuring a policy instance.\n *\n * @alpha\n */\nexport interface PolicyOptions {\n\t/**\n\t * A stable identifier for this configured policy instance.\n\t *\n\t * This is required when the same policy definition is configured more than once.\n\t */\n\tinstanceId?: PolicyInstanceId;\n\n\t/**\n\t * File paths matching these patterns will be excluded from this policy.\n\t * Patterns are matched against repo-relative paths.\n\t */\n\texclude?: (string | RegExp)[];\n}\n\n/**\n * Normalizes a handler to always return an Effection Operation.\n * Detection happens once at registration time, not per-invocation.\n */\nfunction normalizeHandler<C>(\n\thandler: PolicyHandler<C>,\n): (args: PolicyArgs<C>) => Operation<PolicyHandlerResult> {\n\tif (isGeneratorFunction(handler)) {\n\t\t// Already a generator, return as-is\n\t\treturn handler as (args: PolicyArgs<C>) => Operation<PolicyHandlerResult>;\n\t}\n\n\t// Async function - wrap with call()\n\treturn function* (args: PolicyArgs<C>): Operation<PolicyHandlerResult> {\n\t\tconst asyncHandler = handler as (\n\t\t\tpolicyArgs: PolicyArgs<C>,\n\t\t) => Promise<PolicyHandlerResult>;\n\t\treturn yield* call(() => asyncHandler(args));\n\t};\n}\n\n/**\n * Configure a policy for use in repopo.\n *\n * @remarks\n * This function takes a policy definition and returns a configured policy instance\n * that can be added to the `policies` array in `repopo.config.ts`.\n *\n * Handlers are automatically normalized: async functions are wrapped for Effection\n * compatibility, while generator functions are used directly.\n *\n * @example\n * ```typescript\n * // Policy with no config, just options\n * policy(NoJsFileExtensions, { exclude: [\"bin/*\"] })\n *\n * // Policy with config\n * policy(PackageJsonProperties, { verbatim: { license: \"MIT\" } })\n *\n * // Policy with config and options\n * policy(PackageJsonProperties, { verbatim: { license: \"MIT\" } }, { exclude: [\"vendor/*\"] })\n *\n * // Duplicate policies need stable instance IDs\n * policy(PackageJsonProperties, sourceConfig, { instanceId: \"source-packages\" })\n * policy(PackageJsonProperties, testConfig, { instanceId: \"test-packages\" })\n * ```\n *\n * @alpha\n */\nexport function policy<C = void>(\n\tpolicyDef: PolicyShape<C>,\n\toptions?: PolicyOptions & { exclude: (string | RegExp)[] },\n): ConfiguredPolicy<C>;\n/** @alpha */\nexport function policy<C>(\n\tpolicyDef: PolicyShape<C>,\n\tconfig: C,\n\toptions?: PolicyOptions,\n): ConfiguredPolicy<C>;\n/** @alpha */\nexport function policy<C>(\n\tpolicyDef: PolicyShape<C>,\n\tconfigOrOptions?: C | PolicyOptions,\n\tmaybeOptions?: PolicyOptions,\n): ConfiguredPolicy<C> {\n\t// Determine if the second argument is config or options\n\tlet config: C | undefined;\n\tlet options: PolicyOptions | undefined;\n\n\tif (maybeOptions !== undefined) {\n\t\t// Three-argument form: policy(def, config, options)\n\t\tconfig = configOrOptions as C;\n\t\toptions = maybeOptions;\n\t} else if (configOrOptions !== undefined) {\n\t\t// Two-argument form: need to determine if it's config or options\n\t\t// PolicyOptions has a specific shape with 'exclude' property\n\t\tif (\n\t\t\ttypeof configOrOptions === \"object\" &&\n\t\t\tconfigOrOptions !== null &&\n\t\t\t\"exclude\" in configOrOptions &&\n\t\t\t!(\"name\" in configOrOptions) &&\n\t\t\tObject.keys(configOrOptions).every(\n\t\t\t\t(k) => k === \"exclude\" || k === \"instanceId\",\n\t\t\t)\n\t\t) {\n\t\t\t// It's options (has 'exclude' and only option keys)\n\t\t\toptions = configOrOptions as PolicyOptions;\n\t\t} else {\n\t\t\t// It's config\n\t\t\tconfig = configOrOptions as C;\n\t\t}\n\t}\n\n\t// Merge with default config if available\n\tconst effectiveConfig = config ?? (policyDef.defaultConfig as C | undefined);\n\n\t// Support both 'exclude' and 'excludeFiles' for backward compatibility\n\tconst excludePatterns = options?.exclude;\n\n\treturn {\n\t\t...policyDef,\n\t\tconfig: effectiveConfig,\n\t\texclude: excludePatterns,\n\t\texcludeFiles: excludePatterns,\n\t\tinstanceId: options?.instanceId,\n\t\t_internalHandler: normalizeHandler(policyDef.handler),\n\t};\n}\n\n/**\n * Assigns stable identities to configured policy instances.\n *\n * Single instances retain the policy name for compatibility. Duplicate instances\n * must declare explicit identities so their identities remain stable across config\n * reordering and policy renames.\n *\n * @internal\n */\nexport function identifyPolicyInstances<\n\tT extends {\n\t\tname: PolicyName;\n\t\tinstanceId?: PolicyInstanceId | undefined;\n\t},\n>(policies: readonly T[]): (T & { instanceId: PolicyInstanceId })[] {\n\tconst explicitIds = new Set<PolicyInstanceId>();\n\tconst nameCounts = new Map<PolicyName, number>();\n\n\tfor (const configuredPolicy of policies) {\n\t\tnameCounts.set(\n\t\t\tconfiguredPolicy.name,\n\t\t\t(nameCounts.get(configuredPolicy.name) ?? 0) + 1,\n\t\t);\n\t\tif (configuredPolicy.instanceId !== undefined) {\n\t\t\tif (explicitIds.has(configuredPolicy.instanceId)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Duplicate policy instance ID: ${configuredPolicy.instanceId}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\texplicitIds.add(configuredPolicy.instanceId);\n\t\t}\n\t}\n\n\tconst usedIds = new Set(explicitIds);\n\n\treturn policies.map((configuredPolicy) => {\n\t\tif (configuredPolicy.instanceId !== undefined) {\n\t\t\treturn {\n\t\t\t\t...configuredPolicy,\n\t\t\t\tinstanceId: configuredPolicy.instanceId,\n\t\t\t};\n\t\t}\n\n\t\tif ((nameCounts.get(configuredPolicy.name) ?? 0) > 1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Policy '${configuredPolicy.name}' is configured multiple times. Set a unique instanceId for each instance.`,\n\t\t\t);\n\t\t}\n\n\t\tconst instanceId = configuredPolicy.name;\n\t\tif (usedIds.has(instanceId)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Policy instance ID '${instanceId}' conflicts with another configured policy. Set an explicit unique instanceId.`,\n\t\t\t);\n\t\t}\n\t\tusedIds.add(instanceId);\n\n\t\treturn {\n\t\t\t...configuredPolicy,\n\t\t\tinstanceId,\n\t\t};\n\t});\n}\n\n// ============================================================================\n// Legacy API (Still supported for backward compatibility)\n// ============================================================================\n\n/**\n * Input arguments for creating a policy definition.\n *\n * @deprecated Use {@link PolicyShape} directly instead.\n *\n * @alpha\n */\nexport type PolicyDefinitionInput<C = undefined> = PolicyDefinition<C>;\n\n/**\n * Creates a {@link PolicyDefinition} from the provided arguments.\n *\n * @deprecated Define policies as object literals satisfying {@link PolicyShape} instead.\n *\n * @example\n * ```typescript\n * const MyPolicy = makePolicyDefinition({\n * name: \"MyPolicy\",\n * description: \"Ensures files follow conventions\",\n * match: /\\.ts$/,\n * handler: async ({ file }) => true,\n * });\n * ```\n *\n * @alpha\n */\nexport function makePolicyDefinition<C = undefined>(\n\targs: PolicyDefinitionInput<C>,\n): PolicyDefinition<C> {\n\treturn {\n\t\tname: args.name,\n\t\tdescription: args.description,\n\t\tmatch: args.match,\n\t\thandler: args.handler,\n\t\tdefaultConfig: args.defaultConfig,\n\t\tresolver: args.resolver,\n\t};\n}\n\n/**\n * Combine a {@link PolicyDefinition} with a policy-specific config and other settings.\n *\n * @deprecated Use the `policy` function instead, which has a simpler API.\n *\n * @example\n * ```typescript\n * makePolicy(NoJsFileExtensions, undefined, { excludeFiles: [\"bin/*\"] })\n * ```\n *\n * @alpha\n */\nexport function makePolicy<C>(\n\tdefinition: PolicyDefinition<C>,\n\tconfig?: C,\n\tsettings?: PolicyInstanceSettings<C>,\n): PolicyInstance<C> {\n\treturn {\n\t\t...definition,\n\t\t...settings,\n\t\tconfig,\n\t} satisfies PolicyInstance<C>;\n}\n"]}
package/esm/perf.d.ts CHANGED
@@ -1,14 +1,19 @@
1
1
  import type { Logger } from "@tylerbu/cli-api";
2
2
  import type { Operation } from "effection";
3
- import type { PolicyName } from "./policy.js";
3
+ import type { PolicyInstanceId } from "./policy.js";
4
+ /**
5
+ * The type of action a policy can perform.
6
+ * @alpha
7
+ */
4
8
  export type PolicyAction = "check" | "resolve" | "handle";
5
9
  /**
6
10
  * Stores performance data for each handler. Used to collect and display performance stats.
11
+ * @alpha
7
12
  */
8
13
  export interface PolicyHandlerPerfStats {
9
14
  count: number;
10
15
  processed: number;
11
- data: Map<PolicyAction, Map<PolicyName, number>>;
16
+ data: Map<PolicyAction, Map<PolicyInstanceId, number>>;
12
17
  }
13
18
  export declare function newPerfStats(): PolicyHandlerPerfStats;
14
19
  export declare function runWithPerf<T>(name: string, action: PolicyAction, stats: PolicyHandlerPerfStats, run: () => Operation<T>): Operation<T>;
package/esm/perf.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD;AAED,wBAAgB,YAAY,IAAI,sBAAsB,CAMrD;AAED,wBAAiB,WAAW,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,sBAAsB,EAC7B,GAAG,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,GACrB,SAAS,CAAC,CAAC,CAAC,CAWd;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWzE"}
1
+ {"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,wBAAgB,YAAY,IAAI,sBAAsB,CAMrD;AAED,wBAAiB,WAAW,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,sBAAsB,EAC7B,GAAG,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,GACrB,SAAS,CAAC,CAAC,CAAC,CAWd;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWzE"}
package/esm/perf.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,YAAY;IAC3B,OAAO;QACN,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,CAAC;QACZ,IAAI,EAAE,IAAI,GAAG,EAAyC;KACtD,CAAC;AACH,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,WAAW,CAC3B,IAAY,EACZ,MAAoB,EACpB,KAA6B,EAC7B,GAAuB;IAEvB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,EAAkB,CAAC;IACtE,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC;IAC5B,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE1B,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAA6B,EAAE,GAAW;IAClE,GAAG,CAAC,GAAG,CACN,eAAe,KAAK,CAAC,SAAS,oBAAoB;QACjD,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,cAAc,KAAK,CAAC,KAAK,QAAQ,CAClE,CAAC;IACF,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,oBAAoB,MAAM,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,OAAO,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;AACF,CAAC","sourcesContent":["import type { Logger } from \"@tylerbu/cli-api\";\nimport type { Operation } from \"effection\";\nimport type { PolicyName } from \"./policy.js\";\n\nexport type PolicyAction = \"check\" | \"resolve\" | \"handle\";\n\n/**\n * Stores performance data for each handler. Used to collect and display performance stats.\n */\nexport interface PolicyHandlerPerfStats {\n\tcount: number;\n\tprocessed: number;\n\tdata: Map<PolicyAction, Map<PolicyName, number>>;\n}\n\nexport function newPerfStats(): PolicyHandlerPerfStats {\n\treturn {\n\t\tcount: 0,\n\t\tprocessed: 0,\n\t\tdata: new Map<PolicyAction, Map<PolicyName, number>>(),\n\t};\n}\n\nexport function* runWithPerf<T>(\n\tname: string,\n\taction: PolicyAction,\n\tstats: PolicyHandlerPerfStats,\n\trun: () => Operation<T>,\n): Operation<T> {\n\tconst actionMap = stats.data.get(action) ?? new Map<string, number>();\n\tlet dur = actionMap.get(name) ?? 0;\n\n\tconst start = Date.now();\n\tconst result = yield* run();\n\tdur += Date.now() - start;\n\n\tactionMap.set(name, dur);\n\tstats.data.set(action, actionMap);\n\treturn result;\n}\n\nexport function logStats(stats: PolicyHandlerPerfStats, log: Logger): void {\n\tlog.log(\n\t\t`Statistics: ${stats.processed} files processed, ` +\n\t\t\t`${stats.count - stats.processed} excluded, ${stats.count} total`,\n\t);\n\tfor (const [action, handlerPerf] of stats.data.entries()) {\n\t\tlog.log(`Performance for \"${action}\":`);\n\t\tfor (const [handler, dur] of handlerPerf.entries()) {\n\t\t\tlog.log(` ${handler}: ${dur}ms`);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAoBA,MAAM,UAAU,YAAY;IAC3B,OAAO;QACN,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,CAAC;QACZ,IAAI,EAAE,IAAI,GAAG,EAA+C;KAC5D,CAAC;AACH,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,WAAW,CAC3B,IAAY,EACZ,MAAoB,EACpB,KAA6B,EAC7B,GAAuB;IAEvB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,EAAkB,CAAC;IACtE,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC;IAC5B,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE1B,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAA6B,EAAE,GAAW;IAClE,GAAG,CAAC,GAAG,CACN,eAAe,KAAK,CAAC,SAAS,oBAAoB;QACjD,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,cAAc,KAAK,CAAC,KAAK,QAAQ,CAClE,CAAC;IACF,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,oBAAoB,MAAM,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,OAAO,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;AACF,CAAC","sourcesContent":["import type { Logger } from \"@tylerbu/cli-api\";\nimport type { Operation } from \"effection\";\nimport type { PolicyInstanceId } from \"./policy.js\";\n\n/**\n * The type of action a policy can perform.\n * @alpha\n */\nexport type PolicyAction = \"check\" | \"resolve\" | \"handle\";\n\n/**\n * Stores performance data for each handler. Used to collect and display performance stats.\n * @alpha\n */\nexport interface PolicyHandlerPerfStats {\n\tcount: number;\n\tprocessed: number;\n\tdata: Map<PolicyAction, Map<PolicyInstanceId, number>>;\n}\n\nexport function newPerfStats(): PolicyHandlerPerfStats {\n\treturn {\n\t\tcount: 0,\n\t\tprocessed: 0,\n\t\tdata: new Map<PolicyAction, Map<PolicyInstanceId, number>>(),\n\t};\n}\n\nexport function* runWithPerf<T>(\n\tname: string,\n\taction: PolicyAction,\n\tstats: PolicyHandlerPerfStats,\n\trun: () => Operation<T>,\n): Operation<T> {\n\tconst actionMap = stats.data.get(action) ?? new Map<string, number>();\n\tlet dur = actionMap.get(name) ?? 0;\n\n\tconst start = Date.now();\n\tconst result = yield* run();\n\tdur += Date.now() - start;\n\n\tactionMap.set(name, dur);\n\tstats.data.set(action, actionMap);\n\treturn result;\n}\n\nexport function logStats(stats: PolicyHandlerPerfStats, log: Logger): void {\n\tlog.log(\n\t\t`Statistics: ${stats.processed} files processed, ` +\n\t\t\t`${stats.count - stats.processed} excluded, ${stats.count} total`,\n\t);\n\tfor (const [action, handlerPerf] of stats.data.entries()) {\n\t\tlog.log(`Performance for \"${action}\":`);\n\t\tfor (const [handler, dur] of handlerPerf.entries()) {\n\t\t\tlog.log(` ${handler}: ${dur}ms`);\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,41 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the CargoLicenceValidated policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface CargoLicenceValidatedConfig {
8
+ /**
9
+ * Allowed SPDX licence identifiers. If set, only these are accepted.
10
+ */
11
+ allowedLicences?: string[];
12
+ /**
13
+ * If true, validate the licence value against the SPDX licence list
14
+ * using `spdx-correct`. When enabled, typos like "MIIT" are detected
15
+ * and can be auto-fixed to the correct identifier ("MIT").
16
+ *
17
+ * Requires the optional peer dependency `spdx-correct` to be installed.
18
+ *
19
+ * @defaultValue true
20
+ */
21
+ validateSpdx?: boolean;
22
+ /**
23
+ * If true, skip workspace-only Cargo.toml files (those without a [package] section).
24
+ *
25
+ * @defaultValue true
26
+ */
27
+ skipWorkspace?: boolean;
28
+ }
29
+ /**
30
+ * A policy that validates the `license` field in Cargo.toml against the SPDX
31
+ * licence list. Supports auto-fixing correctable identifiers.
32
+ *
33
+ * @remarks
34
+ * Cargo.toml uses a single `license` string field (not an array like Gleam's
35
+ * `licences`). This policy validates that the value is a recognized SPDX
36
+ * identifier and can auto-fix common mistakes like wrong casing.
37
+ *
38
+ * @alpha
39
+ */
40
+ export declare const CargoLicenceValidated: PolicyShape<CargoLicenceValidatedConfig>;
41
+ //# sourceMappingURL=CargoLicenceValidated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CargoLicenceValidated.d.ts","sourceRoot":"","sources":["../../src/policies/CargoLicenceValidated.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOhD;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC3C;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAKD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,2BAA2B,CAuCxE,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { resolve } from "pathe";
2
+ import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
3
+ import { validateLicenceField } from "../policyDefiners/spdxValidator.js";
4
+ const MANUAL_FIX = "Use a valid SPDX licence identifier (e.g., MIT, Apache-2.0, MPL-2.0).";
5
+ /**
6
+ * A policy that validates the `license` field in Cargo.toml against the SPDX
7
+ * licence list. Supports auto-fixing correctable identifiers.
8
+ *
9
+ * @remarks
10
+ * Cargo.toml uses a single `license` string field (not an array like Gleam's
11
+ * `licences`). This policy validates that the value is a recognized SPDX
12
+ * identifier and can auto-fix common mistakes like wrong casing.
13
+ *
14
+ * @alpha
15
+ */
16
+ export const CargoLicenceValidated = defineCargoPolicy({
17
+ name: "CargoLicenceValidated",
18
+ description: "Validates that Cargo.toml has a valid SPDX licence identifier.",
19
+ handler: async (toml, { file, root, resolve: shouldResolve, config }) => {
20
+ const skipWorkspace = config?.skipWorkspace ?? true;
21
+ const pkg = toml.package;
22
+ if (!pkg && skipWorkspace) {
23
+ return true;
24
+ }
25
+ const licence = pkg?.license;
26
+ if (!licence || licence.trim() === "") {
27
+ return {
28
+ error: "Missing or empty license field in [package] section.",
29
+ manualFix: 'Add license = "MIT" (or appropriate SPDX identifier) to [package] in Cargo.toml.',
30
+ };
31
+ }
32
+ const result = await validateLicenceField({
33
+ licences: [licence],
34
+ ...(config?.allowedLicences !== undefined && {
35
+ allowedLicences: config.allowedLicences,
36
+ }),
37
+ validateSpdx: config?.validateSpdx ?? true,
38
+ shouldResolve,
39
+ filePath: resolve(root, file),
40
+ manualFixMessage: MANUAL_FIX,
41
+ });
42
+ return result ?? true;
43
+ },
44
+ });
45
+ //# sourceMappingURL=CargoLicenceValidated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CargoLicenceValidated.js","sourceRoot":"","sources":["../../src/policies/CargoLicenceValidated.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAgC1E,MAAM,UAAU,GACf,uEAAuE,CAAC;AAEzE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,qBAAqB,GACjC,iBAAiB,CAAC;IACjB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACV,gEAAgE;IACjE,OAAO,EAAE,KAAK,EACb,IAAe,EACf,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,EAC7C,EAAE;QACH,MAAM,aAAa,GAAG,MAAM,EAAE,aAAa,IAAI,IAAI,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,OAA8C,CAAC;QAEhE,IAAI,CAAC,GAAG,IAAI,aAAa,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,EAAE,OAA6B,CAAC;QAEnD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvC,OAAO;gBACN,KAAK,EAAE,sDAAsD;gBAC7D,SAAS,EACR,kFAAkF;aACnF,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC;YACzC,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,GAAG,CAAC,MAAM,EAAE,eAAe,KAAK,SAAS,IAAI;gBAC5C,eAAe,EAAE,MAAM,CAAC,eAAe;aACvC,CAAC;YACF,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,IAAI;YAC1C,aAAa;YACb,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;YAC7B,gBAAgB,EAAE,UAAU;SAC5B,CAAC,CAAC;QAEH,OAAO,MAAM,IAAI,IAAI,CAAC;IACvB,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { resolve } from \"pathe\";\nimport type { PolicyShape } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\nimport { validateLicenceField } from \"../policyDefiners/spdxValidator.js\";\n\n/**\n * Configuration for the CargoLicenceValidated policy.\n *\n * @alpha\n */\nexport interface CargoLicenceValidatedConfig {\n\t/**\n\t * Allowed SPDX licence identifiers. If set, only these are accepted.\n\t */\n\tallowedLicences?: string[];\n\n\t/**\n\t * If true, validate the licence value against the SPDX licence list\n\t * using `spdx-correct`. When enabled, typos like \"MIIT\" are detected\n\t * and can be auto-fixed to the correct identifier (\"MIT\").\n\t *\n\t * Requires the optional peer dependency `spdx-correct` to be installed.\n\t *\n\t * @defaultValue true\n\t */\n\tvalidateSpdx?: boolean;\n\n\t/**\n\t * If true, skip workspace-only Cargo.toml files (those without a [package] section).\n\t *\n\t * @defaultValue true\n\t */\n\tskipWorkspace?: boolean;\n}\n\nconst MANUAL_FIX =\n\t\"Use a valid SPDX licence identifier (e.g., MIT, Apache-2.0, MPL-2.0).\";\n\n/**\n * A policy that validates the `license` field in Cargo.toml against the SPDX\n * licence list. Supports auto-fixing correctable identifiers.\n *\n * @remarks\n * Cargo.toml uses a single `license` string field (not an array like Gleam's\n * `licences`). This policy validates that the value is a recognized SPDX\n * identifier and can auto-fix common mistakes like wrong casing.\n *\n * @alpha\n */\nexport const CargoLicenceValidated: PolicyShape<CargoLicenceValidatedConfig> =\n\tdefineCargoPolicy({\n\t\tname: \"CargoLicenceValidated\",\n\t\tdescription:\n\t\t\t\"Validates that Cargo.toml has a valid SPDX licence identifier.\",\n\t\thandler: async (\n\t\t\ttoml: CargoToml,\n\t\t\t{ file, root, resolve: shouldResolve, config },\n\t\t) => {\n\t\t\tconst skipWorkspace = config?.skipWorkspace ?? true;\n\t\t\tconst pkg = toml.package as Record<string, unknown> | undefined;\n\n\t\t\tif (!pkg && skipWorkspace) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst licence = pkg?.license as string | undefined;\n\n\t\t\tif (!licence || licence.trim() === \"\") {\n\t\t\t\treturn {\n\t\t\t\t\terror: \"Missing or empty license field in [package] section.\",\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t'Add license = \"MIT\" (or appropriate SPDX identifier) to [package] in Cargo.toml.',\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst result = await validateLicenceField({\n\t\t\t\tlicences: [licence],\n\t\t\t\t...(config?.allowedLicences !== undefined && {\n\t\t\t\t\tallowedLicences: config.allowedLicences,\n\t\t\t\t}),\n\t\t\t\tvalidateSpdx: config?.validateSpdx ?? true,\n\t\t\t\tshouldResolve,\n\t\t\t\tfilePath: resolve(root, file),\n\t\t\t\tmanualFixMessage: MANUAL_FIX,\n\t\t\t});\n\n\t\t\treturn result ?? true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,30 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the CargoLintsConfigured policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface CargoLintsConfiguredConfig {
8
+ /**
9
+ * Required clippy lint levels. Keys are lint names (without the `clippy::` prefix),
10
+ * values are the minimum level ("warn" or "deny").
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * { pedantic: "warn", nursery: "warn" }
15
+ * ```
16
+ */
17
+ required?: Record<string, string>;
18
+ /**
19
+ * If true, just require that a [lints.clippy] section exists (without checking specific lints).
20
+ * @defaultValue true
21
+ */
22
+ requireSection?: boolean;
23
+ }
24
+ /**
25
+ * A policy that ensures Cargo.toml has a [lints.clippy] section configured.
26
+ *
27
+ * @alpha
28
+ */
29
+ export declare const CargoLintsConfigured: PolicyShape<CargoLintsConfiguredConfig>;
30
+ //# sourceMappingURL=CargoLintsConfigured.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CargoLintsConfigured.d.ts","sourceRoot":"","sources":["../../src/policies/CargoLintsConfigured.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,WAAW,EAAE,MAAM,cAAc,CAAC;AAMrE;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAElC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAgED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,0BAA0B,CAatE,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
2
+ function checkClippyLints(clippy, required) {
3
+ const errors = [];
4
+ for (const [lint, expectedLevel] of Object.entries(required)) {
5
+ const actual = clippy[lint];
6
+ if (actual === undefined) {
7
+ errors.push(`Missing clippy lint: ${lint} (expected level: "${expectedLevel}")`);
8
+ }
9
+ else if (String(actual) !== expectedLevel) {
10
+ errors.push(`Clippy lint ${lint} = "${String(actual)}", expected "${expectedLevel}"`);
11
+ }
12
+ }
13
+ return errors;
14
+ }
15
+ function checkLintsSection(toml, config) {
16
+ const lints = toml.lints;
17
+ const requireSection = config?.requireSection ?? true;
18
+ if (requireSection && lints === undefined) {
19
+ return {
20
+ error: "Missing [lints] section in Cargo.toml.",
21
+ manualFix: 'Add a [lints.clippy] section, e.g.:\n[lints.clippy]\npedantic = "warn"',
22
+ };
23
+ }
24
+ if (lints === undefined) {
25
+ return true;
26
+ }
27
+ const clippy = lints.clippy;
28
+ if (requireSection && clippy === undefined) {
29
+ return {
30
+ error: "Missing [lints.clippy] section in Cargo.toml.",
31
+ manualFix: 'Add a [lints.clippy] section, e.g.:\n[lints.clippy]\npedantic = "warn"',
32
+ };
33
+ }
34
+ if (config?.required && clippy) {
35
+ const errors = checkClippyLints(clippy, config.required);
36
+ if (errors.length > 0) {
37
+ return {
38
+ error: errors.join("; "),
39
+ manualFix: "Update the [lints.clippy] section with the required lint levels.",
40
+ };
41
+ }
42
+ }
43
+ return true;
44
+ }
45
+ /**
46
+ * A policy that ensures Cargo.toml has a [lints.clippy] section configured.
47
+ *
48
+ * @alpha
49
+ */
50
+ export const CargoLintsConfigured = defineCargoPolicy({
51
+ name: "CargoLintsConfigured",
52
+ description: "Ensures Cargo.toml has clippy lints configured in the [lints] section.",
53
+ handler: async (toml, { config }) => {
54
+ // Skip workspace root Cargo.toml files
55
+ if (toml.workspace !== undefined && toml.package === undefined) {
56
+ return true;
57
+ }
58
+ return checkLintsSection(toml, config);
59
+ },
60
+ });
61
+ //# sourceMappingURL=CargoLintsConfigured.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CargoLintsConfigured.js","sourceRoot":"","sources":["../../src/policies/CargoLintsConfigured.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AA0BhD,SAAS,gBAAgB,CACxB,MAA+B,EAC/B,QAAgC;IAEhC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CACV,wBAAwB,IAAI,sBAAsB,aAAa,IAAI,CACnE,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,aAAa,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CACV,eAAe,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,gBAAgB,aAAa,GAAG,CACxE,CAAC;QACH,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CACzB,IAAe,EACf,MAA8C;IAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAA4C,CAAC;IAChE,MAAM,cAAc,GAAG,MAAM,EAAE,cAAc,IAAI,IAAI,CAAC;IAEtD,IAAI,cAAc,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO;YACN,KAAK,EAAE,wCAAwC;YAC/C,SAAS,EACR,wEAAwE;SACzE,CAAC;IACH,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAA6C,CAAC;IACnE,IAAI,cAAc,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO;YACN,KAAK,EAAE,+CAA+C;YACtD,SAAS,EACR,wEAAwE;SACzE,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,QAAQ,IAAI,MAAM,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EACR,kEAAkE;aACnE,CAAC;QACH,CAAC;IACF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAChC,iBAAiB,CAAC;IACjB,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACV,wEAAwE;IACzE,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,uCAAuC;QACvC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PolicyHandlerResult, PolicyShape } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\n\n/**\n * Configuration for the CargoLintsConfigured policy.\n *\n * @alpha\n */\nexport interface CargoLintsConfiguredConfig {\n\t/**\n\t * Required clippy lint levels. Keys are lint names (without the `clippy::` prefix),\n\t * values are the minimum level (\"warn\" or \"deny\").\n\t *\n\t * @example\n\t * ```typescript\n\t * { pedantic: \"warn\", nursery: \"warn\" }\n\t * ```\n\t */\n\trequired?: Record<string, string>;\n\n\t/**\n\t * If true, just require that a [lints.clippy] section exists (without checking specific lints).\n\t * @defaultValue true\n\t */\n\trequireSection?: boolean;\n}\n\nfunction checkClippyLints(\n\tclippy: Record<string, unknown>,\n\trequired: Record<string, string>,\n): string[] {\n\tconst errors: string[] = [];\n\tfor (const [lint, expectedLevel] of Object.entries(required)) {\n\t\tconst actual = clippy[lint];\n\t\tif (actual === undefined) {\n\t\t\terrors.push(\n\t\t\t\t`Missing clippy lint: ${lint} (expected level: \"${expectedLevel}\")`,\n\t\t\t);\n\t\t} else if (String(actual) !== expectedLevel) {\n\t\t\terrors.push(\n\t\t\t\t`Clippy lint ${lint} = \"${String(actual)}\", expected \"${expectedLevel}\"`,\n\t\t\t);\n\t\t}\n\t}\n\treturn errors;\n}\n\nfunction checkLintsSection(\n\ttoml: CargoToml,\n\tconfig: CargoLintsConfiguredConfig | undefined,\n): PolicyHandlerResult {\n\tconst lints = toml.lints as Record<string, unknown> | undefined;\n\tconst requireSection = config?.requireSection ?? true;\n\n\tif (requireSection && lints === undefined) {\n\t\treturn {\n\t\t\terror: \"Missing [lints] section in Cargo.toml.\",\n\t\t\tmanualFix:\n\t\t\t\t'Add a [lints.clippy] section, e.g.:\\n[lints.clippy]\\npedantic = \"warn\"',\n\t\t};\n\t}\n\n\tif (lints === undefined) {\n\t\treturn true;\n\t}\n\n\tconst clippy = lints.clippy as Record<string, unknown> | undefined;\n\tif (requireSection && clippy === undefined) {\n\t\treturn {\n\t\t\terror: \"Missing [lints.clippy] section in Cargo.toml.\",\n\t\t\tmanualFix:\n\t\t\t\t'Add a [lints.clippy] section, e.g.:\\n[lints.clippy]\\npedantic = \"warn\"',\n\t\t};\n\t}\n\n\tif (config?.required && clippy) {\n\t\tconst errors = checkClippyLints(clippy, config.required);\n\t\tif (errors.length > 0) {\n\t\t\treturn {\n\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\tmanualFix:\n\t\t\t\t\t\"Update the [lints.clippy] section with the required lint levels.\",\n\t\t\t};\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * A policy that ensures Cargo.toml has a [lints.clippy] section configured.\n *\n * @alpha\n */\nexport const CargoLintsConfigured: PolicyShape<CargoLintsConfiguredConfig> =\n\tdefineCargoPolicy({\n\t\tname: \"CargoLintsConfigured\",\n\t\tdescription:\n\t\t\t\"Ensures Cargo.toml has clippy lints configured in the [lints] section.\",\n\t\thandler: async (toml: CargoToml, { config }) => {\n\t\t\t// Skip workspace root Cargo.toml files\n\t\t\tif (toml.workspace !== undefined && toml.package === undefined) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn checkLintsSection(toml, config);\n\t\t},\n\t});\n"]}
@@ -0,0 +1,34 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the CargoLockPolicy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface CargoLockPolicyConfig {
8
+ /**
9
+ * Policy for binary crates.
10
+ * - "require": Cargo.lock must be committed (default for binaries)
11
+ * - "warn": Emit a warning if missing
12
+ * - "ignore": Skip check
13
+ *
14
+ * @defaultValue "require"
15
+ */
16
+ binaries?: "require" | "warn" | "ignore";
17
+ /**
18
+ * Policy for library crates.
19
+ * - "require": Cargo.lock must be committed
20
+ * - "warn": Emit a warning if committed (default for libraries)
21
+ * - "ignore": Skip check
22
+ *
23
+ * @defaultValue "ignore"
24
+ */
25
+ libraries?: "require" | "warn" | "ignore";
26
+ }
27
+ /**
28
+ * A context-aware policy for Cargo.lock files.
29
+ * Binary crates should commit Cargo.lock; library crates typically shouldn't.
30
+ *
31
+ * @alpha
32
+ */
33
+ export declare const CargoLockPolicy: PolicyShape<CargoLockPolicyConfig>;
34
+ //# sourceMappingURL=CargoLockPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CargoLockPolicy.d.ts","sourceRoot":"","sources":["../../src/policies/CargoLockPolicy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAEzC;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;CAC1C;AAsBD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,qBAAqB,CAuC5D,CAAC"}