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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamTomlRequired.js","sourceRoot":"","sources":["../../src/policies/GleamTomlRequired.ts"],"names":[],"mappings":"AACA,OAAO,EACN,iBAAiB,GAEjB,MAAM,wCAAwC,CAAC;AA2BhD,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEpD,SAAS,mBAAmB,CAAC,IAAe,EAAE,MAAgB;IAC7D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAC;QACjD,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC7B,iBAAiB,CAAC;IACjB,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,oFAAoF;IACrF,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAG,mBAAmB,CACjC,IAAI,EACJ,MAAM,EAAE,QAAQ,IAAI,uBAAuB,CAC3C,CAAC;QAEF,IAAI,MAAM,EAAE,mBAAmB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7D,MAAM,CAAC,IAAI,CACV,yEAAyE,CACzE,CAAC;QACH,CAAC;QAED,IAAI,MAAM,EAAE,iBAAiB,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAChE,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EAAE,iDAAiD;aAC5D,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PolicyShape } from \"../policy.js\";\nimport {\n\tdefineGleamPolicy,\n\ttype GleamToml,\n} from \"../policyDefiners/defineGleamPolicy.js\";\n\n/**\n * Configuration for the GleamTomlRequired policy.\n *\n * @alpha\n */\nexport interface GleamTomlRequiredConfig {\n\t/**\n\t * Top-level fields that must exist in gleam.toml.\n\t * @defaultValue [\"name\", \"version\"]\n\t */\n\trequired?: string[];\n\n\t/**\n\t * If true, require the `gleam` compiler version constraint.\n\t * @defaultValue false\n\t */\n\trequireGleamVersion?: boolean;\n\n\t/**\n\t * If true, require the `[repository]` section.\n\t * @defaultValue false\n\t */\n\trequireRepository?: boolean;\n}\n\nconst DEFAULT_REQUIRED_FIELDS = [\"name\", \"version\"];\n\nfunction checkRequiredFields(toml: GleamToml, fields: string[]): string[] {\n\tconst errors: string[] = [];\n\tfor (const field of fields) {\n\t\tif (toml[field] === undefined || toml[field] === \"\") {\n\t\t\terrors.push(`Missing required field: ${field}`);\n\t\t}\n\t}\n\treturn errors;\n}\n\n/**\n * A policy that enforces required fields exist in gleam.toml.\n *\n * @alpha\n */\nexport const GleamTomlRequired: PolicyShape<GleamTomlRequiredConfig> =\n\tdefineGleamPolicy({\n\t\tname: \"GleamTomlRequired\",\n\t\tdescription:\n\t\t\t\"Ensures gleam.toml files contain required fields for proper project configuration.\",\n\t\thandler: async (toml: GleamToml, { config }) => {\n\t\t\tconst errors = checkRequiredFields(\n\t\t\t\ttoml,\n\t\t\t\tconfig?.required ?? DEFAULT_REQUIRED_FIELDS,\n\t\t\t);\n\n\t\t\tif (config?.requireGleamVersion && toml.gleam === undefined) {\n\t\t\t\terrors.push(\n\t\t\t\t\t'Missing gleam version constraint. Add gleam = \">= x.y.z\" to gleam.toml.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (config?.requireRepository && toml.repository === undefined) {\n\t\t\t\terrors.push(\"Missing [repository] section in gleam.toml.\");\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix: \"Add the missing fields to your gleam.toml file.\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,20 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamTomlSorted policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamTomlSortedConfig {
8
+ /**
9
+ * Sections whose keys should be sorted alphabetically.
10
+ * @defaultValue ["dependencies", "dev-dependencies"]
11
+ */
12
+ sections?: string[];
13
+ }
14
+ /**
15
+ * A policy that ensures dependency sections in gleam.toml are sorted alphabetically.
16
+ *
17
+ * @alpha
18
+ */
19
+ export declare const GleamTomlSorted: PolicyShape<GleamTomlSortedConfig>;
20
+ //# sourceMappingURL=GleamTomlSorted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamTomlSorted.d.ts","sourceRoot":"","sources":["../../src/policies/GleamTomlSorted.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAwID;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,qBAAqB,CAoD5D,CAAC"}
@@ -0,0 +1,153 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { resolve } from "pathe";
3
+ import { defineGleamPolicy, } from "../policyDefiners/defineGleamPolicy.js";
4
+ const DEFAULT_SORTED_SECTIONS = ["dependencies", "dev-dependencies"];
5
+ const SECTION_HEADER_REGEX = /^\[([^\]]+)\]\s*$/;
6
+ const KEY_VALUE_REGEX = /^(\S+)\s*=/;
7
+ function isSorted(keys) {
8
+ for (let i = 1; i < keys.length; i++) {
9
+ const prev = keys[i - 1];
10
+ const curr = keys[i];
11
+ if (prev !== undefined && curr !== undefined && curr < prev) {
12
+ return false;
13
+ }
14
+ }
15
+ return true;
16
+ }
17
+ function classifyLine(line) {
18
+ if (SECTION_HEADER_REGEX.test(line)) {
19
+ return "section";
20
+ }
21
+ if (line.trim() === "") {
22
+ return "blank";
23
+ }
24
+ if (line.trim().startsWith("#")) {
25
+ return "comment";
26
+ }
27
+ if (KEY_VALUE_REGEX.test(line)) {
28
+ return "key";
29
+ }
30
+ return "continuation";
31
+ }
32
+ function handleCommentLine(entryLine, currentEntry) {
33
+ if (currentEntry) {
34
+ currentEntry.lines.push(entryLine);
35
+ return currentEntry;
36
+ }
37
+ return { key: "", lines: [entryLine] };
38
+ }
39
+ function processKeyLine(entryLine, currentEntry, entries) {
40
+ if (currentEntry) {
41
+ entries.push(currentEntry);
42
+ }
43
+ const keyMatch = entryLine.match(KEY_VALUE_REGEX);
44
+ return { key: keyMatch?.[1] ?? "", lines: [entryLine] };
45
+ }
46
+ function collectSectionEntries(lines, startIndex) {
47
+ const entries = [];
48
+ let currentEntry;
49
+ let i = startIndex;
50
+ while (i < lines.length) {
51
+ const entryLine = lines[i] ?? "";
52
+ const kind = classifyLine(entryLine);
53
+ if (kind === "section") {
54
+ break;
55
+ }
56
+ switch (kind) {
57
+ case "blank": {
58
+ break;
59
+ }
60
+ case "comment": {
61
+ currentEntry = handleCommentLine(entryLine, currentEntry);
62
+ break;
63
+ }
64
+ case "key": {
65
+ currentEntry = processKeyLine(entryLine, currentEntry, entries);
66
+ break;
67
+ }
68
+ case "continuation": {
69
+ currentEntry?.lines.push(entryLine);
70
+ break;
71
+ }
72
+ default: {
73
+ break;
74
+ }
75
+ }
76
+ i++;
77
+ }
78
+ if (currentEntry) {
79
+ entries.push(currentEntry);
80
+ }
81
+ return { entries, endIndex: i };
82
+ }
83
+ function sortTomlSections(content, sectionsToSort) {
84
+ const lines = content.split("\n");
85
+ const result = [];
86
+ let i = 0;
87
+ while (i < lines.length) {
88
+ const line = lines[i] ?? "";
89
+ const sectionMatch = line.match(SECTION_HEADER_REGEX);
90
+ if (sectionMatch && sectionsToSort.includes(sectionMatch[1] ?? "")) {
91
+ result.push(line);
92
+ i++;
93
+ const { entries, endIndex } = collectSectionEntries(lines, i);
94
+ entries.sort((a, b) => a.key.localeCompare(b.key));
95
+ for (const entry of entries) {
96
+ result.push(...entry.lines);
97
+ }
98
+ i = endIndex;
99
+ continue;
100
+ }
101
+ result.push(line);
102
+ i++;
103
+ }
104
+ return result.join("\n");
105
+ }
106
+ /**
107
+ * A policy that ensures dependency sections in gleam.toml are sorted alphabetically.
108
+ *
109
+ * @alpha
110
+ */
111
+ export const GleamTomlSorted = defineGleamPolicy({
112
+ name: "GleamTomlSorted",
113
+ description: "Ensures dependency sections in gleam.toml are sorted alphabetically.",
114
+ handler: async (toml, { file, root, resolve: shouldResolve, config }) => {
115
+ const sections = config?.sections ?? DEFAULT_SORTED_SECTIONS;
116
+ const unsortedSections = [];
117
+ for (const section of sections) {
118
+ const sectionData = toml[section];
119
+ if (sectionData !== undefined && !isSorted(Object.keys(sectionData))) {
120
+ unsortedSections.push(section);
121
+ }
122
+ }
123
+ if (unsortedSections.length === 0) {
124
+ return true;
125
+ }
126
+ if (shouldResolve) {
127
+ try {
128
+ const filePath = resolve(root, file);
129
+ const content = await readFile(filePath, "utf-8");
130
+ const sorted = sortTomlSections(content, unsortedSections);
131
+ await writeFile(filePath, sorted);
132
+ return {
133
+ error: `Unsorted sections: [${unsortedSections.join("], [")}]`,
134
+ fixable: true,
135
+ fixed: true,
136
+ };
137
+ }
138
+ catch {
139
+ return {
140
+ error: `Unsorted sections: [${unsortedSections.join("], [")}]. Auto-fix failed.`,
141
+ fixable: true,
142
+ fixed: false,
143
+ };
144
+ }
145
+ }
146
+ return {
147
+ error: `Unsorted sections: [${unsortedSections.join("], [")}]`,
148
+ fixable: true,
149
+ manualFix: "Sort the dependency keys alphabetically in the listed sections.",
150
+ };
151
+ },
152
+ });
153
+ //# sourceMappingURL=GleamTomlSorted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamTomlSorted.js","sourceRoot":"","sources":["../../src/policies/GleamTomlSorted.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve } from \"pathe\";\nimport type { PolicyShape } from \"../policy.js\";\nimport {\n\tdefineGleamPolicy,\n\ttype GleamToml,\n} from \"../policyDefiners/defineGleamPolicy.js\";\n\n/**\n * Configuration for the GleamTomlSorted policy.\n *\n * @alpha\n */\nexport interface GleamTomlSortedConfig {\n\t/**\n\t * Sections whose keys should be sorted alphabetically.\n\t * @defaultValue [\"dependencies\", \"dev-dependencies\"]\n\t */\n\tsections?: string[];\n}\n\nconst DEFAULT_SORTED_SECTIONS = [\"dependencies\", \"dev-dependencies\"];\n\nconst SECTION_HEADER_REGEX = /^\\[([^\\]]+)\\]\\s*$/;\nconst KEY_VALUE_REGEX = /^(\\S+)\\s*=/;\n\nfunction isSorted(keys: string[]): boolean {\n\tfor (let i = 1; i < keys.length; i++) {\n\t\tconst prev = keys[i - 1];\n\t\tconst curr = keys[i];\n\t\tif (prev !== undefined && curr !== undefined && curr < prev) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\ninterface TomlEntry {\n\tkey: string;\n\tlines: string[];\n}\n\nfunction classifyLine(\n\tline: string,\n): \"section\" | \"blank\" | \"comment\" | \"key\" | \"continuation\" {\n\tif (SECTION_HEADER_REGEX.test(line)) {\n\t\treturn \"section\";\n\t}\n\tif (line.trim() === \"\") {\n\t\treturn \"blank\";\n\t}\n\tif (line.trim().startsWith(\"#\")) {\n\t\treturn \"comment\";\n\t}\n\tif (KEY_VALUE_REGEX.test(line)) {\n\t\treturn \"key\";\n\t}\n\treturn \"continuation\";\n}\n\nfunction handleCommentLine(\n\tentryLine: string,\n\tcurrentEntry: TomlEntry | undefined,\n): TomlEntry {\n\tif (currentEntry) {\n\t\tcurrentEntry.lines.push(entryLine);\n\t\treturn currentEntry;\n\t}\n\treturn { key: \"\", lines: [entryLine] };\n}\n\nfunction processKeyLine(\n\tentryLine: string,\n\tcurrentEntry: TomlEntry | undefined,\n\tentries: TomlEntry[],\n): TomlEntry {\n\tif (currentEntry) {\n\t\tentries.push(currentEntry);\n\t}\n\tconst keyMatch = entryLine.match(KEY_VALUE_REGEX);\n\treturn { key: keyMatch?.[1] ?? \"\", lines: [entryLine] };\n}\n\nfunction collectSectionEntries(\n\tlines: string[],\n\tstartIndex: number,\n): { entries: TomlEntry[]; endIndex: number } {\n\tconst entries: TomlEntry[] = [];\n\tlet currentEntry: TomlEntry | undefined;\n\tlet i = startIndex;\n\n\twhile (i < lines.length) {\n\t\tconst entryLine = lines[i] ?? \"\";\n\t\tconst kind = classifyLine(entryLine);\n\n\t\tif (kind === \"section\") {\n\t\t\tbreak;\n\t\t}\n\n\t\tswitch (kind) {\n\t\t\tcase \"blank\": {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"comment\": {\n\t\t\t\tcurrentEntry = handleCommentLine(entryLine, currentEntry);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"key\": {\n\t\t\t\tcurrentEntry = processKeyLine(entryLine, currentEntry, entries);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"continuation\": {\n\t\t\t\tcurrentEntry?.lines.push(entryLine);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ti++;\n\t}\n\tif (currentEntry) {\n\t\tentries.push(currentEntry);\n\t}\n\treturn { entries, endIndex: i };\n}\n\nfunction sortTomlSections(content: string, sectionsToSort: string[]): string {\n\tconst lines = content.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet i = 0;\n\n\twhile (i < lines.length) {\n\t\tconst line = lines[i] ?? \"\";\n\t\tconst sectionMatch = line.match(SECTION_HEADER_REGEX);\n\n\t\tif (sectionMatch && sectionsToSort.includes(sectionMatch[1] ?? \"\")) {\n\t\t\tresult.push(line);\n\t\t\ti++;\n\t\t\tconst { entries, endIndex } = collectSectionEntries(lines, i);\n\t\t\tentries.sort((a, b) => a.key.localeCompare(b.key));\n\t\t\tfor (const entry of entries) {\n\t\t\t\tresult.push(...entry.lines);\n\t\t\t}\n\t\t\ti = endIndex;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(line);\n\t\ti++;\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * A policy that ensures dependency sections in gleam.toml are sorted alphabetically.\n *\n * @alpha\n */\nexport const GleamTomlSorted: PolicyShape<GleamTomlSortedConfig> =\n\tdefineGleamPolicy({\n\t\tname: \"GleamTomlSorted\",\n\t\tdescription:\n\t\t\t\"Ensures dependency sections in gleam.toml are sorted alphabetically.\",\n\t\thandler: async (\n\t\t\ttoml: GleamToml,\n\t\t\t{ file, root, resolve: shouldResolve, config },\n\t\t) => {\n\t\t\tconst sections = config?.sections ?? DEFAULT_SORTED_SECTIONS;\n\t\t\tconst unsortedSections: string[] = [];\n\n\t\t\tfor (const section of sections) {\n\t\t\t\tconst sectionData = toml[section] as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined;\n\t\t\t\tif (sectionData !== undefined && !isSorted(Object.keys(sectionData))) {\n\t\t\t\t\tunsortedSections.push(section);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (unsortedSections.length === 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (shouldResolve) {\n\t\t\t\ttry {\n\t\t\t\t\tconst filePath = resolve(root, file);\n\t\t\t\t\tconst content = await readFile(filePath, \"utf-8\");\n\t\t\t\t\tconst sorted = sortTomlSections(content, unsortedSections);\n\t\t\t\t\tawait writeFile(filePath, sorted);\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: `Unsorted sections: [${unsortedSections.join(\"], [\")}]`,\n\t\t\t\t\t\tfixable: true,\n\t\t\t\t\t\tfixed: true,\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: `Unsorted sections: [${unsortedSections.join(\"], [\")}]. Auto-fix failed.`,\n\t\t\t\t\t\tfixable: true,\n\t\t\t\t\t\tfixed: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\terror: `Unsorted sections: [${unsortedSections.join(\"], [\")}]`,\n\t\t\t\tfixable: true,\n\t\t\t\tmanualFix:\n\t\t\t\t\t\"Sort the dependency keys alphabetically in the listed sections.\",\n\t\t\t};\n\t\t},\n\t});\n"]}
@@ -0,0 +1,20 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamVersionConstraint policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamVersionConstraintConfig {
8
+ /**
9
+ * Minimum Gleam compiler version to require (e.g., "1.0.0").
10
+ * If set, the constraint must specify at least this version.
11
+ */
12
+ minimumVersion?: string;
13
+ }
14
+ /**
15
+ * A policy that ensures the Gleam compiler version constraint is set in gleam.toml.
16
+ *
17
+ * @alpha
18
+ */
19
+ export declare const GleamVersionConstraint: PolicyShape<GleamVersionConstraintConfig>;
20
+ //# sourceMappingURL=GleamVersionConstraint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamVersionConstraint.d.ts","sourceRoot":"","sources":["../../src/policies/GleamVersionConstraint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAyCD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,4BAA4B,CA4B1E,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { defineGleamPolicy, } from "../policyDefiners/defineGleamPolicy.js";
2
+ const SEMVER_PREFIX_REGEX = /^[><=~^!\s]+/;
3
+ /**
4
+ * Parse a simple semver string into comparable parts.
5
+ */
6
+ function parseSemver(version) {
7
+ const cleaned = version.replace(SEMVER_PREFIX_REGEX, "").trim();
8
+ const parts = cleaned.split(".");
9
+ if (parts.length < 2) {
10
+ return undefined;
11
+ }
12
+ const major = Number.parseInt(parts[0] ?? "0", 10);
13
+ const minor = Number.parseInt(parts[1] ?? "0", 10);
14
+ const patch = Number.parseInt(parts[2] ?? "0", 10);
15
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) {
16
+ return undefined;
17
+ }
18
+ return [major, minor, patch];
19
+ }
20
+ function isVersionAtLeast(constraint, minimum) {
21
+ const constraintParts = parseSemver(constraint);
22
+ const minimumParts = parseSemver(minimum);
23
+ if (!(constraintParts && minimumParts)) {
24
+ return false;
25
+ }
26
+ for (let i = 0; i < 3; i++) {
27
+ const c = constraintParts[i] ?? 0;
28
+ const m = minimumParts[i] ?? 0;
29
+ if (c > m) {
30
+ return true;
31
+ }
32
+ if (c < m) {
33
+ return false;
34
+ }
35
+ }
36
+ return true;
37
+ }
38
+ /**
39
+ * A policy that ensures the Gleam compiler version constraint is set in gleam.toml.
40
+ *
41
+ * @alpha
42
+ */
43
+ export const GleamVersionConstraint = defineGleamPolicy({
44
+ name: "GleamVersionConstraint",
45
+ description: "Ensures gleam.toml has a Gleam compiler version constraint to prevent incompatible builds.",
46
+ handler: async (toml, { config }) => {
47
+ const gleamVersion = toml.gleam;
48
+ if (gleamVersion === undefined || gleamVersion === "") {
49
+ return {
50
+ error: "Missing gleam version constraint in gleam.toml.",
51
+ manualFix: 'Add gleam = ">= 1.0.0" (or appropriate version) to gleam.toml.',
52
+ };
53
+ }
54
+ if (config?.minimumVersion &&
55
+ !isVersionAtLeast(gleamVersion, config.minimumVersion)) {
56
+ return {
57
+ error: `Gleam version constraint "${gleamVersion}" is below minimum "${config.minimumVersion}".`,
58
+ manualFix: `Update to gleam = ">= ${config.minimumVersion}" or higher.`,
59
+ };
60
+ }
61
+ return true;
62
+ },
63
+ });
64
+ //# sourceMappingURL=GleamVersionConstraint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamVersionConstraint.js","sourceRoot":"","sources":["../../src/policies/GleamVersionConstraint.ts"],"names":[],"mappings":"AACA,OAAO,EACN,iBAAiB,GAEjB,MAAM,wCAAwC,CAAC;AAehD,MAAM,mBAAmB,GAAG,cAAc,CAAC;AAE3C;;GAEG;AACH,SAAS,WAAW,CAAC,OAAe;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACvE,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,OAAe;IAC5D,MAAM,eAAe,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,CAAC,eAAe,IAAI,YAAY,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACd,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAClC,iBAAiB,CAAC;IACjB,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACV,4FAA4F;IAC7F,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,KAA2B,CAAC;QAEtD,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,EAAE,EAAE,CAAC;YACvD,OAAO;gBACN,KAAK,EAAE,iDAAiD;gBACxD,SAAS,EACR,gEAAgE;aACjE,CAAC;QACH,CAAC;QAED,IACC,MAAM,EAAE,cAAc;YACtB,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC,cAAc,CAAC,EACrD,CAAC;YACF,OAAO;gBACN,KAAK,EAAE,6BAA6B,YAAY,uBAAuB,MAAM,CAAC,cAAc,IAAI;gBAChG,SAAS,EAAE,yBAAyB,MAAM,CAAC,cAAc,cAAc;aACvE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PolicyShape } from \"../policy.js\";\nimport {\n\tdefineGleamPolicy,\n\ttype GleamToml,\n} from \"../policyDefiners/defineGleamPolicy.js\";\n\n/**\n * Configuration for the GleamVersionConstraint policy.\n *\n * @alpha\n */\nexport interface GleamVersionConstraintConfig {\n\t/**\n\t * Minimum Gleam compiler version to require (e.g., \"1.0.0\").\n\t * If set, the constraint must specify at least this version.\n\t */\n\tminimumVersion?: string;\n}\n\nconst SEMVER_PREFIX_REGEX = /^[><=~^!\\s]+/;\n\n/**\n * Parse a simple semver string into comparable parts.\n */\nfunction parseSemver(version: string): [number, number, number] | undefined {\n\tconst cleaned = version.replace(SEMVER_PREFIX_REGEX, \"\").trim();\n\tconst parts = cleaned.split(\".\");\n\tif (parts.length < 2) {\n\t\treturn undefined;\n\t}\n\tconst major = Number.parseInt(parts[0] ?? \"0\", 10);\n\tconst minor = Number.parseInt(parts[1] ?? \"0\", 10);\n\tconst patch = Number.parseInt(parts[2] ?? \"0\", 10);\n\tif (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) {\n\t\treturn undefined;\n\t}\n\treturn [major, minor, patch];\n}\n\nfunction isVersionAtLeast(constraint: string, minimum: string): boolean {\n\tconst constraintParts = parseSemver(constraint);\n\tconst minimumParts = parseSemver(minimum);\n\tif (!(constraintParts && minimumParts)) {\n\t\treturn false;\n\t}\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst c = constraintParts[i] ?? 0;\n\t\tconst m = minimumParts[i] ?? 0;\n\t\tif (c > m) {\n\t\t\treturn true;\n\t\t}\n\t\tif (c < m) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * A policy that ensures the Gleam compiler version constraint is set in gleam.toml.\n *\n * @alpha\n */\nexport const GleamVersionConstraint: PolicyShape<GleamVersionConstraintConfig> =\n\tdefineGleamPolicy({\n\t\tname: \"GleamVersionConstraint\",\n\t\tdescription:\n\t\t\t\"Ensures gleam.toml has a Gleam compiler version constraint to prevent incompatible builds.\",\n\t\thandler: async (toml: GleamToml, { config }) => {\n\t\t\tconst gleamVersion = toml.gleam as string | undefined;\n\n\t\t\tif (gleamVersion === undefined || gleamVersion === \"\") {\n\t\t\t\treturn {\n\t\t\t\t\terror: \"Missing gleam version constraint in gleam.toml.\",\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t'Add gleam = \">= 1.0.0\" (or appropriate version) to gleam.toml.',\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tconfig?.minimumVersion &&\n\t\t\t\t!isVersionAtLeast(gleamVersion, config.minimumVersion)\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\terror: `Gleam version constraint \"${gleamVersion}\" is below minimum \"${config.minimumVersion}\".`,\n\t\t\t\t\tmanualFix: `Update to gleam = \">= ${config.minimumVersion}\" or higher.`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -4,5 +4,5 @@ import { type FileHeaderPolicyConfig } from "../policyDefiners/defineFileHeaderP
4
4
  *
5
5
  * @alpha
6
6
  */
7
- export declare const HtmlFileHeaders: import("../policy.js").PolicyDefinition<FileHeaderPolicyConfig>;
7
+ export declare const HtmlFileHeaders: import("../policy.js").PolicyShape<FileHeaderPolicyConfig>;
8
8
  //# sourceMappingURL=HtmlFileHeaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/HtmlFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,eAAe,iEAkB1B,CAAC"}
1
+ {"version":3,"file":"HtmlFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/HtmlFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,eAAe,4DAkB1B,CAAC"}
@@ -9,7 +9,7 @@ export const HtmlFileHeaders = defineFileHeaderPolicy({
9
9
  name: "HtmlFileHeaders",
10
10
  description: "Ensures HTML files have the configured header comment.",
11
11
  config: {
12
- match: /(^|\/)[^/]+\.[mc]?[jt]sx?$/i,
12
+ match: /(^|\/)[^/]+\.html?$/i,
13
13
  lineStart: /<!-- /, // Lines begin with '<!-- '
14
14
  lineEnd: / -->\r?\n/, // Lines end with ' -->' followed by CRLF or LF
15
15
  replacer: (content, { headerText }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlFileHeaders.js","sourceRoot":"","sources":["../../src/policies/HtmlFileHeaders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EACN,sBAAsB,GAEtB,MAAM,6CAA6C,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;IACrD,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,wDAAwD;IACrE,MAAM,EAAE;QACP,KAAK,EAAE,6BAA6B;QACpC,SAAS,EAAE,OAAO,EAAE,2BAA2B;QAC/C,OAAO,EAAE,WAAW,EAAE,+CAA+C;QACrE,QAAQ,EAAE,CACT,OAAe,EACf,EAAE,UAAU,EAA0B,EAC7B,EAAE;YACX,MAAM,UAAU,GAAG,QAAQ,UAAU,CAAC,OAAO,CAC5C,OAAO,EACP,OAAO,OAAO,OAAO,CACrB,OAAO,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE,CAAC;YACtC,OAAO,UAAU,CAAC;QACnB,CAAC;KACD;CACD,CAAC,CAAC","sourcesContent":["import { EOL as newline } from \"node:os\";\nimport {\n\tdefineFileHeaderPolicy,\n\ttype FileHeaderPolicyConfig,\n} from \"../policyDefiners/defineFileHeaderPolicy.js\";\n\n/**\n * A RepoPolicy that checks that HTML files have the configured header comment.\n *\n * @alpha\n */\nexport const HtmlFileHeaders = defineFileHeaderPolicy({\n\tname: \"HtmlFileHeaders\",\n\tdescription: \"Ensures HTML files have the configured header comment.\",\n\tconfig: {\n\t\tmatch: /(^|\\/)[^/]+\\.[mc]?[jt]sx?$/i,\n\t\tlineStart: /<!-- /, // Lines begin with '<!-- '\n\t\tlineEnd: / -->\\r?\\n/, // Lines end with ' -->' followed by CRLF or LF\n\t\treplacer: (\n\t\t\tcontent: string,\n\t\t\t{ headerText }: FileHeaderPolicyConfig,\n\t\t): string => {\n\t\t\tconst newContent = `<!-- ${headerText.replace(\n\t\t\t\tnewline,\n\t\t\t\t` -->${newline}<!-- `,\n\t\t\t)} -->${newline}${newline}${content}`;\n\t\t\treturn newContent;\n\t\t},\n\t},\n});\n"]}
1
+ {"version":3,"file":"HtmlFileHeaders.js","sourceRoot":"","sources":["../../src/policies/HtmlFileHeaders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EACN,sBAAsB,GAEtB,MAAM,6CAA6C,CAAC;AAErD;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC;IACrD,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,wDAAwD;IACrE,MAAM,EAAE;QACP,KAAK,EAAE,sBAAsB;QAC7B,SAAS,EAAE,OAAO,EAAE,2BAA2B;QAC/C,OAAO,EAAE,WAAW,EAAE,+CAA+C;QACrE,QAAQ,EAAE,CACT,OAAe,EACf,EAAE,UAAU,EAA0B,EAC7B,EAAE;YACX,MAAM,UAAU,GAAG,QAAQ,UAAU,CAAC,OAAO,CAC5C,OAAO,EACP,OAAO,OAAO,OAAO,CACrB,OAAO,OAAO,GAAG,OAAO,GAAG,OAAO,EAAE,CAAC;YACtC,OAAO,UAAU,CAAC;QACnB,CAAC;KACD;CACD,CAAC,CAAC","sourcesContent":["import { EOL as newline } from \"node:os\";\nimport {\n\tdefineFileHeaderPolicy,\n\ttype FileHeaderPolicyConfig,\n} from \"../policyDefiners/defineFileHeaderPolicy.js\";\n\n/**\n * A RepoPolicy that checks that HTML files have the configured header comment.\n *\n * @alpha\n */\nexport const HtmlFileHeaders = defineFileHeaderPolicy({\n\tname: \"HtmlFileHeaders\",\n\tdescription: \"Ensures HTML files have the configured header comment.\",\n\tconfig: {\n\t\tmatch: /(^|\\/)[^/]+\\.html?$/i,\n\t\tlineStart: /<!-- /, // Lines begin with '<!-- '\n\t\tlineEnd: / -->\\r?\\n/, // Lines end with ' -->' followed by CRLF or LF\n\t\treplacer: (\n\t\t\tcontent: string,\n\t\t\t{ headerText }: FileHeaderPolicyConfig,\n\t\t): string => {\n\t\t\tconst newContent = `<!-- ${headerText.replace(\n\t\t\t\tnewline,\n\t\t\t\t` -->${newline}<!-- `,\n\t\t\t)} -->${newline}${newline}${content}`;\n\t\t\treturn newContent;\n\t\t},\n\t},\n});\n"]}
@@ -4,5 +4,5 @@ import { type FileHeaderPolicyConfig } from "../policyDefiners/defineFileHeaderP
4
4
  *
5
5
  * @alpha
6
6
  */
7
- export declare const JsTsFileHeaders: import("../policy.js").PolicyDefinition<FileHeaderPolicyConfig>;
7
+ export declare const JsTsFileHeaders: import("../policy.js").PolicyShape<FileHeaderPolicyConfig>;
8
8
  //# sourceMappingURL=JsTsFileHeaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JsTsFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/JsTsFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAkBrD;;;;GAIG;AACH,eAAO,MAAM,eAAe,iEAY1B,CAAC"}
1
+ {"version":3,"file":"JsTsFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/JsTsFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAkBrD;;;;GAIG;AACH,eAAO,MAAM,eAAe,4DAY1B,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Configuration for the MutuallyExclusiveScripts policy.
3
+ *
4
+ * @alpha
5
+ */
6
+ export interface MutuallyExclusiveScriptsConfig {
7
+ /**
8
+ * List of mutually exclusive script groups. Each group is an array of script names
9
+ * where at most one script from the group can be present.
10
+ *
11
+ * Packages can have zero scripts from the group (all optional), but cannot have
12
+ * multiple scripts from the same group.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Allow "test:unit" OR "test:vitest" OR neither, but not both
17
+ * groups: [["test:unit", "test:vitest"]]
18
+ * ```
19
+ */
20
+ groups: string[][];
21
+ }
22
+ /**
23
+ * A policy that validates mutually exclusive script groups in package.json.
24
+ *
25
+ * @remarks
26
+ * Use this policy when you want to enforce that only one script from a group
27
+ * can exist in a package. This is useful for ensuring that packages don't have
28
+ * conflicting scripts (e.g., both "lint:eslint" and "lint:biome").
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { policy } from "repopo";
33
+ * import { MutuallyExclusiveScripts } from "repopo/policies";
34
+ *
35
+ * policy(MutuallyExclusiveScripts, {
36
+ * groups: [
37
+ * ["lint:eslint", "lint:biome"],
38
+ * ["test:jest", "test:vitest"],
39
+ * ],
40
+ * })
41
+ * ```
42
+ *
43
+ * @alpha
44
+ */
45
+ export declare const MutuallyExclusiveScripts: import("../policy.js").PolicyShape<MutuallyExclusiveScriptsConfig | undefined>;
46
+ //# sourceMappingURL=MutuallyExclusiveScripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MutuallyExclusiveScripts.d.ts","sourceRoot":"","sources":["../../src/policies/MutuallyExclusiveScripts.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;;;;;;;;;;;OAYG;IACH,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACnB;AAID;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,wBAAwB,gFAsCnC,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
2
+ const POLICY_NAME = "MutuallyExclusiveScripts";
3
+ /**
4
+ * A policy that validates mutually exclusive script groups in package.json.
5
+ *
6
+ * @remarks
7
+ * Use this policy when you want to enforce that only one script from a group
8
+ * can exist in a package. This is useful for ensuring that packages don't have
9
+ * conflicting scripts (e.g., both "lint:eslint" and "lint:biome").
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { policy } from "repopo";
14
+ * import { MutuallyExclusiveScripts } from "repopo/policies";
15
+ *
16
+ * policy(MutuallyExclusiveScripts, {
17
+ * groups: [
18
+ * ["lint:eslint", "lint:biome"],
19
+ * ["test:jest", "test:vitest"],
20
+ * ],
21
+ * })
22
+ * ```
23
+ *
24
+ * @alpha
25
+ */
26
+ export const MutuallyExclusiveScripts = definePackagePolicy({
27
+ name: POLICY_NAME,
28
+ description: "Validates that at most one script from each exclusive group exists in package.json.",
29
+ handler: async (json, { file, config }) => {
30
+ if (config === undefined || config.groups.length === 0) {
31
+ return true;
32
+ }
33
+ const scripts = json.scripts ?? {};
34
+ const errors = [];
35
+ for (const group of config.groups) {
36
+ const presentScripts = group.filter((scriptName) => Object.hasOwn(scripts, scriptName));
37
+ if (presentScripts.length > 1) {
38
+ errors.push(`Scripts are mutually exclusive, but found ${presentScripts.length}: ${presentScripts.join(", ")}`);
39
+ }
40
+ }
41
+ if (errors.length === 0) {
42
+ return true;
43
+ }
44
+ return {
45
+ name: POLICY_NAME,
46
+ file,
47
+ autoFixable: false,
48
+ errorMessages: errors,
49
+ };
50
+ },
51
+ });
52
+ //# sourceMappingURL=MutuallyExclusiveScripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MutuallyExclusiveScripts.js","sourceRoot":"","sources":["../../src/policies/MutuallyExclusiveScripts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAwB/E,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,mBAAmB,CAGzD;IACD,IAAI,EAAE,WAAW;IACjB,WAAW,EACV,qFAAqF;IACtF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QACnC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAClD,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAClC,CAAC;YAEF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CACV,6CAA6C,cAAc,CAAC,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClG,CAAC;YACH,CAAC;QACF,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO;YACN,IAAI,EAAE,WAAW;YACjB,IAAI;YACJ,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE,MAAM;SACrB,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PackageJson } from \"type-fest\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Configuration for the MutuallyExclusiveScripts policy.\n *\n * @alpha\n */\nexport interface MutuallyExclusiveScriptsConfig {\n\t/**\n\t * List of mutually exclusive script groups. Each group is an array of script names\n\t * where at most one script from the group can be present.\n\t *\n\t * Packages can have zero scripts from the group (all optional), but cannot have\n\t * multiple scripts from the same group.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Allow \"test:unit\" OR \"test:vitest\" OR neither, but not both\n\t * groups: [[\"test:unit\", \"test:vitest\"]]\n\t * ```\n\t */\n\tgroups: string[][];\n}\n\nconst POLICY_NAME = \"MutuallyExclusiveScripts\";\n\n/**\n * A policy that validates mutually exclusive script groups in package.json.\n *\n * @remarks\n * Use this policy when you want to enforce that only one script from a group\n * can exist in a package. This is useful for ensuring that packages don't have\n * conflicting scripts (e.g., both \"lint:eslint\" and \"lint:biome\").\n *\n * @example\n * ```typescript\n * import { policy } from \"repopo\";\n * import { MutuallyExclusiveScripts } from \"repopo/policies\";\n *\n * policy(MutuallyExclusiveScripts, {\n * groups: [\n * [\"lint:eslint\", \"lint:biome\"],\n * [\"test:jest\", \"test:vitest\"],\n * ],\n * })\n * ```\n *\n * @alpha\n */\nexport const MutuallyExclusiveScripts = definePackagePolicy<\n\tPackageJson,\n\tMutuallyExclusiveScriptsConfig | undefined\n>({\n\tname: POLICY_NAME,\n\tdescription:\n\t\t\"Validates that at most one script from each exclusive group exists in package.json.\",\n\thandler: async (json, { file, config }) => {\n\t\tif (config === undefined || config.groups.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst scripts = json.scripts ?? {};\n\t\tconst errors: string[] = [];\n\n\t\tfor (const group of config.groups) {\n\t\t\tconst presentScripts = group.filter((scriptName) =>\n\t\t\t\tObject.hasOwn(scripts, scriptName),\n\t\t\t);\n\n\t\t\tif (presentScripts.length > 1) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Scripts are mutually exclusive, but found ${presentScripts.length}: ${presentScripts.join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (errors.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn {\n\t\t\tname: POLICY_NAME,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: errors,\n\t\t};\n\t},\n});\n"]}
@@ -0,0 +1,9 @@
1
+ import type { PolicyDefinition } from "../policy.js";
2
+ /**
3
+ * A policy that prevents accidental commits of build directory contents.
4
+ * Applies to Gleam's `build/` output directory.
5
+ *
6
+ * @alpha
7
+ */
8
+ export declare const NoBuildDirectory: PolicyDefinition;
9
+ //# sourceMappingURL=NoBuildDirectory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoBuildDirectory.d.ts","sourceRoot":"","sources":["../../src/policies/NoBuildDirectory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAOpE;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAkB7B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { makePolicyDefinition } from "../makePolicy.js";
2
+ /**
3
+ * Build output extensions and directory patterns that should not be committed.
4
+ */
5
+ const BUILD_DIR_REGEX = /(?:^|\/)(build)\//;
6
+ /**
7
+ * A policy that prevents accidental commits of build directory contents.
8
+ * Applies to Gleam's `build/` output directory.
9
+ *
10
+ * @alpha
11
+ */
12
+ export const NoBuildDirectory = makePolicyDefinition({
13
+ name: "NoBuildDirectory",
14
+ description: "Prevents accidental commits of build directory contents (Gleam build/ output).",
15
+ match: BUILD_DIR_REGEX,
16
+ // biome-ignore lint/correctness/useYield: no yield needed
17
+ handler: function* ({ file }) {
18
+ return {
19
+ name: NoBuildDirectory.name,
20
+ file,
21
+ autoFixable: false,
22
+ errorMessages: [
23
+ `Build artifact detected in build/ directory: ${file}. The build/ directory should be in .gitignore.`,
24
+ ],
25
+ manualFix: "Remove the build/ directory from source control and add it to .gitignore.",
26
+ };
27
+ },
28
+ });
29
+ //# sourceMappingURL=NoBuildDirectory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoBuildDirectory.js","sourceRoot":"","sources":["../../src/policies/NoBuildDirectory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;GAEG;AACH,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAqB,oBAAoB,CAAC;IACtE,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACV,gFAAgF;IACjF,KAAK,EAAE,eAAe;IACtB,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE;QAC3B,OAAO;YACN,IAAI,EAAE,gBAAgB,CAAC,IAAI;YAC3B,IAAI;YACJ,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE;gBACd,gDAAgD,IAAI,iDAAiD;aACrG;YACD,SAAS,EACR,2EAA2E;SAC5E,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { Operation } from \"effection\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition, PolicyFailure } from \"../policy.js\";\n\n/**\n * Build output extensions and directory patterns that should not be committed.\n */\nconst BUILD_DIR_REGEX = /(?:^|\\/)(build)\\//;\n\n/**\n * A policy that prevents accidental commits of build directory contents.\n * Applies to Gleam's `build/` output directory.\n *\n * @alpha\n */\nexport const NoBuildDirectory: PolicyDefinition = makePolicyDefinition({\n\tname: \"NoBuildDirectory\",\n\tdescription:\n\t\t\"Prevents accidental commits of build directory contents (Gleam build/ output).\",\n\tmatch: BUILD_DIR_REGEX,\n\t// biome-ignore lint/correctness/useYield: no yield needed\n\thandler: function* ({ file }): Operation<PolicyFailure> {\n\t\treturn {\n\t\t\tname: NoBuildDirectory.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t`Build artifact detected in build/ directory: ${file}. The build/ directory should be in .gitignore.`,\n\t\t\t],\n\t\t\tmanualFix:\n\t\t\t\t\"Remove the build/ directory from source control and add it to .gitignore.\",\n\t\t};\n\t},\n});\n"]}
@@ -33,5 +33,5 @@ export interface NoPrivateWorkspaceDependenciesSettings {
33
33
  * });
34
34
  * ```
35
35
  */
36
- export declare const NoPrivateWorkspaceDependencies: import("../policy.js").PolicyDefinition<NoPrivateWorkspaceDependenciesSettings | undefined>;
36
+ export declare const NoPrivateWorkspaceDependencies: import("../policy.js").PolicyShape<NoPrivateWorkspaceDependenciesSettings | undefined>;
37
37
  //# sourceMappingURL=NoPrivateWorkspaceDependencies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoPrivateWorkspaceDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoPrivateWorkspaceDependencies.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACtD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,8BAA8B,6FAyEzC,CAAC"}
1
+ {"version":3,"file":"NoPrivateWorkspaceDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoPrivateWorkspaceDependencies.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACtD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,8BAA8B,wFAyEzC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { PolicyDefinition } from "../policy.js";
2
+ /**
3
+ * A policy that prevents accidental commits of Rust build artifacts.
4
+ *
5
+ * @alpha
6
+ */
7
+ export declare const NoTargetArtifacts: PolicyDefinition;
8
+ //# sourceMappingURL=NoTargetArtifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoTargetArtifacts.d.ts","sourceRoot":"","sources":["../../src/policies/NoTargetArtifacts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAqBpE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAuB9B,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { makePolicyDefinition } from "../makePolicy.js";
2
+ /**
3
+ * Build artifact extensions that should not be committed to source control.
4
+ */
5
+ const ARTIFACT_EXTENSIONS = [
6
+ ".rlib",
7
+ ".rmeta",
8
+ ".d",
9
+ ".so",
10
+ ".dylib",
11
+ ".dll",
12
+ ".exe",
13
+ ".pdb",
14
+ ];
15
+ const ARTIFACT_REGEX = new RegExp(`(${ARTIFACT_EXTENSIONS.map((ext) => ext.replace(".", "\\.")).join("|")})$`, "i");
16
+ /**
17
+ * A policy that prevents accidental commits of Rust build artifacts.
18
+ *
19
+ * @alpha
20
+ */
21
+ export const NoTargetArtifacts = makePolicyDefinition({
22
+ name: "NoTargetArtifacts",
23
+ description: "Prevents accidental commits of Rust build artifacts (.rlib, .rmeta, .so, .dylib, etc.).",
24
+ match: ARTIFACT_REGEX,
25
+ // biome-ignore lint/correctness/useYield: no yield needed
26
+ handler: function* ({ file }) {
27
+ // Allow files inside test/fixture directories
28
+ if (file.includes("test/") || file.includes("fixture")) {
29
+ return true;
30
+ }
31
+ return {
32
+ name: NoTargetArtifacts.name,
33
+ file,
34
+ autoFixable: false,
35
+ errorMessages: [
36
+ `Build artifact detected: ${file}. Rust build artifacts should not be committed to source control.`,
37
+ ],
38
+ manualFix: "Remove the file from source control and ensure /target/ is in .gitignore.",
39
+ };
40
+ },
41
+ });
42
+ //# sourceMappingURL=NoTargetArtifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoTargetArtifacts.js","sourceRoot":"","sources":["../../src/policies/NoTargetArtifacts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;GAEG;AACH,MAAM,mBAAmB,GAAG;IAC3B,OAAO;IACP,QAAQ;IACR,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;CACN,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,MAAM,CAChC,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAC3E,GAAG,CACH,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqB,oBAAoB,CAAC;IACvE,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,yFAAyF;IAC1F,KAAK,EAAE,cAAc;IACrB,0DAA0D;IAC1D,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE;QAC3B,8CAA8C;QAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,OAAO,IAAgC,CAAC;QACzC,CAAC;QAED,OAAO;YACN,IAAI,EAAE,iBAAiB,CAAC,IAAI;YAC5B,IAAI;YACJ,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE;gBACd,4BAA4B,IAAI,mEAAmE;aACnG;YACD,SAAS,EACR,2EAA2E;SAC5E,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { Operation } from \"effection\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition, PolicyFailure } from \"../policy.js\";\n\n/**\n * Build artifact extensions that should not be committed to source control.\n */\nconst ARTIFACT_EXTENSIONS = [\n\t\".rlib\",\n\t\".rmeta\",\n\t\".d\",\n\t\".so\",\n\t\".dylib\",\n\t\".dll\",\n\t\".exe\",\n\t\".pdb\",\n];\n\nconst ARTIFACT_REGEX = new RegExp(\n\t`(${ARTIFACT_EXTENSIONS.map((ext) => ext.replace(\".\", \"\\\\.\")).join(\"|\")})$`,\n\t\"i\",\n);\n\n/**\n * A policy that prevents accidental commits of Rust build artifacts.\n *\n * @alpha\n */\nexport const NoTargetArtifacts: PolicyDefinition = makePolicyDefinition({\n\tname: \"NoTargetArtifacts\",\n\tdescription:\n\t\t\"Prevents accidental commits of Rust build artifacts (.rlib, .rmeta, .so, .dylib, etc.).\",\n\tmatch: ARTIFACT_REGEX,\n\t// biome-ignore lint/correctness/useYield: no yield needed\n\thandler: function* ({ file }): Operation<PolicyFailure> {\n\t\t// Allow files inside test/fixture directories\n\t\tif (file.includes(\"test/\") || file.includes(\"fixture\")) {\n\t\t\treturn true as unknown as PolicyFailure;\n\t\t}\n\n\t\treturn {\n\t\t\tname: NoTargetArtifacts.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t`Build artifact detected: ${file}. Rust build artifacts should not be committed to source control.`,\n\t\t\t],\n\t\t\tmanualFix:\n\t\t\t\t\"Remove the file from source control and ensure /target/ is in .gitignore.\",\n\t\t};\n\t},\n});\n"]}
@@ -0,0 +1,24 @@
1
+ import type { PolicyDefinition } from "../policy.js";
2
+ /**
3
+ * Configuration for the NoUnsafeWithoutJustification policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface NoUnsafeWithoutJustificationConfig {
8
+ /**
9
+ * The comment prefix to look for before unsafe blocks.
10
+ * @defaultValue "// SAFETY:"
11
+ */
12
+ requireComment?: string;
13
+ /**
14
+ * Paths to exclude from this check (e.g., FFI modules).
15
+ */
16
+ excludePaths?: string[];
17
+ }
18
+ /**
19
+ * A policy that requires SAFETY comments on unsafe blocks in Rust source files.
20
+ *
21
+ * @alpha
22
+ */
23
+ export declare const NoUnsafeWithoutJustification: PolicyDefinition<NoUnsafeWithoutJustificationConfig>;
24
+ //# sourceMappingURL=NoUnsafeWithoutJustification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoUnsafeWithoutJustification.d.ts","sourceRoot":"","sources":["../../src/policies/NoUnsafeWithoutJustification.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,kCAAkC;IAClD;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AA+CD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,gBAAgB,CAAC,kCAAkC,CA4C3F,CAAC"}