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
package/esm/makePolicy.js
CHANGED
|
@@ -1,102 +1,58 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { exclusionRegex } from "./context.js";
|
|
2
|
+
export function makePolicy(definition, options, ...extra) {
|
|
3
|
+
const guidance = "Use makePolicy(definition, { config, exclude, instanceId }); positional config, third arguments and excludeFiles are no longer supported.";
|
|
4
|
+
if (extra.length > 0 ||
|
|
5
|
+
(options !== undefined &&
|
|
6
|
+
(typeof options !== "object" ||
|
|
7
|
+
options === null ||
|
|
8
|
+
Array.isArray(options) ||
|
|
9
|
+
Object.keys(options).some((key) => !["config", "exclude", "instanceId"].includes(key))))) {
|
|
10
|
+
throw new TypeError(guidance);
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
if (definition.scope === "repository" && definition.resolver !== undefined) {
|
|
13
|
+
throw new TypeError("Repository policies support inline fixes only; remove resolver.");
|
|
14
|
+
}
|
|
15
|
+
if (options?.exclude !== undefined &&
|
|
16
|
+
!(Array.isArray(options.exclude) &&
|
|
17
|
+
options.exclude.every((value) => typeof value === "string" || value instanceof RegExp))) {
|
|
18
|
+
throw new TypeError(guidance);
|
|
19
|
+
}
|
|
20
|
+
if (options?.instanceId !== undefined &&
|
|
21
|
+
(typeof options.instanceId !== "string" || options.instanceId.length === 0)) {
|
|
22
|
+
throw new TypeError("instanceId must be a nonempty string.");
|
|
23
|
+
}
|
|
24
|
+
options?.exclude?.forEach(exclusionRegex);
|
|
25
|
+
const config = options?.config === undefined ? definition.defaultConfig : options.config;
|
|
26
|
+
if (definition.requiresConfig && config === undefined) {
|
|
27
|
+
throw new TypeError(`Policy '${definition.name}' requires config. ${guidance}`);
|
|
28
|
+
}
|
|
29
|
+
return { ...definition, ...options, config };
|
|
17
30
|
}
|
|
18
|
-
/** @
|
|
19
|
-
export function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
/** Assign stable IDs, rejecting ambiguous duplicates. @internal */
|
|
32
|
+
export function identifyPolicyInstances(policies) {
|
|
33
|
+
const names = new Map();
|
|
34
|
+
const ids = new Set();
|
|
35
|
+
for (const policy of policies) {
|
|
36
|
+
names.set(policy.name, (names.get(policy.name) ?? 0) + 1);
|
|
37
|
+
if (policy.instanceId !== undefined) {
|
|
38
|
+
if (ids.has(policy.instanceId)) {
|
|
39
|
+
throw new Error(`Duplicate policy instance ID: ${policy.instanceId}`);
|
|
40
|
+
}
|
|
41
|
+
ids.add(policy.instanceId);
|
|
42
|
+
}
|
|
27
43
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (typeof configOrOptions === "object" &&
|
|
32
|
-
configOrOptions !== null &&
|
|
33
|
-
"exclude" in configOrOptions &&
|
|
34
|
-
!("name" in configOrOptions) &&
|
|
35
|
-
Object.keys(configOrOptions).every((k) => k === "exclude")) {
|
|
36
|
-
// It's options (has only 'exclude')
|
|
37
|
-
options = configOrOptions;
|
|
44
|
+
return policies.map((policy) => {
|
|
45
|
+
if (policy.instanceId !== undefined) {
|
|
46
|
+
return { ...policy, instanceId: policy.instanceId };
|
|
38
47
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
config = configOrOptions;
|
|
48
|
+
if ((names.get(policy.name) ?? 0) > 1) {
|
|
49
|
+
throw new Error(`Policy '${policy.name}' is configured multiple times. Set a unique instanceId for each instance.`);
|
|
42
50
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
...policyDef,
|
|
50
|
-
config: effectiveConfig,
|
|
51
|
-
exclude: excludePatterns,
|
|
52
|
-
excludeFiles: excludePatterns,
|
|
53
|
-
_internalHandler: normalizeHandler(policyDef.handler),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Creates a {@link PolicyDefinition} from the provided arguments.
|
|
58
|
-
*
|
|
59
|
-
* @deprecated Define policies as object literals satisfying {@link PolicyShape} instead.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```typescript
|
|
63
|
-
* const MyPolicy = makePolicyDefinition({
|
|
64
|
-
* name: "MyPolicy",
|
|
65
|
-
* description: "Ensures files follow conventions",
|
|
66
|
-
* match: /\.ts$/,
|
|
67
|
-
* handler: async ({ file }) => true,
|
|
68
|
-
* });
|
|
69
|
-
* ```
|
|
70
|
-
*
|
|
71
|
-
* @alpha
|
|
72
|
-
*/
|
|
73
|
-
export function makePolicyDefinition(args) {
|
|
74
|
-
return {
|
|
75
|
-
name: args.name,
|
|
76
|
-
description: args.description,
|
|
77
|
-
match: args.match,
|
|
78
|
-
handler: args.handler,
|
|
79
|
-
defaultConfig: args.defaultConfig,
|
|
80
|
-
resolver: args.resolver,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Combine a {@link PolicyDefinition} with a policy-specific config and other settings.
|
|
85
|
-
*
|
|
86
|
-
* @deprecated Use the `policy` function instead, which has a simpler API.
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```typescript
|
|
90
|
-
* makePolicy(NoJsFileExtensions, undefined, { excludeFiles: ["bin/*"] })
|
|
91
|
-
* ```
|
|
92
|
-
*
|
|
93
|
-
* @alpha
|
|
94
|
-
*/
|
|
95
|
-
export function makePolicy(definition, config, settings) {
|
|
96
|
-
return {
|
|
97
|
-
...definition,
|
|
98
|
-
...settings,
|
|
99
|
-
config,
|
|
100
|
-
};
|
|
51
|
+
if (ids.has(policy.name)) {
|
|
52
|
+
throw new Error(`Policy instance ID '${policy.name}' conflicts with another configured policy. Set an explicit unique instanceId.`);
|
|
53
|
+
}
|
|
54
|
+
ids.add(policy.name);
|
|
55
|
+
return { ...policy, instanceId: policy.name };
|
|
56
|
+
});
|
|
101
57
|
}
|
|
102
58
|
//# sourceMappingURL=makePolicy.js.map
|
package/esm/makePolicy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makePolicy.js","sourceRoot":"","sources":["../src/makePolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"makePolicy.js","sourceRoot":"","sources":["../src/makePolicy.ts"],"names":[],"mappings":"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","sourcesContent":["import { exclusionRegex } from \"./context.js\";\nimport type {\n\tConfiguredFilePolicy,\n\tConfiguredPolicy,\n\tConfiguredRepositoryPolicy,\n\tDefinedConfig,\n\tFilePolicyDefinition,\n\tPolicyDefinition,\n\tPolicyInstanceId,\n\tPolicyName,\n\tPolicyOptions,\n\tRepositoryPolicyDefinition,\n} from \"./policy.js\";\n\ntype ConfigOf<D> = D extends PolicyDefinition<infer C> ? C : never;\ntype RequiredConfigDefinitions<D> = D extends { requiresConfig: true }\n\t? D extends { defaultConfig: infer Default }\n\t\t? undefined extends Default\n\t\t\t? D\n\t\t\t: never\n\t\t: D\n\t: never;\ntype OptionsFor<D> = [RequiredConfigDefinitions<D>] extends [never]\n\t? [options?: PolicyOptions<ConfigOf<D>>]\n\t: [\n\t\t\toptions: PolicyOptions<ConfigOf<D>> & {\n\t\t\t\tconfig: DefinedConfig<ConfigOf<RequiredConfigDefinitions<D>>>;\n\t\t\t},\n\t\t];\n\n/** Configure a file definition using a single options object. @public */\nexport function makePolicy<D extends FilePolicyDefinition<unknown>>(\n\tdefinition: D,\n\t...options: OptionsFor<D>\n): ConfiguredFilePolicy<ConfigOf<D>>;\n/** Configure a repository definition using a single options object. @public */\nexport function makePolicy<D extends RepositoryPolicyDefinition<unknown>>(\n\tdefinition: D,\n\t...options: OptionsFor<D>\n): ConfiguredRepositoryPolicy<ConfigOf<D>>;\n/** Configure a common-union definition without losing scope discrimination. @public */\nexport function makePolicy<D extends PolicyDefinition<unknown>>(\n\tdefinition: D,\n\t...options: OptionsFor<D>\n): ConfiguredPolicy<ConfigOf<D>>;\nexport function makePolicy(\n\tdefinition: PolicyDefinition<unknown>,\n\toptions?: PolicyOptions<unknown>,\n\t...extra: unknown[]\n): ConfiguredPolicy<unknown> {\n\tconst guidance =\n\t\t\"Use makePolicy(definition, { config, exclude, instanceId }); positional config, third arguments and excludeFiles are no longer supported.\";\n\tif (\n\t\textra.length > 0 ||\n\t\t(options !== undefined &&\n\t\t\t(typeof options !== \"object\" ||\n\t\t\t\toptions === null ||\n\t\t\t\tArray.isArray(options) ||\n\t\t\t\tObject.keys(options).some(\n\t\t\t\t\t(key) => ![\"config\", \"exclude\", \"instanceId\"].includes(key),\n\t\t\t\t)))\n\t) {\n\t\tthrow new TypeError(guidance);\n\t}\n\tif (definition.scope === \"repository\" && definition.resolver !== undefined) {\n\t\tthrow new TypeError(\n\t\t\t\"Repository policies support inline fixes only; remove resolver.\",\n\t\t);\n\t}\n\tif (\n\t\toptions?.exclude !== undefined &&\n\t\t!(\n\t\t\tArray.isArray(options.exclude) &&\n\t\t\toptions.exclude.every(\n\t\t\t\t(value) => typeof value === \"string\" || value instanceof RegExp,\n\t\t\t)\n\t\t)\n\t) {\n\t\tthrow new TypeError(guidance);\n\t}\n\tif (\n\t\toptions?.instanceId !== undefined &&\n\t\t(typeof options.instanceId !== \"string\" || options.instanceId.length === 0)\n\t) {\n\t\tthrow new TypeError(\"instanceId must be a nonempty string.\");\n\t}\n\toptions?.exclude?.forEach(exclusionRegex);\n\tconst config =\n\t\toptions?.config === undefined ? definition.defaultConfig : options.config;\n\tif (definition.requiresConfig && config === undefined) {\n\t\tthrow new TypeError(\n\t\t\t`Policy '${definition.name}' requires config. ${guidance}`,\n\t\t);\n\t}\n\treturn { ...definition, ...options, config };\n}\n\n/** Assign stable IDs, rejecting ambiguous duplicates. @internal */\nexport function identifyPolicyInstances<\n\tT extends { name: PolicyName; instanceId?: PolicyInstanceId | undefined },\n>(policies: readonly T[]): (T & { instanceId: PolicyInstanceId })[] {\n\tconst names = new Map<string, number>();\n\tconst ids = new Set<string>();\n\tfor (const policy of policies) {\n\t\tnames.set(policy.name, (names.get(policy.name) ?? 0) + 1);\n\t\tif (policy.instanceId !== undefined) {\n\t\t\tif (ids.has(policy.instanceId)) {\n\t\t\t\tthrow new Error(`Duplicate policy instance ID: ${policy.instanceId}`);\n\t\t\t}\n\t\t\tids.add(policy.instanceId);\n\t\t}\n\t}\n\treturn policies.map((policy) => {\n\t\tif (policy.instanceId !== undefined) {\n\t\t\treturn { ...policy, instanceId: policy.instanceId };\n\t\t}\n\t\tif ((names.get(policy.name) ?? 0) > 1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Policy '${policy.name}' is configured multiple times. Set a unique instanceId for each instance.`,\n\t\t\t);\n\t\t}\n\t\tif (ids.has(policy.name)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Policy instance ID '${policy.name}' conflicts with another configured policy. Set an explicit unique instanceId.`,\n\t\t\t);\n\t\t}\n\t\tids.add(policy.name);\n\t\treturn { ...policy, instanceId: policy.name };\n\t});\n}\n"]}
|
package/esm/perf.d.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import type { Logger } from "@tylerbu/cli-api";
|
|
2
2
|
import type { Operation } from "effection";
|
|
3
|
-
import type {
|
|
3
|
+
import type { PolicyInstanceId } from "./policy.js";
|
|
4
|
+
/**
|
|
5
|
+
* The type of action a policy can perform.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
4
8
|
export type PolicyAction = "check" | "resolve" | "handle";
|
|
5
9
|
/**
|
|
6
10
|
* Stores performance data for each handler. Used to collect and display performance stats.
|
|
11
|
+
* @public
|
|
7
12
|
*/
|
|
8
13
|
export interface PolicyHandlerPerfStats {
|
|
14
|
+
/** Number of candidate file paths supplied to the runner. */
|
|
9
15
|
count: number;
|
|
16
|
+
/** Number of candidate files admitted past global exclusions. */
|
|
10
17
|
processed: number;
|
|
11
|
-
|
|
18
|
+
/** Total elapsed milliseconds per action and configured policy instance. */
|
|
19
|
+
data: Map<PolicyAction, Map<PolicyInstanceId, number>>;
|
|
12
20
|
}
|
|
13
21
|
export declare function newPerfStats(): PolicyHandlerPerfStats;
|
|
14
22
|
export declare function runWithPerf<T>(name: string, action: PolicyAction, stats: PolicyHandlerPerfStats, run: () => Operation<T>): Operation<T>;
|
package/esm/perf.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,IAAI,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,wBAAgB,YAAY,IAAI,sBAAsB,CAMrD;AAED,wBAAiB,WAAW,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,sBAAsB,EAC7B,GAAG,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,GACrB,SAAS,CAAC,CAAC,CAAC,CASd;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWzE"}
|
package/esm/perf.js
CHANGED
|
@@ -6,14 +6,15 @@ export function newPerfStats() {
|
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
8
|
export function* runWithPerf(name, action, stats, run) {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
const start = performance.now();
|
|
10
|
+
try {
|
|
11
|
+
return yield* run();
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
const actionMap = stats.data.get(action) ?? new Map();
|
|
15
|
+
actionMap.set(name, (actionMap.get(name) ?? 0) + performance.now() - start);
|
|
16
|
+
stats.data.set(action, actionMap);
|
|
17
|
+
}
|
|
17
18
|
}
|
|
18
19
|
export function logStats(stats, log) {
|
|
19
20
|
log.log(`Statistics: ${stats.processed} files processed, ` +
|
|
@@ -21,7 +22,7 @@ export function logStats(stats, log) {
|
|
|
21
22
|
for (const [action, handlerPerf] of stats.data.entries()) {
|
|
22
23
|
log.log(`Performance for "${action}":`);
|
|
23
24
|
for (const [handler, dur] of handlerPerf.entries()) {
|
|
24
|
-
log.log(` ${handler}: ${dur}ms`);
|
|
25
|
+
log.log(` ${handler}: ${Math.round(dur * 10) / 10}ms`);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
}
|
package/esm/perf.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,YAAY;IAC3B,OAAO;QACN,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,CAAC;QACZ,IAAI,EAAE,IAAI,GAAG,EAA+C;KAC5D,CAAC;AACH,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,WAAW,CAC3B,IAAY,EACZ,MAAoB,EACpB,KAA6B,EAC7B,GAAuB;IAEvB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,IAAI,CAAC;QACJ,OAAO,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;YAAS,CAAC;QACV,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,EAAkB,CAAC;QACtE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,CAAC;AACF,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAA6B,EAAE,GAAW;IAClE,GAAG,CAAC,GAAG,CACN,eAAe,KAAK,CAAC,SAAS,oBAAoB;QACjD,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,cAAc,KAAK,CAAC,KAAK,QAAQ,CAClE,CAAC;IACF,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,oBAAoB,MAAM,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,OAAO,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;IACF,CAAC;AACF,CAAC","sourcesContent":["import type { Logger } from \"@tylerbu/cli-api\";\nimport type { Operation } from \"effection\";\nimport type { PolicyInstanceId } from \"./policy.js\";\n\n/**\n * The type of action a policy can perform.\n * @public\n */\nexport type PolicyAction = \"check\" | \"resolve\" | \"handle\";\n\n/**\n * Stores performance data for each handler. Used to collect and display performance stats.\n * @public\n */\nexport interface PolicyHandlerPerfStats {\n\t/** Number of candidate file paths supplied to the runner. */\n\tcount: number;\n\t/** Number of candidate files admitted past global exclusions. */\n\tprocessed: number;\n\t/** Total elapsed milliseconds per action and configured policy instance. */\n\tdata: Map<PolicyAction, Map<PolicyInstanceId, number>>;\n}\n\nexport function newPerfStats(): PolicyHandlerPerfStats {\n\treturn {\n\t\tcount: 0,\n\t\tprocessed: 0,\n\t\tdata: new Map<PolicyAction, Map<PolicyInstanceId, number>>(),\n\t};\n}\n\nexport function* runWithPerf<T>(\n\tname: string,\n\taction: PolicyAction,\n\tstats: PolicyHandlerPerfStats,\n\trun: () => Operation<T>,\n): Operation<T> {\n\tconst start = performance.now();\n\ttry {\n\t\treturn yield* run();\n\t} finally {\n\t\tconst actionMap = stats.data.get(action) ?? new Map<string, number>();\n\t\tactionMap.set(name, (actionMap.get(name) ?? 0) + performance.now() - start);\n\t\tstats.data.set(action, actionMap);\n\t}\n}\n\nexport function logStats(stats: PolicyHandlerPerfStats, log: Logger): void {\n\tlog.log(\n\t\t`Statistics: ${stats.processed} files processed, ` +\n\t\t\t`${stats.count - stats.processed} excluded, ${stats.count} total`,\n\t);\n\tfor (const [action, handlerPerf] of stats.data.entries()) {\n\t\tlog.log(`Performance for \"${action}\":`);\n\t\tfor (const [handler, dur] of handlerPerf.entries()) {\n\t\t\tlog.log(` ${handler}: ${Math.round(dur * 10) / 10}ms`);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { FilePolicyDefinition } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the CargoLicenceValidated policy.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface CargoLicenceValidatedConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Allowed SPDX licence identifiers. If set, only these are accepted.
|
|
10
|
+
*/
|
|
11
|
+
allowedLicences?: string[];
|
|
12
|
+
/**
|
|
13
|
+
* If true, validate the licence value against the SPDX licence list
|
|
14
|
+
* using `spdx-correct`. When enabled, typos like "MIIT" are detected
|
|
15
|
+
* and can be auto-fixed to the correct identifier ("MIT").
|
|
16
|
+
*
|
|
17
|
+
* Requires the optional peer dependency `spdx-correct` to be installed.
|
|
18
|
+
*
|
|
19
|
+
* @defaultValue true
|
|
20
|
+
*/
|
|
21
|
+
validateSpdx?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* If true, skip workspace-only Cargo.toml files (those without a [package] section).
|
|
24
|
+
*
|
|
25
|
+
* @defaultValue true
|
|
26
|
+
*/
|
|
27
|
+
skipWorkspace?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A policy that validates the `license` field in Cargo.toml against the SPDX
|
|
31
|
+
* licence list. Supports auto-fixing correctable identifiers.
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* Cargo.toml uses a single `license` string field (not an array like Gleam's
|
|
35
|
+
* `licences`). This policy validates that the value is a recognized SPDX
|
|
36
|
+
* identifier and can auto-fix common mistakes like wrong casing.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export declare const CargoLicenceValidated: FilePolicyDefinition<CargoLicenceValidatedConfig>;
|
|
41
|
+
//# sourceMappingURL=CargoLicenceValidated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CargoLicenceValidated.d.ts","sourceRoot":"","sources":["../../src/policies/CargoLicenceValidated.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAOzD;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC3C;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAKD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,mDAsC4B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { resolve } from "pathe";
|
|
2
|
+
import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
|
|
3
|
+
import { validateLicenceField } from "../policyDefiners/spdxValidator.js";
|
|
4
|
+
const MANUAL_FIX = "Use a valid SPDX licence identifier (e.g., MIT, Apache-2.0, MPL-2.0).";
|
|
5
|
+
/**
|
|
6
|
+
* A policy that validates the `license` field in Cargo.toml against the SPDX
|
|
7
|
+
* licence list. Supports auto-fixing correctable identifiers.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Cargo.toml uses a single `license` string field (not an array like Gleam's
|
|
11
|
+
* `licences`). This policy validates that the value is a recognized SPDX
|
|
12
|
+
* identifier and can auto-fix common mistakes like wrong casing.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export const CargoLicenceValidated = defineCargoPolicy({
|
|
17
|
+
name: "CargoLicenceValidated",
|
|
18
|
+
description: "Validates that Cargo.toml has a valid SPDX licence identifier.",
|
|
19
|
+
handler: async (toml, { file, root, resolve: shouldResolve, config }) => {
|
|
20
|
+
const skipWorkspace = config?.skipWorkspace ?? true;
|
|
21
|
+
const pkg = toml.package;
|
|
22
|
+
if (!pkg && skipWorkspace) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const licence = pkg?.license;
|
|
26
|
+
if (!licence || licence.trim() === "") {
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
message: "Missing or empty license field in [package] section.",
|
|
30
|
+
manualFix: 'Add license = "MIT" (or appropriate SPDX identifier) to [package] in Cargo.toml.',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
const result = await validateLicenceField({
|
|
35
|
+
licences: [licence],
|
|
36
|
+
...(config?.allowedLicences !== undefined && {
|
|
37
|
+
allowedLicences: config.allowedLicences,
|
|
38
|
+
}),
|
|
39
|
+
validateSpdx: config?.validateSpdx ?? true,
|
|
40
|
+
shouldResolve,
|
|
41
|
+
filePath: resolve(root, file),
|
|
42
|
+
manualFixMessage: MANUAL_FIX,
|
|
43
|
+
});
|
|
44
|
+
return result;
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=CargoLicenceValidated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CargoLicenceValidated.js","sourceRoot":"","sources":["../../src/policies/CargoLicenceValidated.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAgC1E,MAAM,UAAU,GACf,uEAAuE,CAAC;AAEzE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;IACtD,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,gEAAgE;IAC7E,OAAO,EAAE,KAAK,EACb,IAAe,EACf,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,EAC7C,EAAE;QACH,MAAM,aAAa,GAAG,MAAM,EAAE,aAAa,IAAI,IAAI,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,OAA8C,CAAC;QAEhE,IAAI,CAAC,GAAG,IAAI,aAAa,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACX,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,EAAE,OAA6B,CAAC;QAEnD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvC,OAAO;gBACN;oBACC,OAAO,EAAE,sDAAsD;oBAC/D,SAAS,EACR,kFAAkF;iBACnF;aACD,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC;YACzC,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,GAAG,CAAC,MAAM,EAAE,eAAe,KAAK,SAAS,IAAI;gBAC5C,eAAe,EAAE,MAAM,CAAC,eAAe;aACvC,CAAC;YACF,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,IAAI;YAC1C,aAAa;YACb,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;YAC7B,gBAAgB,EAAE,UAAU;SAC5B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IACf,CAAC;CACD,CAA6D,CAAC","sourcesContent":["import { resolve } from \"pathe\";\nimport type { FilePolicyDefinition } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\nimport { validateLicenceField } from \"../policyDefiners/spdxValidator.js\";\n\n/**\n * Configuration for the CargoLicenceValidated policy.\n *\n * @public\n */\nexport interface CargoLicenceValidatedConfig {\n\t/**\n\t * Allowed SPDX licence identifiers. If set, only these are accepted.\n\t */\n\tallowedLicences?: string[];\n\n\t/**\n\t * If true, validate the licence value against the SPDX licence list\n\t * using `spdx-correct`. When enabled, typos like \"MIIT\" are detected\n\t * and can be auto-fixed to the correct identifier (\"MIT\").\n\t *\n\t * Requires the optional peer dependency `spdx-correct` to be installed.\n\t *\n\t * @defaultValue true\n\t */\n\tvalidateSpdx?: boolean;\n\n\t/**\n\t * If true, skip workspace-only Cargo.toml files (those without a [package] section).\n\t *\n\t * @defaultValue true\n\t */\n\tskipWorkspace?: boolean;\n}\n\nconst MANUAL_FIX =\n\t\"Use a valid SPDX licence identifier (e.g., MIT, Apache-2.0, MPL-2.0).\";\n\n/**\n * A policy that validates the `license` field in Cargo.toml against the SPDX\n * licence list. Supports auto-fixing correctable identifiers.\n *\n * @remarks\n * Cargo.toml uses a single `license` string field (not an array like Gleam's\n * `licences`). This policy validates that the value is a recognized SPDX\n * identifier and can auto-fix common mistakes like wrong casing.\n *\n * @public\n */\nexport const CargoLicenceValidated = defineCargoPolicy({\n\tname: \"CargoLicenceValidated\",\n\tdescription: \"Validates that Cargo.toml has a valid SPDX licence identifier.\",\n\thandler: async (\n\t\ttoml: CargoToml,\n\t\t{ file, root, resolve: shouldResolve, config },\n\t) => {\n\t\tconst skipWorkspace = config?.skipWorkspace ?? true;\n\t\tconst pkg = toml.package as Record<string, unknown> | undefined;\n\n\t\tif (!pkg && skipWorkspace) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst licence = pkg?.license as string | undefined;\n\n\t\tif (!licence || licence.trim() === \"\") {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tmessage: \"Missing or empty license field in [package] section.\",\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t'Add license = \"MIT\" (or appropriate SPDX identifier) to [package] in Cargo.toml.',\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\tconst result = await validateLicenceField({\n\t\t\tlicences: [licence],\n\t\t\t...(config?.allowedLicences !== undefined && {\n\t\t\t\tallowedLicences: config.allowedLicences,\n\t\t\t}),\n\t\t\tvalidateSpdx: config?.validateSpdx ?? true,\n\t\t\tshouldResolve,\n\t\t\tfilePath: resolve(root, file),\n\t\t\tmanualFixMessage: MANUAL_FIX,\n\t\t});\n\t\treturn result;\n\t},\n}) satisfies FilePolicyDefinition<CargoLicenceValidatedConfig>;\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { FilePolicyDefinition } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the CargoLintsConfigured policy.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface CargoLintsConfiguredConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Required clippy lint levels. Keys are lint names (without the `clippy::` prefix),
|
|
10
|
+
* values are the minimum level ("warn" or "deny").
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* { pedantic: "warn", nursery: "warn" }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
required?: Record<string, string>;
|
|
18
|
+
/**
|
|
19
|
+
* If true, just require that a [lints.clippy] section exists (without checking specific lints).
|
|
20
|
+
* @defaultValue true
|
|
21
|
+
*/
|
|
22
|
+
requireSection?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A policy that ensures Cargo.toml has a [lints.clippy] section configured.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export declare const CargoLintsConfigured: FilePolicyDefinition<CargoLintsConfiguredConfig>;
|
|
30
|
+
//# sourceMappingURL=CargoLintsConfigured.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CargoLintsConfigured.d.ts","sourceRoot":"","sources":["../../src/policies/CargoLintsConfigured.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAgB,MAAM,cAAc,CAAC;AAMvE;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAElC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAmED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,kDAY4B,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
|
|
2
|
+
function checkClippyLints(clippy, required) {
|
|
3
|
+
const errors = [];
|
|
4
|
+
for (const [lint, expectedLevel] of Object.entries(required)) {
|
|
5
|
+
const actual = clippy[lint];
|
|
6
|
+
if (actual === undefined) {
|
|
7
|
+
errors.push(`Missing clippy lint: ${lint} (expected level: "${expectedLevel}")`);
|
|
8
|
+
}
|
|
9
|
+
else if (String(actual) !== expectedLevel) {
|
|
10
|
+
errors.push(`Clippy lint ${lint} = "${String(actual)}", expected "${expectedLevel}"`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return errors;
|
|
14
|
+
}
|
|
15
|
+
function checkLintsSection(toml, config) {
|
|
16
|
+
const lints = toml.lints;
|
|
17
|
+
const requireSection = config?.requireSection ?? true;
|
|
18
|
+
if (requireSection && lints === undefined) {
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
message: "Missing [lints] section in Cargo.toml.",
|
|
22
|
+
manualFix: 'Add a [lints.clippy] section, e.g.:\n[lints.clippy]\npedantic = "warn"',
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
if (lints === undefined) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const clippy = lints.clippy;
|
|
30
|
+
if (requireSection && clippy === undefined) {
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
message: "Missing [lints.clippy] section in Cargo.toml.",
|
|
34
|
+
manualFix: 'Add a [lints.clippy] section, e.g.:\n[lints.clippy]\npedantic = "warn"',
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
if (config?.required && clippy) {
|
|
39
|
+
const errors = checkClippyLints(clippy, config.required);
|
|
40
|
+
if (errors.length > 0) {
|
|
41
|
+
return errors.map((message) => ({
|
|
42
|
+
message,
|
|
43
|
+
manualFix: "Update the [lints.clippy] section with the required lint levels.",
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A policy that ensures Cargo.toml has a [lints.clippy] section configured.
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export const CargoLintsConfigured = defineCargoPolicy({
|
|
55
|
+
name: "CargoLintsConfigured",
|
|
56
|
+
description: "Ensures Cargo.toml has clippy lints configured in the [lints] section.",
|
|
57
|
+
handler: async (toml, { config }) => {
|
|
58
|
+
// Skip workspace root Cargo.toml files
|
|
59
|
+
if (toml.workspace !== undefined && toml.package === undefined) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return checkLintsSection(toml, config);
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=CargoLintsConfigured.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CargoLintsConfigured.js","sourceRoot":"","sources":["../../src/policies/CargoLintsConfigured.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AA0BhD,SAAS,gBAAgB,CACxB,MAA+B,EAC/B,QAAgC;IAEhC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CACV,wBAAwB,IAAI,sBAAsB,aAAa,IAAI,CACnE,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,aAAa,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CACV,eAAe,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,gBAAgB,aAAa,GAAG,CACxE,CAAC;QACH,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CACzB,IAAe,EACf,MAA8C;IAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAA4C,CAAC;IAChE,MAAM,cAAc,GAAG,MAAM,EAAE,cAAc,IAAI,IAAI,CAAC;IAEtD,IAAI,cAAc,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO;YACN;gBACC,OAAO,EAAE,wCAAwC;gBACjD,SAAS,EACR,wEAAwE;aACzE;SACD,CAAC;IACH,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAA6C,CAAC;IACnE,IAAI,cAAc,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO;YACN;gBACC,OAAO,EAAE,+CAA+C;gBACxD,SAAS,EACR,wEAAwE;aACzE;SACD,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,QAAQ,IAAI,MAAM,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC/B,OAAO;gBACP,SAAS,EACR,kEAAkE;aACnE,CAAC,CAAC,CAAC;QACL,CAAC;IACF,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;IACrD,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACV,wEAAwE;IACzE,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,uCAAuC;QACvC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;CACD,CAA4D,CAAC","sourcesContent":["import type { FilePolicyDefinition, PolicyResult } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\n\n/**\n * Configuration for the CargoLintsConfigured policy.\n *\n * @public\n */\nexport interface CargoLintsConfiguredConfig {\n\t/**\n\t * Required clippy lint levels. Keys are lint names (without the `clippy::` prefix),\n\t * values are the minimum level (\"warn\" or \"deny\").\n\t *\n\t * @example\n\t * ```typescript\n\t * { pedantic: \"warn\", nursery: \"warn\" }\n\t * ```\n\t */\n\trequired?: Record<string, string>;\n\n\t/**\n\t * If true, just require that a [lints.clippy] section exists (without checking specific lints).\n\t * @defaultValue true\n\t */\n\trequireSection?: boolean;\n}\n\nfunction checkClippyLints(\n\tclippy: Record<string, unknown>,\n\trequired: Record<string, string>,\n): string[] {\n\tconst errors: string[] = [];\n\tfor (const [lint, expectedLevel] of Object.entries(required)) {\n\t\tconst actual = clippy[lint];\n\t\tif (actual === undefined) {\n\t\t\terrors.push(\n\t\t\t\t`Missing clippy lint: ${lint} (expected level: \"${expectedLevel}\")`,\n\t\t\t);\n\t\t} else if (String(actual) !== expectedLevel) {\n\t\t\terrors.push(\n\t\t\t\t`Clippy lint ${lint} = \"${String(actual)}\", expected \"${expectedLevel}\"`,\n\t\t\t);\n\t\t}\n\t}\n\treturn errors;\n}\n\nfunction checkLintsSection(\n\ttoml: CargoToml,\n\tconfig: CargoLintsConfiguredConfig | undefined,\n): PolicyResult {\n\tconst lints = toml.lints as Record<string, unknown> | undefined;\n\tconst requireSection = config?.requireSection ?? true;\n\n\tif (requireSection && lints === undefined) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tmessage: \"Missing [lints] section in Cargo.toml.\",\n\t\t\t\tmanualFix:\n\t\t\t\t\t'Add a [lints.clippy] section, e.g.:\\n[lints.clippy]\\npedantic = \"warn\"',\n\t\t\t},\n\t\t];\n\t}\n\n\tif (lints === undefined) {\n\t\treturn [];\n\t}\n\n\tconst clippy = lints.clippy as Record<string, unknown> | undefined;\n\tif (requireSection && clippy === undefined) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tmessage: \"Missing [lints.clippy] section in Cargo.toml.\",\n\t\t\t\tmanualFix:\n\t\t\t\t\t'Add a [lints.clippy] section, e.g.:\\n[lints.clippy]\\npedantic = \"warn\"',\n\t\t\t},\n\t\t];\n\t}\n\n\tif (config?.required && clippy) {\n\t\tconst errors = checkClippyLints(clippy, config.required);\n\t\tif (errors.length > 0) {\n\t\t\treturn errors.map((message) => ({\n\t\t\t\tmessage,\n\t\t\t\tmanualFix:\n\t\t\t\t\t\"Update the [lints.clippy] section with the required lint levels.\",\n\t\t\t}));\n\t\t}\n\t}\n\treturn [];\n}\n\n/**\n * A policy that ensures Cargo.toml has a [lints.clippy] section configured.\n *\n * @public\n */\nexport const CargoLintsConfigured = defineCargoPolicy({\n\tname: \"CargoLintsConfigured\",\n\tdescription:\n\t\t\"Ensures Cargo.toml has clippy lints configured in the [lints] section.\",\n\thandler: async (toml: CargoToml, { config }) => {\n\t\t// Skip workspace root Cargo.toml files\n\t\tif (toml.workspace !== undefined && toml.package === undefined) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn checkLintsSection(toml, config);\n\t},\n}) satisfies FilePolicyDefinition<CargoLintsConfiguredConfig>;\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FilePolicyDefinition } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the CargoLockPolicy.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface CargoLockPolicyConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Policy for binary crates.
|
|
10
|
+
* - "require": Cargo.lock must be committed (default for binaries)
|
|
11
|
+
* - "warn": Emit a warning if missing
|
|
12
|
+
* - "ignore": Skip check
|
|
13
|
+
*
|
|
14
|
+
* @defaultValue "require"
|
|
15
|
+
*/
|
|
16
|
+
binaries?: "require" | "warn" | "ignore";
|
|
17
|
+
/**
|
|
18
|
+
* Policy for library crates.
|
|
19
|
+
* - "require": Cargo.lock must be committed
|
|
20
|
+
* - "warn": Emit a warning if committed (default for libraries)
|
|
21
|
+
* - "ignore": Skip check
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue "ignore"
|
|
24
|
+
*/
|
|
25
|
+
libraries?: "require" | "warn" | "ignore";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A context-aware policy for Cargo.lock files.
|
|
29
|
+
* Binary crates should commit Cargo.lock; library crates typically shouldn't.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export declare const CargoLockPolicy: FilePolicyDefinition<CargoLockPolicyConfig>;
|
|
34
|
+
//# sourceMappingURL=CargoLockPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CargoLockPolicy.d.ts","sourceRoot":"","sources":["../../src/policies/CargoLockPolicy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAMzD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAEzC;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;CAC1C;AAsBD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,6CAyC4B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "pathe";
|
|
3
|
+
import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
|
|
4
|
+
function isBinaryCrate(toml) {
|
|
5
|
+
// Has [[bin]] entries
|
|
6
|
+
if (Array.isArray(toml.bin) && toml.bin.length > 0) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
// Has a default binary (src/main.rs is handled by Cargo implicitly)
|
|
10
|
+
const pkg = toml.package;
|
|
11
|
+
if (pkg) {
|
|
12
|
+
// If there's no explicit lib section and no [[bin]], Cargo assumes binary
|
|
13
|
+
// if src/main.rs exists, but we can't check filesystem here.
|
|
14
|
+
// Best heuristic: if there's no [lib] section, it could be a binary.
|
|
15
|
+
return toml.lib === undefined;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
function isLibraryCrate(toml) {
|
|
20
|
+
return toml.lib !== undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A context-aware policy for Cargo.lock files.
|
|
24
|
+
* Binary crates should commit Cargo.lock; library crates typically shouldn't.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export const CargoLockPolicy = defineCargoPolicy({
|
|
29
|
+
name: "CargoLockPolicy",
|
|
30
|
+
description: "Context-aware Cargo.lock validation: binaries should commit it, libraries typically should not.",
|
|
31
|
+
handler: async (toml, { root, file, config }) => {
|
|
32
|
+
// Skip workspace root Cargo.toml
|
|
33
|
+
if (toml.workspace !== undefined && toml.package === undefined) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const dir = path.dirname(path.resolve(root, file));
|
|
37
|
+
const lockExists = existsSync(path.join(dir, "Cargo.lock"));
|
|
38
|
+
const isBinary = isBinaryCrate(toml);
|
|
39
|
+
const isLib = isLibraryCrate(toml);
|
|
40
|
+
const binaryPolicy = config?.binaries ?? "require";
|
|
41
|
+
const libraryPolicy = config?.libraries ?? "ignore";
|
|
42
|
+
if (isBinary && binaryPolicy === "require" && !lockExists) {
|
|
43
|
+
return [
|
|
44
|
+
{
|
|
45
|
+
message: "Binary crate is missing Cargo.lock. Binary crates should commit their lockfile for reproducible builds.",
|
|
46
|
+
manualFix: "Run `cargo generate-lockfile` and commit the Cargo.lock file.",
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
if (isLib && !isBinary && libraryPolicy === "warn" && lockExists) {
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
message: "Library crate has Cargo.lock committed. Library crates typically should not commit their lockfile.",
|
|
54
|
+
manualFix: "Consider adding Cargo.lock to .gitignore for library crates.",
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
return [];
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=CargoLockPolicy.js.map
|