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,74 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "pathe";
3
+ import { makePolicyDefinition } from "../makePolicy.js";
4
+ import { parseToml } from "../policyDefiners/tomlParser.js";
5
+ const DEFAULT_SYNC_FIELDS = ["licences"];
6
+ async function loadGleamToml(filePath) {
7
+ try {
8
+ const content = await readFile(filePath, "utf-8");
9
+ return await parseToml(content);
10
+ }
11
+ catch {
12
+ return undefined;
13
+ }
14
+ }
15
+ function checkFieldConsistency(packages, field) {
16
+ const values = new Map();
17
+ for (const [pkg, toml] of packages) {
18
+ const value = JSON.stringify(toml[field] ?? null);
19
+ if (!values.has(value)) {
20
+ values.set(value, []);
21
+ }
22
+ values.get(value)?.push(pkg);
23
+ }
24
+ if (values.size <= 1) {
25
+ return [];
26
+ }
27
+ const details = [...values.entries()]
28
+ .map(([val, pkgs]) => `${val} in ${pkgs.join(", ")}`)
29
+ .join("; ");
30
+ return [`Inconsistent "${field}" across packages: ${details}`];
31
+ }
32
+ /**
33
+ * A policy that enforces consistent metadata across Gleam packages in a monorepo.
34
+ *
35
+ * @alpha
36
+ */
37
+ export const GleamMonorepoConsistency = makePolicyDefinition({
38
+ name: "GleamMonorepoConsistency",
39
+ description: "Enforces consistent metadata (licences, gleam version, etc.) across Gleam packages in a monorepo.",
40
+ match: /^gleam\.toml$/,
41
+ handler: async ({ root, config }) => {
42
+ const packagePaths = config?.packages;
43
+ if (!packagePaths || packagePaths.length < 2) {
44
+ return true;
45
+ }
46
+ const syncFields = config?.syncFields ?? DEFAULT_SYNC_FIELDS;
47
+ const syncGleamVersion = config?.syncGleamVersion ?? true;
48
+ const packages = new Map();
49
+ for (const pkgPath of packagePaths) {
50
+ const toml = await loadGleamToml(path.resolve(root, pkgPath));
51
+ if (toml) {
52
+ packages.set(pkgPath, toml);
53
+ }
54
+ }
55
+ if (packages.size < 2) {
56
+ return true;
57
+ }
58
+ const errors = [];
59
+ for (const field of syncFields) {
60
+ errors.push(...checkFieldConsistency(packages, field));
61
+ }
62
+ if (syncGleamVersion) {
63
+ errors.push(...checkFieldConsistency(packages, "gleam"));
64
+ }
65
+ if (errors.length > 0) {
66
+ return {
67
+ error: errors.join("; "),
68
+ manualFix: "Ensure all Gleam packages in the monorepo use consistent metadata values.",
69
+ };
70
+ }
71
+ return true;
72
+ },
73
+ });
74
+ //# sourceMappingURL=GleamMonorepoConsistency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamMonorepoConsistency.js","sourceRoot":"","sources":["../../src/policies/GleamMonorepoConsistency.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition } from \"../policy.js\";\nimport { parseToml } from \"../policyDefiners/tomlParser.js\";\n\n/**\n * Configuration for the GleamMonorepoConsistency policy.\n *\n * @alpha\n */\nexport interface GleamMonorepoConsistencyConfig {\n\t/**\n\t * Top-level fields that should be consistent across all packages.\n\t * @defaultValue [\"licences\"]\n\t */\n\tsyncFields?: string[];\n\n\t/**\n\t * If true, ensure the `gleam` version constraint is consistent.\n\t * @defaultValue true\n\t */\n\tsyncGleamVersion?: boolean;\n\n\t/**\n\t * Paths to gleam.toml files to compare (relative to repo root).\n\t * If not specified, the policy only checks the file it matches against.\n\t */\n\tpackages?: string[];\n}\n\nconst DEFAULT_SYNC_FIELDS = [\"licences\"];\n\nasync function loadGleamToml(\n\tfilePath: string,\n): Promise<Record<string, unknown> | undefined> {\n\ttry {\n\t\tconst content = await readFile(filePath, \"utf-8\");\n\t\treturn await parseToml(content);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction checkFieldConsistency(\n\tpackages: Map<string, Record<string, unknown>>,\n\tfield: string,\n): string[] {\n\tconst values = new Map<string, string[]>();\n\n\tfor (const [pkg, toml] of packages) {\n\t\tconst value = JSON.stringify(toml[field] ?? null);\n\t\tif (!values.has(value)) {\n\t\t\tvalues.set(value, []);\n\t\t}\n\t\tvalues.get(value)?.push(pkg);\n\t}\n\n\tif (values.size <= 1) {\n\t\treturn [];\n\t}\n\n\tconst details = [...values.entries()]\n\t\t.map(([val, pkgs]) => `${val} in ${pkgs.join(\", \")}`)\n\t\t.join(\"; \");\n\treturn [`Inconsistent \"${field}\" across packages: ${details}`];\n}\n\n/**\n * A policy that enforces consistent metadata across Gleam packages in a monorepo.\n *\n * @alpha\n */\nexport const GleamMonorepoConsistency: PolicyDefinition<GleamMonorepoConsistencyConfig> =\n\tmakePolicyDefinition({\n\t\tname: \"GleamMonorepoConsistency\",\n\t\tdescription:\n\t\t\t\"Enforces consistent metadata (licences, gleam version, etc.) across Gleam packages in a monorepo.\",\n\t\tmatch: /^gleam\\.toml$/,\n\t\thandler: async ({ root, config }) => {\n\t\t\tconst packagePaths = config?.packages;\n\t\t\tif (!packagePaths || packagePaths.length < 2) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst syncFields = config?.syncFields ?? DEFAULT_SYNC_FIELDS;\n\t\t\tconst syncGleamVersion = config?.syncGleamVersion ?? true;\n\n\t\t\tconst packages = new Map<string, Record<string, unknown>>();\n\t\t\tfor (const pkgPath of packagePaths) {\n\t\t\t\tconst toml = await loadGleamToml(path.resolve(root, pkgPath));\n\t\t\t\tif (toml) {\n\t\t\t\t\tpackages.set(pkgPath, toml);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (packages.size < 2) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst errors: string[] = [];\n\n\t\t\tfor (const field of syncFields) {\n\t\t\t\terrors.push(...checkFieldConsistency(packages, field));\n\t\t\t}\n\n\t\t\tif (syncGleamVersion) {\n\t\t\t\terrors.push(...checkFieldConsistency(packages, \"gleam\"));\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t\"Ensure all Gleam packages in the monorepo use consistent metadata values.\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,25 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamNameRestrictions policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamNameRestrictionsConfig {
8
+ /**
9
+ * Prefixes that are denied for package names.
10
+ * @defaultValue ["gleam_"]
11
+ */
12
+ denyPrefixes?: string[];
13
+ /**
14
+ * If true, require snake_case naming.
15
+ * @defaultValue true
16
+ */
17
+ requireSnakeCase?: boolean;
18
+ }
19
+ /**
20
+ * A policy that enforces naming conventions for Gleam packages.
21
+ *
22
+ * @alpha
23
+ */
24
+ export declare const GleamNameRestrictions: PolicyShape<GleamNameRestrictionsConfig>;
25
+ //# sourceMappingURL=GleamNameRestrictions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamNameRestrictions.d.ts","sourceRoot":"","sources":["../../src/policies/GleamNameRestrictions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC3C;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B;AAiBD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,2BAA2B,CAoCxE,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { defineGleamPolicy, } from "../policyDefiners/defineGleamPolicy.js";
2
+ const DEFAULT_DENY_PREFIXES = ["gleam_"];
3
+ const SNAKE_CASE_REGEX = /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/;
4
+ function checkDeniedPrefixes(name, prefixes) {
5
+ for (const prefix of prefixes) {
6
+ if (name.startsWith(prefix)) {
7
+ return `Package name "${name}" uses reserved prefix "${prefix}". The "gleam_" prefix is reserved for official Gleam packages.`;
8
+ }
9
+ }
10
+ return undefined;
11
+ }
12
+ /**
13
+ * A policy that enforces naming conventions for Gleam packages.
14
+ *
15
+ * @alpha
16
+ */
17
+ export const GleamNameRestrictions = defineGleamPolicy({
18
+ name: "GleamNameRestrictions",
19
+ description: 'Enforces Gleam package naming conventions: no "gleam_" prefix, snake_case required.',
20
+ handler: async (toml, { config }) => {
21
+ const name = toml.name;
22
+ if (!name) {
23
+ return true;
24
+ }
25
+ const errors = [];
26
+ const denyPrefixes = config?.denyPrefixes ?? DEFAULT_DENY_PREFIXES;
27
+ const requireSnakeCase = config?.requireSnakeCase ?? true;
28
+ const prefixError = checkDeniedPrefixes(name, denyPrefixes);
29
+ if (prefixError) {
30
+ errors.push(prefixError);
31
+ }
32
+ if (requireSnakeCase && !SNAKE_CASE_REGEX.test(name)) {
33
+ errors.push(`Package name "${name}" is not snake_case. Gleam package names should use lowercase letters, digits, and underscores.`);
34
+ }
35
+ if (errors.length > 0) {
36
+ return {
37
+ error: errors.join("; "),
38
+ manualFix: "Rename the package to follow Gleam naming conventions (snake_case, no gleam_ prefix).",
39
+ };
40
+ }
41
+ return true;
42
+ },
43
+ });
44
+ //# sourceMappingURL=GleamNameRestrictions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamNameRestrictions.js","sourceRoot":"","sources":["../../src/policies/GleamNameRestrictions.ts"],"names":[],"mappings":"AACA,OAAO,EACN,iBAAiB,GAEjB,MAAM,wCAAwC,CAAC;AAqBhD,MAAM,qBAAqB,GAAG,CAAC,QAAQ,CAAC,CAAC;AACzC,MAAM,gBAAgB,GAAG,+BAA+B,CAAC;AAEzD,SAAS,mBAAmB,CAC3B,IAAY,EACZ,QAAkB;IAElB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,iBAAiB,IAAI,2BAA2B,MAAM,iEAAiE,CAAC;QAChI,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GACjC,iBAAiB,CAAC;IACjB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACV,qFAAqF;IACtF,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAA0B,CAAC;QAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,MAAM,EAAE,YAAY,IAAI,qBAAqB,CAAC;QACnE,MAAM,gBAAgB,GAAG,MAAM,EAAE,gBAAgB,IAAI,IAAI,CAAC;QAE1D,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC5D,IAAI,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;QAED,IAAI,gBAAgB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACtD,MAAM,CAAC,IAAI,CACV,iBAAiB,IAAI,iGAAiG,CACtH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EACR,uFAAuF;aACxF,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 GleamNameRestrictions policy.\n *\n * @alpha\n */\nexport interface GleamNameRestrictionsConfig {\n\t/**\n\t * Prefixes that are denied for package names.\n\t * @defaultValue [\"gleam_\"]\n\t */\n\tdenyPrefixes?: string[];\n\n\t/**\n\t * If true, require snake_case naming.\n\t * @defaultValue true\n\t */\n\trequireSnakeCase?: boolean;\n}\n\nconst DEFAULT_DENY_PREFIXES = [\"gleam_\"];\nconst SNAKE_CASE_REGEX = /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/;\n\nfunction checkDeniedPrefixes(\n\tname: string,\n\tprefixes: string[],\n): string | undefined {\n\tfor (const prefix of prefixes) {\n\t\tif (name.startsWith(prefix)) {\n\t\t\treturn `Package name \"${name}\" uses reserved prefix \"${prefix}\". The \"gleam_\" prefix is reserved for official Gleam packages.`;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * A policy that enforces naming conventions for Gleam packages.\n *\n * @alpha\n */\nexport const GleamNameRestrictions: PolicyShape<GleamNameRestrictionsConfig> =\n\tdefineGleamPolicy({\n\t\tname: \"GleamNameRestrictions\",\n\t\tdescription:\n\t\t\t'Enforces Gleam package naming conventions: no \"gleam_\" prefix, snake_case required.',\n\t\thandler: async (toml: GleamToml, { config }) => {\n\t\t\tconst name = toml.name as string | undefined;\n\t\t\tif (!name) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst errors: string[] = [];\n\t\t\tconst denyPrefixes = config?.denyPrefixes ?? DEFAULT_DENY_PREFIXES;\n\t\t\tconst requireSnakeCase = config?.requireSnakeCase ?? true;\n\n\t\t\tconst prefixError = checkDeniedPrefixes(name, denyPrefixes);\n\t\t\tif (prefixError) {\n\t\t\t\terrors.push(prefixError);\n\t\t\t}\n\n\t\t\tif (requireSnakeCase && !SNAKE_CASE_REGEX.test(name)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Package name \"${name}\" is not snake_case. Gleam package names should use lowercase letters, digits, and underscores.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t\"Rename the package to follow Gleam naming conventions (snake_case, no gleam_ prefix).\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,22 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamNoPathDepsInPublished policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamNoPathDepsInPublishedConfig {
8
+ /**
9
+ * If true, only check packages that don't have a "private" marker.
10
+ * Since Gleam doesn't have a native "private" field, this checks for
11
+ * the absence of a description (unpublished packages often lack one).
12
+ * @defaultValue false
13
+ */
14
+ onlyPublishable?: boolean;
15
+ }
16
+ /**
17
+ * A policy that warns when path dependencies are used in packages intended for publishing.
18
+ *
19
+ * @alpha
20
+ */
21
+ export declare const GleamNoPathDepsInPublished: PolicyShape<GleamNoPathDepsInPublishedConfig>;
22
+ //# sourceMappingURL=GleamNoPathDepsInPublished.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamNoPathDepsInPublished.d.ts","sourceRoot":"","sources":["../../src/policies/GleamNoPathDepsInPublished.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,gCAAgC;IAChD;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAeD;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,gCAAgC,CAgClF,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { defineGleamPolicy, } from "../policyDefiners/defineGleamPolicy.js";
2
+ function findPathDeps(deps) {
3
+ const pathDeps = [];
4
+ for (const [name, value] of Object.entries(deps)) {
5
+ if (typeof value === "object" && value !== null) {
6
+ const record = value;
7
+ if (typeof record.path === "string") {
8
+ pathDeps.push(name);
9
+ }
10
+ }
11
+ }
12
+ return pathDeps;
13
+ }
14
+ /**
15
+ * A policy that warns when path dependencies are used in packages intended for publishing.
16
+ *
17
+ * @alpha
18
+ */
19
+ export const GleamNoPathDepsInPublished = defineGleamPolicy({
20
+ name: "GleamNoPathDepsInPublished",
21
+ description: "Warns when path dependencies are used in packages intended for publishing to Hex.",
22
+ handler: async (toml, { config }) => {
23
+ if (config?.onlyPublishable && !toml.description) {
24
+ return true;
25
+ }
26
+ const errors = [];
27
+ const deps = toml.dependencies;
28
+ if (deps) {
29
+ const pathDeps = findPathDeps(deps);
30
+ for (const dep of pathDeps) {
31
+ errors.push(`[dependencies] "${dep}" uses a path dependency, which will break when published to Hex`);
32
+ }
33
+ }
34
+ if (errors.length > 0) {
35
+ return {
36
+ error: errors.join("; "),
37
+ manualFix: "Replace path dependencies with version constraints before publishing.",
38
+ };
39
+ }
40
+ return true;
41
+ },
42
+ });
43
+ //# sourceMappingURL=GleamNoPathDepsInPublished.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamNoPathDepsInPublished.js","sourceRoot":"","sources":["../../src/policies/GleamNoPathDepsInPublished.ts"],"names":[],"mappings":"AACA,OAAO,EACN,iBAAiB,GAEjB,MAAM,wCAAwC,CAAC;AAiBhD,SAAS,YAAY,CAAC,IAA6B;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACjD,MAAM,MAAM,GAAG,KAAgC,CAAC;YAChD,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACtC,iBAAiB,CAAC;IACjB,IAAI,EAAE,4BAA4B;IAClC,WAAW,EACV,mFAAmF;IACpF,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,IAAI,MAAM,EAAE,eAAe,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAmD,CAAC;QACtE,IAAI,IAAI,EAAE,CAAC;YACV,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CACV,mBAAmB,GAAG,kEAAkE,CACxF,CAAC;YACH,CAAC;QACF,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EACR,uEAAuE;aACxE,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 GleamNoPathDepsInPublished policy.\n *\n * @alpha\n */\nexport interface GleamNoPathDepsInPublishedConfig {\n\t/**\n\t * If true, only check packages that don't have a \"private\" marker.\n\t * Since Gleam doesn't have a native \"private\" field, this checks for\n\t * the absence of a description (unpublished packages often lack one).\n\t * @defaultValue false\n\t */\n\tonlyPublishable?: boolean;\n}\n\nfunction findPathDeps(deps: Record<string, unknown>): string[] {\n\tconst pathDeps: string[] = [];\n\tfor (const [name, value] of Object.entries(deps)) {\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\tconst record = value as Record<string, unknown>;\n\t\t\tif (typeof record.path === \"string\") {\n\t\t\t\tpathDeps.push(name);\n\t\t\t}\n\t\t}\n\t}\n\treturn pathDeps;\n}\n\n/**\n * A policy that warns when path dependencies are used in packages intended for publishing.\n *\n * @alpha\n */\nexport const GleamNoPathDepsInPublished: PolicyShape<GleamNoPathDepsInPublishedConfig> =\n\tdefineGleamPolicy({\n\t\tname: \"GleamNoPathDepsInPublished\",\n\t\tdescription:\n\t\t\t\"Warns when path dependencies are used in packages intended for publishing to Hex.\",\n\t\thandler: async (toml: GleamToml, { config }) => {\n\t\t\tif (config?.onlyPublishable && !toml.description) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst errors: string[] = [];\n\n\t\t\tconst deps = toml.dependencies as Record<string, unknown> | undefined;\n\t\t\tif (deps) {\n\t\t\t\tconst pathDeps = findPathDeps(deps);\n\t\t\t\tfor (const dep of pathDeps) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`[dependencies] \"${dep}\" uses a path dependency, which will break when published to Hex`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t\"Replace path dependencies with version constraints before publishing.\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,9 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * A policy that validates all path dependency targets in gleam.toml exist
4
+ * and contain a gleam.toml file.
5
+ *
6
+ * @alpha
7
+ */
8
+ export declare const GleamPathDepsValid: PolicyShape;
9
+ //# sourceMappingURL=GleamPathDepsValid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamPathDepsValid.d.ts","sourceRoot":"","sources":["../../src/policies/GleamPathDepsValid.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAkDhD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAqB/B,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "pathe";
3
+ import { defineGleamPolicy, } from "../policyDefiners/defineGleamPolicy.js";
4
+ function validatePathDep(depName, depValue, sectionName, baseDir) {
5
+ if (typeof depValue !== "object" || depValue === null) {
6
+ return undefined;
7
+ }
8
+ const record = depValue;
9
+ if (typeof record.path !== "string") {
10
+ return undefined;
11
+ }
12
+ const depDir = path.resolve(baseDir, record.path);
13
+ if (!existsSync(depDir)) {
14
+ return `[${sectionName}] "${depName}" path "${record.path}" does not exist`;
15
+ }
16
+ if (!existsSync(path.join(depDir, "gleam.toml"))) {
17
+ return `[${sectionName}] "${depName}" path "${record.path}" exists but has no gleam.toml`;
18
+ }
19
+ return undefined;
20
+ }
21
+ function checkSection(sectionName, data, baseDir) {
22
+ if (!data || typeof data !== "object") {
23
+ return [];
24
+ }
25
+ const deps = data;
26
+ const errors = [];
27
+ for (const [depName, depValue] of Object.entries(deps)) {
28
+ const error = validatePathDep(depName, depValue, sectionName, baseDir);
29
+ if (error) {
30
+ errors.push(error);
31
+ }
32
+ }
33
+ return errors;
34
+ }
35
+ /**
36
+ * A policy that validates all path dependency targets in gleam.toml exist
37
+ * and contain a gleam.toml file.
38
+ *
39
+ * @alpha
40
+ */
41
+ export const GleamPathDepsValid = defineGleamPolicy({
42
+ name: "GleamPathDepsValid",
43
+ description: "Validates that all path dependency targets exist and contain a gleam.toml file.",
44
+ handler: async (toml, { file, root }) => {
45
+ const baseDir = path.resolve(root, path.dirname(file));
46
+ const errors = [
47
+ ...checkSection("dependencies", toml.dependencies, baseDir),
48
+ ...checkSection("dev-dependencies", toml["dev-dependencies"], baseDir),
49
+ ];
50
+ if (errors.length > 0) {
51
+ return {
52
+ error: errors.join("; "),
53
+ manualFix: "Fix the path dependencies to point to valid Gleam project directories.",
54
+ };
55
+ }
56
+ return true;
57
+ },
58
+ });
59
+ //# sourceMappingURL=GleamPathDepsValid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamPathDepsValid.js","sourceRoot":"","sources":["../../src/policies/GleamPathDepsValid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AAEzB,OAAO,EACN,iBAAiB,GAEjB,MAAM,wCAAwC,CAAC;AAEhD,SAAS,eAAe,CACvB,OAAe,EACf,QAAiB,EACjB,WAAmB,EACnB,OAAe;IAEf,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACvD,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,QAAmC,CAAC;IACnD,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAElD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,WAAW,MAAM,OAAO,WAAW,MAAM,CAAC,IAAI,kBAAkB,CAAC;IAC7E,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO,IAAI,WAAW,MAAM,OAAO,WAAW,MAAM,CAAC,IAAI,gCAAgC,CAAC;IAC3F,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CACpB,WAAmB,EACnB,IAAa,EACb,OAAe;IAEf,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvC,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,IAAI,GAAG,IAA+B,CAAC;IAC7C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QACvE,IAAI,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgB,iBAAiB,CAAC;IAChE,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACV,iFAAiF;IAClF,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACvD,MAAM,MAAM,GAAa;YACxB,GAAG,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;YAC3D,GAAG,YAAY,CAAC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;SACtE,CAAC;QAEF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EACR,wEAAwE;aACzE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"pathe\";\nimport type { PolicyShape } from \"../policy.js\";\nimport {\n\tdefineGleamPolicy,\n\ttype GleamToml,\n} from \"../policyDefiners/defineGleamPolicy.js\";\n\nfunction validatePathDep(\n\tdepName: string,\n\tdepValue: unknown,\n\tsectionName: string,\n\tbaseDir: string,\n): string | undefined {\n\tif (typeof depValue !== \"object\" || depValue === null) {\n\t\treturn undefined;\n\t}\n\tconst record = depValue as Record<string, unknown>;\n\tif (typeof record.path !== \"string\") {\n\t\treturn undefined;\n\t}\n\n\tconst depDir = path.resolve(baseDir, record.path);\n\n\tif (!existsSync(depDir)) {\n\t\treturn `[${sectionName}] \"${depName}\" path \"${record.path}\" does not exist`;\n\t}\n\tif (!existsSync(path.join(depDir, \"gleam.toml\"))) {\n\t\treturn `[${sectionName}] \"${depName}\" path \"${record.path}\" exists but has no gleam.toml`;\n\t}\n\treturn undefined;\n}\n\nfunction checkSection(\n\tsectionName: string,\n\tdata: unknown,\n\tbaseDir: string,\n): string[] {\n\tif (!data || typeof data !== \"object\") {\n\t\treturn [];\n\t}\n\tconst deps = data as Record<string, unknown>;\n\tconst errors: string[] = [];\n\tfor (const [depName, depValue] of Object.entries(deps)) {\n\t\tconst error = validatePathDep(depName, depValue, sectionName, baseDir);\n\t\tif (error) {\n\t\t\terrors.push(error);\n\t\t}\n\t}\n\treturn errors;\n}\n\n/**\n * A policy that validates all path dependency targets in gleam.toml exist\n * and contain a gleam.toml file.\n *\n * @alpha\n */\nexport const GleamPathDepsValid: PolicyShape = defineGleamPolicy({\n\tname: \"GleamPathDepsValid\",\n\tdescription:\n\t\t\"Validates that all path dependency targets exist and contain a gleam.toml file.\",\n\thandler: async (toml: GleamToml, { file, root }) => {\n\t\tconst baseDir = path.resolve(root, path.dirname(file));\n\t\tconst errors: string[] = [\n\t\t\t...checkSection(\"dependencies\", toml.dependencies, baseDir),\n\t\t\t...checkSection(\"dev-dependencies\", toml[\"dev-dependencies\"], baseDir),\n\t\t];\n\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\"Fix the path dependencies to point to valid Gleam project directories.\",\n\t\t\t};\n\t\t}\n\n\t\treturn true;\n\t},\n});\n"]}
@@ -0,0 +1,25 @@
1
+ import type { PolicyDefinition } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamProjectStructure policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamProjectStructureConfig {
8
+ /**
9
+ * If true, require the src/ directory to exist.
10
+ * @defaultValue true
11
+ */
12
+ requireSrcDir?: boolean;
13
+ /**
14
+ * If true, require the test/ directory to exist.
15
+ * @defaultValue false
16
+ */
17
+ requireTestDir?: boolean;
18
+ }
19
+ /**
20
+ * A policy that validates standard Gleam project structure.
21
+ *
22
+ * @alpha
23
+ */
24
+ export declare const GleamProjectStructure: PolicyDefinition<GleamProjectStructureConfig>;
25
+ //# sourceMappingURL=GleamProjectStructure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamProjectStructure.d.ts","sourceRoot":"","sources":["../../src/policies/GleamProjectStructure.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC3C;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,2BAA2B,CA+B7E,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "pathe";
3
+ import { makePolicyDefinition } from "../makePolicy.js";
4
+ /**
5
+ * A policy that validates standard Gleam project structure.
6
+ *
7
+ * @alpha
8
+ */
9
+ export const GleamProjectStructure = makePolicyDefinition({
10
+ name: "GleamProjectStructure",
11
+ description: "Validates that Gleam projects have the standard directory structure (src/, test/).",
12
+ match: /gleam\.toml$/,
13
+ handler: async ({ file, root, config }) => {
14
+ const dir = path.dirname(path.resolve(root, file));
15
+ const requireSrc = config?.requireSrcDir ?? true;
16
+ const requireTest = config?.requireTestDir ?? false;
17
+ const errors = [];
18
+ if (requireSrc && !existsSync(path.join(dir, "src"))) {
19
+ errors.push("Missing src/ directory. Gleam projects require a src/ directory for source modules.");
20
+ }
21
+ if (requireTest && !existsSync(path.join(dir, "test"))) {
22
+ errors.push("Missing test/ directory.");
23
+ }
24
+ if (errors.length > 0) {
25
+ return {
26
+ error: errors.join("; "),
27
+ manualFix: "Create the missing directories in your Gleam project.",
28
+ };
29
+ }
30
+ return true;
31
+ },
32
+ });
33
+ //# sourceMappingURL=GleamProjectStructure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamProjectStructure.js","sourceRoot":"","sources":["../../src/policies/GleamProjectStructure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAsBxD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GACjC,oBAAoB,CAAC;IACpB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACV,oFAAoF;IACrF,KAAK,EAAE,cAAc;IACrB,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,MAAM,EAAE,aAAa,IAAI,IAAI,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,EAAE,cAAc,IAAI,KAAK,CAAC;QACpD,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;YACtD,MAAM,CAAC,IAAI,CACV,qFAAqF,CACrF,CAAC;QACH,CAAC;QAED,IAAI,WAAW,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EAAE,uDAAuD;aAClE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition } from \"../policy.js\";\n\n/**\n * Configuration for the GleamProjectStructure policy.\n *\n * @alpha\n */\nexport interface GleamProjectStructureConfig {\n\t/**\n\t * If true, require the src/ directory to exist.\n\t * @defaultValue true\n\t */\n\trequireSrcDir?: boolean;\n\n\t/**\n\t * If true, require the test/ directory to exist.\n\t * @defaultValue false\n\t */\n\trequireTestDir?: boolean;\n}\n\n/**\n * A policy that validates standard Gleam project structure.\n *\n * @alpha\n */\nexport const GleamProjectStructure: PolicyDefinition<GleamProjectStructureConfig> =\n\tmakePolicyDefinition({\n\t\tname: \"GleamProjectStructure\",\n\t\tdescription:\n\t\t\t\"Validates that Gleam projects have the standard directory structure (src/, test/).\",\n\t\tmatch: /gleam\\.toml$/,\n\t\thandler: async ({ file, root, config }) => {\n\t\t\tconst dir = path.dirname(path.resolve(root, file));\n\t\t\tconst requireSrc = config?.requireSrcDir ?? true;\n\t\t\tconst requireTest = config?.requireTestDir ?? false;\n\t\t\tconst errors: string[] = [];\n\n\t\t\tif (requireSrc && !existsSync(path.join(dir, \"src\"))) {\n\t\t\t\terrors.push(\n\t\t\t\t\t\"Missing src/ directory. Gleam projects require a src/ directory for source modules.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (requireTest && !existsSync(path.join(dir, \"test\"))) {\n\t\t\t\terrors.push(\"Missing test/ directory.\");\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: \"Create the missing directories in your Gleam project.\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,29 @@
1
+ import type { PolicyDefinition } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamSharedDependencyVersions policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamSharedDependencyVersionsConfig {
8
+ /**
9
+ * If true, detect version mismatches across packages.
10
+ * @defaultValue true
11
+ */
12
+ detectMismatches?: boolean;
13
+ /**
14
+ * If true, also check dev-dependencies for mismatches.
15
+ * @defaultValue false
16
+ */
17
+ includeDev?: boolean;
18
+ /**
19
+ * Paths to gleam.toml files to compare (relative to repo root).
20
+ */
21
+ packages?: string[];
22
+ }
23
+ /**
24
+ * A policy that detects dependency version mismatches across Gleam packages in a monorepo.
25
+ *
26
+ * @alpha
27
+ */
28
+ export declare const GleamSharedDependencyVersions: PolicyDefinition<GleamSharedDependencyVersionsConfig>;
29
+ //# sourceMappingURL=GleamSharedDependencyVersions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamSharedDependencyVersions.d.ts","sourceRoot":"","sources":["../../src/policies/GleamSharedDependencyVersions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD;;;;GAIG;AACH,MAAM,WAAW,mCAAmC;IACnD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AA2DD;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,gBAAgB,CAAC,mCAAmC,CAsD7F,CAAC"}
@@ -0,0 +1,101 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "pathe";
3
+ import { makePolicyDefinition } from "../makePolicy.js";
4
+ import { parseToml } from "../policyDefiners/tomlParser.js";
5
+ function extractVersion(dep) {
6
+ if (typeof dep === "string") {
7
+ return dep;
8
+ }
9
+ if (typeof dep === "object" && dep !== null) {
10
+ const record = dep;
11
+ if (typeof record.version === "string") {
12
+ return record.version;
13
+ }
14
+ }
15
+ return undefined;
16
+ }
17
+ function collectDeps(toml, includeDev) {
18
+ const deps = new Map();
19
+ const sections = ["dependencies"];
20
+ if (includeDev) {
21
+ sections.push("dev-dependencies");
22
+ }
23
+ for (const section of sections) {
24
+ const sectionDeps = toml[section];
25
+ if (!sectionDeps) {
26
+ continue;
27
+ }
28
+ for (const [name, value] of Object.entries(sectionDeps)) {
29
+ const version = extractVersion(value);
30
+ if (version) {
31
+ deps.set(name, version);
32
+ }
33
+ }
34
+ }
35
+ return deps;
36
+ }
37
+ function recordDependency(allDeps, depName, version, pkgPath) {
38
+ if (!allDeps.has(depName)) {
39
+ allDeps.set(depName, new Map());
40
+ }
41
+ const versionMap = allDeps.get(depName);
42
+ if (versionMap === undefined) {
43
+ return;
44
+ }
45
+ if (!versionMap.has(version)) {
46
+ versionMap.set(version, []);
47
+ }
48
+ versionMap.get(version)?.push(pkgPath);
49
+ }
50
+ /**
51
+ * A policy that detects dependency version mismatches across Gleam packages in a monorepo.
52
+ *
53
+ * @alpha
54
+ */
55
+ export const GleamSharedDependencyVersions = makePolicyDefinition({
56
+ name: "GleamSharedDependencyVersions",
57
+ description: "Detects dependency version mismatches across Gleam packages in a monorepo.",
58
+ match: /^gleam\.toml$/,
59
+ handler: async ({ root, config }) => {
60
+ const packagePaths = config?.packages;
61
+ if (!packagePaths || packagePaths.length < 2) {
62
+ return true;
63
+ }
64
+ const detectMismatches = config?.detectMismatches ?? true;
65
+ if (!detectMismatches) {
66
+ return true;
67
+ }
68
+ const includeDev = config?.includeDev ?? false;
69
+ const allDeps = new Map();
70
+ for (const pkgPath of packagePaths) {
71
+ try {
72
+ const content = await readFile(path.resolve(root, pkgPath), "utf-8");
73
+ const toml = await parseToml(content);
74
+ const deps = collectDeps(toml, includeDev);
75
+ for (const [name, version] of deps) {
76
+ recordDependency(allDeps, name, version, pkgPath);
77
+ }
78
+ }
79
+ catch {
80
+ // Package might not exist
81
+ }
82
+ }
83
+ const errors = [];
84
+ for (const [dep, versionMap] of allDeps) {
85
+ if (versionMap.size > 1) {
86
+ const details = [...versionMap.entries()]
87
+ .map(([ver, pkgs]) => `"${ver}" in ${pkgs.join(", ")}`)
88
+ .join("; ");
89
+ errors.push(`Version mismatch for "${dep}": ${details}`);
90
+ }
91
+ }
92
+ if (errors.length > 0) {
93
+ return {
94
+ error: errors.join("; "),
95
+ manualFix: "Align dependency versions across all Gleam packages in the monorepo.",
96
+ };
97
+ }
98
+ return true;
99
+ },
100
+ });
101
+ //# sourceMappingURL=GleamSharedDependencyVersions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamSharedDependencyVersions.js","sourceRoot":"","sources":["../../src/policies/GleamSharedDependencyVersions.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition } from \"../policy.js\";\nimport { parseToml } from \"../policyDefiners/tomlParser.js\";\n\n/**\n * Configuration for the GleamSharedDependencyVersions policy.\n *\n * @alpha\n */\nexport interface GleamSharedDependencyVersionsConfig {\n\t/**\n\t * If true, detect version mismatches across packages.\n\t * @defaultValue true\n\t */\n\tdetectMismatches?: boolean;\n\n\t/**\n\t * If true, also check dev-dependencies for mismatches.\n\t * @defaultValue false\n\t */\n\tincludeDev?: boolean;\n\n\t/**\n\t * Paths to gleam.toml files to compare (relative to repo root).\n\t */\n\tpackages?: string[];\n}\n\nfunction extractVersion(dep: unknown): string | undefined {\n\tif (typeof dep === \"string\") {\n\t\treturn dep;\n\t}\n\tif (typeof dep === \"object\" && dep !== null) {\n\t\tconst record = dep as Record<string, unknown>;\n\t\tif (typeof record.version === \"string\") {\n\t\t\treturn record.version;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction collectDeps(\n\ttoml: Record<string, unknown>,\n\tincludeDev: boolean,\n): Map<string, string> {\n\tconst deps = new Map<string, string>();\n\tconst sections = [\"dependencies\"];\n\tif (includeDev) {\n\t\tsections.push(\"dev-dependencies\");\n\t}\n\n\tfor (const section of sections) {\n\t\tconst sectionDeps = toml[section] as Record<string, unknown> | undefined;\n\t\tif (!sectionDeps) {\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const [name, value] of Object.entries(sectionDeps)) {\n\t\t\tconst version = extractVersion(value);\n\t\t\tif (version) {\n\t\t\t\tdeps.set(name, version);\n\t\t\t}\n\t\t}\n\t}\n\treturn deps;\n}\n\nfunction recordDependency(\n\tallDeps: Map<string, Map<string, string[]>>,\n\tdepName: string,\n\tversion: string,\n\tpkgPath: string,\n): void {\n\tif (!allDeps.has(depName)) {\n\t\tallDeps.set(depName, new Map());\n\t}\n\tconst versionMap = allDeps.get(depName);\n\tif (versionMap === undefined) {\n\t\treturn;\n\t}\n\tif (!versionMap.has(version)) {\n\t\tversionMap.set(version, []);\n\t}\n\tversionMap.get(version)?.push(pkgPath);\n}\n\n/**\n * A policy that detects dependency version mismatches across Gleam packages in a monorepo.\n *\n * @alpha\n */\nexport const GleamSharedDependencyVersions: PolicyDefinition<GleamSharedDependencyVersionsConfig> =\n\tmakePolicyDefinition({\n\t\tname: \"GleamSharedDependencyVersions\",\n\t\tdescription:\n\t\t\t\"Detects dependency version mismatches across Gleam packages in a monorepo.\",\n\t\tmatch: /^gleam\\.toml$/,\n\t\thandler: async ({ root, config }) => {\n\t\t\tconst packagePaths = config?.packages;\n\t\t\tif (!packagePaths || packagePaths.length < 2) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst detectMismatches = config?.detectMismatches ?? true;\n\t\t\tif (!detectMismatches) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst includeDev = config?.includeDev ?? false;\n\t\t\tconst allDeps = new Map<string, Map<string, string[]>>();\n\n\t\t\tfor (const pkgPath of packagePaths) {\n\t\t\t\ttry {\n\t\t\t\t\tconst content = await readFile(path.resolve(root, pkgPath), \"utf-8\");\n\t\t\t\t\tconst toml = await parseToml(content);\n\t\t\t\t\tconst deps = collectDeps(toml, includeDev);\n\n\t\t\t\t\tfor (const [name, version] of deps) {\n\t\t\t\t\t\trecordDependency(allDeps, name, version, pkgPath);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Package might not exist\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst errors: string[] = [];\n\t\t\tfor (const [dep, versionMap] of allDeps) {\n\t\t\t\tif (versionMap.size > 1) {\n\t\t\t\t\tconst details = [...versionMap.entries()]\n\t\t\t\t\t\t.map(([ver, pkgs]) => `\"${ver}\" in ${pkgs.join(\", \")}`)\n\t\t\t\t\t\t.join(\"; \");\n\t\t\t\t\terrors.push(`Version mismatch for \"${dep}\": ${details}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t\"Align dependency versions across all Gleam packages in the monorepo.\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
@@ -0,0 +1,30 @@
1
+ import type { PolicyShape } from "../policy.js";
2
+ /**
3
+ * Configuration for the GleamTomlRequired policy.
4
+ *
5
+ * @alpha
6
+ */
7
+ export interface GleamTomlRequiredConfig {
8
+ /**
9
+ * Top-level fields that must exist in gleam.toml.
10
+ * @defaultValue ["name", "version"]
11
+ */
12
+ required?: string[];
13
+ /**
14
+ * If true, require the `gleam` compiler version constraint.
15
+ * @defaultValue false
16
+ */
17
+ requireGleamVersion?: boolean;
18
+ /**
19
+ * If true, require the `[repository]` section.
20
+ * @defaultValue false
21
+ */
22
+ requireRepository?: boolean;
23
+ }
24
+ /**
25
+ * A policy that enforces required fields exist in gleam.toml.
26
+ *
27
+ * @alpha
28
+ */
29
+ export declare const GleamTomlRequired: PolicyShape<GleamTomlRequiredConfig>;
30
+ //# sourceMappingURL=GleamTomlRequired.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GleamTomlRequired.d.ts","sourceRoot":"","sources":["../../src/policies/GleamTomlRequired.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAcD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,uBAAuB,CA8BhE,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { defineGleamPolicy, } from "../policyDefiners/defineGleamPolicy.js";
2
+ const DEFAULT_REQUIRED_FIELDS = ["name", "version"];
3
+ function checkRequiredFields(toml, fields) {
4
+ const errors = [];
5
+ for (const field of fields) {
6
+ if (toml[field] === undefined || toml[field] === "") {
7
+ errors.push(`Missing required field: ${field}`);
8
+ }
9
+ }
10
+ return errors;
11
+ }
12
+ /**
13
+ * A policy that enforces required fields exist in gleam.toml.
14
+ *
15
+ * @alpha
16
+ */
17
+ export const GleamTomlRequired = defineGleamPolicy({
18
+ name: "GleamTomlRequired",
19
+ description: "Ensures gleam.toml files contain required fields for proper project configuration.",
20
+ handler: async (toml, { config }) => {
21
+ const errors = checkRequiredFields(toml, config?.required ?? DEFAULT_REQUIRED_FIELDS);
22
+ if (config?.requireGleamVersion && toml.gleam === undefined) {
23
+ errors.push('Missing gleam version constraint. Add gleam = ">= x.y.z" to gleam.toml.');
24
+ }
25
+ if (config?.requireRepository && toml.repository === undefined) {
26
+ errors.push("Missing [repository] section in gleam.toml.");
27
+ }
28
+ if (errors.length > 0) {
29
+ return {
30
+ error: errors.join("; "),
31
+ manualFix: "Add the missing fields to your gleam.toml file.",
32
+ };
33
+ }
34
+ return true;
35
+ },
36
+ });
37
+ //# sourceMappingURL=GleamTomlRequired.js.map