repopo 0.10.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.
- package/CHANGELOG.md +113 -0
- package/README.md +76 -77
- package/THIRD-PARTY-LICENSES.txt +232 -14
- package/bin/dev.js +5 -1
- package/esm/adapters/fluidFramework.d.ts +13 -9
- package/esm/adapters/fluidFramework.d.ts.map +1 -1
- package/esm/adapters/fluidFramework.js +20 -43
- package/esm/adapters/fluidFramework.js.map +1 -1
- package/esm/api.d.ts +64 -1
- package/esm/api.d.ts.map +1 -1
- package/esm/api.js +17 -1
- package/esm/api.js.map +1 -1
- package/esm/baseCommand.d.ts +1 -1
- package/esm/baseCommand.d.ts.map +1 -1
- package/esm/baseCommand.js +7 -10
- package/esm/baseCommand.js.map +1 -1
- package/esm/commands/check-native.d.ts +25 -0
- package/esm/commands/check-native.d.ts.map +1 -0
- package/esm/commands/check-native.js +156 -0
- package/esm/commands/check-native.js.map +1 -0
- package/esm/commands/check.d.ts +7 -34
- package/esm/commands/check.d.ts.map +1 -1
- package/esm/commands/check.js +76 -265
- package/esm/commands/check.js.map +1 -1
- package/esm/commands/list.d.ts.map +1 -1
- package/esm/commands/list.js +6 -6
- package/esm/commands/list.js.map +1 -1
- package/esm/concurrency.d.ts +3 -0
- package/esm/concurrency.d.ts.map +1 -0
- package/esm/concurrency.js +8 -0
- package/esm/concurrency.js.map +1 -0
- package/esm/config.d.ts +5 -39
- package/esm/config.d.ts.map +1 -1
- package/esm/config.js +3 -7
- package/esm/config.js.map +1 -1
- package/esm/context.d.ts +20 -3
- package/esm/context.d.ts.map +1 -1
- package/esm/context.js +18 -1
- package/esm/context.js.map +1 -1
- package/esm/executionContractError.d.ts +4 -0
- package/esm/executionContractError.d.ts.map +1 -0
- package/esm/executionContractError.js +4 -0
- package/esm/executionContractError.js.map +1 -0
- package/esm/fileCache.d.ts +12 -0
- package/esm/fileCache.d.ts.map +1 -0
- package/esm/fileCache.js +37 -0
- package/esm/fileCache.js.map +1 -0
- package/esm/filePaths.d.ts +2 -0
- package/esm/filePaths.d.ts.map +1 -0
- package/esm/filePaths.js +9 -0
- package/esm/filePaths.js.map +1 -0
- package/esm/generators.d.ts +0 -20
- package/esm/generators.d.ts.map +1 -1
- package/esm/generators.js.map +1 -1
- package/esm/index.d.ts +3 -11
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -14
- package/esm/index.js.map +1 -1
- package/esm/makePolicy.d.ts +26 -79
- package/esm/makePolicy.d.ts.map +1 -1
- package/esm/makePolicy.js +51 -95
- package/esm/makePolicy.js.map +1 -1
- package/esm/perf.d.ts +10 -2
- package/esm/perf.d.ts.map +1 -1
- package/esm/perf.js +10 -9
- package/esm/perf.js.map +1 -1
- package/esm/policies/CargoLicenceValidated.d.ts +41 -0
- package/esm/policies/CargoLicenceValidated.d.ts.map +1 -0
- package/esm/policies/CargoLicenceValidated.js +47 -0
- package/esm/policies/CargoLicenceValidated.js.map +1 -0
- package/esm/policies/CargoLintsConfigured.d.ts +30 -0
- package/esm/policies/CargoLintsConfigured.d.ts.map +1 -0
- package/esm/policies/CargoLintsConfigured.js +65 -0
- package/esm/policies/CargoLintsConfigured.js.map +1 -0
- package/esm/policies/CargoLockPolicy.d.ts +34 -0
- package/esm/policies/CargoLockPolicy.d.ts.map +1 -0
- package/esm/policies/CargoLockPolicy.js +61 -0
- package/esm/policies/CargoLockPolicy.js.map +1 -0
- package/esm/policies/CargoTomlRequired.d.ts +34 -0
- package/esm/policies/CargoTomlRequired.d.ts.map +1 -0
- package/esm/policies/CargoTomlRequired.js +77 -0
- package/esm/policies/CargoTomlRequired.js.map +1 -0
- package/esm/policies/CargoTomlSorted.d.ts +20 -0
- package/esm/policies/CargoTomlSorted.d.ts.map +1 -0
- package/esm/policies/CargoTomlSorted.js +168 -0
- package/esm/policies/CargoTomlSorted.js.map +1 -0
- package/esm/policies/ConditionalScripts.d.ts +10 -8
- package/esm/policies/ConditionalScripts.d.ts.map +1 -1
- package/esm/policies/ConditionalScripts.js +27 -24
- package/esm/policies/ConditionalScripts.js.map +1 -1
- package/esm/policies/ExactScripts.d.ts +8 -6
- package/esm/policies/ExactScripts.d.ts.map +1 -1
- package/esm/policies/ExactScripts.js +18 -20
- package/esm/policies/ExactScripts.js.map +1 -1
- package/esm/policies/GleamDepVersions.d.ts +25 -0
- package/esm/policies/GleamDepVersions.d.ts.map +1 -0
- package/esm/policies/GleamDepVersions.js +67 -0
- package/esm/policies/GleamDepVersions.js.map +1 -0
- package/esm/policies/GleamDocExists.d.ts +24 -0
- package/esm/policies/GleamDocExists.d.ts.map +1 -0
- package/esm/policies/GleamDocExists.js +39 -0
- package/esm/policies/GleamDocExists.js.map +1 -0
- package/esm/policies/GleamInternalModulesConfigured.d.ts +21 -0
- package/esm/policies/GleamInternalModulesConfigured.d.ts.map +1 -0
- package/esm/policies/GleamInternalModulesConfigured.js +32 -0
- package/esm/policies/GleamInternalModulesConfigured.js.map +1 -0
- package/esm/policies/GleamLicenceConfigured.d.ts +29 -0
- package/esm/policies/GleamLicenceConfigured.d.ts.map +1 -0
- package/esm/policies/GleamLicenceConfigured.js +36 -0
- package/esm/policies/GleamLicenceConfigured.js.map +1 -0
- package/esm/policies/GleamManifestCommitted.d.ts +16 -0
- package/esm/policies/GleamManifestCommitted.d.ts.map +1 -0
- package/esm/policies/GleamManifestCommitted.js +27 -0
- package/esm/policies/GleamManifestCommitted.js.map +1 -0
- package/esm/policies/GleamMonorepoConsistency.d.ts +38 -0
- package/esm/policies/GleamMonorepoConsistency.d.ts.map +1 -0
- package/esm/policies/GleamMonorepoConsistency.js +74 -0
- package/esm/policies/GleamMonorepoConsistency.js.map +1 -0
- package/esm/policies/GleamNameRestrictions.d.ts +25 -0
- package/esm/policies/GleamNameRestrictions.d.ts.map +1 -0
- package/esm/policies/GleamNameRestrictions.js +44 -0
- package/esm/policies/GleamNameRestrictions.js.map +1 -0
- package/esm/policies/GleamNoPathDepsInPublished.d.ts +22 -0
- package/esm/policies/GleamNoPathDepsInPublished.d.ts.map +1 -0
- package/esm/policies/GleamNoPathDepsInPublished.js +43 -0
- package/esm/policies/GleamNoPathDepsInPublished.js.map +1 -0
- package/esm/policies/GleamPathDepsValid.d.ts +9 -0
- package/esm/policies/GleamPathDepsValid.d.ts.map +1 -0
- package/esm/policies/GleamPathDepsValid.js +59 -0
- package/esm/policies/GleamPathDepsValid.js.map +1 -0
- package/esm/policies/GleamProjectStructure.d.ts +32 -0
- package/esm/policies/GleamProjectStructure.d.ts.map +1 -0
- package/esm/policies/GleamProjectStructure.js +32 -0
- package/esm/policies/GleamProjectStructure.js.map +1 -0
- package/esm/policies/GleamSharedDependencyVersions.d.ts +37 -0
- package/esm/policies/GleamSharedDependencyVersions.d.ts.map +1 -0
- package/esm/policies/GleamSharedDependencyVersions.js +101 -0
- package/esm/policies/GleamSharedDependencyVersions.js.map +1 -0
- package/esm/policies/GleamTomlRequired.d.ts +30 -0
- package/esm/policies/GleamTomlRequired.d.ts.map +1 -0
- package/esm/policies/GleamTomlRequired.js +37 -0
- package/esm/policies/GleamTomlRequired.js.map +1 -0
- package/esm/policies/GleamTomlSorted.d.ts +20 -0
- package/esm/policies/GleamTomlSorted.d.ts.map +1 -0
- package/esm/policies/GleamTomlSorted.js +157 -0
- package/esm/policies/GleamTomlSorted.js.map +1 -0
- package/esm/policies/GleamVersionConstraint.d.ts +20 -0
- package/esm/policies/GleamVersionConstraint.d.ts.map +1 -0
- package/esm/policies/GleamVersionConstraint.js +68 -0
- package/esm/policies/GleamVersionConstraint.js.map +1 -0
- package/esm/policies/HtmlFileHeaders.d.ts +4 -2
- package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
- package/esm/policies/HtmlFileHeaders.js +2 -2
- package/esm/policies/HtmlFileHeaders.js.map +1 -1
- package/esm/policies/JsTsFileHeaders.d.ts +4 -2
- package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
- package/esm/policies/JsTsFileHeaders.js +1 -1
- package/esm/policies/JsTsFileHeaders.js.map +1 -1
- package/esm/policies/LicenseFileExists.d.ts +10 -4
- package/esm/policies/LicenseFileExists.d.ts.map +1 -1
- package/esm/policies/LicenseFileExists.js +27 -20
- package/esm/policies/LicenseFileExists.js.map +1 -1
- package/esm/policies/MutuallyExclusiveScripts.d.ts +8 -6
- package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -1
- package/esm/policies/MutuallyExclusiveScripts.js +9 -13
- package/esm/policies/MutuallyExclusiveScripts.js.map +1 -1
- package/esm/policies/NoBuildDirectory.d.ts +15 -0
- package/esm/policies/NoBuildDirectory.d.ts.map +1 -0
- package/esm/policies/NoBuildDirectory.js +24 -0
- package/esm/policies/NoBuildDirectory.js.map +1 -0
- package/esm/policies/NoJsFileExtensions.d.ts +9 -3
- package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
- package/esm/policies/NoJsFileExtensions.js +9 -14
- package/esm/policies/NoJsFileExtensions.js.map +1 -1
- package/esm/policies/NoLargeBinaryFiles.d.ts +9 -4
- package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
- package/esm/policies/NoLargeBinaryFiles.js +10 -16
- package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +10 -6
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.js +12 -14
- package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
- package/esm/policies/NoTargetArtifacts.d.ts +14 -0
- package/esm/policies/NoTargetArtifacts.d.ts.map +1 -0
- package/esm/policies/NoTargetArtifacts.js +37 -0
- package/esm/policies/NoTargetArtifacts.js.map +1 -0
- package/esm/policies/NoUnsafeWithoutJustification.d.ts +31 -0
- package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -0
- package/esm/policies/NoUnsafeWithoutJustification.js +79 -0
- package/esm/policies/NoUnsafeWithoutJustification.js.map +1 -0
- package/esm/policies/NoWildcardDependencies.d.ts +30 -0
- package/esm/policies/NoWildcardDependencies.d.ts.map +1 -0
- package/esm/policies/NoWildcardDependencies.js +83 -0
- package/esm/policies/NoWildcardDependencies.js.map +1 -0
- package/esm/policies/PackageAllowedScopes.d.ts +9 -5
- package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
- package/esm/policies/PackageAllowedScopes.js +15 -16
- package/esm/policies/PackageAllowedScopes.js.map +1 -1
- package/esm/policies/PackageEsmType.d.ts +7 -5
- package/esm/policies/PackageEsmType.d.ts.map +1 -1
- package/esm/policies/PackageEsmType.js +38 -36
- package/esm/policies/PackageEsmType.js.map +1 -1
- package/esm/policies/PackageFolderName.d.ts +8 -6
- package/esm/policies/PackageFolderName.d.ts.map +1 -1
- package/esm/policies/PackageFolderName.js +13 -16
- package/esm/policies/PackageFolderName.js.map +1 -1
- package/esm/policies/PackageJsonProperties.d.ts +5 -3
- package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
- package/esm/policies/PackageJsonProperties.js +18 -21
- package/esm/policies/PackageJsonProperties.js.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +2 -7
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.js +29 -42
- package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
- package/esm/policies/PackageJsonSorted.d.ts +2 -2
- package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
- package/esm/policies/PackageJsonSorted.js +51 -31
- package/esm/policies/PackageJsonSorted.js.map +1 -1
- package/esm/policies/PackageLicense.d.ts +4 -4
- package/esm/policies/PackageLicense.d.ts.map +1 -1
- package/esm/policies/PackageLicense.js +32 -54
- package/esm/policies/PackageLicense.js.map +1 -1
- package/esm/policies/PackagePrivateField.d.ts +12 -8
- package/esm/policies/PackagePrivateField.d.ts.map +1 -1
- package/esm/policies/PackagePrivateField.js +34 -25
- package/esm/policies/PackagePrivateField.js.map +1 -1
- package/esm/policies/PackageReadme.d.ts +6 -5
- package/esm/policies/PackageReadme.d.ts.map +1 -1
- package/esm/policies/PackageReadme.js +24 -61
- package/esm/policies/PackageReadme.js.map +1 -1
- package/esm/policies/PackageScripts.d.ts +26 -22
- package/esm/policies/PackageScripts.d.ts.map +1 -1
- package/esm/policies/PackageScripts.js +42 -38
- package/esm/policies/PackageScripts.js.map +1 -1
- package/esm/policies/PackageTestScripts.d.ts +10 -6
- package/esm/policies/PackageTestScripts.d.ts.map +1 -1
- package/esm/policies/PackageTestScripts.js +17 -19
- package/esm/policies/PackageTestScripts.js.map +1 -1
- package/esm/policies/PublicApiDocumented.d.ts +21 -0
- package/esm/policies/PublicApiDocumented.d.ts.map +1 -0
- package/esm/policies/PublicApiDocumented.js +38 -0
- package/esm/policies/PublicApiDocumented.js.map +1 -0
- package/esm/policies/RequiredGitignorePatterns.d.ts +11 -4
- package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
- package/esm/policies/RequiredGitignorePatterns.js +29 -36
- package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
- package/esm/policies/RequiredScripts.d.ts +9 -7
- package/esm/policies/RequiredScripts.d.ts.map +1 -1
- package/esm/policies/RequiredScripts.js +27 -26
- package/esm/policies/RequiredScripts.js.map +1 -1
- package/esm/policies/RustDocExists.d.ts +24 -0
- package/esm/policies/RustDocExists.d.ts.map +1 -0
- package/esm/policies/RustDocExists.js +49 -0
- package/esm/policies/RustDocExists.js.map +1 -0
- package/esm/policies/RustToolchainExists.d.ts +27 -0
- package/esm/policies/RustToolchainExists.d.ts.map +1 -0
- package/esm/policies/RustToolchainExists.js +28 -0
- package/esm/policies/RustToolchainExists.js.map +1 -0
- package/esm/policies/RustfmtConfigExists.d.ts +27 -0
- package/esm/policies/RustfmtConfigExists.d.ts.map +1 -0
- package/esm/policies/RustfmtConfigExists.js +28 -0
- package/esm/policies/RustfmtConfigExists.js.map +1 -0
- package/esm/policies/ScriptContains.d.ts +9 -7
- package/esm/policies/ScriptContains.d.ts.map +1 -1
- package/esm/policies/ScriptContains.js +9 -13
- package/esm/policies/ScriptContains.js.map +1 -1
- package/esm/policies/SharedDependencyVersions.d.ts +29 -0
- package/esm/policies/SharedDependencyVersions.d.ts.map +1 -0
- package/esm/policies/SharedDependencyVersions.js +143 -0
- package/esm/policies/SharedDependencyVersions.js.map +1 -0
- package/esm/policies/WorkspaceInheritance.d.ts +31 -0
- package/esm/policies/WorkspaceInheritance.d.ts.map +1 -0
- package/esm/policies/WorkspaceInheritance.js +93 -0
- package/esm/policies/WorkspaceInheritance.js.map +1 -0
- package/esm/policies/WorkspaceMembersValid.d.ts +27 -0
- package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -0
- package/esm/policies/WorkspaceMembersValid.js +87 -0
- package/esm/policies/WorkspaceMembersValid.js.map +1 -0
- package/esm/policies/constants.d.ts +8 -0
- package/esm/policies/constants.d.ts.map +1 -1
- package/esm/policies/constants.js +9 -1
- package/esm/policies/constants.js.map +1 -1
- package/esm/policies.d.ts +43 -5
- package/esm/policies.d.ts.map +1 -1
- package/esm/policies.js +63 -6
- package/esm/policies.js.map +1 -1
- package/esm/policy.d.ts +65 -269
- package/esm/policy.d.ts.map +1 -1
- package/esm/policy.js +1 -122
- package/esm/policy.js.map +1 -1
- package/esm/policyDefiners/defineCargoPolicy.d.ts +82 -0
- package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -0
- package/esm/policyDefiners/defineCargoPolicy.js +42 -0
- package/esm/policyDefiners/defineCargoPolicy.js.map +1 -0
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +27 -14
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.js +19 -39
- package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
- package/esm/policyDefiners/defineGleamPolicy.d.ts +81 -0
- package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -0
- package/esm/policyDefiners/defineGleamPolicy.js +42 -0
- package/esm/policyDefiners/defineGleamPolicy.js.map +1 -0
- package/esm/policyDefiners/definePackagePolicy.d.ts +24 -13
- package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
- package/esm/policyDefiners/definePackagePolicy.js +9 -32
- package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
- package/esm/policyDefiners/spdxValidator.d.ts +66 -0
- package/esm/policyDefiners/spdxValidator.d.ts.map +1 -0
- package/esm/policyDefiners/spdxValidator.js +139 -0
- package/esm/policyDefiners/spdxValidator.js.map +1 -0
- package/esm/policyDefiners/tomlParser.d.ts +8 -0
- package/esm/policyDefiners/tomlParser.d.ts.map +1 -0
- package/esm/policyDefiners/tomlParser.js +17 -0
- package/esm/policyDefiners/tomlParser.js.map +1 -0
- package/esm/policyExecution.d.ts +19 -0
- package/esm/policyExecution.d.ts.map +1 -0
- package/esm/policyExecution.js +224 -0
- package/esm/policyExecution.js.map +1 -0
- package/esm/repositoryFiles.d.ts +4 -0
- package/esm/repositoryFiles.d.ts.map +1 -0
- package/esm/repositoryFiles.js +8 -0
- package/esm/repositoryFiles.js.map +1 -0
- package/esm/runner.d.ts +85 -0
- package/esm/runner.d.ts.map +1 -0
- package/esm/runner.js +189 -0
- package/esm/runner.js.map +1 -0
- package/esm/settlePolicyPromise.d.ts +4 -0
- package/esm/settlePolicyPromise.d.ts.map +1 -0
- package/esm/settlePolicyPromise.js +10 -0
- package/esm/settlePolicyPromise.js.map +1 -0
- package/esm/tsdoc-metadata.json +1 -1
- package/esm/utils/safePaths.d.ts +9 -0
- package/esm/utils/safePaths.d.ts.map +1 -0
- package/esm/utils/safePaths.js +40 -0
- package/esm/utils/safePaths.js.map +1 -0
- package/oclif.manifest.json +117 -3
- package/package.json +66 -36
- package/scripts/benchmark.mjs +341 -0
- package/scripts/postinstall.mjs +154 -0
- package/sidecar/sidecar.mjs +399 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { types } from "node:util";
|
|
2
|
+
import { ExecutionContractError } from "./executionContractError.js";
|
|
3
|
+
import { fileCache } from "./fileCache.js";
|
|
4
|
+
import { runWithPerf } from "./perf.js";
|
|
5
|
+
import { settlePolicyPromise } from "./settlePolicyPromise.js";
|
|
6
|
+
const windowsAbsolutePath = /^[A-Za-z]:/;
|
|
7
|
+
function* execute(handler) {
|
|
8
|
+
const execution = handler();
|
|
9
|
+
if (execution instanceof Promise) {
|
|
10
|
+
return yield* settlePolicyPromise(execution);
|
|
11
|
+
}
|
|
12
|
+
if (typeof execution === "object" &&
|
|
13
|
+
execution !== null &&
|
|
14
|
+
Symbol.iterator in execution &&
|
|
15
|
+
!Array.isArray(execution)) {
|
|
16
|
+
return yield* execution;
|
|
17
|
+
}
|
|
18
|
+
throw new ExecutionContractError("Handlers and resolvers must be async functions or Effection generators.");
|
|
19
|
+
}
|
|
20
|
+
function validPath(path) {
|
|
21
|
+
return (typeof path === "string" &&
|
|
22
|
+
path.length > 0 &&
|
|
23
|
+
!path.includes("\\") &&
|
|
24
|
+
!path.includes("\0") &&
|
|
25
|
+
!path.startsWith("/") &&
|
|
26
|
+
!windowsAbsolutePath.test(path) &&
|
|
27
|
+
path
|
|
28
|
+
.split("/")
|
|
29
|
+
.every((part) => part !== "" && part !== "." && part !== ".."));
|
|
30
|
+
}
|
|
31
|
+
function validateResult(result, repository, fix) {
|
|
32
|
+
const invalid = () => new ExecutionContractError("Policy handlers and resolvers must return readonly PolicyFinding[] with message, optional manualFix, fixStatus and repository-only files; legacy results are not supported.");
|
|
33
|
+
if (!Array.isArray(result)) {
|
|
34
|
+
throw invalid();
|
|
35
|
+
}
|
|
36
|
+
for (const finding of result) {
|
|
37
|
+
if (typeof finding !== "object" ||
|
|
38
|
+
finding === null ||
|
|
39
|
+
Array.isArray(finding) ||
|
|
40
|
+
Reflect.ownKeys(finding).some((key) => typeof key !== "string" ||
|
|
41
|
+
!["message", "manualFix", "fixStatus", "files"].includes(key)) ||
|
|
42
|
+
!("message" in finding) ||
|
|
43
|
+
typeof finding.message !== "string" ||
|
|
44
|
+
finding.message.length === 0 ||
|
|
45
|
+
("manualFix" in finding &&
|
|
46
|
+
finding.manualFix !== undefined &&
|
|
47
|
+
typeof finding.manualFix !== "string") ||
|
|
48
|
+
("fixStatus" in finding &&
|
|
49
|
+
finding.fixStatus !== undefined &&
|
|
50
|
+
!["available", "fixed", "failed"].includes(finding.fixStatus)) ||
|
|
51
|
+
(!fix &&
|
|
52
|
+
(finding.fixStatus === "fixed" || finding.fixStatus === "failed")) ||
|
|
53
|
+
("files" in finding &&
|
|
54
|
+
!(repository &&
|
|
55
|
+
(finding.files === undefined ||
|
|
56
|
+
(Array.isArray(finding.files) && finding.files.every(validPath)))))) {
|
|
57
|
+
throw invalid();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function mergeFindings(checked, resolved) {
|
|
62
|
+
// Omission is not resolution; messages identify independent findings.
|
|
63
|
+
const merged = [...checked];
|
|
64
|
+
const used = new Set();
|
|
65
|
+
for (const finding of resolved) {
|
|
66
|
+
const index = checked.findIndex((previous, candidateIndex) => !used.has(candidateIndex) && previous.message === finding.message);
|
|
67
|
+
if (index === -1) {
|
|
68
|
+
merged.push(finding);
|
|
69
|
+
}
|
|
70
|
+
else if (merged[index]?.fixStatus !== "fixed") {
|
|
71
|
+
merged[index] = { ...merged[index], ...finding };
|
|
72
|
+
used.add(index);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return merged;
|
|
76
|
+
}
|
|
77
|
+
function nativeErrorMessage(cause) {
|
|
78
|
+
let current = cause;
|
|
79
|
+
while (current && !types.isProxy(current)) {
|
|
80
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, "message");
|
|
81
|
+
if (descriptor) {
|
|
82
|
+
return "value" in descriptor && typeof descriptor.value === "string"
|
|
83
|
+
? descriptor.value
|
|
84
|
+
: undefined;
|
|
85
|
+
}
|
|
86
|
+
current = Object.getPrototypeOf(current);
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
/** Describe thrown values without allowing hostile coercion to discard a run. */
|
|
91
|
+
export function executionMessage(cause) {
|
|
92
|
+
try {
|
|
93
|
+
if (cause === null ||
|
|
94
|
+
(typeof cause !== "object" && typeof cause !== "function")) {
|
|
95
|
+
return String(cause);
|
|
96
|
+
}
|
|
97
|
+
const message = !types.isProxy(cause) && types.isNativeError(cause)
|
|
98
|
+
? nativeErrorMessage(cause)
|
|
99
|
+
: undefined;
|
|
100
|
+
return message ?? "Policy threw a non-Error or uninspectable value.";
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return "Policy threw a value that cannot be inspected.";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function errorKind(cause) {
|
|
107
|
+
try {
|
|
108
|
+
if (cause === null ||
|
|
109
|
+
(typeof cause !== "object" && typeof cause !== "function")) {
|
|
110
|
+
return "exception";
|
|
111
|
+
}
|
|
112
|
+
let current = cause;
|
|
113
|
+
while (current && !types.isProxy(current)) {
|
|
114
|
+
if (current === ExecutionContractError.prototype) {
|
|
115
|
+
return "contract";
|
|
116
|
+
}
|
|
117
|
+
current = Object.getPrototypeOf(current);
|
|
118
|
+
}
|
|
119
|
+
return "exception";
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return "exception";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Internal single-policy execution; engines own matching and scheduling. */
|
|
126
|
+
export class PolicyExecutor {
|
|
127
|
+
root;
|
|
128
|
+
fix;
|
|
129
|
+
constructor(root, fix) {
|
|
130
|
+
this.root = root;
|
|
131
|
+
this.fix = fix;
|
|
132
|
+
}
|
|
133
|
+
*repository(policy, eligible, output) {
|
|
134
|
+
try {
|
|
135
|
+
const findings = yield* runWithPerf(policy.instanceId, "handle", output.perfStats, () => execute(() => policy.handler({
|
|
136
|
+
files: eligible,
|
|
137
|
+
root: this.root,
|
|
138
|
+
resolve: this.fix,
|
|
139
|
+
config: policy.config,
|
|
140
|
+
})));
|
|
141
|
+
validateResult(findings, true, this.fix);
|
|
142
|
+
for (const finding of findings) {
|
|
143
|
+
output.findings.push({
|
|
144
|
+
...finding,
|
|
145
|
+
scope: "repository",
|
|
146
|
+
policy: policy.name,
|
|
147
|
+
policyId: policy.instanceId,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (cause) {
|
|
152
|
+
output.errors.push({
|
|
153
|
+
scope: "repository",
|
|
154
|
+
files: eligible,
|
|
155
|
+
policy: policy.name,
|
|
156
|
+
policyId: policy.instanceId,
|
|
157
|
+
phase: "handle",
|
|
158
|
+
kind: errorKind(cause),
|
|
159
|
+
message: executionMessage(cause),
|
|
160
|
+
cause,
|
|
161
|
+
});
|
|
162
|
+
return this.fix;
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
*file(file, policy, output, cache) {
|
|
167
|
+
let stopped = false;
|
|
168
|
+
let phase = "handle";
|
|
169
|
+
let checked = [];
|
|
170
|
+
try {
|
|
171
|
+
const args = {
|
|
172
|
+
file,
|
|
173
|
+
root: this.root,
|
|
174
|
+
resolve: this.fix,
|
|
175
|
+
config: policy.config,
|
|
176
|
+
[fileCache]: cache,
|
|
177
|
+
};
|
|
178
|
+
checked = yield* runWithPerf(policy.instanceId, "handle", output.perfStats, () => execute(() => policy.handler(args)));
|
|
179
|
+
validateResult(checked, false, this.fix);
|
|
180
|
+
if (this.fix &&
|
|
181
|
+
checked.length > 0 &&
|
|
182
|
+
policy.resolver &&
|
|
183
|
+
!checked.some((finding) => finding.fixStatus === "fixed" || finding.fixStatus === "failed")) {
|
|
184
|
+
phase = "resolve";
|
|
185
|
+
const resolver = policy.resolver;
|
|
186
|
+
const resolved = yield* runWithPerf(policy.instanceId, "resolve", output.perfStats, () => execute(() => resolver({
|
|
187
|
+
file,
|
|
188
|
+
root: args.root,
|
|
189
|
+
config: args.config,
|
|
190
|
+
findings: checked.map((finding) => ({ ...finding })),
|
|
191
|
+
})));
|
|
192
|
+
validateResult(resolved, false, true);
|
|
193
|
+
checked = mergeFindings(checked, resolved);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (cause) {
|
|
197
|
+
output.errors.push({
|
|
198
|
+
scope: "file",
|
|
199
|
+
file,
|
|
200
|
+
policy: policy.name,
|
|
201
|
+
policyId: policy.instanceId,
|
|
202
|
+
phase,
|
|
203
|
+
kind: errorKind(cause),
|
|
204
|
+
message: executionMessage(cause),
|
|
205
|
+
cause,
|
|
206
|
+
});
|
|
207
|
+
stopped = this.fix;
|
|
208
|
+
if (phase === "handle") {
|
|
209
|
+
checked = [];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (const { files: _files, ...finding } of checked) {
|
|
213
|
+
output.findings.push({
|
|
214
|
+
...finding,
|
|
215
|
+
scope: "file",
|
|
216
|
+
file,
|
|
217
|
+
policy: policy.name,
|
|
218
|
+
policyId: policy.instanceId,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return stopped;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=policyExecution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policyExecution.js","sourceRoot":"","sources":["../src/policyExecution.ts"],"names":[],"mappings":"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","sourcesContent":["import { types } from \"node:util\";\nimport type { Operation } from \"effection\";\nimport { ExecutionContractError } from \"./executionContractError.js\";\nimport { fileCache, type ParsedFileCache } from \"./fileCache.js\";\nimport { runWithPerf } from \"./perf.js\";\nimport type { IdentifiedPolicy, PolicyResult } from \"./policy.js\";\nimport type { PolicyRunResults } from \"./runner.js\";\nimport { settlePolicyPromise } from \"./settlePolicyPromise.js\";\n\nconst windowsAbsolutePath = /^[A-Za-z]:/;\n\nfunction* execute<T>(handler: () => Promise<T> | Operation<T>): Operation<T> {\n\tconst execution = handler();\n\tif (execution instanceof Promise) {\n\t\treturn yield* settlePolicyPromise(execution);\n\t}\n\tif (\n\t\ttypeof execution === \"object\" &&\n\t\texecution !== null &&\n\t\tSymbol.iterator in execution &&\n\t\t!Array.isArray(execution)\n\t) {\n\t\treturn yield* execution;\n\t}\n\tthrow new ExecutionContractError(\n\t\t\"Handlers and resolvers must be async functions or Effection generators.\",\n\t);\n}\n\nfunction validPath(path: unknown): path is string {\n\treturn (\n\t\ttypeof path === \"string\" &&\n\t\tpath.length > 0 &&\n\t\t!path.includes(\"\\\\\") &&\n\t\t!path.includes(\"\\0\") &&\n\t\t!path.startsWith(\"/\") &&\n\t\t!windowsAbsolutePath.test(path) &&\n\t\tpath\n\t\t\t.split(\"/\")\n\t\t\t.every((part) => part !== \"\" && part !== \".\" && part !== \"..\")\n\t);\n}\n\nfunction validateResult(\n\tresult: unknown,\n\trepository: boolean,\n\tfix: boolean,\n): asserts result is PolicyResult {\n\tconst invalid = () =>\n\t\tnew ExecutionContractError(\n\t\t\t\"Policy handlers and resolvers must return readonly PolicyFinding[] with message, optional manualFix, fixStatus and repository-only files; legacy results are not supported.\",\n\t\t);\n\tif (!Array.isArray(result)) {\n\t\tthrow invalid();\n\t}\n\tfor (const finding of result) {\n\t\tif (\n\t\t\ttypeof finding !== \"object\" ||\n\t\t\tfinding === null ||\n\t\t\tArray.isArray(finding) ||\n\t\t\tReflect.ownKeys(finding).some(\n\t\t\t\t(key) =>\n\t\t\t\t\ttypeof key !== \"string\" ||\n\t\t\t\t\t![\"message\", \"manualFix\", \"fixStatus\", \"files\"].includes(key),\n\t\t\t) ||\n\t\t\t!(\"message\" in finding) ||\n\t\t\ttypeof finding.message !== \"string\" ||\n\t\t\tfinding.message.length === 0 ||\n\t\t\t(\"manualFix\" in finding &&\n\t\t\t\tfinding.manualFix !== undefined &&\n\t\t\t\ttypeof finding.manualFix !== \"string\") ||\n\t\t\t(\"fixStatus\" in finding &&\n\t\t\t\tfinding.fixStatus !== undefined &&\n\t\t\t\t![\"available\", \"fixed\", \"failed\"].includes(finding.fixStatus)) ||\n\t\t\t(!fix &&\n\t\t\t\t(finding.fixStatus === \"fixed\" || finding.fixStatus === \"failed\")) ||\n\t\t\t(\"files\" in finding &&\n\t\t\t\t!(\n\t\t\t\t\trepository &&\n\t\t\t\t\t(finding.files === undefined ||\n\t\t\t\t\t\t(Array.isArray(finding.files) && finding.files.every(validPath)))\n\t\t\t\t))\n\t\t) {\n\t\t\tthrow invalid();\n\t\t}\n\t}\n}\n\nfunction mergeFindings(\n\tchecked: PolicyResult,\n\tresolved: PolicyResult,\n): PolicyResult {\n\t// Omission is not resolution; messages identify independent findings.\n\tconst merged = [...checked];\n\tconst used = new Set<number>();\n\tfor (const finding of resolved) {\n\t\tconst index = checked.findIndex(\n\t\t\t(previous, candidateIndex) =>\n\t\t\t\t!used.has(candidateIndex) && previous.message === finding.message,\n\t\t);\n\t\tif (index === -1) {\n\t\t\tmerged.push(finding);\n\t\t} else if (merged[index]?.fixStatus !== \"fixed\") {\n\t\t\tmerged[index] = { ...merged[index], ...finding };\n\t\t\tused.add(index);\n\t\t}\n\t}\n\treturn merged;\n}\n\nfunction nativeErrorMessage(cause: object): string | undefined {\n\tlet current: object | null = cause;\n\twhile (current && !types.isProxy(current)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(current, \"message\");\n\t\tif (descriptor) {\n\t\t\treturn \"value\" in descriptor && typeof descriptor.value === \"string\"\n\t\t\t\t? descriptor.value\n\t\t\t\t: undefined;\n\t\t}\n\t\tcurrent = Object.getPrototypeOf(current);\n\t}\n\treturn undefined;\n}\n\n/** Describe thrown values without allowing hostile coercion to discard a run. */\nexport function executionMessage(cause: unknown): string {\n\ttry {\n\t\tif (\n\t\t\tcause === null ||\n\t\t\t(typeof cause !== \"object\" && typeof cause !== \"function\")\n\t\t) {\n\t\t\treturn String(cause);\n\t\t}\n\t\tconst message =\n\t\t\t!types.isProxy(cause) && types.isNativeError(cause)\n\t\t\t\t? nativeErrorMessage(cause)\n\t\t\t\t: undefined;\n\t\treturn message ?? \"Policy threw a non-Error or uninspectable value.\";\n\t} catch {\n\t\treturn \"Policy threw a value that cannot be inspected.\";\n\t}\n}\n\nfunction errorKind(cause: unknown): \"contract\" | \"exception\" {\n\ttry {\n\t\tif (\n\t\t\tcause === null ||\n\t\t\t(typeof cause !== \"object\" && typeof cause !== \"function\")\n\t\t) {\n\t\t\treturn \"exception\";\n\t\t}\n\t\tlet current: object | null = cause;\n\t\twhile (current && !types.isProxy(current)) {\n\t\t\tif (current === ExecutionContractError.prototype) {\n\t\t\t\treturn \"contract\";\n\t\t\t}\n\t\t\tcurrent = Object.getPrototypeOf(current);\n\t\t}\n\t\treturn \"exception\";\n\t} catch {\n\t\treturn \"exception\";\n\t}\n}\n\n/** Internal single-policy execution; engines own matching and scheduling. */\nexport class PolicyExecutor {\n\tpublic constructor(\n\t\tprivate readonly root: string,\n\t\tprivate readonly fix: boolean,\n\t) {}\n\n\tpublic *repository(\n\t\tpolicy: Extract<IdentifiedPolicy, { scope: \"repository\" }>,\n\t\teligible: readonly string[],\n\t\toutput: PolicyRunResults,\n\t): Operation<boolean> {\n\t\ttry {\n\t\t\tconst findings = yield* runWithPerf(\n\t\t\t\tpolicy.instanceId,\n\t\t\t\t\"handle\",\n\t\t\t\toutput.perfStats,\n\t\t\t\t() =>\n\t\t\t\t\texecute(() =>\n\t\t\t\t\t\tpolicy.handler({\n\t\t\t\t\t\t\tfiles: eligible,\n\t\t\t\t\t\t\troot: this.root,\n\t\t\t\t\t\t\tresolve: this.fix,\n\t\t\t\t\t\t\tconfig: policy.config,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tvalidateResult(findings, true, this.fix);\n\t\t\tfor (const finding of findings) {\n\t\t\t\toutput.findings.push({\n\t\t\t\t\t...finding,\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});\n\t\t\t}\n\t\t} catch (cause: unknown) {\n\t\t\toutput.errors.push({\n\t\t\t\tscope: \"repository\",\n\t\t\t\tfiles: eligible,\n\t\t\t\tpolicy: policy.name,\n\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t\tphase: \"handle\",\n\t\t\t\tkind: errorKind(cause),\n\t\t\t\tmessage: executionMessage(cause),\n\t\t\t\tcause,\n\t\t\t});\n\t\t\treturn this.fix;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic *file(\n\t\tfile: string,\n\t\tpolicy: Exclude<IdentifiedPolicy, { scope: \"repository\" }>,\n\t\toutput: PolicyRunResults,\n\t\tcache: ParsedFileCache | undefined,\n\t): Operation<boolean> {\n\t\tlet stopped = false;\n\t\tlet phase: \"handle\" | \"resolve\" = \"handle\";\n\t\tlet checked: PolicyResult = [];\n\t\ttry {\n\t\t\tconst args = {\n\t\t\t\tfile,\n\t\t\t\troot: this.root,\n\t\t\t\tresolve: this.fix,\n\t\t\t\tconfig: policy.config,\n\t\t\t\t[fileCache]: cache,\n\t\t\t};\n\t\t\tchecked = yield* runWithPerf(\n\t\t\t\tpolicy.instanceId,\n\t\t\t\t\"handle\",\n\t\t\t\toutput.perfStats,\n\t\t\t\t() => execute(() => policy.handler(args)),\n\t\t\t);\n\t\t\tvalidateResult(checked, false, this.fix);\n\t\t\tif (\n\t\t\t\tthis.fix &&\n\t\t\t\tchecked.length > 0 &&\n\t\t\t\tpolicy.resolver &&\n\t\t\t\t!checked.some(\n\t\t\t\t\t(finding) =>\n\t\t\t\t\t\tfinding.fixStatus === \"fixed\" || finding.fixStatus === \"failed\",\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphase = \"resolve\";\n\t\t\t\tconst resolver = policy.resolver;\n\t\t\t\tconst resolved = yield* runWithPerf(\n\t\t\t\t\tpolicy.instanceId,\n\t\t\t\t\t\"resolve\",\n\t\t\t\t\toutput.perfStats,\n\t\t\t\t\t() =>\n\t\t\t\t\t\texecute(() =>\n\t\t\t\t\t\t\tresolver({\n\t\t\t\t\t\t\t\tfile,\n\t\t\t\t\t\t\t\troot: args.root,\n\t\t\t\t\t\t\t\tconfig: args.config,\n\t\t\t\t\t\t\t\tfindings: checked.map((finding) => ({ ...finding })),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tvalidateResult(resolved, false, true);\n\t\t\t\tchecked = mergeFindings(checked, resolved);\n\t\t\t}\n\t\t} catch (cause: unknown) {\n\t\t\toutput.errors.push({\n\t\t\t\tscope: \"file\",\n\t\t\t\tfile,\n\t\t\t\tpolicy: policy.name,\n\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t\tphase,\n\t\t\t\tkind: errorKind(cause),\n\t\t\t\tmessage: executionMessage(cause),\n\t\t\t\tcause,\n\t\t\t});\n\t\t\tstopped = this.fix;\n\t\t\tif (phase === \"handle\") {\n\t\t\t\tchecked = [];\n\t\t\t}\n\t\t}\n\t\tfor (const { files: _files, ...finding } of checked) {\n\t\t\toutput.findings.push({\n\t\t\t\t...finding,\n\t\t\t\tscope: \"file\",\n\t\t\t\tfile,\n\t\t\t\tpolicy: policy.name,\n\t\t\t\tpolicyId: policy.instanceId,\n\t\t\t});\n\t\t}\n\t\treturn stopped;\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repositoryFiles.d.ts","sourceRoot":"","sources":["../src/repositoryFiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,oFAAoF;AACpF,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ3E"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { parseFilePaths } from "./filePaths.js";
|
|
2
|
+
/** Git's cached inventory includes unstaged deletions; those are not live files. */
|
|
3
|
+
export async function readRepositoryFiles(git) {
|
|
4
|
+
const files = parseFilePaths(await git.raw("ls-files", "-co", "-z", "--exclude-standard", "--full-name"));
|
|
5
|
+
const deleted = new Set(parseFilePaths(await git.raw("ls-files", "--deleted", "-z", "--full-name")));
|
|
6
|
+
return files.filter((file) => !deleted.has(file));
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=repositoryFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repositoryFiles.js","sourceRoot":"","sources":["../src/repositoryFiles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAc;IACvD,MAAM,KAAK,GAAG,cAAc,CAC3B,MAAM,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAC3E,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,CACtB,cAAc,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAC3E,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import type { SimpleGit } from \"simple-git\";\nimport { parseFilePaths } from \"./filePaths.js\";\n\n/** Git's cached inventory includes unstaged deletions; those are not live files. */\nexport async function readRepositoryFiles(git: SimpleGit): Promise<string[]> {\n\tconst files = parseFilePaths(\n\t\tawait git.raw(\"ls-files\", \"-co\", \"-z\", \"--exclude-standard\", \"--full-name\"),\n\t);\n\tconst deleted = new Set(\n\t\tparseFilePaths(await git.raw(\"ls-files\", \"--deleted\", \"-z\", \"--full-name\")),\n\t);\n\treturn files.filter((file) => !deleted.has(file));\n}\n"]}
|
package/esm/runner.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type Operation } from "effection";
|
|
2
|
+
import { type PolicyHandlerPerfStats } from "./perf.js";
|
|
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";
|
|
7
|
+
file: string;
|
|
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 */
|
|
47
|
+
export interface PolicyRunResults {
|
|
48
|
+
findings: PolicyRunFinding[];
|
|
49
|
+
errors: PolicyExecutionError[];
|
|
50
|
+
skipped: PolicySkippedWork[];
|
|
51
|
+
perfStats: PolicyHandlerPerfStats;
|
|
52
|
+
}
|
|
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 */
|
|
56
|
+
export interface PolicyRunnerOptions {
|
|
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;
|
|
66
|
+
}
|
|
67
|
+
/** Effection runner; cancellation unwinds active generator handlers and resolvers. @public */
|
|
68
|
+
export declare class PolicyRunner {
|
|
69
|
+
private readonly options;
|
|
70
|
+
private readonly policies;
|
|
71
|
+
private readonly exclusions;
|
|
72
|
+
private readonly policyExclusions;
|
|
73
|
+
private readonly concurrency;
|
|
74
|
+
constructor(options: PolicyRunnerOptions);
|
|
75
|
+
run(): Operation<PolicyRunResults>;
|
|
76
|
+
private runInternal;
|
|
77
|
+
private runReadOnlyFiles;
|
|
78
|
+
private runRepositories;
|
|
79
|
+
private loadInventory;
|
|
80
|
+
private excluded;
|
|
81
|
+
private runFile;
|
|
82
|
+
}
|
|
83
|
+
/** Promise entry point sharing the Effection runner's contracts and cancellation. @public */
|
|
84
|
+
export declare function runPolicies(options: PolicyRunnerOptions): Promise<PolicyRunResults>;
|
|
85
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/esm/runner.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
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";
|
|
5
|
+
import { identifyPolicyInstances } from "./makePolicy.js";
|
|
6
|
+
import { newPerfStats } from "./perf.js";
|
|
7
|
+
import { PolicyExecutor } from "./policyExecution.js";
|
|
8
|
+
function matches(regex, file) {
|
|
9
|
+
const index = regex.lastIndex;
|
|
10
|
+
try {
|
|
11
|
+
regex.lastIndex = 0;
|
|
12
|
+
return regex.test(file);
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
regex.lastIndex = index;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Effection runner; cancellation unwinds active generator handlers and resolvers. @public */
|
|
19
|
+
export class PolicyRunner {
|
|
20
|
+
options;
|
|
21
|
+
policies;
|
|
22
|
+
exclusions;
|
|
23
|
+
policyExclusions;
|
|
24
|
+
concurrency;
|
|
25
|
+
constructor(options) {
|
|
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
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
*run() {
|
|
50
|
+
const signal = this.options.signal;
|
|
51
|
+
if (signal?.aborted) {
|
|
52
|
+
throw signal.reason;
|
|
53
|
+
}
|
|
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
|
+
};
|
|
59
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
60
|
+
try {
|
|
61
|
+
if (signal?.aborted) {
|
|
62
|
+
abort();
|
|
63
|
+
}
|
|
64
|
+
return yield* task;
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
signal?.removeEventListener("abort", abort);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
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();
|
|
82
|
+
}
|
|
83
|
+
const files = this.options.files ?? inventory ?? [];
|
|
84
|
+
let fileFixError = false;
|
|
85
|
+
try {
|
|
86
|
+
if (fix) {
|
|
87
|
+
for (const file of files) {
|
|
88
|
+
if (yield* this.runFile(file, result, cache)) {
|
|
89
|
+
fileFixError = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
yield* this.runReadOnlyFiles(files, result, cache);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
cache?.clear();
|
|
99
|
+
}
|
|
100
|
+
yield* this.runRepositories(result, inventory, fileFixError);
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
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
|
+
}
|
|
125
|
+
}
|
|
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;
|
|
133
|
+
}
|
|
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;
|
|
142
|
+
}
|
|
143
|
+
if (inventory === undefined || fix) {
|
|
144
|
+
inventory = yield* this.loadInventory();
|
|
145
|
+
}
|
|
146
|
+
const eligible = (inventory ?? []).filter((file) => !this.excluded(file, policy));
|
|
147
|
+
repositoryFixError = yield* new PolicyExecutor(this.options.root, fix).repository(policy, eligible, result);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
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;
|
|
168
|
+
}
|
|
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;
|
|
178
|
+
}
|
|
179
|
+
stopped = yield* new PolicyExecutor(this.options.root, this.options.fix ?? false).file(file, policy, output, cache);
|
|
180
|
+
}
|
|
181
|
+
return stopped;
|
|
182
|
+
}
|
|
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
|
+
}
|
|
189
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,GAAG,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EACN,2BAA2B,EAE3B,cAAc,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAA+B,MAAM,WAAW,CAAC;AAMtE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAgEtD,SAAS,OAAO,CAAC,KAAa,EAAE,IAAY;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC;IAC9B,IAAI,CAAC;QACJ,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QACpB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;YAAS,CAAC;QACV,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;AACF,CAAC;AAED,8FAA8F;AAC9F,MAAM,OAAO,YAAY;IAMY;IALnB,QAAQ,CAAqB;IAC7B,UAAU,CAAW;IACrB,gBAAgB,CAAwB;IACxC,WAAW,CAAS;IAErC,YAAoC,OAA4B;QAA5B,YAAO,GAAP,OAAO,CAAqB;QAC/D,IAAI,CAAC,QAAQ,GAAG,uBAAuB,CACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACjC,GAAG,MAAM;YACT,MAAM,EACL,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM;SACnE,CAAC,CAAC,CACH,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,gBAAgB,GAAG,2BAA2B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,CAAC,WAAW,GAAG,mBAAmB,CACrC,OAAO,CAAC,WAAW,IAAI,mBAAmB,CAC1C,CAAC;QACF,IACC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,YAAY,CAAC;YAC7D,OAAO,CAAC,SAAS,KAAK,SAAS,EAC9B,CAAC;YACF,MAAM,IAAI,SAAS,CAClB,+FAA+F,CAC/F,CAAC;QACH,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,KAAK,KAAK,YAAY,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACpE,MAAM,IAAI,SAAS,CAClB,iEAAiE,CACjE,CAAC;YACH,CAAC;YACD,IACC,MAAM,CAAC,cAAc;gBACrB,MAAM,CAAC,MAAM,KAAK,SAAS;gBAC3B,MAAM,CAAC,aAAa,KAAK,SAAS,EACjC,CAAC;gBACF,MAAM,IAAI,SAAS,CAAC,WAAW,MAAM,CAAC,IAAI,oBAAoB,CAAC,CAAC;YACjE,CAAC;QACF,CAAC;IACF,CAAC;IAEM,CAAC,GAAG;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACnC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACrB,MAAM,MAAM,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACpD,wFAAwF;QACxF,MAAM,KAAK,GAAG,GAAG,EAAE;YAClB,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC;YACJ,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACrB,KAAK,EAAE,CAAC;YACT,CAAC;YACD,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC;QACpB,CAAC;gBAAS,CAAC;YACV,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;IACF,CAAC;IAEO,CAAC,WAAW;QACnB,MAAM,MAAM,GAAqB;YAChC,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,YAAY,EAAE;SACzB,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,CAAC;QACtC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;QACtD,IAAI,SAAwC,CAAC;QAC7C,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACtC,SAAS,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACzC,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,SAAS,IAAI,EAAE,CAAC;QACpD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC;YACJ,IAAI,GAAG,EAAE,CAAC;gBACT,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBAC1B,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;wBAC9C,YAAY,GAAG,IAAI,CAAC;oBACrB,CAAC;gBACF,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACpD,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,KAAK,EAAE,KAAK,EAAE,CAAC;QAChB,CAAC;QACD,KAAK,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC;IACf,CAAC;IAEO,CAAC,gBAAgB,CACxB,KAAwB,EACxB,MAAwB,EACxB,KAAkC;QAElC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAChC,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,CAAC,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CACT,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EACpD,QAAQ,CAAC;YACR,KACC,IAAI,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,EAC1B,CAAC,KAAK,CAAC,IAAI,EACX,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,EACrB,CAAC;gBACF,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;gBAClC,MAAM,KAAK,GAAqB;oBAC/B,QAAQ,EAAE,EAAE;oBACZ,MAAM,EAAE,EAAE;oBACV,OAAO,EAAE,EAAE;oBACX,SAAS,EAAE,MAAM,CAAC,SAAS;iBAC3B,CAAC;gBACF,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC1C,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;YACxB,CAAC;QACF,CAAC,CACD,CACD,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAEO,CAAC,eAAe,CACvB,MAAwB,EACxB,gBAA+C,EAC/C,YAAqB;QAErB,IAAI,SAAS,GAAG,gBAAgB,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,CAAC;QACtC,IAAI,kBAAkB,GAAG,KAAK,CAAC;QAC/B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;gBACnC,SAAS;YACV,CAAC;YACD,IAAI,YAAY,IAAI,kBAAkB,EAAE,CAAC;gBACxC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,YAAY;oBACnB,MAAM,EAAE,MAAM,CAAC,IAAI;oBACnB,QAAQ,EAAE,MAAM,CAAC,UAAU;oBAC3B,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,sBAAsB;iBAChE,CAAC,CAAC;gBACH,SAAS;YACV,CAAC;YACD,IAAI,SAAS,KAAK,SAAS,IAAI,GAAG,EAAE,CAAC;gBACpC,SAAS,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACzC,CAAC;YACD,MAAM,QAAQ,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CACxC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CACtC,CAAC;YACF,kBAAkB,GAAG,KAAK,CAAC,CAAC,IAAI,cAAc,CAC7C,IAAI,CAAC,OAAO,CAAC,IAAI,EACjB,GAAG,CACH,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAEO,CAAC,aAAa;QACrB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;QACzC,OAAO,OAAO,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,CAAC;IAEO,QAAQ,CAAC,IAAY,EAAE,MAAwB;QACtD,OAAO,CACN,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACrD,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CACnE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CACpB,CACD,CAAC;IACH,CAAC;IAEO,CAAC,OAAO,CACf,IAAY,EACZ,MAAwB,EACxB,KAAkC;QAElC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CACvD,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CACpB,CAAC;QACF,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvB,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;QAC9B,CAAC;QACD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,KAAK,KAAK,YAAY,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;gBACnE,SAAS;YACV,CAAC;YACD,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;gBAC5C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,MAAM;oBACb,IAAI;oBACJ,MAAM,EAAE,MAAM,CAAC,IAAI;oBACnB,QAAQ,EAAE,MAAM,CAAC,UAAU;oBAC3B,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU;iBAC/C,CAAC,CAAC;gBACH,SAAS;YACV,CAAC;YACD,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,cAAc,CAClC,IAAI,CAAC,OAAO,CAAC,IAAI,EACjB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,CACzB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;CACD;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,OAA4B;IAE5B,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;AACtC,CAAC","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 @@
|
|
|
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"]}
|
package/esm/tsdoc-metadata.json
CHANGED
|
@@ -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
|