repopo 0.12.0 → 0.14.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 +70 -0
- package/README.md +57 -90
- package/THIRD-PARTY-LICENSES.txt +169 -11
- package/bin/dev.js +0 -0
- 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 +66 -1
- package/esm/api.d.ts.map +1 -1
- package/esm/api.js +18 -1
- package/esm/api.js.map +1 -1
- package/esm/baseCommand.d.ts.map +1 -1
- package/esm/baseCommand.js +2 -2
- package/esm/baseCommand.js.map +1 -1
- package/esm/commands/check-native.d.ts +5 -3
- package/esm/commands/check-native.d.ts.map +1 -1
- package/esm/commands/check-native.js +35 -7
- package/esm/commands/check-native.js.map +1 -1
- package/esm/commands/check.d.ts +8 -21
- package/esm/commands/check.d.ts.map +1 -1
- package/esm/commands/check.js +98 -154
- package/esm/commands/check.js.map +1 -1
- package/esm/commands/list.d.ts.map +1 -1
- package/esm/commands/list.js +1 -0
- 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 +10 -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 +10 -1
- package/esm/context.d.ts.map +1 -1
- package/esm/context.js +19 -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 -16
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -17
- package/esm/index.js.map +1 -1
- package/esm/makePolicy.d.ts +20 -100
- package/esm/makePolicy.d.ts.map +1 -1
- package/esm/makePolicy.js +46 -132
- package/esm/makePolicy.js.map +1 -1
- package/esm/perf.d.ts +5 -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 +4 -4
- package/esm/policies/CargoLicenceValidated.d.ts.map +1 -1
- package/esm/policies/CargoLicenceValidated.js +9 -7
- package/esm/policies/CargoLicenceValidated.js.map +1 -1
- package/esm/policies/CargoLintsConfigured.d.ts +4 -4
- package/esm/policies/CargoLintsConfigured.d.ts.map +1 -1
- package/esm/policies/CargoLintsConfigured.js +19 -15
- package/esm/policies/CargoLintsConfigured.js.map +1 -1
- package/esm/policies/CargoLockPolicy.d.ts +4 -4
- package/esm/policies/CargoLockPolicy.d.ts.map +1 -1
- package/esm/policies/CargoLockPolicy.js +15 -11
- package/esm/policies/CargoLockPolicy.js.map +1 -1
- package/esm/policies/CargoTomlRequired.d.ts +5 -5
- package/esm/policies/CargoTomlRequired.d.ts.map +1 -1
- package/esm/policies/CargoTomlRequired.js +7 -7
- package/esm/policies/CargoTomlRequired.js.map +1 -1
- package/esm/policies/CargoTomlSorted.d.ts +4 -4
- package/esm/policies/CargoTomlSorted.d.ts.map +1 -1
- package/esm/policies/CargoTomlSorted.js +21 -17
- package/esm/policies/CargoTomlSorted.js.map +1 -1
- package/esm/policies/ConditionalScripts.d.ts +10 -8
- package/esm/policies/ConditionalScripts.d.ts.map +1 -1
- package/esm/policies/ConditionalScripts.js +24 -22
- 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 +15 -18
- package/esm/policies/ExactScripts.js.map +1 -1
- package/esm/policies/GleamDepVersions.d.ts +5 -5
- package/esm/policies/GleamDepVersions.d.ts.map +1 -1
- package/esm/policies/GleamDepVersions.js +5 -5
- package/esm/policies/GleamDepVersions.js.map +1 -1
- package/esm/policies/GleamDocExists.d.ts +4 -4
- package/esm/policies/GleamDocExists.d.ts.map +1 -1
- package/esm/policies/GleamDocExists.js +6 -6
- package/esm/policies/GleamDocExists.js.map +1 -1
- package/esm/policies/GleamInternalModulesConfigured.d.ts +4 -4
- package/esm/policies/GleamInternalModulesConfigured.d.ts.map +1 -1
- package/esm/policies/GleamInternalModulesConfigured.js +8 -6
- package/esm/policies/GleamInternalModulesConfigured.js.map +1 -1
- package/esm/policies/GleamLicenceConfigured.d.ts +4 -4
- package/esm/policies/GleamLicenceConfigured.d.ts.map +1 -1
- package/esm/policies/GleamLicenceConfigured.js +8 -6
- package/esm/policies/GleamLicenceConfigured.js.map +1 -1
- package/esm/policies/GleamManifestCommitted.d.ts +10 -3
- package/esm/policies/GleamManifestCommitted.d.ts.map +1 -1
- package/esm/policies/GleamManifestCommitted.js +10 -9
- package/esm/policies/GleamManifestCommitted.js.map +1 -1
- package/esm/policies/GleamMonorepoConsistency.d.ts +13 -5
- package/esm/policies/GleamMonorepoConsistency.d.ts.map +1 -1
- package/esm/policies/GleamMonorepoConsistency.js +10 -10
- package/esm/policies/GleamMonorepoConsistency.js.map +1 -1
- package/esm/policies/GleamNameRestrictions.d.ts +4 -4
- package/esm/policies/GleamNameRestrictions.d.ts.map +1 -1
- package/esm/policies/GleamNameRestrictions.js +6 -6
- package/esm/policies/GleamNameRestrictions.js.map +1 -1
- package/esm/policies/GleamNoPathDepsInPublished.d.ts +4 -4
- package/esm/policies/GleamNoPathDepsInPublished.d.ts.map +1 -1
- package/esm/policies/GleamNoPathDepsInPublished.js +6 -6
- package/esm/policies/GleamNoPathDepsInPublished.js.map +1 -1
- package/esm/policies/GleamPathDepsValid.d.ts +3 -3
- package/esm/policies/GleamPathDepsValid.d.ts.map +1 -1
- package/esm/policies/GleamPathDepsValid.js +5 -5
- package/esm/policies/GleamPathDepsValid.js.map +1 -1
- package/esm/policies/GleamProjectStructure.d.ts +11 -4
- package/esm/policies/GleamProjectStructure.d.ts.map +1 -1
- package/esm/policies/GleamProjectStructure.js +7 -8
- package/esm/policies/GleamProjectStructure.js.map +1 -1
- package/esm/policies/GleamSharedDependencyVersions.d.ts +12 -4
- package/esm/policies/GleamSharedDependencyVersions.d.ts.map +1 -1
- package/esm/policies/GleamSharedDependencyVersions.js +10 -10
- package/esm/policies/GleamSharedDependencyVersions.js.map +1 -1
- package/esm/policies/GleamTomlRequired.d.ts +4 -4
- package/esm/policies/GleamTomlRequired.d.ts.map +1 -1
- package/esm/policies/GleamTomlRequired.js +5 -5
- package/esm/policies/GleamTomlRequired.js.map +1 -1
- package/esm/policies/GleamTomlSorted.d.ts +4 -4
- package/esm/policies/GleamTomlSorted.d.ts.map +1 -1
- package/esm/policies/GleamTomlSorted.js +21 -17
- package/esm/policies/GleamTomlSorted.js.map +1 -1
- package/esm/policies/GleamVersionConstraint.d.ts +4 -4
- package/esm/policies/GleamVersionConstraint.d.ts.map +1 -1
- package/esm/policies/GleamVersionConstraint.js +14 -10
- package/esm/policies/GleamVersionConstraint.js.map +1 -1
- package/esm/policies/HtmlFileHeaders.d.ts +4 -2
- package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
- package/esm/policies/HtmlFileHeaders.js +1 -1
- 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/MaxChangedFiles.d.ts +17 -0
- package/esm/policies/MaxChangedFiles.d.ts.map +1 -0
- package/esm/policies/MaxChangedFiles.js +22 -0
- package/esm/policies/MaxChangedFiles.js.map +1 -0
- 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 +9 -3
- package/esm/policies/NoBuildDirectory.d.ts.map +1 -1
- package/esm/policies/NoBuildDirectory.js +8 -13
- package/esm/policies/NoBuildDirectory.js.map +1 -1
- 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 +9 -3
- package/esm/policies/NoTargetArtifacts.d.ts.map +1 -1
- package/esm/policies/NoTargetArtifacts.js +9 -14
- package/esm/policies/NoTargetArtifacts.js.map +1 -1
- package/esm/policies/NoUnsafeWithoutJustification.d.ts +11 -4
- package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -1
- package/esm/policies/NoUnsafeWithoutJustification.js +8 -9
- package/esm/policies/NoUnsafeWithoutJustification.js.map +1 -1
- package/esm/policies/NoWildcardDependencies.d.ts +5 -5
- package/esm/policies/NoWildcardDependencies.d.ts.map +1 -1
- package/esm/policies/NoWildcardDependencies.js +6 -6
- package/esm/policies/NoWildcardDependencies.js.map +1 -1
- 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 +31 -31
- 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 +6 -17
- 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 +28 -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 +15 -30
- 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 +31 -52
- 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 +31 -23
- 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 +22 -59
- 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 +39 -36
- 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 +14 -16
- package/esm/policies/PackageTestScripts.js.map +1 -1
- package/esm/policies/PublicApiDocumented.d.ts +4 -4
- package/esm/policies/PublicApiDocumented.d.ts.map +1 -1
- package/esm/policies/PublicApiDocumented.js +10 -8
- package/esm/policies/PublicApiDocumented.js.map +1 -1
- package/esm/policies/RequireCompanionChanges.d.ts +16 -0
- package/esm/policies/RequireCompanionChanges.d.ts.map +1 -0
- package/esm/policies/RequireCompanionChanges.js +42 -0
- package/esm/policies/RequireCompanionChanges.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 +24 -24
- package/esm/policies/RequiredScripts.js.map +1 -1
- package/esm/policies/RustDocExists.d.ts +4 -4
- package/esm/policies/RustDocExists.d.ts.map +1 -1
- package/esm/policies/RustDocExists.js +6 -6
- package/esm/policies/RustDocExists.js.map +1 -1
- package/esm/policies/RustToolchainExists.d.ts +11 -4
- package/esm/policies/RustToolchainExists.d.ts.map +1 -1
- package/esm/policies/RustToolchainExists.js +10 -9
- package/esm/policies/RustToolchainExists.js.map +1 -1
- package/esm/policies/RustfmtConfigExists.d.ts +11 -4
- package/esm/policies/RustfmtConfigExists.d.ts.map +1 -1
- package/esm/policies/RustfmtConfigExists.js +10 -9
- package/esm/policies/RustfmtConfigExists.js.map +1 -1
- 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 +9 -4
- package/esm/policies/SharedDependencyVersions.d.ts.map +1 -1
- package/esm/policies/SharedDependencyVersions.js +28 -20
- package/esm/policies/SharedDependencyVersions.js.map +1 -1
- package/esm/policies/WorkspaceInheritance.d.ts +11 -4
- package/esm/policies/WorkspaceInheritance.d.ts.map +1 -1
- package/esm/policies/WorkspaceInheritance.js +10 -11
- package/esm/policies/WorkspaceInheritance.js.map +1 -1
- package/esm/policies/WorkspaceMembersValid.d.ts +11 -4
- package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -1
- package/esm/policies/WorkspaceMembersValid.js +10 -11
- package/esm/policies/WorkspaceMembersValid.js.map +1 -1
- package/esm/policies/constants.d.ts.map +1 -1
- package/esm/policies/constants.js +1 -1
- package/esm/policies/constants.js.map +1 -1
- package/esm/policies.d.ts +15 -5
- package/esm/policies.d.ts.map +1 -1
- package/esm/policies.js +14 -5
- package/esm/policies.js.map +1 -1
- package/esm/policy.d.ts +67 -289
- 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 +25 -9
- package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineCargoPolicy.js +10 -28
- package/esm/policyDefiners/defineCargoPolicy.js.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +27 -14
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.js +16 -35
- package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
- package/esm/policyDefiners/defineGleamPolicy.d.ts +25 -9
- package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineGleamPolicy.js +10 -27
- package/esm/policyDefiners/defineGleamPolicy.js.map +1 -1
- 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 +4 -12
- package/esm/policyDefiners/spdxValidator.d.ts.map +1 -1
- package/esm/policyDefiners/spdxValidator.js +26 -14
- package/esm/policyDefiners/spdxValidator.js.map +1 -1
- package/esm/policyExecution.d.ts +20 -0
- package/esm/policyExecution.d.ts.map +1 -0
- package/esm/policyExecution.js +234 -0
- package/esm/policyExecution.js.map +1 -0
- package/esm/repositoryChanges.d.ts +26 -0
- package/esm/repositoryChanges.d.ts.map +1 -0
- package/esm/repositoryChanges.js +172 -0
- package/esm/repositoryChanges.js.map +1 -0
- package/esm/repositoryFiles.d.ts +6 -0
- package/esm/repositoryFiles.d.ts.map +1 -0
- package/esm/repositoryFiles.js +11 -0
- package/esm/repositoryFiles.js.map +1 -0
- package/esm/runner.d.ts +73 -47
- package/esm/runner.d.ts.map +1 -1
- package/esm/runner.js +158 -144
- package/esm/runner.js.map +1 -1
- 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 +57 -2
- package/package.json +42 -27
- package/scripts/benchmark.mjs +341 -0
- package/sidecar/sidecar.mjs +388 -417
package/sidecar/sidecar.mjs
CHANGED
|
@@ -1,468 +1,439 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Newline-delimited JSON bridge for the native CLI.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* policy
|
|
6
|
-
* happens over stdin/stdout using newline-delimited JSON.
|
|
7
|
-
*
|
|
8
|
-
* Protocol:
|
|
9
|
-
* Rust -> Node: JSON request (one per line)
|
|
10
|
-
* Node -> Rust: JSON response (one per line)
|
|
11
|
-
*
|
|
12
|
-
* Request format:
|
|
13
|
-
* { "method": "load_config", "params": { "configPath": "...", "gitRoot": "..." } }
|
|
14
|
-
* { "method": "run_handler", "params": { "policyName": "...", "file": "...", "root": "...", "resolve": false } }
|
|
15
|
-
* { "method": "run_resolver", "params": { "policyName": "...", "file": "...", "root": "..." } }
|
|
16
|
-
* { "method": "run_handler_batch", "params": { "policyName": "...", "files": [...], "root": "...", "resolve": false } }
|
|
17
|
-
* { "method": "run_resolver_batch", "params": { "policyName": "...", "files": [...], "root": "..." } }
|
|
18
|
-
* { "method": "shutdown" }
|
|
19
|
-
*
|
|
20
|
-
* Response format:
|
|
21
|
-
* { "ok": true, "data": ... }
|
|
22
|
-
* { "ok": false, "error": "message" }
|
|
4
|
+
* Rust owns matching and scheduling. This bridge executes only explicitly
|
|
5
|
+
* selected policy units, sharing contracts and reconciliation with `check`.
|
|
23
6
|
*/
|
|
24
|
-
|
|
7
|
+
import { Console } from "node:console";
|
|
25
8
|
import { stat } from "node:fs/promises";
|
|
9
|
+
import { env } from "node:process";
|
|
26
10
|
import { createInterface } from "node:readline";
|
|
11
|
+
import { types } from "node:util";
|
|
27
12
|
import { TypeScriptLoader } from "@tylerbu/lilconfig-loader-ts";
|
|
28
|
-
import { run } from "effection";
|
|
13
|
+
import { all, run } from "effection";
|
|
29
14
|
import { lilconfig } from "lilconfig";
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
15
|
+
import { DefaultPolicyConfig } from "../esm/config.js";
|
|
16
|
+
import {
|
|
17
|
+
createExcludedPolicyFileMap,
|
|
18
|
+
exclusionRegex,
|
|
19
|
+
matchesPath,
|
|
20
|
+
} from "../esm/context.js";
|
|
21
|
+
import { ParsedFileCache } from "../esm/fileCache.js";
|
|
22
|
+
import { identifyPolicyInstances, makePolicy } from "../esm/makePolicy.js";
|
|
23
|
+
import { newPerfStats } from "../esm/perf.js";
|
|
24
|
+
import { executionMessage, PolicyExecutor } from "../esm/policyExecution.js";
|
|
25
|
+
import {
|
|
26
|
+
annotateInventory,
|
|
27
|
+
collectRepositoryInventory,
|
|
28
|
+
validateChangeOptions,
|
|
29
|
+
} from "../esm/repositoryChanges.js";
|
|
30
|
+
|
|
31
|
+
// Policy logging must not corrupt the JSON response stream.
|
|
32
|
+
globalThis.console = new Console(process.stderr);
|
|
33
|
+
const nativeStackGetter = Object.getOwnPropertyDescriptor(
|
|
34
|
+
new Error(),
|
|
35
|
+
"stack",
|
|
36
|
+
)?.get;
|
|
37
|
+
const nativePrepareStackTrace = Object.getOwnPropertyDescriptor(
|
|
38
|
+
Error,
|
|
39
|
+
"prepareStackTrace",
|
|
40
|
+
)?.value;
|
|
41
|
+
|
|
42
|
+
let registration;
|
|
43
|
+
let active;
|
|
44
|
+
let session;
|
|
45
|
+
let interrupted = false;
|
|
46
|
+
let closeInput;
|
|
47
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
48
|
+
process.on(signal, () => {
|
|
49
|
+
interrupted = true;
|
|
50
|
+
active?.abort(new Error(`Sidecar received ${signal}`));
|
|
51
|
+
closeInput?.();
|
|
52
|
+
});
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
source: regex.source,
|
|
60
|
-
flags: regex.flags,
|
|
61
|
-
};
|
|
55
|
+
async function respond(response) {
|
|
56
|
+
await new Promise((resolve, reject) => {
|
|
57
|
+
process.stdout.write(`${JSON.stringify(response)}\n`, (error) =>
|
|
58
|
+
error ? reject(error) : resolve(),
|
|
59
|
+
);
|
|
60
|
+
});
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
* Strips out functions and sends only what Rust needs for matching.
|
|
67
|
-
* @param {import("../src/policy.js").ConfiguredPolicy} policy
|
|
68
|
-
* @returns {object}
|
|
69
|
-
*/
|
|
70
|
-
function serializePolicy(policy) {
|
|
71
|
-
const match = serializeRegex(policy.match);
|
|
72
|
-
|
|
73
|
-
// Convert excludeFiles to regex pattern strings
|
|
74
|
-
const excludeFiles = (policy.excludeFiles ?? policy.exclude ?? []).map(
|
|
75
|
-
(e) => {
|
|
76
|
-
if (e instanceof RegExp) {
|
|
77
|
-
return e.source;
|
|
78
|
-
}
|
|
79
|
-
return String(e);
|
|
80
|
-
},
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
name: policy.name,
|
|
85
|
-
description: policy.description,
|
|
86
|
-
matchPattern: match.source,
|
|
87
|
-
matchFlags: match.flags,
|
|
88
|
-
hasResolver: typeof policy.resolver === "function",
|
|
89
|
-
excludeFiles,
|
|
90
|
-
};
|
|
63
|
+
function serializeRegex(regex) {
|
|
64
|
+
return { source: regex.source, flags: regex.flags };
|
|
91
65
|
}
|
|
92
66
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* @param {unknown} value
|
|
96
|
-
* @returns {boolean}
|
|
97
|
-
*/
|
|
98
|
-
function isOperation(value) {
|
|
99
|
-
return (
|
|
100
|
-
typeof value === "object" &&
|
|
101
|
-
value !== null &&
|
|
102
|
-
"next" in value &&
|
|
103
|
-
typeof value.next === "function"
|
|
104
|
-
);
|
|
67
|
+
function serializeExclusion(pattern) {
|
|
68
|
+
return pattern instanceof RegExp ? serializeRegex(pattern) : pattern;
|
|
105
69
|
}
|
|
106
70
|
|
|
107
|
-
/**
|
|
108
|
-
|
|
109
|
-
* @param {import("../src/policy.js").PolicyHandler} handler
|
|
110
|
-
* @param {import("../src/policy.js").PolicyArgs} args
|
|
111
|
-
* @returns {Promise<import("../src/policy.js").PolicyHandlerResult>}
|
|
112
|
-
*/
|
|
113
|
-
async function executeHandler(handler, args) {
|
|
114
|
-
const result = handler(args);
|
|
115
|
-
|
|
116
|
-
if (result instanceof Promise) {
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (isOperation(result)) {
|
|
121
|
-
// Run the generator through Effection
|
|
122
|
-
return run(function* () {
|
|
123
|
-
return yield* result;
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Shouldn't happen, but handle it
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Handle a load_config request.
|
|
133
|
-
* @param {object} params
|
|
134
|
-
*/
|
|
135
|
-
async function handleLoadConfig(params) {
|
|
71
|
+
/** Preserve Error's non-enumerable details and safely encode non-JSON causes. */
|
|
72
|
+
function serializeCause(value, seen = new WeakSet(), depth = 0) {
|
|
136
73
|
try {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const configLoader = lilconfig("repopo", {
|
|
141
|
-
searchPlaces: [
|
|
142
|
-
"repopo.config.ts",
|
|
143
|
-
"repopo.config.mjs",
|
|
144
|
-
"repopo.config.cjs",
|
|
145
|
-
],
|
|
146
|
-
loaders: {
|
|
147
|
-
".ts": TypeScriptLoader,
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const pathStats = await stat(searchPath);
|
|
152
|
-
const maybeConfig = pathStats.isDirectory()
|
|
153
|
-
? await configLoader.search(searchPath)
|
|
154
|
-
: await configLoader.load(searchPath);
|
|
155
|
-
|
|
156
|
-
if (maybeConfig !== null) {
|
|
157
|
-
loadedConfig = maybeConfig.config?.default ?? maybeConfig.config;
|
|
158
|
-
} else {
|
|
159
|
-
// Use default config
|
|
160
|
-
const { DefaultPolicyConfig } = await import("../esm/config.js");
|
|
161
|
-
loadedConfig = DefaultPolicyConfig;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Store git root for reuse in batch calls
|
|
165
|
-
storedGitRoot = params.gitRoot ?? process.cwd();
|
|
166
|
-
|
|
167
|
-
// Build the policy map and index array
|
|
168
|
-
policiesByName.clear();
|
|
169
|
-
policiesByIndex = [];
|
|
170
|
-
const policies =
|
|
171
|
-
loadedConfig?.policies ??
|
|
172
|
-
(await import("../esm/config.js")).DefaultPolicyConfig.policies;
|
|
173
|
-
for (const p of policies) {
|
|
174
|
-
policiesByName.set(p.name, p);
|
|
175
|
-
policiesByIndex.push(p);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Serialize for Rust
|
|
179
|
-
const serializedPolicies = policies.map(serializePolicy);
|
|
180
|
-
const excludeFiles = (loadedConfig?.excludeFiles ?? []).map((e) => {
|
|
181
|
-
if (e instanceof RegExp) {
|
|
182
|
-
return e.source;
|
|
183
|
-
}
|
|
184
|
-
return String(e);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
respond({
|
|
188
|
-
ok: true,
|
|
189
|
-
data: {
|
|
190
|
-
policies: serializedPolicies,
|
|
191
|
-
excludeFiles,
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
} catch (err) {
|
|
195
|
-
respond({
|
|
196
|
-
ok: false,
|
|
197
|
-
error: `Failed to load config: ${err.message}`,
|
|
198
|
-
});
|
|
74
|
+
return serializeValue(value, seen, depth);
|
|
75
|
+
} catch {
|
|
76
|
+
return { type: "uninspectable" };
|
|
199
77
|
}
|
|
200
78
|
}
|
|
201
79
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
async function handleRunHandler(params) {
|
|
207
|
-
try {
|
|
208
|
-
const policy = policiesByName.get(params.policyName);
|
|
209
|
-
if (!policy) {
|
|
210
|
-
respond({
|
|
211
|
-
ok: false,
|
|
212
|
-
error: `Unknown policy: ${params.policyName}`,
|
|
213
|
-
});
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const handler = policy._internalHandler ?? policy.handler;
|
|
218
|
-
const args = {
|
|
219
|
-
file: params.file,
|
|
220
|
-
root: params.root,
|
|
221
|
-
resolve: params.resolve ?? false,
|
|
222
|
-
config: policy.config,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const result = await executeHandler(handler, args);
|
|
226
|
-
|
|
227
|
-
// Serialize the result — `true` passes through as-is,
|
|
228
|
-
// objects (PolicyError/PolicyFailure) are serialized.
|
|
229
|
-
respond({ ok: true, data: result });
|
|
230
|
-
} catch (err) {
|
|
231
|
-
respond({
|
|
232
|
-
ok: false,
|
|
233
|
-
error: `Handler error for ${params.policyName}: ${err.message}`,
|
|
234
|
-
});
|
|
80
|
+
function serializeValue(value, seen, depth) {
|
|
81
|
+
if (value === undefined) return { type: "undefined" };
|
|
82
|
+
if (typeof value === "bigint" || typeof value === "symbol") {
|
|
83
|
+
return { type: typeof value, value: String(value) };
|
|
235
84
|
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
85
|
+
if (typeof value === "function") return { type: "function" };
|
|
86
|
+
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
87
|
+
return { type: "number", value: String(value) };
|
|
88
|
+
}
|
|
89
|
+
if (value === null || typeof value !== "object") return value;
|
|
90
|
+
// Proxy traps are arbitrary code, including during descriptor inspection.
|
|
91
|
+
if (types.isProxy(value)) return { type: "proxy" };
|
|
92
|
+
if (seen.has(value)) return { type: "circular" };
|
|
93
|
+
if (depth >= 20) return { type: "truncated" };
|
|
94
|
+
seen.add(value);
|
|
245
95
|
try {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
const length = Object.getOwnPropertyDescriptor(value, "length").value;
|
|
98
|
+
const array = Array.from(
|
|
99
|
+
{ length: Math.min(length, 10000) },
|
|
100
|
+
(_, index) => {
|
|
101
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
102
|
+
value,
|
|
103
|
+
String(index),
|
|
104
|
+
);
|
|
105
|
+
return descriptor && "value" in descriptor
|
|
106
|
+
? serializeCause(descriptor.value, seen, depth + 1)
|
|
107
|
+
: { type: descriptor ? "accessor" : "hole" };
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
if (length > array.length) array.push({ type: "truncated" });
|
|
111
|
+
return array;
|
|
253
112
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
pass.push(file);
|
|
273
|
-
} else {
|
|
274
|
-
fail.push({
|
|
275
|
-
file,
|
|
276
|
-
error: result.error,
|
|
277
|
-
errorMessages: result.errorMessages,
|
|
278
|
-
fixable: result.fixable ?? result.autoFixable,
|
|
279
|
-
fixed: result.fixed ?? result.resolved,
|
|
280
|
-
manualFix: result.manualFix,
|
|
281
|
-
});
|
|
113
|
+
const entries = [];
|
|
114
|
+
if (types.isNativeError(value)) {
|
|
115
|
+
for (const key of ["name", "message"]) {
|
|
116
|
+
let current = value;
|
|
117
|
+
let found = false;
|
|
118
|
+
while (current && !types.isProxy(current)) {
|
|
119
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key);
|
|
120
|
+
if (descriptor) {
|
|
121
|
+
found = true;
|
|
122
|
+
entries.push([
|
|
123
|
+
key,
|
|
124
|
+
"value" in descriptor
|
|
125
|
+
? serializeCause(descriptor.value, seen, depth + 1)
|
|
126
|
+
: { type: "accessor" },
|
|
127
|
+
]);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
current = Object.getPrototypeOf(current);
|
|
282
131
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
132
|
+
if (!found && current) entries.push([key, { type: "proxy" }]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
136
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
137
|
+
// V8 lazily exposes native Error stacks via a native accessor.
|
|
138
|
+
// Never call a user getter or Error.prepareStackTrace hook.
|
|
139
|
+
if (key === "stack" && types.isNativeError(value) && descriptor?.get) {
|
|
140
|
+
const prepare = Object.getOwnPropertyDescriptor(
|
|
141
|
+
Error,
|
|
142
|
+
"prepareStackTrace",
|
|
143
|
+
);
|
|
144
|
+
const plain = ["name", "message"].every((field) => {
|
|
145
|
+
const entry = entries.find(([name]) => name === field)?.[1];
|
|
146
|
+
return entry === undefined || typeof entry === "string";
|
|
288
147
|
});
|
|
148
|
+
if (
|
|
149
|
+
descriptor.get === nativeStackGetter &&
|
|
150
|
+
(!prepare ||
|
|
151
|
+
("value" in prepare &&
|
|
152
|
+
prepare.value === nativePrepareStackTrace)) &&
|
|
153
|
+
plain
|
|
154
|
+
) {
|
|
155
|
+
const stack = descriptor.get.call(value);
|
|
156
|
+
entries.push([
|
|
157
|
+
key,
|
|
158
|
+
typeof stack === "string" ? stack : { type: "uninspectable" },
|
|
159
|
+
]);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
289
162
|
}
|
|
163
|
+
entries.push([
|
|
164
|
+
key,
|
|
165
|
+
descriptor && "value" in descriptor
|
|
166
|
+
? serializeCause(descriptor.value, seen, depth + 1)
|
|
167
|
+
: { type: "accessor" },
|
|
168
|
+
]);
|
|
290
169
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
respond({
|
|
295
|
-
ok: false,
|
|
296
|
-
error: `Batch handler error for policy index ${params.policyId}: ${err.message}`,
|
|
297
|
-
});
|
|
170
|
+
return Object.fromEntries(entries);
|
|
171
|
+
} finally {
|
|
172
|
+
seen.delete(value);
|
|
298
173
|
}
|
|
299
174
|
}
|
|
300
175
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
176
|
+
function serializeRun(result) {
|
|
177
|
+
return {
|
|
178
|
+
...result,
|
|
179
|
+
errors: result.errors.map((error) => ({
|
|
180
|
+
...error,
|
|
181
|
+
cause: serializeCause(error.cause),
|
|
182
|
+
})),
|
|
183
|
+
perfStats: {
|
|
184
|
+
...result.perfStats,
|
|
185
|
+
data: Object.fromEntries(
|
|
186
|
+
[...result.perfStats.data].map(([action, timings]) => [
|
|
187
|
+
action,
|
|
188
|
+
Object.fromEntries(timings),
|
|
189
|
+
]),
|
|
190
|
+
),
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
315
194
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
195
|
+
async function loadConfig(params) {
|
|
196
|
+
registration = undefined;
|
|
197
|
+
session?.cache?.clear();
|
|
198
|
+
session = undefined;
|
|
199
|
+
const searchPath = params.configPath ?? process.cwd();
|
|
200
|
+
const loader = lilconfig("repopo", {
|
|
201
|
+
searchPlaces: [
|
|
202
|
+
"repopo.config.ts",
|
|
203
|
+
"repopo.config.mjs",
|
|
204
|
+
"repopo.config.cjs",
|
|
205
|
+
],
|
|
206
|
+
loaders: { ".ts": TypeScriptLoader },
|
|
207
|
+
});
|
|
208
|
+
const pathStats = await stat(searchPath);
|
|
209
|
+
const loaded = pathStats.isDirectory()
|
|
210
|
+
? await loader.search(searchPath)
|
|
211
|
+
: await loader.load(searchPath);
|
|
212
|
+
const config =
|
|
213
|
+
loaded?.config?.default ?? loaded?.config ?? DefaultPolicyConfig;
|
|
214
|
+
const policies = identifyPolicyInstances(
|
|
215
|
+
(config.policies ?? DefaultPolicyConfig.policies).map((policy) => {
|
|
216
|
+
if ("excludeFiles" in policy) {
|
|
217
|
+
throw new TypeError(
|
|
218
|
+
"Per-instance excludeFiles is retired; use exclude.",
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return makePolicy(policy, {
|
|
222
|
+
config: policy.config,
|
|
223
|
+
exclude: policy.exclude,
|
|
224
|
+
instanceId: policy.instanceId,
|
|
320
225
|
});
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
226
|
+
}),
|
|
227
|
+
);
|
|
228
|
+
const options = {
|
|
229
|
+
policies,
|
|
230
|
+
root: params.gitRoot ?? process.cwd(),
|
|
231
|
+
exclude: config.excludeFiles ?? [],
|
|
232
|
+
changes: config.changes,
|
|
233
|
+
};
|
|
234
|
+
options.exclude.forEach(exclusionRegex);
|
|
235
|
+
createExcludedPolicyFileMap(policies);
|
|
236
|
+
const metadata = {
|
|
237
|
+
policies: policies.map((policy) => ({
|
|
238
|
+
name: policy.name,
|
|
239
|
+
instanceId: policy.instanceId,
|
|
240
|
+
description: policy.description,
|
|
241
|
+
scope: policy.scope ?? "file",
|
|
242
|
+
...(policy.match ? { match: serializeRegex(policy.match) } : {}),
|
|
243
|
+
hasResolver: typeof policy.resolver === "function",
|
|
244
|
+
exclude: (policy.exclude ?? []).map(serializeExclusion),
|
|
245
|
+
})),
|
|
246
|
+
excludeFiles: options.exclude.map(serializeExclusion),
|
|
247
|
+
};
|
|
248
|
+
registration = options;
|
|
249
|
+
return metadata;
|
|
250
|
+
}
|
|
329
251
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
252
|
+
async function beginRun(params) {
|
|
253
|
+
if (!registration)
|
|
254
|
+
throw new Error("Load configuration before running policies.");
|
|
255
|
+
session?.cache?.clear();
|
|
256
|
+
session = undefined;
|
|
257
|
+
const mode = params.changeMode ?? registration.changes?.mode;
|
|
258
|
+
const options = {
|
|
259
|
+
mode,
|
|
260
|
+
base:
|
|
261
|
+
params.changeBase ??
|
|
262
|
+
((mode ?? "pr") === "pr"
|
|
263
|
+
? env.GITHUB_BASE_REF ||
|
|
264
|
+
env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME ||
|
|
265
|
+
registration.changes?.base
|
|
266
|
+
: undefined),
|
|
267
|
+
};
|
|
268
|
+
validateChangeOptions(options);
|
|
269
|
+
const inventory =
|
|
270
|
+
registration.policies.some((policy) => policy.scope === "changes") ||
|
|
271
|
+
params.changeMode != null ||
|
|
272
|
+
params.changeBase != null
|
|
273
|
+
? await collectRepositoryInventory(registration.root, options)
|
|
274
|
+
: [];
|
|
275
|
+
session = {
|
|
276
|
+
inventory,
|
|
277
|
+
executor: new PolicyExecutor(registration.root, params.fix ?? false),
|
|
278
|
+
cache: params.fix ? undefined : new ParsedFileCache(),
|
|
279
|
+
};
|
|
280
|
+
return {};
|
|
338
281
|
}
|
|
339
282
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
283
|
+
async function executeUnits(params) {
|
|
284
|
+
if (!registration || !session)
|
|
285
|
+
throw new Error(
|
|
286
|
+
"Load configuration and begin a run before executing units.",
|
|
287
|
+
);
|
|
288
|
+
active = new AbortController();
|
|
289
|
+
const task = run(function* () {
|
|
290
|
+
return yield* all(
|
|
291
|
+
params.units.map((unit) =>
|
|
292
|
+
(function* () {
|
|
293
|
+
const policy = registration.policies.find(
|
|
294
|
+
(entry) => entry.instanceId === unit.policyId,
|
|
295
|
+
);
|
|
296
|
+
if (!policy)
|
|
297
|
+
throw new Error(`Unknown policy instance: ${unit.policyId}`);
|
|
298
|
+
const result = {
|
|
299
|
+
findings: [],
|
|
300
|
+
errors: [],
|
|
301
|
+
skipped: [],
|
|
302
|
+
perfStats: newPerfStats(),
|
|
303
|
+
};
|
|
304
|
+
if (policy.scope === "repository" || policy.scope === "changes") {
|
|
305
|
+
if (!Array.isArray(unit.files))
|
|
306
|
+
throw new Error("Repository units require explicit inventory.");
|
|
307
|
+
const exclusions = [
|
|
308
|
+
...registration.exclude,
|
|
309
|
+
...(policy.exclude ?? []),
|
|
310
|
+
].map(exclusionRegex);
|
|
311
|
+
const entries = annotateInventory(
|
|
312
|
+
unit.files,
|
|
313
|
+
session.inventory,
|
|
314
|
+
).filter(
|
|
315
|
+
(entry) =>
|
|
316
|
+
!exclusions.some((regex) => matchesPath(regex, entry.path)),
|
|
317
|
+
);
|
|
318
|
+
yield* session.executor.repository(policy, entries, result);
|
|
319
|
+
} else {
|
|
320
|
+
if (typeof unit.file !== "string")
|
|
321
|
+
throw new Error("File units require a file.");
|
|
322
|
+
yield* session.executor.file(
|
|
323
|
+
unit.file,
|
|
324
|
+
policy,
|
|
325
|
+
result,
|
|
326
|
+
session.cache,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return serializeRun(result);
|
|
330
|
+
})(),
|
|
331
|
+
),
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
const abort = () => {
|
|
335
|
+
task.halt().catch(() => undefined);
|
|
336
|
+
};
|
|
337
|
+
active.signal.addEventListener("abort", abort, { once: true });
|
|
347
338
|
try {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (typeof policy.resolver !== "function") {
|
|
358
|
-
respond({
|
|
359
|
-
ok: false,
|
|
360
|
-
error: `Policy index ${params.policyId} has no resolver`,
|
|
361
|
-
});
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
339
|
+
return await task;
|
|
340
|
+
} finally {
|
|
341
|
+
active.signal.removeEventListener("abort", abort);
|
|
342
|
+
active = undefined;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
364
345
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
346
|
+
function matchFiles(params) {
|
|
347
|
+
const regex =
|
|
348
|
+
typeof params.pattern === "string"
|
|
349
|
+
? exclusionRegex(params.pattern)
|
|
350
|
+
: new RegExp(params.pattern.source, params.pattern.flags);
|
|
351
|
+
return params.files.map((file) => {
|
|
352
|
+
regex.lastIndex = 0;
|
|
353
|
+
return regex.test(file);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
369
356
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
fixed: result.fixed ?? result.resolved,
|
|
387
|
-
manualFix: result.manualFix,
|
|
388
|
-
});
|
|
357
|
+
async function main() {
|
|
358
|
+
const rl = createInterface({ input: process.stdin, terminal: false });
|
|
359
|
+
closeInput = () => rl.close();
|
|
360
|
+
let closing = false;
|
|
361
|
+
let shutdownRequested = false;
|
|
362
|
+
let pendingWork = 0;
|
|
363
|
+
rl.on("line", (line) => {
|
|
364
|
+
try {
|
|
365
|
+
const { method } = JSON.parse(line);
|
|
366
|
+
if (method === "execute_units") pendingWork++;
|
|
367
|
+
if (method === "shutdown") {
|
|
368
|
+
closing = true;
|
|
369
|
+
shutdownRequested = true;
|
|
370
|
+
if (active || pendingWork > 0) {
|
|
371
|
+
interrupted = true;
|
|
372
|
+
active?.abort(new Error("Native parent requested shutdown"));
|
|
389
373
|
}
|
|
390
|
-
} catch (err) {
|
|
391
|
-
fail.push({
|
|
392
|
-
file,
|
|
393
|
-
error: `Resolver error: ${err.message}`,
|
|
394
|
-
fixable: false,
|
|
395
|
-
fixed: false,
|
|
396
|
-
});
|
|
397
374
|
}
|
|
375
|
+
} catch {
|
|
376
|
+
// The request loop reports malformed JSON.
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
// A dead native parent closes the pipe. Halt owned operations before exit.
|
|
380
|
+
rl.on("close", () => {
|
|
381
|
+
if (!closing) {
|
|
382
|
+
interrupted = true;
|
|
383
|
+
active?.abort(new Error("Native parent closed the request stream"));
|
|
398
384
|
}
|
|
399
|
-
|
|
400
|
-
respond({ ok: true, data: { pass, fail } });
|
|
401
|
-
} catch (err) {
|
|
402
|
-
respond({
|
|
403
|
-
ok: false,
|
|
404
|
-
error: `Batch resolver error for policy index ${params.policyId}: ${err.message}`,
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* Main loop: read JSON requests from stdin, dispatch, respond on stdout.
|
|
411
|
-
*/
|
|
412
|
-
async function main() {
|
|
413
|
-
const rl = createInterface({
|
|
414
|
-
input: process.stdin,
|
|
415
|
-
terminal: false,
|
|
416
385
|
});
|
|
417
|
-
|
|
418
386
|
for await (const line of rl) {
|
|
387
|
+
if (interrupted || shutdownRequested) break;
|
|
419
388
|
if (!line.trim()) continue;
|
|
420
|
-
|
|
421
|
-
let request;
|
|
422
389
|
try {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
const { method, params } = request;
|
|
430
|
-
|
|
431
|
-
switch (method) {
|
|
432
|
-
case "load_config":
|
|
433
|
-
await handleLoadConfig(params ?? {});
|
|
434
|
-
break;
|
|
435
|
-
|
|
436
|
-
case "run_handler":
|
|
437
|
-
await handleRunHandler(params ?? {});
|
|
438
|
-
break;
|
|
439
|
-
|
|
440
|
-
case "run_resolver":
|
|
441
|
-
await handleRunResolver(params ?? {});
|
|
442
|
-
break;
|
|
443
|
-
|
|
444
|
-
case "run_handler_batch":
|
|
445
|
-
await handleRunHandlerBatch(params ?? {});
|
|
446
|
-
break;
|
|
447
|
-
|
|
448
|
-
case "run_resolver_batch":
|
|
449
|
-
await handleRunResolverBatch(params ?? {});
|
|
450
|
-
break;
|
|
451
|
-
|
|
452
|
-
case "shutdown":
|
|
453
|
-
process.exit(0);
|
|
390
|
+
const { method, params = {} } = JSON.parse(line);
|
|
391
|
+
if (method === "shutdown") {
|
|
392
|
+
closing = true;
|
|
454
393
|
break;
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
394
|
+
}
|
|
395
|
+
let data;
|
|
396
|
+
switch (method) {
|
|
397
|
+
case "load_config":
|
|
398
|
+
data = await loadConfig(params);
|
|
399
|
+
break;
|
|
400
|
+
case "begin_run":
|
|
401
|
+
data = await beginRun(params);
|
|
402
|
+
break;
|
|
403
|
+
case "execute_units":
|
|
404
|
+
try {
|
|
405
|
+
data = await executeUnits(params);
|
|
406
|
+
} finally {
|
|
407
|
+
pendingWork--;
|
|
408
|
+
}
|
|
409
|
+
break;
|
|
410
|
+
case "match_files":
|
|
411
|
+
if (!registration)
|
|
412
|
+
throw new Error("Load configuration before matching.");
|
|
413
|
+
data = matchFiles(params);
|
|
414
|
+
break;
|
|
415
|
+
default:
|
|
416
|
+
throw new Error(`Unknown method: ${method}`);
|
|
417
|
+
}
|
|
418
|
+
if (interrupted) break;
|
|
419
|
+
await respond({ ok: true, data });
|
|
420
|
+
} catch (error) {
|
|
421
|
+
if (interrupted) break;
|
|
422
|
+
await respond({
|
|
423
|
+
ok: false,
|
|
424
|
+
error: executionMessage(error),
|
|
425
|
+
cause: serializeCause(error),
|
|
426
|
+
});
|
|
458
427
|
}
|
|
428
|
+
if (interrupted) break;
|
|
459
429
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
430
|
+
closing = true;
|
|
431
|
+
session?.cache?.clear();
|
|
432
|
+
rl.close();
|
|
433
|
+
process.exit(interrupted ? 130 : 0);
|
|
463
434
|
}
|
|
464
435
|
|
|
465
|
-
main().catch((
|
|
466
|
-
process.stderr.write(`Sidecar fatal error: ${
|
|
436
|
+
main().catch((error) => {
|
|
437
|
+
process.stderr.write(`Sidecar fatal error: ${error.message}\n`);
|
|
467
438
|
process.exit(1);
|
|
468
439
|
});
|