repopo 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +50 -90
  3. package/THIRD-PARTY-LICENSES.txt +169 -11
  4. package/bin/dev.js +0 -0
  5. package/esm/adapters/fluidFramework.d.ts +13 -9
  6. package/esm/adapters/fluidFramework.d.ts.map +1 -1
  7. package/esm/adapters/fluidFramework.js +20 -43
  8. package/esm/adapters/fluidFramework.js.map +1 -1
  9. package/esm/api.d.ts +64 -1
  10. package/esm/api.d.ts.map +1 -1
  11. package/esm/api.js +17 -1
  12. package/esm/api.js.map +1 -1
  13. package/esm/baseCommand.d.ts.map +1 -1
  14. package/esm/baseCommand.js +2 -2
  15. package/esm/baseCommand.js.map +1 -1
  16. package/esm/commands/check-native.d.ts +3 -3
  17. package/esm/commands/check-native.d.ts.map +1 -1
  18. package/esm/commands/check-native.js +26 -7
  19. package/esm/commands/check-native.js.map +1 -1
  20. package/esm/commands/check.d.ts +6 -21
  21. package/esm/commands/check.d.ts.map +1 -1
  22. package/esm/commands/check.js +73 -153
  23. package/esm/commands/check.js.map +1 -1
  24. package/esm/commands/list.d.ts.map +1 -1
  25. package/esm/commands/list.js +2 -1
  26. package/esm/commands/list.js.map +1 -1
  27. package/esm/concurrency.d.ts +3 -0
  28. package/esm/concurrency.d.ts.map +1 -0
  29. package/esm/concurrency.js +8 -0
  30. package/esm/concurrency.js.map +1 -0
  31. package/esm/config.d.ts +5 -39
  32. package/esm/config.d.ts.map +1 -1
  33. package/esm/config.js +3 -7
  34. package/esm/config.js.map +1 -1
  35. package/esm/context.d.ts +8 -1
  36. package/esm/context.d.ts.map +1 -1
  37. package/esm/context.js +8 -1
  38. package/esm/context.js.map +1 -1
  39. package/esm/executionContractError.d.ts +4 -0
  40. package/esm/executionContractError.d.ts.map +1 -0
  41. package/esm/executionContractError.js +4 -0
  42. package/esm/executionContractError.js.map +1 -0
  43. package/esm/fileCache.d.ts +12 -0
  44. package/esm/fileCache.d.ts.map +1 -0
  45. package/esm/fileCache.js +37 -0
  46. package/esm/fileCache.js.map +1 -0
  47. package/esm/filePaths.d.ts +2 -0
  48. package/esm/filePaths.d.ts.map +1 -0
  49. package/esm/filePaths.js +9 -0
  50. package/esm/filePaths.js.map +1 -0
  51. package/esm/generators.d.ts +0 -20
  52. package/esm/generators.d.ts.map +1 -1
  53. package/esm/generators.js.map +1 -1
  54. package/esm/index.d.ts +3 -16
  55. package/esm/index.d.ts.map +1 -1
  56. package/esm/index.js +3 -17
  57. package/esm/index.js.map +1 -1
  58. package/esm/makePolicy.d.ts +20 -100
  59. package/esm/makePolicy.d.ts.map +1 -1
  60. package/esm/makePolicy.js +44 -132
  61. package/esm/makePolicy.js.map +1 -1
  62. package/esm/perf.d.ts +5 -2
  63. package/esm/perf.d.ts.map +1 -1
  64. package/esm/perf.js +10 -9
  65. package/esm/perf.js.map +1 -1
  66. package/esm/policies/CargoLicenceValidated.d.ts +4 -4
  67. package/esm/policies/CargoLicenceValidated.d.ts.map +1 -1
  68. package/esm/policies/CargoLicenceValidated.js +9 -7
  69. package/esm/policies/CargoLicenceValidated.js.map +1 -1
  70. package/esm/policies/CargoLintsConfigured.d.ts +4 -4
  71. package/esm/policies/CargoLintsConfigured.d.ts.map +1 -1
  72. package/esm/policies/CargoLintsConfigured.js +19 -15
  73. package/esm/policies/CargoLintsConfigured.js.map +1 -1
  74. package/esm/policies/CargoLockPolicy.d.ts +4 -4
  75. package/esm/policies/CargoLockPolicy.d.ts.map +1 -1
  76. package/esm/policies/CargoLockPolicy.js +15 -11
  77. package/esm/policies/CargoLockPolicy.js.map +1 -1
  78. package/esm/policies/CargoTomlRequired.d.ts +5 -5
  79. package/esm/policies/CargoTomlRequired.d.ts.map +1 -1
  80. package/esm/policies/CargoTomlRequired.js +7 -7
  81. package/esm/policies/CargoTomlRequired.js.map +1 -1
  82. package/esm/policies/CargoTomlSorted.d.ts +4 -4
  83. package/esm/policies/CargoTomlSorted.d.ts.map +1 -1
  84. package/esm/policies/CargoTomlSorted.js +21 -17
  85. package/esm/policies/CargoTomlSorted.js.map +1 -1
  86. package/esm/policies/ConditionalScripts.d.ts +10 -8
  87. package/esm/policies/ConditionalScripts.d.ts.map +1 -1
  88. package/esm/policies/ConditionalScripts.js +24 -22
  89. package/esm/policies/ConditionalScripts.js.map +1 -1
  90. package/esm/policies/ExactScripts.d.ts +8 -6
  91. package/esm/policies/ExactScripts.d.ts.map +1 -1
  92. package/esm/policies/ExactScripts.js +15 -18
  93. package/esm/policies/ExactScripts.js.map +1 -1
  94. package/esm/policies/GleamDepVersions.d.ts +5 -5
  95. package/esm/policies/GleamDepVersions.d.ts.map +1 -1
  96. package/esm/policies/GleamDepVersions.js +5 -5
  97. package/esm/policies/GleamDepVersions.js.map +1 -1
  98. package/esm/policies/GleamDocExists.d.ts +4 -4
  99. package/esm/policies/GleamDocExists.d.ts.map +1 -1
  100. package/esm/policies/GleamDocExists.js +6 -6
  101. package/esm/policies/GleamDocExists.js.map +1 -1
  102. package/esm/policies/GleamInternalModulesConfigured.d.ts +4 -4
  103. package/esm/policies/GleamInternalModulesConfigured.d.ts.map +1 -1
  104. package/esm/policies/GleamInternalModulesConfigured.js +8 -6
  105. package/esm/policies/GleamInternalModulesConfigured.js.map +1 -1
  106. package/esm/policies/GleamLicenceConfigured.d.ts +4 -4
  107. package/esm/policies/GleamLicenceConfigured.d.ts.map +1 -1
  108. package/esm/policies/GleamLicenceConfigured.js +8 -6
  109. package/esm/policies/GleamLicenceConfigured.js.map +1 -1
  110. package/esm/policies/GleamManifestCommitted.d.ts +10 -3
  111. package/esm/policies/GleamManifestCommitted.d.ts.map +1 -1
  112. package/esm/policies/GleamManifestCommitted.js +10 -9
  113. package/esm/policies/GleamManifestCommitted.js.map +1 -1
  114. package/esm/policies/GleamMonorepoConsistency.d.ts +13 -5
  115. package/esm/policies/GleamMonorepoConsistency.d.ts.map +1 -1
  116. package/esm/policies/GleamMonorepoConsistency.js +10 -10
  117. package/esm/policies/GleamMonorepoConsistency.js.map +1 -1
  118. package/esm/policies/GleamNameRestrictions.d.ts +4 -4
  119. package/esm/policies/GleamNameRestrictions.d.ts.map +1 -1
  120. package/esm/policies/GleamNameRestrictions.js +6 -6
  121. package/esm/policies/GleamNameRestrictions.js.map +1 -1
  122. package/esm/policies/GleamNoPathDepsInPublished.d.ts +4 -4
  123. package/esm/policies/GleamNoPathDepsInPublished.d.ts.map +1 -1
  124. package/esm/policies/GleamNoPathDepsInPublished.js +6 -6
  125. package/esm/policies/GleamNoPathDepsInPublished.js.map +1 -1
  126. package/esm/policies/GleamPathDepsValid.d.ts +3 -3
  127. package/esm/policies/GleamPathDepsValid.d.ts.map +1 -1
  128. package/esm/policies/GleamPathDepsValid.js +5 -5
  129. package/esm/policies/GleamPathDepsValid.js.map +1 -1
  130. package/esm/policies/GleamProjectStructure.d.ts +11 -4
  131. package/esm/policies/GleamProjectStructure.d.ts.map +1 -1
  132. package/esm/policies/GleamProjectStructure.js +7 -8
  133. package/esm/policies/GleamProjectStructure.js.map +1 -1
  134. package/esm/policies/GleamSharedDependencyVersions.d.ts +12 -4
  135. package/esm/policies/GleamSharedDependencyVersions.d.ts.map +1 -1
  136. package/esm/policies/GleamSharedDependencyVersions.js +10 -10
  137. package/esm/policies/GleamSharedDependencyVersions.js.map +1 -1
  138. package/esm/policies/GleamTomlRequired.d.ts +4 -4
  139. package/esm/policies/GleamTomlRequired.d.ts.map +1 -1
  140. package/esm/policies/GleamTomlRequired.js +5 -5
  141. package/esm/policies/GleamTomlRequired.js.map +1 -1
  142. package/esm/policies/GleamTomlSorted.d.ts +4 -4
  143. package/esm/policies/GleamTomlSorted.d.ts.map +1 -1
  144. package/esm/policies/GleamTomlSorted.js +21 -17
  145. package/esm/policies/GleamTomlSorted.js.map +1 -1
  146. package/esm/policies/GleamVersionConstraint.d.ts +4 -4
  147. package/esm/policies/GleamVersionConstraint.d.ts.map +1 -1
  148. package/esm/policies/GleamVersionConstraint.js +14 -10
  149. package/esm/policies/GleamVersionConstraint.js.map +1 -1
  150. package/esm/policies/HtmlFileHeaders.d.ts +4 -2
  151. package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
  152. package/esm/policies/HtmlFileHeaders.js +1 -1
  153. package/esm/policies/HtmlFileHeaders.js.map +1 -1
  154. package/esm/policies/JsTsFileHeaders.d.ts +4 -2
  155. package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
  156. package/esm/policies/JsTsFileHeaders.js +1 -1
  157. package/esm/policies/JsTsFileHeaders.js.map +1 -1
  158. package/esm/policies/LicenseFileExists.d.ts +10 -4
  159. package/esm/policies/LicenseFileExists.d.ts.map +1 -1
  160. package/esm/policies/LicenseFileExists.js +27 -20
  161. package/esm/policies/LicenseFileExists.js.map +1 -1
  162. package/esm/policies/MutuallyExclusiveScripts.d.ts +8 -6
  163. package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -1
  164. package/esm/policies/MutuallyExclusiveScripts.js +9 -13
  165. package/esm/policies/MutuallyExclusiveScripts.js.map +1 -1
  166. package/esm/policies/NoBuildDirectory.d.ts +9 -3
  167. package/esm/policies/NoBuildDirectory.d.ts.map +1 -1
  168. package/esm/policies/NoBuildDirectory.js +8 -13
  169. package/esm/policies/NoBuildDirectory.js.map +1 -1
  170. package/esm/policies/NoJsFileExtensions.d.ts +9 -3
  171. package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
  172. package/esm/policies/NoJsFileExtensions.js +9 -14
  173. package/esm/policies/NoJsFileExtensions.js.map +1 -1
  174. package/esm/policies/NoLargeBinaryFiles.d.ts +9 -4
  175. package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
  176. package/esm/policies/NoLargeBinaryFiles.js +10 -16
  177. package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
  178. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +10 -6
  179. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  180. package/esm/policies/NoPrivateWorkspaceDependencies.js +12 -14
  181. package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
  182. package/esm/policies/NoTargetArtifacts.d.ts +9 -3
  183. package/esm/policies/NoTargetArtifacts.d.ts.map +1 -1
  184. package/esm/policies/NoTargetArtifacts.js +9 -14
  185. package/esm/policies/NoTargetArtifacts.js.map +1 -1
  186. package/esm/policies/NoUnsafeWithoutJustification.d.ts +11 -4
  187. package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -1
  188. package/esm/policies/NoUnsafeWithoutJustification.js +8 -9
  189. package/esm/policies/NoUnsafeWithoutJustification.js.map +1 -1
  190. package/esm/policies/NoWildcardDependencies.d.ts +5 -5
  191. package/esm/policies/NoWildcardDependencies.d.ts.map +1 -1
  192. package/esm/policies/NoWildcardDependencies.js +6 -6
  193. package/esm/policies/NoWildcardDependencies.js.map +1 -1
  194. package/esm/policies/PackageAllowedScopes.d.ts +9 -5
  195. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  196. package/esm/policies/PackageAllowedScopes.js +15 -16
  197. package/esm/policies/PackageAllowedScopes.js.map +1 -1
  198. package/esm/policies/PackageEsmType.d.ts +7 -5
  199. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  200. package/esm/policies/PackageEsmType.js +31 -31
  201. package/esm/policies/PackageEsmType.js.map +1 -1
  202. package/esm/policies/PackageFolderName.d.ts +8 -6
  203. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  204. package/esm/policies/PackageFolderName.js +13 -16
  205. package/esm/policies/PackageFolderName.js.map +1 -1
  206. package/esm/policies/PackageJsonProperties.d.ts +5 -3
  207. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  208. package/esm/policies/PackageJsonProperties.js +6 -17
  209. package/esm/policies/PackageJsonProperties.js.map +1 -1
  210. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +2 -7
  211. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  212. package/esm/policies/PackageJsonRepoDirectoryProperty.js +28 -42
  213. package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
  214. package/esm/policies/PackageJsonSorted.d.ts +2 -2
  215. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  216. package/esm/policies/PackageJsonSorted.js +15 -30
  217. package/esm/policies/PackageJsonSorted.js.map +1 -1
  218. package/esm/policies/PackageLicense.d.ts +4 -4
  219. package/esm/policies/PackageLicense.d.ts.map +1 -1
  220. package/esm/policies/PackageLicense.js +31 -52
  221. package/esm/policies/PackageLicense.js.map +1 -1
  222. package/esm/policies/PackagePrivateField.d.ts +12 -8
  223. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  224. package/esm/policies/PackagePrivateField.js +31 -23
  225. package/esm/policies/PackagePrivateField.js.map +1 -1
  226. package/esm/policies/PackageReadme.d.ts +6 -5
  227. package/esm/policies/PackageReadme.d.ts.map +1 -1
  228. package/esm/policies/PackageReadme.js +22 -59
  229. package/esm/policies/PackageReadme.js.map +1 -1
  230. package/esm/policies/PackageScripts.d.ts +26 -22
  231. package/esm/policies/PackageScripts.d.ts.map +1 -1
  232. package/esm/policies/PackageScripts.js +39 -36
  233. package/esm/policies/PackageScripts.js.map +1 -1
  234. package/esm/policies/PackageTestScripts.d.ts +10 -6
  235. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  236. package/esm/policies/PackageTestScripts.js +14 -16
  237. package/esm/policies/PackageTestScripts.js.map +1 -1
  238. package/esm/policies/PublicApiDocumented.d.ts +4 -4
  239. package/esm/policies/PublicApiDocumented.d.ts.map +1 -1
  240. package/esm/policies/PublicApiDocumented.js +10 -8
  241. package/esm/policies/PublicApiDocumented.js.map +1 -1
  242. package/esm/policies/RequiredGitignorePatterns.d.ts +11 -4
  243. package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
  244. package/esm/policies/RequiredGitignorePatterns.js +29 -36
  245. package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
  246. package/esm/policies/RequiredScripts.d.ts +9 -7
  247. package/esm/policies/RequiredScripts.d.ts.map +1 -1
  248. package/esm/policies/RequiredScripts.js +24 -24
  249. package/esm/policies/RequiredScripts.js.map +1 -1
  250. package/esm/policies/RustDocExists.d.ts +4 -4
  251. package/esm/policies/RustDocExists.d.ts.map +1 -1
  252. package/esm/policies/RustDocExists.js +6 -6
  253. package/esm/policies/RustDocExists.js.map +1 -1
  254. package/esm/policies/RustToolchainExists.d.ts +11 -4
  255. package/esm/policies/RustToolchainExists.d.ts.map +1 -1
  256. package/esm/policies/RustToolchainExists.js +10 -9
  257. package/esm/policies/RustToolchainExists.js.map +1 -1
  258. package/esm/policies/RustfmtConfigExists.d.ts +11 -4
  259. package/esm/policies/RustfmtConfigExists.d.ts.map +1 -1
  260. package/esm/policies/RustfmtConfigExists.js +10 -9
  261. package/esm/policies/RustfmtConfigExists.js.map +1 -1
  262. package/esm/policies/ScriptContains.d.ts +9 -7
  263. package/esm/policies/ScriptContains.d.ts.map +1 -1
  264. package/esm/policies/ScriptContains.js +9 -13
  265. package/esm/policies/ScriptContains.js.map +1 -1
  266. package/esm/policies/SharedDependencyVersions.d.ts +9 -4
  267. package/esm/policies/SharedDependencyVersions.d.ts.map +1 -1
  268. package/esm/policies/SharedDependencyVersions.js +28 -20
  269. package/esm/policies/SharedDependencyVersions.js.map +1 -1
  270. package/esm/policies/WorkspaceInheritance.d.ts +11 -4
  271. package/esm/policies/WorkspaceInheritance.d.ts.map +1 -1
  272. package/esm/policies/WorkspaceInheritance.js +10 -11
  273. package/esm/policies/WorkspaceInheritance.js.map +1 -1
  274. package/esm/policies/WorkspaceMembersValid.d.ts +11 -4
  275. package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -1
  276. package/esm/policies/WorkspaceMembersValid.js +10 -11
  277. package/esm/policies/WorkspaceMembersValid.js.map +1 -1
  278. package/esm/policies/constants.d.ts.map +1 -1
  279. package/esm/policies/constants.js +1 -1
  280. package/esm/policies/constants.js.map +1 -1
  281. package/esm/policies.d.ts +13 -5
  282. package/esm/policies.d.ts.map +1 -1
  283. package/esm/policies.js +12 -5
  284. package/esm/policies.js.map +1 -1
  285. package/esm/policy.d.ts +61 -289
  286. package/esm/policy.d.ts.map +1 -1
  287. package/esm/policy.js +1 -122
  288. package/esm/policy.js.map +1 -1
  289. package/esm/policyDefiners/defineCargoPolicy.d.ts +25 -9
  290. package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -1
  291. package/esm/policyDefiners/defineCargoPolicy.js +10 -28
  292. package/esm/policyDefiners/defineCargoPolicy.js.map +1 -1
  293. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +27 -14
  294. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  295. package/esm/policyDefiners/defineFileHeaderPolicy.js +16 -35
  296. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  297. package/esm/policyDefiners/defineGleamPolicy.d.ts +25 -9
  298. package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -1
  299. package/esm/policyDefiners/defineGleamPolicy.js +10 -27
  300. package/esm/policyDefiners/defineGleamPolicy.js.map +1 -1
  301. package/esm/policyDefiners/definePackagePolicy.d.ts +24 -13
  302. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  303. package/esm/policyDefiners/definePackagePolicy.js +9 -32
  304. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  305. package/esm/policyDefiners/spdxValidator.d.ts +4 -12
  306. package/esm/policyDefiners/spdxValidator.d.ts.map +1 -1
  307. package/esm/policyDefiners/spdxValidator.js +26 -14
  308. package/esm/policyDefiners/spdxValidator.js.map +1 -1
  309. package/esm/policyExecution.d.ts +19 -0
  310. package/esm/policyExecution.d.ts.map +1 -0
  311. package/esm/policyExecution.js +224 -0
  312. package/esm/policyExecution.js.map +1 -0
  313. package/esm/repositoryFiles.d.ts +4 -0
  314. package/esm/repositoryFiles.d.ts.map +1 -0
  315. package/esm/repositoryFiles.js +8 -0
  316. package/esm/repositoryFiles.js.map +1 -0
  317. package/esm/runner.d.ts +72 -47
  318. package/esm/runner.d.ts.map +1 -1
  319. package/esm/runner.js +153 -138
  320. package/esm/runner.js.map +1 -1
  321. package/esm/settlePolicyPromise.d.ts +4 -0
  322. package/esm/settlePolicyPromise.d.ts.map +1 -0
  323. package/esm/settlePolicyPromise.js +10 -0
  324. package/esm/settlePolicyPromise.js.map +1 -0
  325. package/esm/tsdoc-metadata.json +1 -1
  326. package/esm/utils/safePaths.d.ts +9 -0
  327. package/esm/utils/safePaths.d.ts.map +1 -0
  328. package/esm/utils/safePaths.js +40 -0
  329. package/esm/utils/safePaths.js.map +1 -0
  330. package/oclif.manifest.json +19 -2
  331. package/package.json +42 -27
  332. package/scripts/benchmark.mjs +341 -0
  333. package/sidecar/sidecar.mjs +348 -417
package/esm/runner.d.ts CHANGED
@@ -1,60 +1,85 @@
1
- import type { Logger } from "@tylerbu/cli-api";
2
1
  import { type Operation } from "effection";
3
- import { type ExcludedPolicyFileMap } from "./context.js";
4
2
  import { type PolicyHandlerPerfStats } from "./perf.js";
5
- import type { PolicyFixResult, PolicyHandlerResult, PolicyInstance, PolicyInstanceId, PolicyName } from "./policy.js";
6
- /**
7
- * Result of running a single policy on a single file.
8
- * @alpha
9
- */
10
- export interface PolicyFileResult {
3
+ import type { ConfiguredPolicy, PolicyFinding } from "./policy.js";
4
+ /** A finding with runner-owned identity and scope-safe location. @public */
5
+ export type PolicyRunFinding = (Omit<PolicyFinding, "files"> & {
6
+ scope: "file";
11
7
  file: string;
12
- policy: PolicyName;
13
- /** Stable identity of the configured policy instance */
14
- policyId: PolicyInstanceId;
15
- /** The raw result from the policy handler */
16
- outcome: PolicyHandlerResult;
17
- /** Set when a standalone resolver was attempted (legacy resolver path) */
18
- resolution?: PolicyFixResult;
19
- }
20
- /**
21
- * Aggregated results from a full policy run.
22
- * @alpha
23
- */
8
+ files?: never;
9
+ policy: string;
10
+ policyId: string;
11
+ }) | (PolicyFinding & {
12
+ scope: "repository";
13
+ file?: never;
14
+ policy: string;
15
+ policyId: string;
16
+ });
17
+ /** An execution failure, separate from ordinary policy findings. @public */
18
+ export type PolicyExecutionError = {
19
+ policy: string;
20
+ policyId: string;
21
+ phase: "handle" | "resolve";
22
+ kind: "contract" | "exception";
23
+ message: string;
24
+ cause: unknown;
25
+ } & ({
26
+ scope: "file";
27
+ file: string;
28
+ files?: never;
29
+ } | {
30
+ scope: "repository";
31
+ files: readonly string[];
32
+ file?: never;
33
+ });
34
+ /** A unit that was not executed. @public */
35
+ export type PolicySkippedWork = {
36
+ policy: string;
37
+ policyId: string;
38
+ reason: "excluded" | "file-fix-error" | "repository-fix-error";
39
+ } & ({
40
+ scope: "file";
41
+ file: string;
42
+ } | {
43
+ scope: "repository";
44
+ file?: never;
45
+ });
46
+ /** Findings, failures, skipped units, and file/per-instance timing statistics. @public */
24
47
  export interface PolicyRunResults {
25
- results: PolicyFileResult[];
48
+ findings: PolicyRunFinding[];
49
+ errors: PolicyExecutionError[];
50
+ skipped: PolicySkippedWork[];
26
51
  perfStats: PolicyHandlerPerfStats;
27
52
  }
28
- /**
29
- * Options for configuring a {@link PolicyRunner}.
30
- * @alpha
31
- */
53
+ /** Full repository inventory, never inferred from a file selection. @public */
54
+ export type RepositoryInventory = readonly string[] | (() => Promise<readonly string[]>);
55
+ /** Shared Promise and Effection runner options. @public */
32
56
  export interface PolicyRunnerOptions {
33
- policies: PolicyInstance[];
34
- excludeFromAll: RegExp[];
35
- excludePoliciesForFiles: ExcludedPolicyFileMap;
36
- gitRoot: string;
37
- resolve: boolean;
38
- logger?: Pick<Logger, "verbose">;
57
+ policies: readonly ConfiguredPolicy[];
58
+ root: string;
59
+ inventory?: RepositoryInventory | undefined;
60
+ /** Selection limits only file policies. Defaults to inventory when supplied. */
61
+ files?: readonly string[] | undefined;
62
+ exclude?: readonly (string | RegExp)[] | undefined;
63
+ fix?: boolean | undefined;
64
+ concurrency?: number | undefined;
65
+ signal?: AbortSignal | undefined;
39
66
  }
40
- /**
41
- * Runs configured policies against files and collects results.
42
- * @alpha
43
- */
67
+ /** Effection runner; cancellation unwinds active generator handlers and resolvers. @public */
44
68
  export declare class PolicyRunner {
69
+ private readonly options;
45
70
  private readonly policies;
46
- private readonly excludeFromAll;
47
- private readonly excludePoliciesForFiles;
48
- private readonly gitRoot;
49
- private readonly resolve;
50
- private readonly logger;
71
+ private readonly exclusions;
72
+ private readonly policyExclusions;
73
+ private readonly concurrency;
51
74
  constructor(options: PolicyRunnerOptions);
52
- run(filePaths: string[]): Operation<PolicyRunResults>;
53
- private checkOrExcludeFile;
54
- private routeToPolicies;
55
- private runPolicyOnFile;
56
- private isPolicyExcluded;
57
- private executePolicyHandler;
58
- private attemptResolution;
75
+ run(): Operation<PolicyRunResults>;
76
+ private runInternal;
77
+ private runReadOnlyFiles;
78
+ private runRepositories;
79
+ private loadInventory;
80
+ private excluded;
81
+ private runFile;
59
82
  }
83
+ /** Promise entry point sharing the Effection runner's contracts and cancellation. @public */
84
+ export declare function runPolicies(options: PolicyRunnerOptions): Promise<PolicyRunResults>;
60
85
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAEN,KAAK,qBAAqB,EAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEN,KAAK,sBAAsB,EAE3B,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAEX,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,UAAU,EAEV,MAAM,aAAa,CAAC;AA0BrB;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,wDAAwD;IACxD,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,6CAA6C;IAC7C,OAAO,EAAE,mBAAmB,CAAC;IAC7B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,SAAS,EAAE,sBAAsB,CAAC;CAClC;AAOD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,uBAAuB,EAAE,qBAAqB,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAwB;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;gBAE1C,OAAO,EAAE,mBAAmB;IAYvC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,gBAAgB,CAAC;IAgB7D,OAAO,CAAE,kBAAkB;IAc3B,OAAO,CAAE,eAAe;IA2BxB,OAAO,CAAE,eAAe;IAyDxB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAE,oBAAoB;IA2C7B,OAAO,CAAE,iBAAiB;CA4B1B"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
package/esm/runner.js CHANGED
@@ -1,174 +1,189 @@
1
- import { all, call } from "effection";
2
- import { createExcludedPolicyFileMap, } from "./context.js";
1
+ import { all, call, run, spawn } from "effection";
2
+ import { DEFAULT_CONCURRENCY, validateConcurrency } from "./concurrency.js";
3
+ import { createExcludedPolicyFileMap, exclusionRegex, } from "./context.js";
4
+ import { ParsedFileCache } from "./fileCache.js";
3
5
  import { identifyPolicyInstances } from "./makePolicy.js";
4
- import { newPerfStats, runWithPerf, } from "./perf.js";
5
- import { isPolicyError, isPolicyFixResult } from "./policy.js";
6
- function isOperation(value) {
7
- return (typeof value === "object" &&
8
- value !== null &&
9
- "next" in value &&
10
- typeof value.next === "function");
11
- }
12
- function matches(regex, value) {
13
- if (!(regex.global || regex.sticky)) {
14
- return regex.test(value);
15
- }
16
- const savedLastIndex = regex.lastIndex;
6
+ import { newPerfStats } from "./perf.js";
7
+ import { PolicyExecutor } from "./policyExecution.js";
8
+ function matches(regex, file) {
9
+ const index = regex.lastIndex;
17
10
  try {
18
11
  regex.lastIndex = 0;
19
- return regex.test(value);
12
+ return regex.test(file);
20
13
  }
21
14
  finally {
22
- regex.lastIndex = savedLastIndex;
15
+ regex.lastIndex = index;
23
16
  }
24
17
  }
25
- /**
26
- * Runs configured policies against files and collects results.
27
- * @alpha
28
- */
18
+ /** Effection runner; cancellation unwinds active generator handlers and resolvers. @public */
29
19
  export class PolicyRunner {
20
+ options;
30
21
  policies;
31
- excludeFromAll;
32
- excludePoliciesForFiles;
33
- gitRoot;
34
- resolve;
35
- logger;
22
+ exclusions;
23
+ policyExclusions;
24
+ concurrency;
36
25
  constructor(options) {
37
- this.policies = identifyPolicyInstances(options.policies);
38
- this.excludeFromAll = options.excludeFromAll;
39
- this.excludePoliciesForFiles = createExcludedPolicyFileMap(this.policies);
40
- for (const [instanceId, exclusions] of options.excludePoliciesForFiles) {
41
- this.excludePoliciesForFiles.set(instanceId, exclusions);
26
+ this.options = options;
27
+ this.policies = identifyPolicyInstances(options.policies.map((policy) => ({
28
+ ...policy,
29
+ config: policy.config === undefined ? policy.defaultConfig : policy.config,
30
+ })));
31
+ this.exclusions = (options.exclude ?? []).map(exclusionRegex);
32
+ this.policyExclusions = createExcludedPolicyFileMap(this.policies);
33
+ this.concurrency = validateConcurrency(options.concurrency ?? DEFAULT_CONCURRENCY);
34
+ if (this.policies.some((policy) => policy.scope === "repository") &&
35
+ options.inventory === undefined) {
36
+ throw new TypeError("Repository policies require an explicit inventory array or loader; files is only a selection.");
37
+ }
38
+ for (const policy of this.policies) {
39
+ if (policy.scope === "repository" && policy.resolver !== undefined) {
40
+ throw new TypeError("Repository policies support inline fixes only; remove resolver.");
41
+ }
42
+ if (policy.requiresConfig &&
43
+ policy.config === undefined &&
44
+ policy.defaultConfig === undefined) {
45
+ throw new TypeError(`Policy '${policy.name}' requires config.`);
46
+ }
42
47
  }
43
- this.gitRoot = options.gitRoot;
44
- this.resolve = options.resolve;
45
- this.logger = options.logger;
46
48
  }
47
- *run(filePaths) {
48
- const state = {
49
- results: [],
50
- perfStats: newPerfStats(),
51
- };
52
- for (const filePath of filePaths) {
53
- yield* this.checkOrExcludeFile(filePath, state);
49
+ *run() {
50
+ const signal = this.options.signal;
51
+ if (signal?.aborted) {
52
+ throw signal.reason;
54
53
  }
55
- return {
56
- results: state.results,
57
- perfStats: state.perfStats,
54
+ const task = yield* spawn(() => this.runInternal());
55
+ // halt() is lazy; consuming it initiates teardown. The task retains any teardown error.
56
+ const abort = () => {
57
+ task.halt().catch(() => undefined);
58
58
  };
59
- }
60
- *checkOrExcludeFile(relPath, state) {
61
- state.perfStats.count++;
59
+ signal?.addEventListener("abort", abort, { once: true });
62
60
  try {
63
- yield* this.routeToPolicies(relPath, state);
64
- }
65
- catch (error) {
66
- throw new Error(`Error routing ${relPath} to handler: ${error}\nStack:\n${error.stack}`);
67
- }
68
- }
69
- *routeToPolicies(relPath, state) {
70
- if (this.excludeFromAll.some((regex) => matches(regex, relPath))) {
71
- this.logger?.verbose(`Excluded all handlers: ${relPath}`);
72
- return;
73
- }
74
- const matchingPolicies = this.policies.filter((policy) => matches(policy.match, relPath));
75
- if (this.resolve) {
76
- // Fixers can read and rewrite the same file.
77
- for (const policy of matchingPolicies) {
78
- yield* this.runPolicyOnFile(relPath, policy, state);
61
+ if (signal?.aborted) {
62
+ abort();
79
63
  }
80
- return;
64
+ return yield* task;
65
+ }
66
+ finally {
67
+ signal?.removeEventListener("abort", abort);
81
68
  }
82
- yield* all(matchingPolicies.map((policy) => {
83
- return this.runPolicyOnFile(relPath, policy, state);
84
- }));
85
69
  }
86
- *runPolicyOnFile(relPath, policy, state) {
87
- if (this.isPolicyExcluded(relPath, policy)) {
88
- this.logger?.verbose(`Excluded from '${policy.instanceId}' policy: ${relPath}`);
89
- return;
70
+ *runInternal() {
71
+ const result = {
72
+ findings: [],
73
+ errors: [],
74
+ skipped: [],
75
+ perfStats: newPerfStats(),
76
+ };
77
+ const fix = this.options.fix ?? false;
78
+ const cache = fix ? undefined : new ParsedFileCache();
79
+ let inventory;
80
+ if (this.options.files === undefined) {
81
+ inventory = yield* this.loadInventory();
90
82
  }
83
+ const files = this.options.files ?? inventory ?? [];
84
+ let fileFixError = false;
91
85
  try {
92
- const result = yield* this.executePolicyHandler(relPath, policy, state);
93
- // Success — nothing to report
94
- if (result === true) {
95
- return;
86
+ if (fix) {
87
+ for (const file of files) {
88
+ if (yield* this.runFile(file, result, cache)) {
89
+ fileFixError = true;
90
+ }
91
+ }
96
92
  }
97
- const fileResult = {
98
- file: relPath,
99
- policy: policy.name,
100
- policyId: policy.instanceId,
101
- outcome: result,
102
- };
103
- // Check if resolution should be attempted: result is a failure that
104
- // wasn't already fixed, resolve mode is on, and a standalone resolver exists.
105
- const alreadyFixed = isPolicyFixResult(result) ||
106
- (isPolicyError(result) && result.fixed !== undefined);
107
- if (!alreadyFixed && this.resolve && policy.resolver) {
108
- const resolution = yield* this.attemptResolution(relPath, policy, policy.resolver, state);
109
- fileResult.resolution = resolution;
93
+ else {
94
+ yield* this.runReadOnlyFiles(files, result, cache);
110
95
  }
111
- state.results.push(fileResult);
112
96
  }
113
- catch (error) {
114
- const message = error instanceof Error ? error.message : String(error);
115
- state.results.push({
116
- file: relPath,
117
- policy: policy.name,
118
- policyId: policy.instanceId,
119
- outcome: {
120
- error: `System Error: Error executing policy '${policy.instanceId}' for file '${relPath}': ${message}`,
121
- },
122
- });
97
+ finally {
98
+ cache?.clear();
123
99
  }
100
+ yield* this.runRepositories(result, inventory, fileFixError);
101
+ return result;
124
102
  }
125
- isPolicyExcluded(relPath, policy) {
126
- return (this.excludePoliciesForFiles
127
- .get(policy.instanceId)
128
- ?.some((regex) => matches(regex, relPath)) ?? false);
103
+ *runReadOnlyFiles(files, result, cache) {
104
+ const entries = files.entries();
105
+ const outputs = [];
106
+ const runner = this;
107
+ yield* all(Array.from({ length: Math.min(this.concurrency, files.length) }, function* () {
108
+ for (let entry = entries.next(); !entry.done; entry = entries.next()) {
109
+ const [index, file] = entry.value;
110
+ const local = {
111
+ findings: [],
112
+ errors: [],
113
+ skipped: [],
114
+ perfStats: result.perfStats,
115
+ };
116
+ yield* runner.runFile(file, local, cache);
117
+ outputs[index] = local;
118
+ }
119
+ }));
120
+ for (const output of outputs) {
121
+ result.findings.push(...output.findings);
122
+ result.errors.push(...output.errors);
123
+ result.skipped.push(...output.skipped);
124
+ }
129
125
  }
130
- *executePolicyHandler(relPath, policy, state) {
131
- const { resolve, gitRoot } = this;
132
- const result = yield* runWithPerf(policy.instanceId, "handle", state.perfStats, function* () {
133
- const args = {
134
- file: relPath,
135
- root: gitRoot,
136
- resolve,
137
- config: policy.config,
138
- };
139
- if (policy._internalHandler) {
140
- return yield* policy._internalHandler(args);
126
+ *runRepositories(result, initialInventory, fileFixError) {
127
+ let inventory = initialInventory;
128
+ const fix = this.options.fix ?? false;
129
+ let repositoryFixError = false;
130
+ for (const policy of this.policies) {
131
+ if (policy.scope !== "repository") {
132
+ continue;
141
133
  }
142
- const handlerResult = policy.handler(args);
143
- if (handlerResult instanceof Promise) {
144
- return yield* call(() => handlerResult);
134
+ if (fileFixError || repositoryFixError) {
135
+ result.skipped.push({
136
+ scope: "repository",
137
+ policy: policy.name,
138
+ policyId: policy.instanceId,
139
+ reason: fileFixError ? "file-fix-error" : "repository-fix-error",
140
+ });
141
+ continue;
145
142
  }
146
- if (isOperation(handlerResult)) {
147
- return yield* handlerResult;
143
+ if (inventory === undefined || fix) {
144
+ inventory = yield* this.loadInventory();
148
145
  }
149
- throw new Error(`Unexpected handler result type: ${typeof handlerResult}`);
150
- });
151
- if (result === undefined) {
152
- throw new Error("Policy result was undefined.");
146
+ const eligible = (inventory ?? []).filter((file) => !this.excluded(file, policy));
147
+ repositoryFixError = yield* new PolicyExecutor(this.options.root, fix).repository(policy, eligible, result);
153
148
  }
154
- return result;
155
149
  }
156
- *attemptResolution(relPath, policy, resolver, state) {
157
- const { gitRoot } = this;
158
- return yield* runWithPerf(policy.instanceId, "resolve", state.perfStats, function* () {
159
- const result = resolver({
160
- file: relPath,
161
- root: gitRoot,
162
- config: policy.config,
163
- });
164
- if (result instanceof Promise) {
165
- return yield* call(() => result);
150
+ *loadInventory() {
151
+ const inventory = this.options.inventory;
152
+ return typeof inventory === "function" ? yield* call(inventory) : inventory;
153
+ }
154
+ excluded(file, policy) {
155
+ return (this.exclusions.some((regex) => matches(regex, file)) ||
156
+ (this.policyExclusions.get(policy.instanceId) ?? []).some((regex) => matches(regex, file)));
157
+ }
158
+ *runFile(file, output, cache) {
159
+ output.perfStats.count++;
160
+ const globallyExcluded = this.exclusions.some((regex) => matches(regex, file));
161
+ if (!globallyExcluded) {
162
+ output.perfStats.processed++;
163
+ }
164
+ let stopped = false;
165
+ for (const policy of this.policies) {
166
+ if (policy.scope === "repository" || !matches(policy.match, file)) {
167
+ continue;
166
168
  }
167
- if (isOperation(result)) {
168
- return yield* result;
169
+ if (stopped || this.excluded(file, policy)) {
170
+ output.skipped.push({
171
+ scope: "file",
172
+ file,
173
+ policy: policy.name,
174
+ policyId: policy.instanceId,
175
+ reason: stopped ? "file-fix-error" : "excluded",
176
+ });
177
+ continue;
169
178
  }
170
- throw new Error(`Unexpected resolver result type: ${typeof result}`);
171
- });
179
+ stopped = yield* new PolicyExecutor(this.options.root, this.options.fix ?? false).file(file, policy, output, cache);
180
+ }
181
+ return stopped;
172
182
  }
173
183
  }
184
+ /** Promise entry point sharing the Effection runner's contracts and cancellation. @public */
185
+ export async function runPolicies(options) {
186
+ const runner = new PolicyRunner(options);
187
+ return await run(() => runner.run());
188
+ }
174
189
  //# sourceMappingURL=runner.js.map
package/esm/runner.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Logger } from \"@tylerbu/cli-api\";\nimport { all, call, type Operation } from \"effection\";\n\nimport {\n\tcreateExcludedPolicyFileMap,\n\ttype ExcludedPolicyFileMap,\n} from \"./context.js\";\nimport { identifyPolicyInstances } from \"./makePolicy.js\";\nimport {\n\tnewPerfStats,\n\ttype PolicyHandlerPerfStats,\n\trunWithPerf,\n} from \"./perf.js\";\nimport type {\n\tIdentifiedPolicy,\n\tPolicyFixResult,\n\tPolicyHandlerResult,\n\tPolicyInstance,\n\tPolicyInstanceId,\n\tPolicyName,\n\tPolicyStandaloneResolver,\n} from \"./policy.js\";\nimport { isPolicyError, isPolicyFixResult } from \"./policy.js\";\n\nfunction isOperation<T>(value: unknown): value is Operation<T> {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"next\" in value &&\n\t\ttypeof (value as { next: unknown }).next === \"function\"\n\t);\n}\n\nfunction matches(regex: RegExp, value: string): boolean {\n\tif (!(regex.global || regex.sticky)) {\n\t\treturn regex.test(value);\n\t}\n\n\tconst savedLastIndex = regex.lastIndex;\n\ttry {\n\t\tregex.lastIndex = 0;\n\t\treturn regex.test(value);\n\t} finally {\n\t\tregex.lastIndex = savedLastIndex;\n\t}\n}\n\n/**\n * Result of running a single policy on a single file.\n * @alpha\n */\nexport interface PolicyFileResult {\n\tfile: string;\n\tpolicy: PolicyName;\n\t/** Stable identity of the configured policy instance */\n\tpolicyId: PolicyInstanceId;\n\t/** The raw result from the policy handler */\n\toutcome: PolicyHandlerResult;\n\t/** Set when a standalone resolver was attempted (legacy resolver path) */\n\tresolution?: PolicyFixResult;\n}\n\n/**\n * Aggregated results from a full policy run.\n * @alpha\n */\nexport interface PolicyRunResults {\n\tresults: PolicyFileResult[];\n\tperfStats: PolicyHandlerPerfStats;\n}\n\ninterface PolicyRunState {\n\tresults: PolicyFileResult[];\n\tperfStats: PolicyHandlerPerfStats;\n}\n\n/**\n * Options for configuring a {@link PolicyRunner}.\n * @alpha\n */\nexport interface PolicyRunnerOptions {\n\tpolicies: PolicyInstance[];\n\texcludeFromAll: RegExp[];\n\texcludePoliciesForFiles: ExcludedPolicyFileMap;\n\tgitRoot: string;\n\tresolve: boolean;\n\tlogger?: Pick<Logger, \"verbose\">;\n}\n\n/**\n * Runs configured policies against files and collects results.\n * @alpha\n */\nexport class PolicyRunner {\n\tprivate readonly policies: IdentifiedPolicy[];\n\tprivate readonly excludeFromAll: RegExp[];\n\tprivate readonly excludePoliciesForFiles: ExcludedPolicyFileMap;\n\tprivate readonly gitRoot: string;\n\tprivate readonly resolve: boolean;\n\tprivate readonly logger: Pick<Logger, \"verbose\"> | undefined;\n\n\tpublic constructor(options: PolicyRunnerOptions) {\n\t\tthis.policies = identifyPolicyInstances(options.policies);\n\t\tthis.excludeFromAll = options.excludeFromAll;\n\t\tthis.excludePoliciesForFiles = createExcludedPolicyFileMap(this.policies);\n\t\tfor (const [instanceId, exclusions] of options.excludePoliciesForFiles) {\n\t\t\tthis.excludePoliciesForFiles.set(instanceId, exclusions);\n\t\t}\n\t\tthis.gitRoot = options.gitRoot;\n\t\tthis.resolve = options.resolve;\n\t\tthis.logger = options.logger;\n\t}\n\n\tpublic *run(filePaths: string[]): Operation<PolicyRunResults> {\n\t\tconst state: PolicyRunState = {\n\t\t\tresults: [],\n\t\t\tperfStats: newPerfStats(),\n\t\t};\n\n\t\tfor (const filePath of filePaths) {\n\t\t\tyield* this.checkOrExcludeFile(filePath, state);\n\t\t}\n\n\t\treturn {\n\t\t\tresults: state.results,\n\t\t\tperfStats: state.perfStats,\n\t\t};\n\t}\n\n\tprivate *checkOrExcludeFile(\n\t\trelPath: string,\n\t\tstate: PolicyRunState,\n\t): Operation<void> {\n\t\tstate.perfStats.count++;\n\t\ttry {\n\t\t\tyield* this.routeToPolicies(relPath, state);\n\t\t} catch (error: unknown) {\n\t\t\tthrow new Error(\n\t\t\t\t`Error routing ${relPath} to handler: ${error}\\nStack:\\n${(error as Error).stack}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate *routeToPolicies(\n\t\trelPath: string,\n\t\tstate: PolicyRunState,\n\t): Operation<void> {\n\t\tif (this.excludeFromAll.some((regex) => matches(regex, relPath))) {\n\t\t\tthis.logger?.verbose(`Excluded all handlers: ${relPath}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst matchingPolicies = this.policies.filter((policy) =>\n\t\t\tmatches(policy.match, relPath),\n\t\t);\n\t\tif (this.resolve) {\n\t\t\t// Fixers can read and rewrite the same file.\n\t\t\tfor (const policy of matchingPolicies) {\n\t\t\t\tyield* this.runPolicyOnFile(relPath, policy, state);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tyield* all(\n\t\t\tmatchingPolicies.map((policy) => {\n\t\t\t\treturn this.runPolicyOnFile(relPath, policy, state);\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate *runPolicyOnFile(\n\t\trelPath: string,\n\t\tpolicy: IdentifiedPolicy,\n\t\tstate: PolicyRunState,\n\t): Operation<void> {\n\t\tif (this.isPolicyExcluded(relPath, policy)) {\n\t\t\tthis.logger?.verbose(\n\t\t\t\t`Excluded from '${policy.instanceId}' policy: ${relPath}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = yield* this.executePolicyHandler(relPath, policy, state);\n\n\t\t\t// Success — nothing to report\n\t\t\tif (result === true) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst fileResult: PolicyFileResult = {\n\t\t\t\tfile: relPath,\n\t\t\t\tpolicy: policy.name,\n\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t\toutcome: result,\n\t\t\t};\n\n\t\t\t// Check if resolution should be attempted: result is a failure that\n\t\t\t// wasn't already fixed, resolve mode is on, and a standalone resolver exists.\n\t\t\tconst alreadyFixed =\n\t\t\t\tisPolicyFixResult(result) ||\n\t\t\t\t(isPolicyError(result) && result.fixed !== undefined);\n\n\t\t\tif (!alreadyFixed && this.resolve && policy.resolver) {\n\t\t\t\tconst resolution = yield* this.attemptResolution(\n\t\t\t\t\trelPath,\n\t\t\t\t\tpolicy,\n\t\t\t\t\tpolicy.resolver,\n\t\t\t\t\tstate,\n\t\t\t\t);\n\t\t\t\tfileResult.resolution = resolution;\n\t\t\t}\n\n\t\t\tstate.results.push(fileResult);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tstate.results.push({\n\t\t\t\tfile: relPath,\n\t\t\t\tpolicy: policy.name,\n\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t\toutcome: {\n\t\t\t\t\terror: `System Error: Error executing policy '${policy.instanceId}' for file '${relPath}': ${message}`,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate isPolicyExcluded(relPath: string, policy: IdentifiedPolicy): boolean {\n\t\treturn (\n\t\t\tthis.excludePoliciesForFiles\n\t\t\t\t.get(policy.instanceId)\n\t\t\t\t?.some((regex) => matches(regex, relPath)) ?? false\n\t\t);\n\t}\n\n\tprivate *executePolicyHandler(\n\t\trelPath: string,\n\t\tpolicy: IdentifiedPolicy,\n\t\tstate: PolicyRunState,\n\t): Operation<PolicyHandlerResult> {\n\t\tconst { resolve, gitRoot } = this;\n\n\t\tconst result = yield* runWithPerf(\n\t\t\tpolicy.instanceId,\n\t\t\t\"handle\",\n\t\t\tstate.perfStats,\n\t\t\tfunction* () {\n\t\t\t\tconst args = {\n\t\t\t\t\tfile: relPath,\n\t\t\t\t\troot: gitRoot,\n\t\t\t\t\tresolve,\n\t\t\t\t\tconfig: policy.config,\n\t\t\t\t};\n\n\t\t\t\tif (policy._internalHandler) {\n\t\t\t\t\treturn yield* policy._internalHandler(args);\n\t\t\t\t}\n\n\t\t\t\tconst handlerResult = policy.handler(args);\n\t\t\t\tif (handlerResult instanceof Promise) {\n\t\t\t\t\treturn yield* call(() => handlerResult);\n\t\t\t\t}\n\t\t\t\tif (isOperation<PolicyHandlerResult>(handlerResult)) {\n\t\t\t\t\treturn yield* handlerResult;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Unexpected handler result type: ${typeof handlerResult}`,\n\t\t\t\t);\n\t\t\t},\n\t\t);\n\n\t\tif (result === undefined) {\n\t\t\tthrow new Error(\"Policy result was undefined.\");\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate *attemptResolution(\n\t\trelPath: string,\n\t\tpolicy: IdentifiedPolicy,\n\t\tresolver: PolicyStandaloneResolver,\n\t\tstate: PolicyRunState,\n\t): Operation<PolicyFixResult> {\n\t\tconst { gitRoot } = this;\n\n\t\treturn yield* runWithPerf(\n\t\t\tpolicy.instanceId,\n\t\t\t\"resolve\",\n\t\t\tstate.perfStats,\n\t\t\tfunction* () {\n\t\t\t\tconst result = resolver({\n\t\t\t\t\tfile: relPath,\n\t\t\t\t\troot: gitRoot,\n\t\t\t\t\tconfig: policy.config,\n\t\t\t\t});\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\treturn yield* call(() => result);\n\t\t\t\t}\n\t\t\t\tif (isOperation<PolicyFixResult>(result)) {\n\t\t\t\t\treturn yield* result;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Unexpected resolver result type: ${typeof result}`);\n\t\t\t},\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { all, call, type Operation, run, spawn } from \"effection\";\nimport { DEFAULT_CONCURRENCY, validateConcurrency } from \"./concurrency.js\";\nimport {\n\tcreateExcludedPolicyFileMap,\n\ttype ExcludedPolicyFileMap,\n\texclusionRegex,\n} from \"./context.js\";\nimport { ParsedFileCache } from \"./fileCache.js\";\nimport { identifyPolicyInstances } from \"./makePolicy.js\";\nimport { newPerfStats, type PolicyHandlerPerfStats } from \"./perf.js\";\nimport type {\n\tConfiguredPolicy,\n\tIdentifiedPolicy,\n\tPolicyFinding,\n} from \"./policy.js\";\nimport { PolicyExecutor } from \"./policyExecution.js\";\n\n/** A finding with runner-owned identity and scope-safe location. @public */\nexport type PolicyRunFinding =\n\t| (Omit<PolicyFinding, \"files\"> & {\n\t\t\tscope: \"file\";\n\t\t\tfile: string;\n\t\t\tfiles?: never;\n\t\t\tpolicy: string;\n\t\t\tpolicyId: string;\n\t })\n\t| (PolicyFinding & {\n\t\t\tscope: \"repository\";\n\t\t\tfile?: never;\n\t\t\tpolicy: string;\n\t\t\tpolicyId: string;\n\t });\n\n/** An execution failure, separate from ordinary policy findings. @public */\nexport type PolicyExecutionError = {\n\tpolicy: string;\n\tpolicyId: string;\n\tphase: \"handle\" | \"resolve\";\n\tkind: \"contract\" | \"exception\";\n\tmessage: string;\n\tcause: unknown;\n} & (\n\t| { scope: \"file\"; file: string; files?: never }\n\t| { scope: \"repository\"; files: readonly string[]; file?: never }\n);\n\n/** A unit that was not executed. @public */\nexport type PolicySkippedWork = {\n\tpolicy: string;\n\tpolicyId: string;\n\treason: \"excluded\" | \"file-fix-error\" | \"repository-fix-error\";\n} & ({ scope: \"file\"; file: string } | { scope: \"repository\"; file?: never });\n\n/** Findings, failures, skipped units, and file/per-instance timing statistics. @public */\nexport interface PolicyRunResults {\n\tfindings: PolicyRunFinding[];\n\terrors: PolicyExecutionError[];\n\tskipped: PolicySkippedWork[];\n\tperfStats: PolicyHandlerPerfStats;\n}\n\n/** Full repository inventory, never inferred from a file selection. @public */\nexport type RepositoryInventory =\n\t| readonly string[]\n\t| (() => Promise<readonly string[]>);\n\n/** Shared Promise and Effection runner options. @public */\nexport interface PolicyRunnerOptions {\n\tpolicies: readonly ConfiguredPolicy[];\n\troot: string;\n\tinventory?: RepositoryInventory | undefined;\n\t/** Selection limits only file policies. Defaults to inventory when supplied. */\n\tfiles?: readonly string[] | undefined;\n\texclude?: readonly (string | RegExp)[] | undefined;\n\tfix?: boolean | undefined;\n\tconcurrency?: number | undefined;\n\tsignal?: AbortSignal | undefined;\n}\n\nfunction matches(regex: RegExp, file: string): boolean {\n\tconst index = regex.lastIndex;\n\ttry {\n\t\tregex.lastIndex = 0;\n\t\treturn regex.test(file);\n\t} finally {\n\t\tregex.lastIndex = index;\n\t}\n}\n\n/** Effection runner; cancellation unwinds active generator handlers and resolvers. @public */\nexport class PolicyRunner {\n\tprivate readonly policies: IdentifiedPolicy[];\n\tprivate readonly exclusions: RegExp[];\n\tprivate readonly policyExclusions: ExcludedPolicyFileMap;\n\tprivate readonly concurrency: number;\n\n\tpublic constructor(private readonly options: PolicyRunnerOptions) {\n\t\tthis.policies = identifyPolicyInstances(\n\t\t\toptions.policies.map((policy) => ({\n\t\t\t\t...policy,\n\t\t\t\tconfig:\n\t\t\t\t\tpolicy.config === undefined ? policy.defaultConfig : policy.config,\n\t\t\t})),\n\t\t);\n\t\tthis.exclusions = (options.exclude ?? []).map(exclusionRegex);\n\t\tthis.policyExclusions = createExcludedPolicyFileMap(this.policies);\n\t\tthis.concurrency = validateConcurrency(\n\t\t\toptions.concurrency ?? DEFAULT_CONCURRENCY,\n\t\t);\n\t\tif (\n\t\t\tthis.policies.some((policy) => policy.scope === \"repository\") &&\n\t\t\toptions.inventory === undefined\n\t\t) {\n\t\t\tthrow new TypeError(\n\t\t\t\t\"Repository policies require an explicit inventory array or loader; files is only a selection.\",\n\t\t\t);\n\t\t}\n\t\tfor (const policy of this.policies) {\n\t\t\tif (policy.scope === \"repository\" && policy.resolver !== undefined) {\n\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\"Repository policies support inline fixes only; remove resolver.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tpolicy.requiresConfig &&\n\t\t\t\tpolicy.config === undefined &&\n\t\t\t\tpolicy.defaultConfig === undefined\n\t\t\t) {\n\t\t\t\tthrow new TypeError(`Policy '${policy.name}' requires config.`);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic *run(): Operation<PolicyRunResults> {\n\t\tconst signal = this.options.signal;\n\t\tif (signal?.aborted) {\n\t\t\tthrow signal.reason;\n\t\t}\n\t\tconst task = yield* spawn(() => this.runInternal());\n\t\t// halt() is lazy; consuming it initiates teardown. The task retains any teardown error.\n\t\tconst abort = () => {\n\t\t\ttask.halt().catch(() => undefined);\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\ttry {\n\t\t\tif (signal?.aborted) {\n\t\t\t\tabort();\n\t\t\t}\n\t\t\treturn yield* task;\n\t\t} finally {\n\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t}\n\t}\n\n\tprivate *runInternal(): Operation<PolicyRunResults> {\n\t\tconst result: PolicyRunResults = {\n\t\t\tfindings: [],\n\t\t\terrors: [],\n\t\t\tskipped: [],\n\t\t\tperfStats: newPerfStats(),\n\t\t};\n\t\tconst fix = this.options.fix ?? false;\n\t\tconst cache = fix ? undefined : new ParsedFileCache();\n\t\tlet inventory: readonly string[] | undefined;\n\t\tif (this.options.files === undefined) {\n\t\t\tinventory = yield* this.loadInventory();\n\t\t}\n\t\tconst files = this.options.files ?? inventory ?? [];\n\t\tlet fileFixError = false;\n\t\ttry {\n\t\t\tif (fix) {\n\t\t\t\tfor (const file of files) {\n\t\t\t\t\tif (yield* this.runFile(file, result, cache)) {\n\t\t\t\t\t\tfileFixError = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tyield* this.runReadOnlyFiles(files, result, cache);\n\t\t\t}\n\t\t} finally {\n\t\t\tcache?.clear();\n\t\t}\n\t\tyield* this.runRepositories(result, inventory, fileFixError);\n\t\treturn result;\n\t}\n\n\tprivate *runReadOnlyFiles(\n\t\tfiles: readonly string[],\n\t\tresult: PolicyRunResults,\n\t\tcache: ParsedFileCache | undefined,\n\t): Operation<void> {\n\t\tconst entries = files.entries();\n\t\tconst outputs: PolicyRunResults[] = [];\n\t\tconst runner = this;\n\t\tyield* all(\n\t\t\tArray.from(\n\t\t\t\t{ length: Math.min(this.concurrency, files.length) },\n\t\t\t\tfunction* () {\n\t\t\t\t\tfor (\n\t\t\t\t\t\tlet entry = entries.next();\n\t\t\t\t\t\t!entry.done;\n\t\t\t\t\t\tentry = entries.next()\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst [index, file] = entry.value;\n\t\t\t\t\t\tconst local: PolicyRunResults = {\n\t\t\t\t\t\t\tfindings: [],\n\t\t\t\t\t\t\terrors: [],\n\t\t\t\t\t\t\tskipped: [],\n\t\t\t\t\t\t\tperfStats: result.perfStats,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tyield* runner.runFile(file, local, cache);\n\t\t\t\t\t\toutputs[index] = local;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t\tfor (const output of outputs) {\n\t\t\tresult.findings.push(...output.findings);\n\t\t\tresult.errors.push(...output.errors);\n\t\t\tresult.skipped.push(...output.skipped);\n\t\t}\n\t}\n\n\tprivate *runRepositories(\n\t\tresult: PolicyRunResults,\n\t\tinitialInventory: readonly string[] | undefined,\n\t\tfileFixError: boolean,\n\t): Operation<void> {\n\t\tlet inventory = initialInventory;\n\t\tconst fix = this.options.fix ?? false;\n\t\tlet repositoryFixError = false;\n\t\tfor (const policy of this.policies) {\n\t\t\tif (policy.scope !== \"repository\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (fileFixError || repositoryFixError) {\n\t\t\t\tresult.skipped.push({\n\t\t\t\t\tscope: \"repository\",\n\t\t\t\t\tpolicy: policy.name,\n\t\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t\t\treason: fileFixError ? \"file-fix-error\" : \"repository-fix-error\",\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (inventory === undefined || fix) {\n\t\t\t\tinventory = yield* this.loadInventory();\n\t\t\t}\n\t\t\tconst eligible = (inventory ?? []).filter(\n\t\t\t\t(file) => !this.excluded(file, policy),\n\t\t\t);\n\t\t\trepositoryFixError = yield* new PolicyExecutor(\n\t\t\t\tthis.options.root,\n\t\t\t\tfix,\n\t\t\t).repository(policy, eligible, result);\n\t\t}\n\t}\n\n\tprivate *loadInventory(): Operation<readonly string[] | undefined> {\n\t\tconst inventory = this.options.inventory;\n\t\treturn typeof inventory === \"function\" ? yield* call(inventory) : inventory;\n\t}\n\n\tprivate excluded(file: string, policy: IdentifiedPolicy): boolean {\n\t\treturn (\n\t\t\tthis.exclusions.some((regex) => matches(regex, file)) ||\n\t\t\t(this.policyExclusions.get(policy.instanceId) ?? []).some((regex) =>\n\t\t\t\tmatches(regex, file),\n\t\t\t)\n\t\t);\n\t}\n\n\tprivate *runFile(\n\t\tfile: string,\n\t\toutput: PolicyRunResults,\n\t\tcache: ParsedFileCache | undefined,\n\t): Operation<boolean> {\n\t\toutput.perfStats.count++;\n\t\tconst globallyExcluded = this.exclusions.some((regex) =>\n\t\t\tmatches(regex, file),\n\t\t);\n\t\tif (!globallyExcluded) {\n\t\t\toutput.perfStats.processed++;\n\t\t}\n\t\tlet stopped = false;\n\t\tfor (const policy of this.policies) {\n\t\t\tif (policy.scope === \"repository\" || !matches(policy.match, file)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (stopped || this.excluded(file, policy)) {\n\t\t\t\toutput.skipped.push({\n\t\t\t\t\tscope: \"file\",\n\t\t\t\t\tfile,\n\t\t\t\t\tpolicy: policy.name,\n\t\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t\t\treason: stopped ? \"file-fix-error\" : \"excluded\",\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstopped = yield* new PolicyExecutor(\n\t\t\t\tthis.options.root,\n\t\t\t\tthis.options.fix ?? false,\n\t\t\t).file(file, policy, output, cache);\n\t\t}\n\t\treturn stopped;\n\t}\n}\n\n/** Promise entry point sharing the Effection runner's contracts and cancellation. @public */\nexport async function runPolicies(\n\toptions: PolicyRunnerOptions,\n): Promise<PolicyRunResults> {\n\tconst runner = new PolicyRunner(options);\n\treturn await run(() => runner.run());\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { type Operation } from "effection";
2
+ /** Keep arbitrary rejected values out of Effection's error normalization. */
3
+ export declare function settlePolicyPromise<T>(promise: Promise<T>): Operation<T>;
4
+ //# sourceMappingURL=settlePolicyPromise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settlePolicyPromise.d.ts","sourceRoot":"","sources":["../src/settlePolicyPromise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEjD,6EAA6E;AAC7E,wBAAiB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAWzE"}
@@ -0,0 +1,10 @@
1
+ import { call } from "effection";
2
+ /** Keep arbitrary rejected values out of Effection's error normalization. */
3
+ export function* settlePolicyPromise(promise) {
4
+ const settled = yield* call(() => promise.then((value) => ({ ok: true, value }), (cause) => ({ ok: false, cause })));
5
+ if (!settled.ok) {
6
+ throw settled.cause;
7
+ }
8
+ return settled.value;
9
+ }
10
+ //# sourceMappingURL=settlePolicyPromise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settlePolicyPromise.js","sourceRoot":"","sources":["../src/settlePolicyPromise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,WAAW,CAAC;AAEjD,6EAA6E;AAC7E,MAAM,SAAS,CAAC,CAAC,mBAAmB,CAAI,OAAmB;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAChC,OAAO,CAAC,IAAI,CACX,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAU,EACzC,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAU,CACnD,CACD,CAAC;IACF,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,OAAO,CAAC,KAAK,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC;AACtB,CAAC","sourcesContent":["import { call, type Operation } from \"effection\";\n\n/** Keep arbitrary rejected values out of Effection's error normalization. */\nexport function* settlePolicyPromise<T>(promise: Promise<T>): Operation<T> {\n\tconst settled = yield* call(() =>\n\t\tpromise.then(\n\t\t\t(value) => ({ ok: true, value }) as const,\n\t\t\t(cause: unknown) => ({ ok: false, cause }) as const,\n\t\t),\n\t);\n\tif (!settled.ok) {\n\t\tthrow settled.cause;\n\t}\n\treturn settled.value;\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.58.11"
8
+ "packageVersion": "7.59.4"
9
9
  }
10
10
  ]
11
11
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolves a candidate file path against the repository root and verifies it does not escape that root.
3
+ */
4
+ export declare function resolveRepoFilePath(root: string, filePath: string): string;
5
+ /**
6
+ * Converts an input path into a normalized repository-relative path after validating root containment.
7
+ */
8
+ export declare function normalizeRepoRelativeFilePath(root: string, filePath: string): string;
9
+ //# sourceMappingURL=safePaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safePaths.d.ts","sourceRoot":"","sources":["../../src/utils/safePaths.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAe1E;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACd,MAAM,CAaR"}