pr-checkmate 1.22.4 → 1.22.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.eslintrc.js +1 -1
  2. package/README.md +12 -2
  3. package/dist/config/constants.d.ts +10 -0
  4. package/dist/config/constants.js +18 -1
  5. package/dist/config/loader.js +3 -1
  6. package/dist/core/checks/circular-deps.js +1 -1
  7. package/dist/core/checks/commitlint.js +1 -1
  8. package/dist/core/checks/cpp-format.js +1 -1
  9. package/dist/core/checks/dead-code.js +3 -2
  10. package/dist/core/checks/dependency-check.js +1 -1
  11. package/dist/core/checks/duplicate-check.js +1 -1
  12. package/dist/core/checks/findings.js +1 -1
  13. package/dist/core/checks/kotlin-lint.js +1 -1
  14. package/dist/core/checks/license-check.js +1 -1
  15. package/dist/core/checks/lint.js +1 -1
  16. package/dist/core/checks/markdown-lint.js +1 -1
  17. package/dist/core/checks/npm-audit.js +1 -1
  18. package/dist/core/checks/outdated-deps.js +7 -2
  19. package/dist/core/checks/pr-size-check.js +1 -1
  20. package/dist/core/checks/prettier.js +1 -1
  21. package/dist/core/checks/security.js +1 -1
  22. package/dist/core/checks/sensitive-file-guard.js +1 -1
  23. package/dist/core/checks/spellcheck.js +1 -1
  24. package/dist/core/checks/swift-lint.js +1 -1
  25. package/dist/core/checks/typecheck.js +1 -1
  26. package/dist/core/context.js +1 -1
  27. package/dist/core/targets.js +1 -1
  28. package/dist/init.js +8 -0
  29. package/dist/interfaces/index.d.ts +14 -0
  30. package/dist/utils/delta.js +1 -1
  31. package/dist/utils/detect-language.js +1 -1
  32. package/dist/utils/execa.d.ts +22 -0
  33. package/dist/utils/execa.js +13 -0
  34. package/eslint.config.mjs +1 -1
  35. package/package.json +1 -1
  36. package/src/config/.eslintrc.js +1 -1
  37. package/src/config/eslint.config.mjs +1 -1
package/.eslintrc.js CHANGED
@@ -81,7 +81,7 @@ module.exports = {
81
81
  { blankLine: 'always', prev: '*', next: 'return' },
82
82
  ],
83
83
  // Complexity analysis (#61)
84
- complexity: ['warn', 15],
84
+ complexity: ['warn', 30],
85
85
  // Import ordering (#65)
86
86
  'import-x/order': [
87
87
  'warn',
package/README.md CHANGED
@@ -226,7 +226,7 @@ jobs:
226
226
  | Ruff Lint | informational | Python linting via WASM |
227
227
  | SwiftLint | informational | Swift linting |
228
228
  | ktlint | informational | Kotlin linting |
229
- | Dead Code | informational | Unused exports (`ts-unused-exports`) |
229
+ | Dead Code | informational | Unused exports (`ts-unused-exports`); test and mock files are excluded from the report by default — override with `deadCode.ignoreFiles` (regex) |
230
230
  | Duplicate Code | informational | `jscpd` — 5 lines / 50 tokens threshold; test files ignored by default (set `duplicate.ignore`); only source-code formats are scanned, so YAML/JSON/Markdown are skipped unless you override `duplicate.formats` |
231
231
  | Diff Smell | informational | `console.*`, `debugger`, `TODO/FIXME` in added lines |
232
232
  | Diff Security | informational | XSS, `eval`, SQLi, weak crypto in added lines |
@@ -265,7 +265,10 @@ All checks can be tuned or disabled per-repo via `pr-checkmate.json`:
265
265
  "formats": ["javascript", "typescript", "jsx", "tsx", "python", "kotlin", "swift", "c", "cpp"],
266
266
  "ignore": ["**/__tests__/**", "**/*.test.*", "**/*.spec.*", "**/test/**", "**/tests/**"]
267
267
  },
268
- "deadCode": { "enabled": false },
268
+ "deadCode": {
269
+ "enabled": true,
270
+ "ignoreFiles": ["src/index\\.ts", "handler"]
271
+ },
269
272
  "dependency": {
270
273
  "enabled": true,
271
274
  "ignore": ["@types/*", "some-cli-tool"]
@@ -294,6 +297,13 @@ A note on `dependency.ignore`:
294
297
  - Use it for packages that only run as CLI binaries or are referenced from config files. depcheck sees no `import` for them and would otherwise flag them as unused.
295
298
  - When set, `dependency.ignore` takes precedence over any `.depcheckrc` file. Leave it empty or unset and your existing `.depcheckrc` still applies.
296
299
 
300
+ A note on `deadCode.ignoreFiles`:
301
+
302
+ - The values are regex sources, not globs, and each one is matched against the file path. So `\.test\.` matches any file with `.test.` in its name.
303
+ - It defaults to test and mock files: `/__tests__/`, `/__mocks__/`, `/__mock__/`, `/tests?/`, `\.test\.`, `\.spec\.`. Their exports are consumed only by the test runner, so they showed up as false-positive "unused" before.
304
+ - Setting it replaces the default list rather than merging with it. Reach for it to exempt entry points or barrels like `src/index.ts` or a lambda `handler` whose exports are the public surface.
305
+ - It applies to the report only and never drops files from analysis, so a match here cannot cascade into missed dead code elsewhere.
306
+
297
307
  ---
298
308
 
299
309
  ## Delta Mode
@@ -9,6 +9,16 @@ export declare const IGNORE_PATTERNS: string[];
9
9
  * override this list via `duplicate.ignore` in pr-checkmate.json.
10
10
  */
11
11
  export declare const DUPLICATE_IGNORE_DEFAULTS: string[];
12
+ /**
13
+ * Files excluded from the dead-code (unused-exports) report by default. These are
14
+ * REGEX sources (matched against each reported file path), not globs — dead-code's
15
+ * `ignoreFiles` is regex-based. Test and mock files legitimately export helpers and
16
+ * mocks consumed only by the test runner (jest.mock, dynamic imports), which
17
+ * ts-unused-exports cannot see as usage, so flagging them is noise. Clients can
18
+ * override via `deadCode.ignoreFiles` in pr-checkmate.json (setting it replaces
19
+ * this list).
20
+ */
21
+ export declare const DEAD_CODE_IGNORE_DEFAULTS: string[];
12
22
  export declare const CONFIG_FILE_PATTERNS: string[];
13
23
  /**
14
24
  * jscpd formats the duplicate-CODE check scans. Restricting to code formats keeps
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CONFIG_FILE = exports.documentation = exports.DEFAULT_ALLOW_PACKAGES = exports.DEFAULT_COMMANDS = exports.SOURCE_EXTENSIONS = exports.DUPLICATE_CODE_FORMATS = exports.CONFIG_FILE_PATTERNS = exports.DUPLICATE_IGNORE_DEFAULTS = exports.IGNORE_PATTERNS = void 0;
6
+ exports.CONFIG_FILE = exports.documentation = exports.DEFAULT_ALLOW_PACKAGES = exports.DEFAULT_COMMANDS = exports.SOURCE_EXTENSIONS = exports.DUPLICATE_CODE_FORMATS = exports.CONFIG_FILE_PATTERNS = exports.DEAD_CODE_IGNORE_DEFAULTS = exports.DUPLICATE_IGNORE_DEFAULTS = exports.IGNORE_PATTERNS = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
8
  /**
9
9
  * Common patterns to ignore in all checks
@@ -71,6 +71,23 @@ exports.DUPLICATE_IGNORE_DEFAULTS = [
71
71
  '**/test/**',
72
72
  '**/tests/**',
73
73
  ];
74
+ /**
75
+ * Files excluded from the dead-code (unused-exports) report by default. These are
76
+ * REGEX sources (matched against each reported file path), not globs — dead-code's
77
+ * `ignoreFiles` is regex-based. Test and mock files legitimately export helpers and
78
+ * mocks consumed only by the test runner (jest.mock, dynamic imports), which
79
+ * ts-unused-exports cannot see as usage, so flagging them is noise. Clients can
80
+ * override via `deadCode.ignoreFiles` in pr-checkmate.json (setting it replaces
81
+ * this list).
82
+ */
83
+ exports.DEAD_CODE_IGNORE_DEFAULTS = [
84
+ '/__tests__/',
85
+ '/__mocks__/',
86
+ '/__mock__/',
87
+ '/tests?/',
88
+ '\\.test\\.',
89
+ '\\.spec\\.',
90
+ ];
74
91
  exports.CONFIG_FILE_PATTERNS = [
75
92
  '**/*.config.js',
76
93
  '**/*.config.cjs',
@@ -70,6 +70,7 @@ function mergeWithDefaults(userConfig) {
70
70
  prBody: { ...defaults.prBody, ...userConfig.prBody },
71
71
  duplicate: { ...defaults.duplicate, ...userConfig.duplicate },
72
72
  dependency: { ...defaults.dependency, ...userConfig.dependency },
73
+ outdatedDeps: { ...defaults.outdatedDeps, ...userConfig.outdatedDeps },
73
74
  commitlint: { ...defaults.commitlint, ...userConfig.commitlint },
74
75
  deadCode: { ...defaults.deadCode, ...userConfig.deadCode },
75
76
  licenseCheck: {
@@ -153,7 +154,8 @@ function getDefaultConfig() {
153
154
  formats: constants_1.DUPLICATE_CODE_FORMATS,
154
155
  },
155
156
  dependency: { enabled: true, ignore: [] },
156
- deadCode: { enabled: true, ignoreFiles: [] },
157
+ outdatedDeps: { enabled: true, ignore: [] },
158
+ deadCode: { enabled: true, ignoreFiles: constants_1.DEAD_CODE_IGNORE_DEFAULTS },
157
159
  commitlint: {
158
160
  enabled: true,
159
161
  types: [
@@ -5,9 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.circularDepsCheck = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
- const execa_1 = require("execa");
9
8
  const config_1 = require("../../config");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  exports.circularDepsCheck = {
13
13
  name: 'Circular Deps',
@@ -7,9 +7,9 @@ exports.commitlintCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_os_1 = __importDefault(require("node:os"));
9
9
  const node_path_1 = __importDefault(require("node:path"));
10
- const execa_1 = require("execa");
11
10
  const config_1 = require("../../config");
12
11
  const utils_1 = require("../../utils");
12
+ const execa_1 = require("../../utils/execa");
13
13
  const types_1 = require("../types");
14
14
  const LOCAL_CONFIG_FILES = [
15
15
  'commitlint.config.cjs',
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.cppFormatCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  /**
13
13
  * C/C++ source & header extensions clang-format understands. `.h` is intentionally
@@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.deadCodeCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
9
+ const constants_1 = require("../../config/constants");
10
10
  const utils_1 = require("../../utils");
11
+ const execa_1 = require("../../utils/execa");
11
12
  const types_1 = require("../types");
12
13
  exports.deadCodeCheck = {
13
14
  name: 'Dead Code',
@@ -39,7 +40,7 @@ exports.deadCodeCheck = {
39
40
  utils_1.logger.info('[Dead Code]: ✅ No unused exports found');
40
41
  return (0, types_1.pass)();
41
42
  }
42
- const ignore = compileIgnorePatterns(ctx.config.deadCode?.ignoreFiles);
43
+ const ignore = compileIgnorePatterns(ctx.config.deadCode?.ignoreFiles ?? constants_1.DEAD_CODE_IGNORE_DEFAULTS);
43
44
  // ts-unused-exports prints one `path: sym1, sym2` line per file, preceded
44
45
  // by a `N modules with unused exports` summary line we skip.
45
46
  const entries = output
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.dependencyCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  exports.dependencyCheck = {
13
13
  name: 'Dependencies',
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.duplicateCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const constants_1 = require("../../config/constants");
11
10
  const utils_1 = require("../../utils");
12
11
  const delta_1 = require("../../utils/delta");
12
+ const execa_1 = require("../../utils/execa");
13
13
  const types_1 = require("../types");
14
14
  // Always excluded regardless of client config — scanning these never yields
15
15
  // meaningful production duplication. Config files (eslint/*.config.*) are data,
@@ -4,8 +4,8 @@ exports.diffAddedLines = diffAddedLines;
4
4
  exports.bucketTotal = bucketTotal;
5
5
  exports.logFindings = logFindings;
6
6
  exports.reportSeverityBuckets = reportSeverityBuckets;
7
- const execa_1 = require("execa");
8
7
  const utils_1 = require("../../utils");
8
+ const execa_1 = require("../../utils/execa");
9
9
  const types_1 = require("../types");
10
10
  /**
11
11
  * Run `git diff` over the given file globs, returning the raw unified diff
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.kotlinLintCheck = void 0;
4
- const execa_1 = require("execa");
5
4
  const utils_1 = require("../../utils");
5
+ const execa_1 = require("../../utils/execa");
6
6
  const targets_1 = require("../targets");
7
7
  const types_1 = require("../types");
8
8
  const KOTLIN_GLOBS = ['*.kt', '*.kts'];
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.licenseCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  const FORBIDDEN_LICENSES = ['GPL-2.0', 'GPL-3.0', 'AGPL-3.0', 'LGPL-2.0', 'LGPL-2.1', 'LGPL-3.0'];
13
13
  /** Strip the trailing "@version" to get the bare package name (scoped-safe). */
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.lintCheck = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
- const execa_1 = require("execa");
9
8
  const config_1 = require("../../config");
10
9
  const utils_1 = require("../../utils");
11
10
  const delta_1 = require("../../utils/delta");
11
+ const execa_1 = require("../../utils/execa");
12
12
  const types_1 = require("../types");
13
13
  async function getESLintMajorVersion(eslintBin) {
14
14
  try {
@@ -7,10 +7,10 @@ exports.markdownLintCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_os_1 = __importDefault(require("node:os"));
9
9
  const node_path_1 = __importDefault(require("node:path"));
10
- const execa_1 = require("execa");
11
10
  const config_1 = require("../../config");
12
11
  const utils_1 = require("../../utils");
13
12
  const delta_1 = require("../../utils/delta");
13
+ const execa_1 = require("../../utils/execa");
14
14
  const types_1 = require("../types");
15
15
  function loadUserMarkdownConfig(cwd) {
16
16
  const configPath = node_path_1.default.join(cwd, 'pr-checkmate.json');
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.npmAuditCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  const SEVERITY_ORDER = ['info', 'low', 'moderate', 'high', 'critical'];
13
13
  function isSeverityAtLeast(severity, level) {
@@ -6,13 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.outdatedDepsCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  exports.outdatedDepsCheck = {
13
13
  name: 'Outdated Deps',
14
14
  phase: 'informational',
15
15
  applies(ctx) {
16
+ if (ctx.config.outdatedDeps?.enabled === false)
17
+ return false;
16
18
  return node_fs_1.default.existsSync(node_path_1.default.join(ctx.cwd, 'package.json'));
17
19
  },
18
20
  async run(ctx) {
@@ -27,7 +29,10 @@ exports.outdatedDepsCheck = {
27
29
  catch {
28
30
  return (0, types_1.pass)();
29
31
  }
30
- const entries = Object.entries(outdated);
32
+ // Packages deliberately pinned behind their latest major (see outdatedDeps.ignore
33
+ // in pr-checkmate.json) are dropped before counting, so they never warn.
34
+ const ignore = new Set(ctx.config.outdatedDeps?.ignore ?? []);
35
+ const entries = Object.entries(outdated).filter(([pkg]) => !ignore.has(pkg));
31
36
  if (entries.length === 0)
32
37
  return (0, types_1.pass)();
33
38
  const majorBehind = entries.filter(([, info]) => {
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.prSizeCheck = void 0;
4
- const execa_1 = require("execa");
5
4
  const utils_1 = require("../../utils");
5
+ const execa_1 = require("../../utils/execa");
6
6
  const types_1 = require("../types");
7
7
  const WARN_FILES = 50;
8
8
  const WARN_LINES = 1000;
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.prettierCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const config_1 = require("../../config");
11
10
  const utils_1 = require("../../utils");
12
11
  const delta_1 = require("../../utils/delta");
12
+ const execa_1 = require("../../utils/execa");
13
13
  const types_1 = require("../types");
14
14
  function loadUserPrettierConfig(cwd) {
15
15
  const configPath = node_path_1.default.join(cwd, 'pr-checkmate.json');
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.securityCheck = void 0;
4
- const execa_1 = require("execa");
5
4
  const config_1 = require("../../config");
6
5
  const utils_1 = require("../../utils");
6
+ const execa_1 = require("../../utils/execa");
7
7
  const types_1 = require("../types");
8
8
  /**
9
9
  * Secret scanning via the bundled gitleaks package. Language-agnostic — runs on
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sensitiveFileGuardCheck = void 0;
4
- const execa_1 = require("execa");
5
4
  const utils_1 = require("../../utils");
5
+ const execa_1 = require("../../utils/execa");
6
6
  const types_1 = require("../types");
7
7
  const findings_1 = require("./findings");
8
8
  const SENSITIVE_CATEGORIES = [
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.spellcheckCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const config_1 = require("../../config");
11
10
  const utils_1 = require("../../utils");
12
11
  const delta_1 = require("../../utils/delta");
12
+ const execa_1 = require("../../utils/execa");
13
13
  const types_1 = require("../types");
14
14
  function loadUserCspellConfig(cwd) {
15
15
  const configPath = node_path_1.default.join(cwd, 'pr-checkmate.json');
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.swiftLintCheck = void 0;
4
- const execa_1 = require("execa");
5
4
  const utils_1 = require("../../utils");
5
+ const execa_1 = require("../../utils/execa");
6
6
  const targets_1 = require("../targets");
7
7
  const types_1 = require("../types");
8
8
  const SWIFT_GLOBS = ['*.swift'];
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.typecheckCheck = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
10
9
  const utils_1 = require("../../utils");
10
+ const execa_1 = require("../../utils/execa");
11
11
  const types_1 = require("../types");
12
12
  /**
13
13
  * Prefer the consumer project's own TypeScript so its tsconfig is compiled by the
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildContext = buildContext;
4
- const execa_1 = require("execa");
5
4
  const loader_1 = require("../config/loader");
6
5
  const utils_1 = require("../utils");
7
6
  const detect_language_1 = require("../utils/detect-language");
7
+ const execa_1 = require("../utils/execa");
8
8
  /**
9
9
  * Resolve the diff range for delta-aware checks.
10
10
  * Prefers explicit opts, then GitHub PR event, then Bitbucket PR env, then git HEAD^.
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveTargetFiles = resolveTargetFiles;
4
- const execa_1 = require("execa");
5
4
  const utils_1 = require("../utils");
5
+ const execa_1 = require("../utils/execa");
6
6
  /**
7
7
  * Lists the files a language check should operate on, matched by pathspec `globs`
8
8
  * (e.g. `['*.py']`). Uses the PR diff range when available (delta mode), else
package/dist/init.js CHANGED
@@ -72,6 +72,14 @@ const DEFAULT_CONFIG = {
72
72
  // which depcheck can't see as imports and would report as unused).
73
73
  ignore: [],
74
74
  },
75
+ // Unused-exports check (ts-unused-exports)
76
+ deadCode: {
77
+ enabled: true,
78
+ // Regex sources matched against file paths; matching files are dropped from
79
+ // the report. Defaults to test/mock files, whose exports are used only by the
80
+ // test runner. Add barrels/entry points here to exempt intentional exports.
81
+ ignoreFiles: config_1.DEAD_CODE_IGNORE_DEFAULTS,
82
+ },
75
83
  documentation: config_1.documentation,
76
84
  };
77
85
  const MANUAL_ENTRY = 'Enter manually';
@@ -98,6 +98,17 @@ export interface PRCheckMateConfig {
98
98
  */
99
99
  ignore?: string[];
100
100
  };
101
+ outdatedDeps?: {
102
+ enabled?: boolean;
103
+ /**
104
+ * Exact package names to exclude from the outdated-deps warning, e.g.
105
+ * "commander". Use for dependencies deliberately pinned behind their latest
106
+ * major (a breaking upgrade you have chosen not to take, or one held back by
107
+ * an `overrides` entry) so `npm outdated` no longer flags them as major-behind.
108
+ * Matched by exact name — no globs or version ranges.
109
+ */
110
+ ignore?: string[];
111
+ };
101
112
  commitlint?: {
102
113
  enabled?: boolean;
103
114
  types?: string[];
@@ -129,6 +140,9 @@ export interface PRCheckMateConfig {
129
140
  * whose exports are consumed by external installers, not within the repo.
130
141
  * Applied to the report (not ts-unused-exports' own `--ignoreFiles`), so it
131
142
  * never removes a file from analysis and cannot cascade onto other files.
143
+ * Defaults to test/mock files (see DEAD_CODE_IGNORE_DEFAULTS), whose exports
144
+ * are consumed only by the test runner and would otherwise show as unused.
145
+ * Setting this replaces the default list.
132
146
  */
133
147
  ignoreFiles?: string[];
134
148
  };
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getChangedFiles = getChangedFiles;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
9
+ const execa_1 = require("./execa");
10
10
  const logger_1 = require("./logger");
11
11
  /**
12
12
  * Returns list of changed files in the current PR filtered by extension.
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.detectLanguages = detectLanguages;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const execa_1 = require("execa");
9
+ const execa_1 = require("./execa");
10
10
  const logger_1 = require("./logger");
11
11
  /**
12
12
  * Marker files that unambiguously indicate a language's presence, independent of
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Lazy loader for {@link https://github.com/sindresorhus/execa | execa}.
3
+ *
4
+ * execa v9 is ESM-only. Because this package compiles to CommonJS, importing
5
+ * execa at module scope forces every consumer to resolve execa's full
6
+ * dependency graph the moment they import pr-checkmate — even consumers that
7
+ * only need the types or a config helper and never run a check. That graph
8
+ * pulls in transitive packages (e.g. `unicorn-magic`) whose `exports` maps some
9
+ * loaders such as `tsx` fail to resolve, which crashes the import for those
10
+ * consumers before any check runs.
11
+ *
12
+ * Loading execa on first use keeps the library entry point cheap and avoids
13
+ * dragging the subprocess toolchain into consumers that never spawn a process.
14
+ */
15
+ import type { Options, Result } from 'execa';
16
+ /**
17
+ * Run a command via execa, loading the module lazily on first call.
18
+ *
19
+ * Drop-in replacement for `execa(file, args, options)` at every call site in
20
+ * this package — all of which await the result and read it synchronously.
21
+ */
22
+ export declare function execa<OptionsType extends Options = {}>(file: string, args?: readonly string[], options?: OptionsType): Promise<Result<OptionsType>>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.execa = execa;
4
+ /**
5
+ * Run a command via execa, loading the module lazily on first call.
6
+ *
7
+ * Drop-in replacement for `execa(file, args, options)` at every call site in
8
+ * this package — all of which await the result and read it synchronously.
9
+ */
10
+ async function execa(file, args, options) {
11
+ const { execa: run } = await import('execa');
12
+ return (await run(file, args, options));
13
+ }
package/eslint.config.mjs CHANGED
@@ -36,7 +36,7 @@ export const defaultRules = {
36
36
  { blankLine: 'always', prev: '*', next: 'return' },
37
37
  ],
38
38
  // Complexity analysis (#61)
39
- 'sonarjs/cognitive-complexity': ['warn', 15],
39
+ 'sonarjs/cognitive-complexity': ['warn', 30],
40
40
  'sonarjs/no-duplicate-string': ['warn', { threshold: 3 }],
41
41
  'sonarjs/no-identical-functions': 'warn',
42
42
  // Import ordering (#65)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-checkmate",
3
- "version": "1.22.4",
3
+ "version": "1.22.5",
4
4
  "description": "Automated PR quality checks: linting, formatting, dependency analysis, and spellcheck",
5
5
  "keywords": [
6
6
  "github-actions",
@@ -81,7 +81,7 @@ module.exports = {
81
81
  { blankLine: 'always', prev: '*', next: 'return' },
82
82
  ],
83
83
  // Complexity analysis (#61)
84
- complexity: ['warn', 15],
84
+ complexity: ['warn', 30],
85
85
  // Import ordering (#65)
86
86
  'import-x/order': [
87
87
  'warn',
@@ -36,7 +36,7 @@ export const defaultRules = {
36
36
  { blankLine: 'always', prev: '*', next: 'return' },
37
37
  ],
38
38
  // Complexity analysis (#61)
39
- 'sonarjs/cognitive-complexity': ['warn', 15],
39
+ 'sonarjs/cognitive-complexity': ['warn', 30],
40
40
  'sonarjs/no-duplicate-string': ['warn', { threshold: 3 }],
41
41
  'sonarjs/no-identical-functions': 'warn',
42
42
  // Import ordering (#65)