repopo 0.9.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/README.md +41 -2
- package/THIRD-PARTY-LICENSES.txt +71 -11
- package/bin/dev.js +5 -1
- package/esm/baseCommand.d.ts +1 -1
- package/esm/baseCommand.d.ts.map +1 -1
- package/esm/baseCommand.js +6 -9
- 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 +137 -0
- package/esm/commands/check-native.js.map +1 -0
- package/esm/commands/check.d.ts +8 -19
- package/esm/commands/check.d.ts.map +1 -1
- package/esm/commands/check.js +97 -169
- package/esm/commands/check.js.map +1 -1
- package/esm/commands/list.d.ts.map +1 -1
- package/esm/commands/list.js +5 -6
- package/esm/commands/list.js.map +1 -1
- package/esm/config.d.ts +19 -4
- package/esm/config.d.ts.map +1 -1
- package/esm/config.js +2 -3
- package/esm/config.js.map +1 -1
- package/esm/context.d.ts +13 -3
- package/esm/context.d.ts.map +1 -1
- package/esm/context.js +11 -1
- package/esm/context.js.map +1 -1
- package/esm/index.d.ts +7 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +9 -1
- package/esm/index.js.map +1 -1
- package/esm/makePolicy.d.ts +77 -8
- package/esm/makePolicy.d.ts.map +1 -1
- package/esm/makePolicy.js +108 -4
- package/esm/makePolicy.js.map +1 -1
- package/esm/perf.d.ts +7 -2
- package/esm/perf.d.ts.map +1 -1
- 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 +45 -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 +61 -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 +57 -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 +164 -0
- package/esm/policies/CargoTomlSorted.js.map +1 -0
- package/esm/policies/ConditionalScripts.d.ts +94 -0
- package/esm/policies/ConditionalScripts.d.ts.map +1 -0
- package/esm/policies/ConditionalScripts.js +145 -0
- package/esm/policies/ConditionalScripts.js.map +1 -0
- package/esm/policies/ExactScripts.d.ts +51 -0
- package/esm/policies/ExactScripts.d.ts.map +1 -0
- package/esm/policies/ExactScripts.js +108 -0
- package/esm/policies/ExactScripts.js.map +1 -0
- 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 +30 -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 +34 -0
- package/esm/policies/GleamLicenceConfigured.js.map +1 -0
- package/esm/policies/GleamManifestCommitted.d.ts +9 -0
- package/esm/policies/GleamManifestCommitted.d.ts.map +1 -0
- package/esm/policies/GleamManifestCommitted.js +26 -0
- package/esm/policies/GleamManifestCommitted.js.map +1 -0
- package/esm/policies/GleamMonorepoConsistency.d.ts +30 -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 +25 -0
- package/esm/policies/GleamProjectStructure.d.ts.map +1 -0
- package/esm/policies/GleamProjectStructure.js +33 -0
- package/esm/policies/GleamProjectStructure.js.map +1 -0
- package/esm/policies/GleamSharedDependencyVersions.d.ts +29 -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 +153 -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 +64 -0
- package/esm/policies/GleamVersionConstraint.js.map +1 -0
- package/esm/policies/HtmlFileHeaders.d.ts +1 -1
- 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 +1 -1
- package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
- package/esm/policies/MutuallyExclusiveScripts.d.ts +46 -0
- package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -0
- package/esm/policies/MutuallyExclusiveScripts.js +52 -0
- package/esm/policies/MutuallyExclusiveScripts.js.map +1 -0
- package/esm/policies/NoBuildDirectory.d.ts +9 -0
- package/esm/policies/NoBuildDirectory.d.ts.map +1 -0
- package/esm/policies/NoBuildDirectory.js +29 -0
- package/esm/policies/NoBuildDirectory.js.map +1 -0
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
- package/esm/policies/NoTargetArtifacts.d.ts +8 -0
- package/esm/policies/NoTargetArtifacts.d.ts.map +1 -0
- package/esm/policies/NoTargetArtifacts.js +42 -0
- package/esm/policies/NoTargetArtifacts.js.map +1 -0
- package/esm/policies/NoUnsafeWithoutJustification.d.ts +24 -0
- package/esm/policies/NoUnsafeWithoutJustification.d.ts.map +1 -0
- package/esm/policies/NoUnsafeWithoutJustification.js +80 -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 +1 -1
- package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
- package/esm/policies/PackageEsmType.d.ts +1 -1
- package/esm/policies/PackageEsmType.d.ts.map +1 -1
- package/esm/policies/PackageEsmType.js +7 -5
- package/esm/policies/PackageEsmType.js.map +1 -1
- package/esm/policies/PackageFolderName.d.ts +1 -1
- package/esm/policies/PackageFolderName.d.ts.map +1 -1
- package/esm/policies/PackageJsonProperties.d.ts +1 -1
- package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
- package/esm/policies/PackageJsonProperties.js +12 -4
- package/esm/policies/PackageJsonProperties.js.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.js +3 -2
- package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
- package/esm/policies/PackageJsonSorted.d.ts +1 -1
- package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
- package/esm/policies/PackageJsonSorted.js +42 -7
- package/esm/policies/PackageJsonSorted.js.map +1 -1
- package/esm/policies/PackageLicense.d.ts +1 -1
- package/esm/policies/PackageLicense.d.ts.map +1 -1
- package/esm/policies/PackageLicense.js +1 -2
- package/esm/policies/PackageLicense.js.map +1 -1
- package/esm/policies/PackagePrivateField.d.ts +1 -1
- package/esm/policies/PackagePrivateField.d.ts.map +1 -1
- package/esm/policies/PackagePrivateField.js +3 -2
- package/esm/policies/PackagePrivateField.js.map +1 -1
- package/esm/policies/PackageReadme.d.ts +1 -1
- package/esm/policies/PackageReadme.d.ts.map +1 -1
- package/esm/policies/PackageReadme.js +2 -2
- package/esm/policies/PackageReadme.js.map +1 -1
- package/esm/policies/PackageScripts.d.ts +1 -1
- package/esm/policies/PackageScripts.d.ts.map +1 -1
- package/esm/policies/PackageScripts.js +3 -2
- package/esm/policies/PackageScripts.js.map +1 -1
- package/esm/policies/PackageTestScripts.d.ts +1 -1
- package/esm/policies/PackageTestScripts.d.ts.map +1 -1
- package/esm/policies/PackageTestScripts.js +3 -3
- 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 +36 -0
- package/esm/policies/PublicApiDocumented.js.map +1 -0
- package/esm/policies/RequiredScripts.d.ts +71 -0
- package/esm/policies/RequiredScripts.d.ts.map +1 -0
- package/esm/policies/RequiredScripts.js +121 -0
- package/esm/policies/RequiredScripts.js.map +1 -0
- 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 +20 -0
- package/esm/policies/RustToolchainExists.d.ts.map +1 -0
- package/esm/policies/RustToolchainExists.js +27 -0
- package/esm/policies/RustToolchainExists.js.map +1 -0
- package/esm/policies/RustfmtConfigExists.d.ts +20 -0
- package/esm/policies/RustfmtConfigExists.d.ts.map +1 -0
- package/esm/policies/RustfmtConfigExists.js +27 -0
- package/esm/policies/RustfmtConfigExists.js.map +1 -0
- package/esm/policies/ScriptContains.d.ts +64 -0
- package/esm/policies/ScriptContains.d.ts.map +1 -0
- package/esm/policies/ScriptContains.js +62 -0
- package/esm/policies/ScriptContains.js.map +1 -0
- package/esm/policies/SharedDependencyVersions.d.ts +24 -0
- package/esm/policies/SharedDependencyVersions.d.ts.map +1 -0
- package/esm/policies/SharedDependencyVersions.js +135 -0
- package/esm/policies/SharedDependencyVersions.js.map +1 -0
- package/esm/policies/WorkspaceInheritance.d.ts +24 -0
- package/esm/policies/WorkspaceInheritance.d.ts.map +1 -0
- package/esm/policies/WorkspaceInheritance.js +94 -0
- package/esm/policies/WorkspaceInheritance.js.map +1 -0
- package/esm/policies/WorkspaceMembersValid.d.ts +20 -0
- package/esm/policies/WorkspaceMembersValid.d.ts.map +1 -0
- package/esm/policies/WorkspaceMembersValid.js +88 -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 +8 -0
- package/esm/policies/constants.js.map +1 -1
- package/esm/policies.d.ts +36 -1
- package/esm/policies.d.ts.map +1 -1
- package/esm/policies.js +68 -0
- package/esm/policies.js.map +1 -1
- package/esm/policy.d.ts +202 -84
- package/esm/policy.d.ts.map +1 -1
- package/esm/policy.js +103 -21
- package/esm/policy.js.map +1 -1
- package/esm/policyDefiners/defineCargoPolicy.d.ts +66 -0
- package/esm/policyDefiners/defineCargoPolicy.d.ts.map +1 -0
- package/esm/policyDefiners/defineCargoPolicy.js +60 -0
- package/esm/policyDefiners/defineCargoPolicy.js.map +1 -0
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +7 -2
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.js +11 -7
- package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
- package/esm/policyDefiners/defineGleamPolicy.d.ts +65 -0
- package/esm/policyDefiners/defineGleamPolicy.d.ts.map +1 -0
- package/esm/policyDefiners/defineGleamPolicy.js +59 -0
- package/esm/policyDefiners/defineGleamPolicy.js.map +1 -0
- package/esm/policyDefiners/definePackagePolicy.d.ts +18 -5
- package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
- package/esm/policyDefiners/definePackagePolicy.js +14 -4
- package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
- package/esm/policyDefiners/spdxValidator.d.ts +74 -0
- package/esm/policyDefiners/spdxValidator.d.ts.map +1 -0
- package/esm/policyDefiners/spdxValidator.js +127 -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/runner.d.ts +60 -0
- package/esm/runner.d.ts.map +1 -0
- package/esm/runner.js +174 -0
- package/esm/runner.js.map +1 -0
- package/esm/tsdoc-metadata.json +1 -1
- package/oclif.manifest.json +100 -3
- package/package.json +46 -31
- package/scripts/postinstall.mjs +154 -0
- package/sidecar/sidecar.mjs +468 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PackageTestScripts.js","sourceRoot":"","sources":["../../src/policies/PackageTestScripts.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { dirname, join } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Configuration for the PackageTestScripts policy.\n *\n * This policy ensures that packages have appropriate test scripts when they\n * contain test files or have test-related dependencies.\n *\n * The policy automatically determines what to check based on what's configured:\n * - If `testDirectories` is set, checks for test directories\n * - If `testDependencies` is set, checks for test dependencies\n * - If both are set, a package triggers validation if either condition is met\n *\n * @example\n * ```typescript\n * const config: PackageTestScriptsConfig = {\n * // Check for these test directories\n * testDirectories: [\"test\", \"tests\", \"__tests__\"],\n * // Require test script if these devDependencies exist\n * testDependencies: [\"vitest\", \"jest\", \"mocha\"],\n * // Required test script names\n * requiredScripts: [\"test\"],\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackageTestScriptsConfig {\n\t/**\n\t * Directory names that indicate test files are present.\n\t *\n\t * If any of these directories exist relative to the package.json,\n\t * the policy will require test scripts to be present.\n\t *\n\t * If not set or empty, directory checking is skipped.\n\t *\n\t * @example\n\t * ```typescript\n\t * testDirectories: [\"test\", \"tests\", \"__tests__\"]\n\t * ```\n\t */\n\ttestDirectories?: string[];\n\n\t/**\n\t * Test framework dependencies that indicate tests are expected.\n\t *\n\t * If any of these appear in devDependencies, the policy will require\n\t * test scripts to be present.\n\t *\n\t * If not set or empty, dependency checking is skipped.\n\t *\n\t * @example\n\t * ```typescript\n\t * testDependencies: [\"vitest\", \"jest\", \"mocha\", \"@jest/globals\"]\n\t * ```\n\t */\n\ttestDependencies?: string[];\n\n\t/**\n\t * Script names that must exist when tests are detected.\n\t *\n\t * @defaultValue [\"test\"]\n\t */\n\trequiredScripts?: string[];\n\n\t/**\n\t * Package names or scopes to exclude from validation.\n\t */\n\texcludePackages?: string[];\n}\n\n/**\n * Check if a package should be excluded from validation.\n */\nfunction isExcluded(\n\tpackageName: string,\n\texcludePackages: string[] | undefined,\n): boolean {\n\tif (excludePackages === undefined || excludePackages.length === 0) {\n\t\treturn false;\n\t}\n\n\tfor (const pattern of excludePackages) {\n\t\tif (pattern.startsWith(\"@\") && packageName.startsWith(`${pattern}/`)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (packageName === pattern) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if any test directories exist.\n */\nfunction hasTestDirectory(\n\tpackageDir: string,\n\ttestDirectories: string[],\n): boolean {\n\tfor (const testDir of testDirectories) {\n\t\tconst testPath = join(packageDir, testDir);\n\t\tif (existsSync(testPath)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if any test dependencies are present.\n */\nfunction hasTestDependency(\n\tdevDependencies: Record<string, string> | undefined,\n\ttestDependencies: string[],\n): boolean {\n\tif (devDependencies === undefined) {\n\t\treturn false;\n\t}\n\n\treturn testDependencies.some((dep) => devDependencies[dep] !== undefined);\n}\n\n/**\n * Find missing scripts from the required list.\n */\nfunction findMissingScripts(\n\tscripts: PackageJson[\"scripts\"],\n\trequiredScripts: string[],\n): string[] {\n\treturn requiredScripts.filter(\n\t\t(scriptName) => scripts?.[scriptName] === undefined,\n\t);\n}\n\n/**\n * Get the list of test dependencies that are present in devDependencies.\n */\nfunction getPresentTestDependencies(\n\tdevDependencies: Record<string, string> | undefined,\n\ttestDependencies: string[],\n): string[] {\n\tif (devDependencies === undefined) {\n\t\treturn [];\n\t}\n\treturn testDependencies.filter((d) => devDependencies[d] !== undefined);\n}\n\n/**\n * Check if a package should be validated based on config and package properties.\n */\nfunction shouldSkipValidation(\n\tjson: PackageJson,\n\tconfig: PackageTestScriptsConfig,\n): boolean {\n\tconst packageName = json.name;\n\n\t// Skip packages without a name or root package\n\tif (packageName === undefined || packageName === \"root\") {\n\t\treturn true;\n\t}\n\n\t// Check exclusions\n\tif (isExcluded(packageName, config.excludePackages)) {\n\t\treturn true;\n\t}\n\n\t// Skip if neither directories nor dependencies are configured\n\tconst testDirectories = config.testDirectories ?? [];\n\tconst testDependencies = config.testDependencies ?? [];\n\n\treturn testDirectories.length === 0 && testDependencies.length === 0;\n}\n\n/**\n * A policy that ensures packages have test scripts when test files exist.\n *\n * This policy helps maintain testing discipline by requiring test scripts\n * for packages that have test directories or test framework dependencies.\n *\n * @remarks\n *\n * The policy detects that tests are expected based on:\n *\n * 1. **Test directories**: If `test/`, `tests/`, or `__tests__/` exists\n * 2. **Test dependencies**: If vitest, jest, mocha, etc. are in devDependencies\n *\n * When tests are detected, the policy requires specified test scripts to exist.\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageTestScripts } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackageTestScripts, {\n * testDirectories: [\"test\", \"tests\"],\n * testDependencies: [\"vitest\", \"jest\"],\n * requiredScripts: [\"test\"],\n * }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackageTestScripts = definePackagePolicy<\n\tPackageJson,\n\tPackageTestScriptsConfig | undefined\n>({\n\tname: \"PackageTestScripts\",\n\tdescription:\n\t\t\"Ensures packages have test scripts when test directories or test framework dependencies exist.\",\n\thandler: async (json, { file, config }) => {\n\t\t// If no config provided, skip validation\n\t\tif (config === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Skip validation based on package properties and config\n\t\tif (shouldSkipValidation(json, config)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Get config values\n\t\tconst testDirectories = config.testDirectories ?? [];\n\t\tconst testDependencies = config.testDependencies ?? [];\n\t\tconst requiredScripts = config.requiredScripts ?? [\"test\"];\n\t\tconst packageDir = dirname(file);\n\t\tconst devDeps = json.devDependencies as Record<string, string> | undefined;\n\n\t\t// Check if tests are expected based on what's configured\n\t\tconst hasTestDir =\n\t\t\ttestDirectories.length > 0 &&\n\t\t\thasTestDirectory(packageDir, testDirectories);\n\t\tconst hasTestDep =\n\t\t\ttestDependencies.length > 0 &&\n\t\t\thasTestDependency(devDeps, testDependencies);\n\n\t\t// If no tests expected based on configured checks, pass\n\t\tif (!(hasTestDir || hasTestDep)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Tests are expected - check for required scripts\n\t\tconst missingScripts = findMissingScripts(json.scripts, requiredScripts);\n\n\t\tif (missingScripts.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Build error message\n\t\tconst reason = hasTestDir\n\t\t\t? \"test directory exists\"\n\t\t\t: `test dependencies found (${getPresentTestDependencies(devDeps, testDependencies).join(\", \")})`;\n\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageTestScripts.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t`Package \"${json.name}\" has ${reason} but is missing test scripts: ${missingScripts.join(\", \")}`,\n\t\t\t],\n\t\t};\n\t\treturn failResult;\n\t},\n});\n"]}
|
|
1
|
+
{"version":3,"file":"PackageTestScripts.js","sourceRoot":"","sources":["../../src/policies/PackageTestScripts.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { dirname, join, resolve as resolvePath } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Configuration for the PackageTestScripts policy.\n *\n * This policy ensures that packages have appropriate test scripts when they\n * contain test files or have test-related dependencies.\n *\n * The policy automatically determines what to check based on what's configured:\n * - If `testDirectories` is set, checks for test directories\n * - If `testDependencies` is set, checks for test dependencies\n * - If both are set, a package triggers validation if either condition is met\n *\n * @example\n * ```typescript\n * const config: PackageTestScriptsConfig = {\n * // Check for these test directories\n * testDirectories: [\"test\", \"tests\", \"__tests__\"],\n * // Require test script if these devDependencies exist\n * testDependencies: [\"vitest\", \"jest\", \"mocha\"],\n * // Required test script names\n * requiredScripts: [\"test\"],\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackageTestScriptsConfig {\n\t/**\n\t * Directory names that indicate test files are present.\n\t *\n\t * If any of these directories exist relative to the package.json,\n\t * the policy will require test scripts to be present.\n\t *\n\t * If not set or empty, directory checking is skipped.\n\t *\n\t * @example\n\t * ```typescript\n\t * testDirectories: [\"test\", \"tests\", \"__tests__\"]\n\t * ```\n\t */\n\ttestDirectories?: string[];\n\n\t/**\n\t * Test framework dependencies that indicate tests are expected.\n\t *\n\t * If any of these appear in devDependencies, the policy will require\n\t * test scripts to be present.\n\t *\n\t * If not set or empty, dependency checking is skipped.\n\t *\n\t * @example\n\t * ```typescript\n\t * testDependencies: [\"vitest\", \"jest\", \"mocha\", \"@jest/globals\"]\n\t * ```\n\t */\n\ttestDependencies?: string[];\n\n\t/**\n\t * Script names that must exist when tests are detected.\n\t *\n\t * @defaultValue [\"test\"]\n\t */\n\trequiredScripts?: string[];\n\n\t/**\n\t * Package names or scopes to exclude from validation.\n\t */\n\texcludePackages?: string[];\n}\n\n/**\n * Check if a package should be excluded from validation.\n */\nfunction isExcluded(\n\tpackageName: string,\n\texcludePackages: string[] | undefined,\n): boolean {\n\tif (excludePackages === undefined || excludePackages.length === 0) {\n\t\treturn false;\n\t}\n\n\tfor (const pattern of excludePackages) {\n\t\tif (pattern.startsWith(\"@\") && packageName.startsWith(`${pattern}/`)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (packageName === pattern) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Check if any test directories exist.\n */\nfunction hasTestDirectory(\n\tpackageDir: string,\n\ttestDirectories: string[],\n): boolean {\n\tfor (const testDir of testDirectories) {\n\t\tconst testPath = join(packageDir, testDir);\n\t\tif (existsSync(testPath)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if any test dependencies are present.\n */\nfunction hasTestDependency(\n\tdevDependencies: Record<string, string> | undefined,\n\ttestDependencies: string[],\n): boolean {\n\tif (devDependencies === undefined) {\n\t\treturn false;\n\t}\n\n\treturn testDependencies.some((dep) => devDependencies[dep] !== undefined);\n}\n\n/**\n * Find missing scripts from the required list.\n */\nfunction findMissingScripts(\n\tscripts: PackageJson[\"scripts\"],\n\trequiredScripts: string[],\n): string[] {\n\treturn requiredScripts.filter(\n\t\t(scriptName) => scripts?.[scriptName] === undefined,\n\t);\n}\n\n/**\n * Get the list of test dependencies that are present in devDependencies.\n */\nfunction getPresentTestDependencies(\n\tdevDependencies: Record<string, string> | undefined,\n\ttestDependencies: string[],\n): string[] {\n\tif (devDependencies === undefined) {\n\t\treturn [];\n\t}\n\treturn testDependencies.filter((d) => devDependencies[d] !== undefined);\n}\n\n/**\n * Check if a package should be validated based on config and package properties.\n */\nfunction shouldSkipValidation(\n\tjson: PackageJson,\n\tconfig: PackageTestScriptsConfig,\n): boolean {\n\tconst packageName = json.name;\n\n\t// Skip packages without a name or root package\n\tif (packageName === undefined || packageName === \"root\") {\n\t\treturn true;\n\t}\n\n\t// Check exclusions\n\tif (isExcluded(packageName, config.excludePackages)) {\n\t\treturn true;\n\t}\n\n\t// Skip if neither directories nor dependencies are configured\n\tconst testDirectories = config.testDirectories ?? [];\n\tconst testDependencies = config.testDependencies ?? [];\n\n\treturn testDirectories.length === 0 && testDependencies.length === 0;\n}\n\n/**\n * A policy that ensures packages have test scripts when test files exist.\n *\n * This policy helps maintain testing discipline by requiring test scripts\n * for packages that have test directories or test framework dependencies.\n *\n * @remarks\n *\n * The policy detects that tests are expected based on:\n *\n * 1. **Test directories**: If `test/`, `tests/`, or `__tests__/` exists\n * 2. **Test dependencies**: If vitest, jest, mocha, etc. are in devDependencies\n *\n * When tests are detected, the policy requires specified test scripts to exist.\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageTestScripts } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackageTestScripts, {\n * testDirectories: [\"test\", \"tests\"],\n * testDependencies: [\"vitest\", \"jest\"],\n * requiredScripts: [\"test\"],\n * }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackageTestScripts = definePackagePolicy<\n\tPackageJson,\n\tPackageTestScriptsConfig | undefined\n>({\n\tname: \"PackageTestScripts\",\n\tdescription:\n\t\t\"Ensures packages have test scripts when test directories or test framework dependencies exist.\",\n\thandler: async (json, { file, root, config }) => {\n\t\t// If no config provided, skip validation\n\t\tif (config === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Skip validation based on package properties and config\n\t\tif (shouldSkipValidation(json, config)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Get config values\n\t\tconst testDirectories = config.testDirectories ?? [];\n\t\tconst testDependencies = config.testDependencies ?? [];\n\t\tconst requiredScripts = config.requiredScripts ?? [\"test\"];\n\t\tconst packageDir = dirname(resolvePath(root, file));\n\t\tconst devDeps = json.devDependencies as Record<string, string> | undefined;\n\n\t\t// Check if tests are expected based on what's configured\n\t\tconst hasTestDir =\n\t\t\ttestDirectories.length > 0 &&\n\t\t\thasTestDirectory(packageDir, testDirectories);\n\t\tconst hasTestDep =\n\t\t\ttestDependencies.length > 0 &&\n\t\t\thasTestDependency(devDeps, testDependencies);\n\n\t\t// If no tests expected based on configured checks, pass\n\t\tif (!(hasTestDir || hasTestDep)) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Tests are expected - check for required scripts\n\t\tconst missingScripts = findMissingScripts(json.scripts, requiredScripts);\n\n\t\tif (missingScripts.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Build error message\n\t\tconst reason = hasTestDir\n\t\t\t? \"test directory exists\"\n\t\t\t: `test dependencies found (${getPresentTestDependencies(devDeps, testDependencies).join(\", \")})`;\n\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackageTestScripts.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t`Package \"${json.name}\" has ${reason} but is missing test scripts: ${missingScripts.join(\", \")}`,\n\t\t\t],\n\t\t};\n\t\treturn failResult;\n\t},\n});\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PolicyShape } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the PublicApiDocumented policy.
|
|
4
|
+
*
|
|
5
|
+
* @alpha
|
|
6
|
+
*/
|
|
7
|
+
export interface PublicApiDocumentedConfig {
|
|
8
|
+
/**
|
|
9
|
+
* If true, check for `#![deny(missing_docs)]` directive via [lints.rust] in Cargo.toml.
|
|
10
|
+
* @defaultValue true
|
|
11
|
+
*/
|
|
12
|
+
checkCargoLints?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A policy that ensures public API documentation is enforced in Rust crates
|
|
16
|
+
* via the `missing_docs` lint configured in Cargo.toml.
|
|
17
|
+
*
|
|
18
|
+
* @alpha
|
|
19
|
+
*/
|
|
20
|
+
export declare const PublicApiDocumented: PolicyShape<PublicApiDocumentedConfig>;
|
|
21
|
+
//# sourceMappingURL=PublicApiDocumented.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublicApiDocumented.d.ts","sourceRoot":"","sources":["../../src/policies/PublicApiDocumented.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,yBAAyB,CAsCpE,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
|
|
2
|
+
/**
|
|
3
|
+
* A policy that ensures public API documentation is enforced in Rust crates
|
|
4
|
+
* via the `missing_docs` lint configured in Cargo.toml.
|
|
5
|
+
*
|
|
6
|
+
* @alpha
|
|
7
|
+
*/
|
|
8
|
+
export const PublicApiDocumented = defineCargoPolicy({
|
|
9
|
+
name: "PublicApiDocumented",
|
|
10
|
+
description: "Ensures the missing_docs lint is configured in Cargo.toml to enforce public API documentation.",
|
|
11
|
+
handler: async (toml, { config }) => {
|
|
12
|
+
// Skip workspace root
|
|
13
|
+
if (toml.workspace !== undefined && toml.package === undefined) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
const checkCargoLints = config?.checkCargoLints ?? true;
|
|
17
|
+
if (checkCargoLints) {
|
|
18
|
+
const lints = toml.lints;
|
|
19
|
+
const rustLints = lints?.rust;
|
|
20
|
+
if (rustLints) {
|
|
21
|
+
const missingDocs = rustLints.missing_docs ?? rustLints["missing-docs"];
|
|
22
|
+
if (missingDocs === "deny" ||
|
|
23
|
+
missingDocs === "warn" ||
|
|
24
|
+
missingDocs === "forbid") {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
error: 'missing_docs lint is not configured. Set [lints.rust] missing_docs = "warn" or "deny" in Cargo.toml.',
|
|
30
|
+
manualFix: 'Add to Cargo.toml:\n[lints.rust]\nmissing_docs = "warn"',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=PublicApiDocumented.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublicApiDocumented.js","sourceRoot":"","sources":["../../src/policies/PublicApiDocumented.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AAehD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC/B,iBAAiB,CAAC;IACjB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACV,gGAAgG;IACjG,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC9C,sBAAsB;QACtB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,EAAE,eAAe,IAAI,IAAI,CAAC;QAExD,IAAI,eAAe,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,KAA4C,CAAC;YAChE,MAAM,SAAS,GAAG,KAAK,EAAE,IAA2C,CAAC;YAErE,IAAI,SAAS,EAAE,CAAC;gBACf,MAAM,WAAW,GAChB,SAAS,CAAC,YAAY,IAAI,SAAS,CAAC,cAAc,CAAC,CAAC;gBACrD,IACC,WAAW,KAAK,MAAM;oBACtB,WAAW,KAAK,MAAM;oBACtB,WAAW,KAAK,QAAQ,EACvB,CAAC;oBACF,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;YAED,OAAO;gBACN,KAAK,EACJ,sGAAsG;gBACvG,SAAS,EAAE,yDAAyD;aACpE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PolicyShape } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\n\n/**\n * Configuration for the PublicApiDocumented policy.\n *\n * @alpha\n */\nexport interface PublicApiDocumentedConfig {\n\t/**\n\t * If true, check for `#![deny(missing_docs)]` directive via [lints.rust] in Cargo.toml.\n\t * @defaultValue true\n\t */\n\tcheckCargoLints?: boolean;\n}\n\n/**\n * A policy that ensures public API documentation is enforced in Rust crates\n * via the `missing_docs` lint configured in Cargo.toml.\n *\n * @alpha\n */\nexport const PublicApiDocumented: PolicyShape<PublicApiDocumentedConfig> =\n\tdefineCargoPolicy({\n\t\tname: \"PublicApiDocumented\",\n\t\tdescription:\n\t\t\t\"Ensures the missing_docs lint is configured in Cargo.toml to enforce public API documentation.\",\n\t\thandler: async (toml: CargoToml, { config }) => {\n\t\t\t// Skip workspace root\n\t\t\tif (toml.workspace !== undefined && toml.package === undefined) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst checkCargoLints = config?.checkCargoLints ?? true;\n\n\t\t\tif (checkCargoLints) {\n\t\t\t\tconst lints = toml.lints as Record<string, unknown> | undefined;\n\t\t\t\tconst rustLints = lints?.rust as Record<string, unknown> | undefined;\n\n\t\t\t\tif (rustLints) {\n\t\t\t\t\tconst missingDocs =\n\t\t\t\t\t\trustLints.missing_docs ?? rustLints[\"missing-docs\"];\n\t\t\t\t\tif (\n\t\t\t\t\t\tmissingDocs === \"deny\" ||\n\t\t\t\t\t\tmissingDocs === \"warn\" ||\n\t\t\t\t\t\tmissingDocs === \"forbid\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\terror:\n\t\t\t\t\t\t'missing_docs lint is not configured. Set [lints.rust] missing_docs = \"warn\" or \"deny\" in Cargo.toml.',\n\t\t\t\t\tmanualFix: 'Add to Cargo.toml:\\n[lints.rust]\\nmissing_docs = \"warn\"',\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A required script entry. Can be either:
|
|
3
|
+
* - A string (script name only, no default value)
|
|
4
|
+
* - An object with a single key-value pair (script name → default value for auto-fix)
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // Script must exist, no auto-fix available
|
|
9
|
+
* "test"
|
|
10
|
+
*
|
|
11
|
+
* // Script must exist, auto-fix will add this value if missing
|
|
12
|
+
* { lint: "biome lint ." }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @alpha
|
|
16
|
+
*/
|
|
17
|
+
export type RequiredScriptEntry = string | Record<string, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for the RequiredScripts policy.
|
|
20
|
+
*
|
|
21
|
+
* @alpha
|
|
22
|
+
*/
|
|
23
|
+
export interface RequiredScriptsConfig {
|
|
24
|
+
/**
|
|
25
|
+
* Scripts that must be present in package.json.
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* Each entry can be:
|
|
29
|
+
* - A string: Script must exist, no auto-fix available, content not validated
|
|
30
|
+
* - An object `{ scriptName: "default value" }`: Script must exist, auto-fix adds the
|
|
31
|
+
* default value if missing, but existing scripts with different content still pass
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* scripts: [
|
|
36
|
+
* "test", // Must exist, no auto-fix
|
|
37
|
+
* { lint: "biome lint ." }, // Must exist, auto-fix available
|
|
38
|
+
* { clean: "rimraf dist esm" }, // Must exist, auto-fix available
|
|
39
|
+
* ]
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
scripts: RequiredScriptEntry[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A policy that validates required scripts exist in package.json.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* Use this policy when you want to ensure specific scripts are present.
|
|
49
|
+
* Scripts can be specified with optional default values that enable auto-fix.
|
|
50
|
+
*
|
|
51
|
+
* Note: This policy only checks for script presence. It does NOT validate
|
|
52
|
+
* the script's content. Use ExactScripts for content validation.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import { policy } from "repopo";
|
|
57
|
+
* import { RequiredScripts } from "repopo/policies";
|
|
58
|
+
*
|
|
59
|
+
* policy(RequiredScripts, {
|
|
60
|
+
* scripts: [
|
|
61
|
+
* "test", // Must exist, no auto-fix
|
|
62
|
+
* { lint: "biome lint ." }, // Must exist, auto-fix adds default if missing
|
|
63
|
+
* { clean: "rimraf dist esm" }, // Must exist, auto-fix adds default if missing
|
|
64
|
+
* ],
|
|
65
|
+
* })
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @alpha
|
|
69
|
+
*/
|
|
70
|
+
export declare const RequiredScripts: import("../policy.js").PolicyShape<RequiredScriptsConfig | undefined>;
|
|
71
|
+
//# sourceMappingURL=RequiredScripts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequiredScripts.d.ts","sourceRoot":"","sources":["../../src/policies/RequiredScripts.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAoFD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,uEA2D1B,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import jsonfile from "jsonfile";
|
|
2
|
+
import { resolve as resolvePath } from "pathe";
|
|
3
|
+
import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
|
|
4
|
+
const POLICY_NAME = "RequiredScripts";
|
|
5
|
+
/**
|
|
6
|
+
* Extracts script name and optional default value from a RequiredScriptEntry.
|
|
7
|
+
*/
|
|
8
|
+
function parseRequiredEntry(entry) {
|
|
9
|
+
if (typeof entry === "string") {
|
|
10
|
+
return { name: entry };
|
|
11
|
+
}
|
|
12
|
+
const keys = Object.keys(entry);
|
|
13
|
+
if (keys.length !== 1) {
|
|
14
|
+
throw new Error(`Invalid required script entry: expected single key-value pair, got ${keys.length} keys`);
|
|
15
|
+
}
|
|
16
|
+
// biome-ignore lint/style/noNonNullAssertion: we verified length is 1
|
|
17
|
+
const name = keys[0];
|
|
18
|
+
const defaultValue = entry[name];
|
|
19
|
+
return defaultValue !== undefined ? { name, defaultValue } : { name };
|
|
20
|
+
}
|
|
21
|
+
function validateRequiredScripts(scripts, requiredEntries) {
|
|
22
|
+
const missingScripts = [];
|
|
23
|
+
const missingWithDefaults = [];
|
|
24
|
+
for (const entry of requiredEntries) {
|
|
25
|
+
const { name, defaultValue } = parseRequiredEntry(entry);
|
|
26
|
+
if (!Object.hasOwn(scripts, name)) {
|
|
27
|
+
missingScripts.push(name);
|
|
28
|
+
if (defaultValue !== undefined) {
|
|
29
|
+
missingWithDefaults.push({ name, defaultValue });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { missingScripts, missingWithDefaults };
|
|
34
|
+
}
|
|
35
|
+
async function fixMissingScripts(json, file, missingWithDefaults, existingScripts) {
|
|
36
|
+
const updatedScripts = {};
|
|
37
|
+
// Copy existing scripts
|
|
38
|
+
for (const [key, value] of Object.entries(existingScripts)) {
|
|
39
|
+
if (value !== undefined) {
|
|
40
|
+
updatedScripts[key] = value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Add missing scripts with defaults
|
|
44
|
+
const fixedScripts = [];
|
|
45
|
+
for (const { name, defaultValue } of missingWithDefaults) {
|
|
46
|
+
updatedScripts[name] = defaultValue;
|
|
47
|
+
fixedScripts.push(name);
|
|
48
|
+
}
|
|
49
|
+
await jsonfile.writeFile(file, { ...json, scripts: updatedScripts }, { spaces: 2 });
|
|
50
|
+
return fixedScripts;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A policy that validates required scripts exist in package.json.
|
|
54
|
+
*
|
|
55
|
+
* @remarks
|
|
56
|
+
* Use this policy when you want to ensure specific scripts are present.
|
|
57
|
+
* Scripts can be specified with optional default values that enable auto-fix.
|
|
58
|
+
*
|
|
59
|
+
* Note: This policy only checks for script presence. It does NOT validate
|
|
60
|
+
* the script's content. Use ExactScripts for content validation.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { policy } from "repopo";
|
|
65
|
+
* import { RequiredScripts } from "repopo/policies";
|
|
66
|
+
*
|
|
67
|
+
* policy(RequiredScripts, {
|
|
68
|
+
* scripts: [
|
|
69
|
+
* "test", // Must exist, no auto-fix
|
|
70
|
+
* { lint: "biome lint ." }, // Must exist, auto-fix adds default if missing
|
|
71
|
+
* { clean: "rimraf dist esm" }, // Must exist, auto-fix adds default if missing
|
|
72
|
+
* ],
|
|
73
|
+
* })
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @alpha
|
|
77
|
+
*/
|
|
78
|
+
export const RequiredScripts = definePackagePolicy({
|
|
79
|
+
name: POLICY_NAME,
|
|
80
|
+
description: "Validates that required scripts exist in package.json.",
|
|
81
|
+
handler: async (json, { file, root, resolve, config }) => {
|
|
82
|
+
if (config === undefined || config.scripts.length === 0) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
const scripts = json.scripts ?? {};
|
|
86
|
+
const validation = validateRequiredScripts(scripts, config.scripts);
|
|
87
|
+
if (validation.missingScripts.length === 0) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
const hasAutoFixableErrors = validation.missingWithDefaults.length > 0;
|
|
91
|
+
if (resolve && hasAutoFixableErrors) {
|
|
92
|
+
try {
|
|
93
|
+
const fixedScripts = await fixMissingScripts(json, resolvePath(root, file), validation.missingWithDefaults, scripts);
|
|
94
|
+
// Check if there are still missing scripts (those without defaults)
|
|
95
|
+
const stillMissing = validation.missingScripts.filter((name) => !fixedScripts.includes(name));
|
|
96
|
+
return {
|
|
97
|
+
name: POLICY_NAME,
|
|
98
|
+
file,
|
|
99
|
+
resolved: stillMissing.length === 0,
|
|
100
|
+
errorMessages: stillMissing.length > 0
|
|
101
|
+
? [
|
|
102
|
+
`Fixed scripts: ${fixedScripts.join(", ")}. Still missing: ${stillMissing.join(", ")}`,
|
|
103
|
+
]
|
|
104
|
+
: [`Fixed scripts: ${fixedScripts.join(", ")}`],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Fall through to return regular failure
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
name: POLICY_NAME,
|
|
113
|
+
file,
|
|
114
|
+
autoFixable: hasAutoFixableErrors,
|
|
115
|
+
errorMessages: [
|
|
116
|
+
`Missing required scripts:\n\t${validation.missingScripts.join("\n\t")}`,
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=RequiredScripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequiredScripts.js","sourceRoot":"","sources":["../../src/policies/RequiredScripts.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport { resolve as resolvePath } from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * A required script entry. Can be either:\n * - A string (script name only, no default value)\n * - An object with a single key-value pair (script name → default value for auto-fix)\n *\n * @example\n * ```typescript\n * // Script must exist, no auto-fix available\n * \"test\"\n *\n * // Script must exist, auto-fix will add this value if missing\n * { lint: \"biome lint .\" }\n * ```\n *\n * @alpha\n */\nexport type RequiredScriptEntry = string | Record<string, string>;\n\n/**\n * Configuration for the RequiredScripts policy.\n *\n * @alpha\n */\nexport interface RequiredScriptsConfig {\n\t/**\n\t * Scripts that must be present in package.json.\n\t *\n\t * @remarks\n\t * Each entry can be:\n\t * - A string: Script must exist, no auto-fix available, content not validated\n\t * - An object `{ scriptName: \"default value\" }`: Script must exist, auto-fix adds the\n\t * default value if missing, but existing scripts with different content still pass\n\t *\n\t * @example\n\t * ```typescript\n\t * scripts: [\n\t * \"test\", // Must exist, no auto-fix\n\t * { lint: \"biome lint .\" }, // Must exist, auto-fix available\n\t * { clean: \"rimraf dist esm\" }, // Must exist, auto-fix available\n\t * ]\n\t * ```\n\t */\n\tscripts: RequiredScriptEntry[];\n}\n\nconst POLICY_NAME = \"RequiredScripts\";\n\ninterface ParsedEntry {\n\tname: string;\n\tdefaultValue?: string;\n}\n\n/**\n * Extracts script name and optional default value from a RequiredScriptEntry.\n */\nfunction parseRequiredEntry(entry: RequiredScriptEntry): ParsedEntry {\n\tif (typeof entry === \"string\") {\n\t\treturn { name: entry };\n\t}\n\tconst keys = Object.keys(entry);\n\tif (keys.length !== 1) {\n\t\tthrow new Error(\n\t\t\t`Invalid required script entry: expected single key-value pair, got ${keys.length} keys`,\n\t\t);\n\t}\n\t// biome-ignore lint/style/noNonNullAssertion: we verified length is 1\n\tconst name = keys[0]!;\n\tconst defaultValue = entry[name];\n\treturn defaultValue !== undefined ? { name, defaultValue } : { name };\n}\n\ninterface ValidationResult {\n\tmissingScripts: string[];\n\tmissingWithDefaults: Array<{ name: string; defaultValue: string }>;\n}\n\nfunction validateRequiredScripts(\n\tscripts: Record<string, string | undefined>,\n\trequiredEntries: RequiredScriptEntry[],\n): ValidationResult {\n\tconst missingScripts: string[] = [];\n\tconst missingWithDefaults: Array<{ name: string; defaultValue: string }> = [];\n\n\tfor (const entry of requiredEntries) {\n\t\tconst { name, defaultValue } = parseRequiredEntry(entry);\n\t\tif (!Object.hasOwn(scripts, name)) {\n\t\t\tmissingScripts.push(name);\n\t\t\tif (defaultValue !== undefined) {\n\t\t\t\tmissingWithDefaults.push({ name, defaultValue });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { missingScripts, missingWithDefaults };\n}\n\nasync function fixMissingScripts(\n\tjson: PackageJson,\n\tfile: string,\n\tmissingWithDefaults: Array<{ name: string; defaultValue: string }>,\n\texistingScripts: Record<string, string | undefined>,\n): Promise<string[]> {\n\tconst updatedScripts: Record<string, string> = {};\n\n\t// Copy existing scripts\n\tfor (const [key, value] of Object.entries(existingScripts)) {\n\t\tif (value !== undefined) {\n\t\t\tupdatedScripts[key] = value;\n\t\t}\n\t}\n\n\t// Add missing scripts with defaults\n\tconst fixedScripts: string[] = [];\n\tfor (const { name, defaultValue } of missingWithDefaults) {\n\t\tupdatedScripts[name] = defaultValue;\n\t\tfixedScripts.push(name);\n\t}\n\n\tawait jsonfile.writeFile(\n\t\tfile,\n\t\t{ ...json, scripts: updatedScripts },\n\t\t{ spaces: 2 },\n\t);\n\n\treturn fixedScripts;\n}\n\n/**\n * A policy that validates required scripts exist in package.json.\n *\n * @remarks\n * Use this policy when you want to ensure specific scripts are present.\n * Scripts can be specified with optional default values that enable auto-fix.\n *\n * Note: This policy only checks for script presence. It does NOT validate\n * the script's content. Use ExactScripts for content validation.\n *\n * @example\n * ```typescript\n * import { policy } from \"repopo\";\n * import { RequiredScripts } from \"repopo/policies\";\n *\n * policy(RequiredScripts, {\n * scripts: [\n * \"test\", // Must exist, no auto-fix\n * { lint: \"biome lint .\" }, // Must exist, auto-fix adds default if missing\n * { clean: \"rimraf dist esm\" }, // Must exist, auto-fix adds default if missing\n * ],\n * })\n * ```\n *\n * @alpha\n */\nexport const RequiredScripts = definePackagePolicy<\n\tPackageJson,\n\tRequiredScriptsConfig | undefined\n>({\n\tname: POLICY_NAME,\n\tdescription: \"Validates that required scripts exist in package.json.\",\n\thandler: async (json, { file, root, resolve, config }) => {\n\t\tif (config === undefined || config.scripts.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst scripts = json.scripts ?? {};\n\t\tconst validation = validateRequiredScripts(scripts, config.scripts);\n\n\t\tif (validation.missingScripts.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst hasAutoFixableErrors = validation.missingWithDefaults.length > 0;\n\n\t\tif (resolve && hasAutoFixableErrors) {\n\t\t\ttry {\n\t\t\t\tconst fixedScripts = await fixMissingScripts(\n\t\t\t\t\tjson,\n\t\t\t\t\tresolvePath(root, file),\n\t\t\t\t\tvalidation.missingWithDefaults,\n\t\t\t\t\tscripts,\n\t\t\t\t);\n\n\t\t\t\t// Check if there are still missing scripts (those without defaults)\n\t\t\t\tconst stillMissing = validation.missingScripts.filter(\n\t\t\t\t\t(name) => !fixedScripts.includes(name),\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\tname: POLICY_NAME,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: stillMissing.length === 0,\n\t\t\t\t\terrorMessages:\n\t\t\t\t\t\tstillMissing.length > 0\n\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t`Fixed scripts: ${fixedScripts.join(\", \")}. Still missing: ${stillMissing.join(\", \")}`,\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t: [`Fixed scripts: ${fixedScripts.join(\", \")}`],\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// Fall through to return regular failure\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tname: POLICY_NAME,\n\t\t\tfile,\n\t\t\tautoFixable: hasAutoFixableErrors,\n\t\t\terrorMessages: [\n\t\t\t\t`Missing required scripts:\\n\\t${validation.missingScripts.join(\"\\n\\t\")}`,\n\t\t\t],\n\t\t};\n\t},\n});\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PolicyShape } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the RustDocExists policy.
|
|
4
|
+
*
|
|
5
|
+
* @alpha
|
|
6
|
+
*/
|
|
7
|
+
export interface RustDocExistsConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Files that must exist alongside the Cargo.toml.
|
|
10
|
+
* @defaultValue ["README.md"]
|
|
11
|
+
*/
|
|
12
|
+
required?: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Files that are recommended but not required. Missing ones produce warnings.
|
|
15
|
+
*/
|
|
16
|
+
recommended?: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A policy that validates documentation files exist for Rust crates.
|
|
20
|
+
*
|
|
21
|
+
* @alpha
|
|
22
|
+
*/
|
|
23
|
+
export declare const RustDocExists: PolicyShape<RustDocExistsConfig>;
|
|
24
|
+
//# sourceMappingURL=RustDocExists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustDocExists.d.ts","sourceRoot":"","sources":["../../src/policies/RustDocExists.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAID;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,mBAAmB,CAoDxD,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "pathe";
|
|
3
|
+
import { defineCargoPolicy, } from "../policyDefiners/defineCargoPolicy.js";
|
|
4
|
+
const DEFAULT_REQUIRED = ["README.md"];
|
|
5
|
+
/**
|
|
6
|
+
* A policy that validates documentation files exist for Rust crates.
|
|
7
|
+
*
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
export const RustDocExists = defineCargoPolicy({
|
|
11
|
+
name: "RustDocExists",
|
|
12
|
+
description: "Validates that documentation files (README.md, etc.) exist for Rust crates.",
|
|
13
|
+
handler: async (toml, { file, root, config }) => {
|
|
14
|
+
// Skip workspace root
|
|
15
|
+
if (toml.workspace !== undefined && toml.package === undefined) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
const dir = path.dirname(path.resolve(root, file));
|
|
19
|
+
const required = config?.required ?? DEFAULT_REQUIRED;
|
|
20
|
+
const recommended = config?.recommended ?? [];
|
|
21
|
+
const missingRequired = [];
|
|
22
|
+
const missingRecommended = [];
|
|
23
|
+
for (const fileName of required) {
|
|
24
|
+
if (!existsSync(path.join(dir, fileName))) {
|
|
25
|
+
missingRequired.push(fileName);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const fileName of recommended) {
|
|
29
|
+
if (!existsSync(path.join(dir, fileName))) {
|
|
30
|
+
missingRecommended.push(fileName);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const errors = [];
|
|
34
|
+
if (missingRequired.length > 0) {
|
|
35
|
+
errors.push(`Missing required documentation: ${missingRequired.join(", ")}`);
|
|
36
|
+
}
|
|
37
|
+
if (missingRecommended.length > 0) {
|
|
38
|
+
errors.push(`Missing recommended documentation: ${missingRecommended.join(", ")}`);
|
|
39
|
+
}
|
|
40
|
+
if (errors.length > 0) {
|
|
41
|
+
return {
|
|
42
|
+
error: errors.join("; "),
|
|
43
|
+
manualFix: "Create the missing documentation files alongside Cargo.toml.",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=RustDocExists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustDocExists.js","sourceRoot":"","sources":["../../src/policies/RustDocExists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AAEzB,OAAO,EAEN,iBAAiB,GACjB,MAAM,wCAAwC,CAAC;AAoBhD,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GACzB,iBAAiB,CAAC;IACjB,IAAI,EAAE,eAAe;IACrB,WAAW,EACV,6EAA6E;IAC9E,OAAO,EAAE,KAAK,EAAE,IAAe,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1D,sBAAsB;QACtB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,gBAAgB,CAAC;QACtD,MAAM,WAAW,GAAG,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC;QAE9C,MAAM,eAAe,GAAa,EAAE,CAAC;QACrC,MAAM,kBAAkB,GAAa,EAAE,CAAC;QAExC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;gBAC3C,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;YACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;gBAC3C,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;QACF,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CACV,mCAAmC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/D,CAAC;QACH,CAAC;QACD,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,CACV,sCAAsC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACrE,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACN,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,SAAS,EACR,8DAA8D;aAC/D,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"pathe\";\nimport type { PolicyShape } from \"../policy.js\";\nimport {\n\ttype CargoToml,\n\tdefineCargoPolicy,\n} from \"../policyDefiners/defineCargoPolicy.js\";\n\n/**\n * Configuration for the RustDocExists policy.\n *\n * @alpha\n */\nexport interface RustDocExistsConfig {\n\t/**\n\t * Files that must exist alongside the Cargo.toml.\n\t * @defaultValue [\"README.md\"]\n\t */\n\trequired?: string[];\n\n\t/**\n\t * Files that are recommended but not required. Missing ones produce warnings.\n\t */\n\trecommended?: string[];\n}\n\nconst DEFAULT_REQUIRED = [\"README.md\"];\n\n/**\n * A policy that validates documentation files exist for Rust crates.\n *\n * @alpha\n */\nexport const RustDocExists: PolicyShape<RustDocExistsConfig> =\n\tdefineCargoPolicy({\n\t\tname: \"RustDocExists\",\n\t\tdescription:\n\t\t\t\"Validates that documentation files (README.md, etc.) exist for Rust crates.\",\n\t\thandler: async (toml: CargoToml, { file, root, config }) => {\n\t\t\t// Skip workspace root\n\t\t\tif (toml.workspace !== undefined && toml.package === undefined) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst dir = path.dirname(path.resolve(root, file));\n\t\t\tconst required = config?.required ?? DEFAULT_REQUIRED;\n\t\t\tconst recommended = config?.recommended ?? [];\n\n\t\t\tconst missingRequired: string[] = [];\n\t\t\tconst missingRecommended: string[] = [];\n\n\t\t\tfor (const fileName of required) {\n\t\t\t\tif (!existsSync(path.join(dir, fileName))) {\n\t\t\t\t\tmissingRequired.push(fileName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const fileName of recommended) {\n\t\t\t\tif (!existsSync(path.join(dir, fileName))) {\n\t\t\t\t\tmissingRecommended.push(fileName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst errors: string[] = [];\n\t\t\tif (missingRequired.length > 0) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Missing required documentation: ${missingRequired.join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (missingRecommended.length > 0) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Missing recommended documentation: ${missingRecommended.join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: errors.join(\"; \"),\n\t\t\t\t\tmanualFix:\n\t\t\t\t\t\t\"Create the missing documentation files alongside Cargo.toml.\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PolicyDefinition } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the RustToolchainExists policy.
|
|
4
|
+
*
|
|
5
|
+
* @alpha
|
|
6
|
+
*/
|
|
7
|
+
export interface RustToolchainExistsConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Accepted file names for the toolchain file.
|
|
10
|
+
* @defaultValue ["rust-toolchain.toml", "rust-toolchain"]
|
|
11
|
+
*/
|
|
12
|
+
acceptedNames?: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A policy that requires a rust-toolchain.toml file for reproducible Rust builds.
|
|
16
|
+
*
|
|
17
|
+
* @alpha
|
|
18
|
+
*/
|
|
19
|
+
export declare const RustToolchainExists: PolicyDefinition<RustToolchainExistsConfig>;
|
|
20
|
+
//# sourceMappingURL=RustToolchainExists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustToolchainExists.d.ts","sourceRoot":"","sources":["../../src/policies/RustToolchainExists.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAID;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,gBAAgB,CAAC,yBAAyB,CAuBzE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "pathe";
|
|
3
|
+
import { makePolicyDefinition } from "../makePolicy.js";
|
|
4
|
+
const DEFAULT_NAMES = ["rust-toolchain.toml", "rust-toolchain"];
|
|
5
|
+
/**
|
|
6
|
+
* A policy that requires a rust-toolchain.toml file for reproducible Rust builds.
|
|
7
|
+
*
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
export const RustToolchainExists = makePolicyDefinition({
|
|
11
|
+
name: "RustToolchainExists",
|
|
12
|
+
description: "Ensures a rust-toolchain.toml file exists for reproducible Rust builds.",
|
|
13
|
+
// Trigger on Cargo.toml to check once per project
|
|
14
|
+
match: /^Cargo\.toml$/,
|
|
15
|
+
handler: async ({ root, config }) => {
|
|
16
|
+
const names = config?.acceptedNames ?? DEFAULT_NAMES;
|
|
17
|
+
const hasToolchain = names.some((name) => existsSync(path.join(root, name)));
|
|
18
|
+
if (hasToolchain) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
error: `No rust-toolchain file found. Expected one of: ${names.join(", ")}`,
|
|
23
|
+
manualFix: "Create a rust-toolchain.toml file specifying the Rust toolchain version.",
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=RustToolchainExists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustToolchainExists.js","sourceRoot":"","sources":["../../src/policies/RustToolchainExists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAgBxD,MAAM,aAAa,GAAG,CAAC,qBAAqB,EAAE,gBAAgB,CAAC,CAAC;AAEhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC/B,oBAAoB,CAAC;IACpB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACV,yEAAyE;IAC1E,kDAAkD;IAClD,KAAK,EAAE,eAAe;IACtB,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,MAAM,EAAE,aAAa,IAAI,aAAa,CAAC;QACrD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACxC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CACjC,CAAC;QAEF,IAAI,YAAY,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO;YACN,KAAK,EAAE,kDAAkD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC3E,SAAS,EACR,0EAA0E;SAC3E,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition } from \"../policy.js\";\n\n/**\n * Configuration for the RustToolchainExists policy.\n *\n * @alpha\n */\nexport interface RustToolchainExistsConfig {\n\t/**\n\t * Accepted file names for the toolchain file.\n\t * @defaultValue [\"rust-toolchain.toml\", \"rust-toolchain\"]\n\t */\n\tacceptedNames?: string[];\n}\n\nconst DEFAULT_NAMES = [\"rust-toolchain.toml\", \"rust-toolchain\"];\n\n/**\n * A policy that requires a rust-toolchain.toml file for reproducible Rust builds.\n *\n * @alpha\n */\nexport const RustToolchainExists: PolicyDefinition<RustToolchainExistsConfig> =\n\tmakePolicyDefinition({\n\t\tname: \"RustToolchainExists\",\n\t\tdescription:\n\t\t\t\"Ensures a rust-toolchain.toml file exists for reproducible Rust builds.\",\n\t\t// Trigger on Cargo.toml to check once per project\n\t\tmatch: /^Cargo\\.toml$/,\n\t\thandler: async ({ root, config }) => {\n\t\t\tconst names = config?.acceptedNames ?? DEFAULT_NAMES;\n\t\t\tconst hasToolchain = names.some((name) =>\n\t\t\t\texistsSync(path.join(root, name)),\n\t\t\t);\n\n\t\t\tif (hasToolchain) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\terror: `No rust-toolchain file found. Expected one of: ${names.join(\", \")}`,\n\t\t\t\tmanualFix:\n\t\t\t\t\t\"Create a rust-toolchain.toml file specifying the Rust toolchain version.\",\n\t\t\t};\n\t\t},\n\t});\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PolicyDefinition } from "../policy.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the RustfmtConfigExists policy.
|
|
4
|
+
*
|
|
5
|
+
* @alpha
|
|
6
|
+
*/
|
|
7
|
+
export interface RustfmtConfigExistsConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Accepted file names for the rustfmt config.
|
|
10
|
+
* @defaultValue ["rustfmt.toml", ".rustfmt.toml"]
|
|
11
|
+
*/
|
|
12
|
+
acceptedNames?: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A policy that requires a rustfmt.toml file for consistent Rust formatting.
|
|
16
|
+
*
|
|
17
|
+
* @alpha
|
|
18
|
+
*/
|
|
19
|
+
export declare const RustfmtConfigExists: PolicyDefinition<RustfmtConfigExistsConfig>;
|
|
20
|
+
//# sourceMappingURL=RustfmtConfigExists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustfmtConfigExists.d.ts","sourceRoot":"","sources":["../../src/policies/RustfmtConfigExists.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAID;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,gBAAgB,CAAC,yBAAyB,CAoBzE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "pathe";
|
|
3
|
+
import { makePolicyDefinition } from "../makePolicy.js";
|
|
4
|
+
const DEFAULT_NAMES = ["rustfmt.toml", ".rustfmt.toml"];
|
|
5
|
+
/**
|
|
6
|
+
* A policy that requires a rustfmt.toml file for consistent Rust formatting.
|
|
7
|
+
*
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
export const RustfmtConfigExists = makePolicyDefinition({
|
|
11
|
+
name: "RustfmtConfigExists",
|
|
12
|
+
description: "Ensures a rustfmt.toml file exists for consistent Rust formatting.",
|
|
13
|
+
// Trigger on Cargo.toml to check once per project
|
|
14
|
+
match: /^Cargo\.toml$/,
|
|
15
|
+
handler: async ({ root, config }) => {
|
|
16
|
+
const names = config?.acceptedNames ?? DEFAULT_NAMES;
|
|
17
|
+
const hasConfig = names.some((name) => existsSync(path.join(root, name)));
|
|
18
|
+
if (hasConfig) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
error: `No rustfmt config found. Expected one of: ${names.join(", ")}`,
|
|
23
|
+
manualFix: "Create a rustfmt.toml file to configure Rust formatting.",
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=RustfmtConfigExists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustfmtConfigExists.js","sourceRoot":"","sources":["../../src/policies/RustfmtConfigExists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAgBxD,MAAM,aAAa,GAAG,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC/B,oBAAoB,CAAC;IACpB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACV,oEAAoE;IACrE,kDAAkD;IAClD,KAAK,EAAE,eAAe;IACtB,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,MAAM,EAAE,aAAa,IAAI,aAAa,CAAC;QACrD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAE1E,IAAI,SAAS,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO;YACN,KAAK,EAAE,6CAA6C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACtE,SAAS,EAAE,0DAA0D;SACrE,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition } from \"../policy.js\";\n\n/**\n * Configuration for the RustfmtConfigExists policy.\n *\n * @alpha\n */\nexport interface RustfmtConfigExistsConfig {\n\t/**\n\t * Accepted file names for the rustfmt config.\n\t * @defaultValue [\"rustfmt.toml\", \".rustfmt.toml\"]\n\t */\n\tacceptedNames?: string[];\n}\n\nconst DEFAULT_NAMES = [\"rustfmt.toml\", \".rustfmt.toml\"];\n\n/**\n * A policy that requires a rustfmt.toml file for consistent Rust formatting.\n *\n * @alpha\n */\nexport const RustfmtConfigExists: PolicyDefinition<RustfmtConfigExistsConfig> =\n\tmakePolicyDefinition({\n\t\tname: \"RustfmtConfigExists\",\n\t\tdescription:\n\t\t\t\"Ensures a rustfmt.toml file exists for consistent Rust formatting.\",\n\t\t// Trigger on Cargo.toml to check once per project\n\t\tmatch: /^Cargo\\.toml$/,\n\t\thandler: async ({ root, config }) => {\n\t\t\tconst names = config?.acceptedNames ?? DEFAULT_NAMES;\n\t\t\tconst hasConfig = names.some((name) => existsSync(path.join(root, name)));\n\n\t\t\tif (hasConfig) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\terror: `No rustfmt config found. Expected one of: ${names.join(\", \")}`,\n\t\t\t\tmanualFix: \"Create a rustfmt.toml file to configure Rust formatting.\",\n\t\t\t};\n\t\t},\n\t});\n"]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for validating that a script's body contains required substrings.
|
|
3
|
+
*
|
|
4
|
+
* @alpha
|
|
5
|
+
*/
|
|
6
|
+
export interface ScriptContainsRule {
|
|
7
|
+
/**
|
|
8
|
+
* The name of the script to validate.
|
|
9
|
+
*/
|
|
10
|
+
script: string;
|
|
11
|
+
/**
|
|
12
|
+
* Substrings that must appear in the script body.
|
|
13
|
+
* All substrings must be present for the script to pass validation.
|
|
14
|
+
*/
|
|
15
|
+
mustContain: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Configuration for the ScriptContains policy.
|
|
19
|
+
*
|
|
20
|
+
* @alpha
|
|
21
|
+
*/
|
|
22
|
+
export interface ScriptContainsConfig {
|
|
23
|
+
/**
|
|
24
|
+
* Rules for validating script body content.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* rules: [
|
|
29
|
+
* { script: "clean", mustContain: ["rimraf"] },
|
|
30
|
+
* { script: "build", mustContain: ["tsc"] },
|
|
31
|
+
* ]
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
rules: ScriptContainsRule[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A policy that validates script bodies contain required substrings.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Use this policy to ensure specific scripts contain required commands or patterns
|
|
41
|
+
* without requiring an exact match. For example, requiring that the "clean" script
|
|
42
|
+
* uses "rimraf" or that "build" includes "tsc".
|
|
43
|
+
*
|
|
44
|
+
* The policy only validates scripts that exist. If a script doesn't exist,
|
|
45
|
+
* it's not an error (use RequiredScripts for that).
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { policy } from "repopo";
|
|
50
|
+
* import { ScriptContains } from "repopo/policies";
|
|
51
|
+
*
|
|
52
|
+
* policy(ScriptContains, {
|
|
53
|
+
* rules: [
|
|
54
|
+
* { script: "clean", mustContain: ["rimraf"] },
|
|
55
|
+
* { script: "build", mustContain: ["tsc"] },
|
|
56
|
+
* { script: "test", mustContain: ["vitest", "run"] },
|
|
57
|
+
* ],
|
|
58
|
+
* })
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @alpha
|
|
62
|
+
*/
|
|
63
|
+
export declare const ScriptContains: import("../policy.js").PolicyShape<ScriptContainsConfig | undefined>;
|
|
64
|
+
//# sourceMappingURL=ScriptContains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScriptContains.d.ts","sourceRoot":"","sources":["../../src/policies/ScriptContains.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;OAUG;IACH,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC5B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,cAAc,sEA2CzB,CAAC"}
|