pr-checkmate 1.22.2 → 1.22.4
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/README.md +79 -3
- package/dist/config/constants.d.ts +14 -0
- package/dist/config/constants.js +36 -1
- package/dist/config/index.d.ts +0 -8
- package/dist/config/index.js +1 -7
- package/dist/config/loader.d.ts +0 -8
- package/dist/config/loader.js +10 -8
- package/dist/core/checks/dead-code.js +45 -7
- package/dist/core/checks/dependency-check.js +11 -1
- package/dist/core/checks/duplicate-check.js +17 -1
- package/dist/core/checks/python-format.js +3 -4
- package/dist/core/checks/python-lint.js +3 -4
- package/dist/core/checks/ruff-shared.d.ts +10 -0
- package/dist/core/checks/ruff-shared.js +14 -0
- package/dist/core/reporters.d.ts +1 -2
- package/dist/core/run-checks.js +6 -1
- package/dist/index.d.ts +1 -0
- package/dist/init.d.ts +0 -1
- package/dist/init.js +17 -6
- package/dist/interfaces/index.d.ts +34 -22
- package/dist/scripts/copy-configs.d.ts +1 -5
- package/dist/scripts/copy-configs.js +0 -1
- package/dist/utils/own-deps.js +14 -17
- package/package.json +4 -2
- package/dist/config/config.d.ts +0 -2
- package/dist/config/config.js +0 -12
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
10
|
+
[](https://pr-checkmate-docs.pages.dev)
|
|
10
11
|
|
|
11
12
|
> **PR CheckMate** is a universal PR quality checker that runs as a single `npm install` and works across **TypeScript, JavaScript, Python, C++, Swift, and Android/Kotlin** repositories — no per-language toolchain setup required.
|
|
12
13
|
|
|
@@ -218,7 +219,7 @@ jobs:
|
|
|
218
219
|
|---|---|---|
|
|
219
220
|
| ESLint + SonarJS + JSDoc | blocking | Lint with complexity, import order, and doc coverage rules |
|
|
220
221
|
| TypeScript | blocking | `tsc --noEmit` type check |
|
|
221
|
-
| Dependency Check | blocking | Unused / missing deps via depcheck |
|
|
222
|
+
| Dependency Check | blocking | Unused / missing deps via depcheck; silence CLI-only false positives with `dependency.ignore` |
|
|
222
223
|
| NPM Audit | blocking | Vulnerability scan (`moderate`+) |
|
|
223
224
|
| Circular Deps | blocking | Circular dependency detection |
|
|
224
225
|
| License Check | blocking | Blocks GPL / AGPL / LGPL packages |
|
|
@@ -226,7 +227,7 @@ jobs:
|
|
|
226
227
|
| SwiftLint | informational | Swift linting |
|
|
227
228
|
| ktlint | informational | Kotlin linting |
|
|
228
229
|
| Dead Code | informational | Unused exports (`ts-unused-exports`) |
|
|
229
|
-
| Duplicate Code | informational | `jscpd` — 5 lines / 50 tokens threshold |
|
|
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` |
|
|
230
231
|
| Diff Smell | informational | `console.*`, `debugger`, `TODO/FIXME` in added lines |
|
|
231
232
|
| Diff Security | informational | XSS, `eval`, SQLi, weak crypto in added lines |
|
|
232
233
|
| Sensitive Files | informational | `.env`, private keys, CI configs touched in PR |
|
|
@@ -258,8 +259,17 @@ All checks can be tuned or disabled per-repo via `pr-checkmate.json`:
|
|
|
258
259
|
"swift": { "enabled": true },
|
|
259
260
|
"kotlin": { "enabled": true },
|
|
260
261
|
"cpp": { "enabled": true, "clangFormat": { "style": "Google" } },
|
|
261
|
-
"duplicate": {
|
|
262
|
+
"duplicate": {
|
|
263
|
+
"enabled": true,
|
|
264
|
+
"minLines": 10,
|
|
265
|
+
"formats": ["javascript", "typescript", "jsx", "tsx", "python", "kotlin", "swift", "c", "cpp"],
|
|
266
|
+
"ignore": ["**/__tests__/**", "**/*.test.*", "**/*.spec.*", "**/test/**", "**/tests/**"]
|
|
267
|
+
},
|
|
262
268
|
"deadCode": { "enabled": false },
|
|
269
|
+
"dependency": {
|
|
270
|
+
"enabled": true,
|
|
271
|
+
"ignore": ["@types/*", "some-cli-tool"]
|
|
272
|
+
},
|
|
263
273
|
"commitlint": {
|
|
264
274
|
"enabled": true,
|
|
265
275
|
"types": ["feat", "fix", "docs", "chore", "ci", "refactor", "test"]
|
|
@@ -272,6 +282,18 @@ All checks can be tuned or disabled per-repo via `pr-checkmate.json`:
|
|
|
272
282
|
}
|
|
273
283
|
```
|
|
274
284
|
|
|
285
|
+
A note on `duplicate.ignore`:
|
|
286
|
+
|
|
287
|
+
- Setting it replaces the default test-file list rather than merging with it. If you add your own patterns, include any test globs you still want excluded.
|
|
288
|
+
- `node_modules/**`, `dist/**`, and `.git/**` are always excluded, regardless of config.
|
|
289
|
+
- `duplicate.formats` defaults to source-code formats only, so data files like YAML, JSON, and Markdown are not scanned. Setting it replaces the default list, so add `"yaml"` if you want duplication flagged in those files too.
|
|
290
|
+
|
|
291
|
+
A note on `dependency.ignore`:
|
|
292
|
+
|
|
293
|
+
- List dependency names or globs (such as `"@types/*"`) to exclude from the unused/missing check. The values are passed straight to depcheck's `--ignores`.
|
|
294
|
+
- 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
|
+
- When set, `dependency.ignore` takes precedence over any `.depcheckrc` file. Leave it empty or unset and your existing `.depcheckrc` still applies.
|
|
296
|
+
|
|
275
297
|
---
|
|
276
298
|
|
|
277
299
|
## Delta Mode
|
|
@@ -280,6 +302,60 @@ In GitHub Actions PR context, language checks automatically switch to **delta mo
|
|
|
280
302
|
|
|
281
303
|
---
|
|
282
304
|
|
|
305
|
+
## Programmatic API
|
|
306
|
+
|
|
307
|
+
Besides the CLI, PR CheckMate ships a typed programmatic API. Install the package and import checks directly — useful for embedding the same quality gates inside your own tooling. The full reference is published at the [API docs site](https://pr-checkmate-docs.pages.dev).
|
|
308
|
+
|
|
309
|
+
Run the built-in checks:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
import { runChecks } from 'pr-checkmate';
|
|
313
|
+
import type { CheckReport } from 'pr-checkmate';
|
|
314
|
+
|
|
315
|
+
const report: CheckReport = await runChecks({
|
|
316
|
+
cwd: process.cwd(),
|
|
317
|
+
reporter: 'stdout', // 'none' | 'stdout' | 'github' | (report) => void
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
if (!report.ok) process.exit(1);
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`runChecks` never throws on violations and never calls `process.exit` — the caller decides. `report.ok` is `true` when nothing failed; warnings and skips do not affect it.
|
|
324
|
+
|
|
325
|
+
Author a custom check:
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
import { runChecks, defineCheck, pass, fail } from 'pr-checkmate';
|
|
329
|
+
|
|
330
|
+
const noFixmes = defineCheck({
|
|
331
|
+
name: 'no-fixmes',
|
|
332
|
+
phase: 'lint',
|
|
333
|
+
applies: () => true,
|
|
334
|
+
run: async (ctx) => {
|
|
335
|
+
// inspect ctx (config, changed files, language, sha range) and return an outcome
|
|
336
|
+
return pass();
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
await runChecks({ checks: [noFixmes] }); // appended to the built-in registry by default
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Key exports
|
|
344
|
+
|
|
345
|
+
| Export | Purpose |
|
|
346
|
+
|---|---|
|
|
347
|
+
| `runChecks` | Run the check pipeline; returns a structured `CheckReport` |
|
|
348
|
+
| `buildContext` | Build the `CheckContext` (language, config, sha range) checks receive |
|
|
349
|
+
| `REGISTRY` | The array of built-in checks |
|
|
350
|
+
| `defineCheck` | Identity helper for authoring a `Check` with full type inference |
|
|
351
|
+
| `pass` / `warn` / `fail` / `skip` | Outcome constructors for check bodies |
|
|
352
|
+
| `getSourcePath` / `getPackageConfigPath` / `hasLocalConfig` | Config-path helpers |
|
|
353
|
+
| Types | `Check`, `CheckContext`, `CheckReport`, `CheckResult`, `CheckOutcome`, `CheckStatus`, `RunOptions`, `Language`, `Phase`, `ReporterKind`, `ReporterFn`, `PRCheckMateConfig` |
|
|
354
|
+
|
|
355
|
+
Regenerate the docs locally with `npm run docs` (output in `docs/api`).
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
283
359
|
## PR Summary Comment
|
|
284
360
|
|
|
285
361
|
After `npx pr-checkmate all`, a summary table is posted to the PR. On repeated pushes the comment is updated in place — no duplicate comments.
|
|
@@ -2,7 +2,21 @@
|
|
|
2
2
|
* Common patterns to ignore in all checks
|
|
3
3
|
*/
|
|
4
4
|
export declare const IGNORE_PATTERNS: string[];
|
|
5
|
+
/**
|
|
6
|
+
* Test files/folders excluded from duplicate-code detection by default.
|
|
7
|
+
* Test suites legitimately repeat setup/arrange/assert boilerplate, so counting
|
|
8
|
+
* them as clones is noise that drowns out real production duplication. Clients can
|
|
9
|
+
* override this list via `duplicate.ignore` in pr-checkmate.json.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DUPLICATE_IGNORE_DEFAULTS: string[];
|
|
5
12
|
export declare const CONFIG_FILE_PATTERNS: string[];
|
|
13
|
+
/**
|
|
14
|
+
* jscpd formats the duplicate-CODE check scans. Restricting to code formats keeps
|
|
15
|
+
* config/CI YAML and JSON out of the report — they are data, not code, and their
|
|
16
|
+
* repetition is not meaningful duplication. This mirrors the code-only file set the
|
|
17
|
+
* check already uses when scanning a git diff, so full-tree and diff scans agree.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DUPLICATE_CODE_FORMATS: string[];
|
|
6
20
|
/**
|
|
7
21
|
* File extensions to check
|
|
8
22
|
*/
|
package/dist/config/constants.js
CHANGED
|
@@ -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.CONFIG_FILE_PATTERNS = 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.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
|
|
@@ -57,14 +57,49 @@ exports.IGNORE_PATTERNS = [
|
|
|
57
57
|
'**/lint-report/**',
|
|
58
58
|
'**/audit-report/**',
|
|
59
59
|
];
|
|
60
|
+
/**
|
|
61
|
+
* Test files/folders excluded from duplicate-code detection by default.
|
|
62
|
+
* Test suites legitimately repeat setup/arrange/assert boilerplate, so counting
|
|
63
|
+
* them as clones is noise that drowns out real production duplication. Clients can
|
|
64
|
+
* override this list via `duplicate.ignore` in pr-checkmate.json.
|
|
65
|
+
*/
|
|
66
|
+
exports.DUPLICATE_IGNORE_DEFAULTS = [
|
|
67
|
+
'**/__tests__/**',
|
|
68
|
+
'**/__mocks__/**',
|
|
69
|
+
'**/*.test.*',
|
|
70
|
+
'**/*.spec.*',
|
|
71
|
+
'**/test/**',
|
|
72
|
+
'**/tests/**',
|
|
73
|
+
];
|
|
60
74
|
exports.CONFIG_FILE_PATTERNS = [
|
|
61
75
|
'**/*.config.js',
|
|
76
|
+
'**/*.config.cjs',
|
|
77
|
+
'**/*.config.mjs',
|
|
62
78
|
'**/*.config.ts',
|
|
79
|
+
'**/.eslintrc.*',
|
|
80
|
+
'**/eslint.config.*',
|
|
63
81
|
'**/jest.config.*',
|
|
64
82
|
'**/wdio.config.*',
|
|
65
83
|
'**/playwright.config.*',
|
|
66
84
|
'**/cypress.config.*',
|
|
67
85
|
];
|
|
86
|
+
/**
|
|
87
|
+
* jscpd formats the duplicate-CODE check scans. Restricting to code formats keeps
|
|
88
|
+
* config/CI YAML and JSON out of the report — they are data, not code, and their
|
|
89
|
+
* repetition is not meaningful duplication. This mirrors the code-only file set the
|
|
90
|
+
* check already uses when scanning a git diff, so full-tree and diff scans agree.
|
|
91
|
+
*/
|
|
92
|
+
exports.DUPLICATE_CODE_FORMATS = [
|
|
93
|
+
'javascript',
|
|
94
|
+
'typescript',
|
|
95
|
+
'jsx',
|
|
96
|
+
'tsx',
|
|
97
|
+
'python',
|
|
98
|
+
'kotlin',
|
|
99
|
+
'swift',
|
|
100
|
+
'c',
|
|
101
|
+
'cpp',
|
|
102
|
+
];
|
|
68
103
|
/**
|
|
69
104
|
* File extensions to check
|
|
70
105
|
*/
|
package/dist/config/index.d.ts
CHANGED
|
@@ -13,11 +13,3 @@ export declare function getPackageConfigPath(fileName: string): string;
|
|
|
13
13
|
* Check if project has local config
|
|
14
14
|
*/
|
|
15
15
|
export declare function hasLocalConfig(configNames: string[]): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* For backward compatibility, also export as constant
|
|
18
|
-
* But this will be evaluated at module load time
|
|
19
|
-
*/
|
|
20
|
-
export declare const config: {
|
|
21
|
-
sourcePath: string;
|
|
22
|
-
};
|
|
23
|
-
export declare const SOURCE_PATH: string;
|
package/dist/config/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.
|
|
20
|
+
exports.loadProjectConfig = void 0;
|
|
21
21
|
exports.getSourcePath = getSourcePath;
|
|
22
22
|
exports.getPackageConfigPath = getPackageConfigPath;
|
|
23
23
|
exports.hasLocalConfig = hasLocalConfig;
|
|
@@ -65,9 +65,3 @@ function hasLocalConfig(configNames) {
|
|
|
65
65
|
const projectRoot = process.cwd();
|
|
66
66
|
return configNames.some(name => node_fs_1.default.existsSync(node_path_1.default.join(projectRoot, name)));
|
|
67
67
|
}
|
|
68
|
-
/**
|
|
69
|
-
* For backward compatibility, also export as constant
|
|
70
|
-
* But this will be evaluated at module load time
|
|
71
|
-
*/
|
|
72
|
-
exports.config = loadConfig();
|
|
73
|
-
exports.SOURCE_PATH = exports.config.sourcePath;
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -4,11 +4,3 @@ import { PRCheckMateConfig } from '../interfaces';
|
|
|
4
4
|
* Falls back to defaults if not found
|
|
5
5
|
*/
|
|
6
6
|
export declare function loadProjectConfig(): PRCheckMateConfig;
|
|
7
|
-
/**
|
|
8
|
-
* Get default configuration
|
|
9
|
-
*/
|
|
10
|
-
export declare function getDefaultConfig(): PRCheckMateConfig;
|
|
11
|
-
/**
|
|
12
|
-
* Export config for external use
|
|
13
|
-
*/
|
|
14
|
-
export declare const DEFAULT_CONFIG: PRCheckMateConfig;
|
package/dist/config/loader.js
CHANGED
|
@@ -3,9 +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.DEFAULT_CONFIG = void 0;
|
|
7
6
|
exports.loadProjectConfig = loadProjectConfig;
|
|
8
|
-
exports.getDefaultConfig = getDefaultConfig;
|
|
9
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
11
9
|
const utils_1 = require("../utils");
|
|
@@ -71,6 +69,7 @@ function mergeWithDefaults(userConfig) {
|
|
|
71
69
|
diffSmell: { ...defaults.diffSmell, ...userConfig.diffSmell },
|
|
72
70
|
prBody: { ...defaults.prBody, ...userConfig.prBody },
|
|
73
71
|
duplicate: { ...defaults.duplicate, ...userConfig.duplicate },
|
|
72
|
+
dependency: { ...defaults.dependency, ...userConfig.dependency },
|
|
74
73
|
commitlint: { ...defaults.commitlint, ...userConfig.commitlint },
|
|
75
74
|
deadCode: { ...defaults.deadCode, ...userConfig.deadCode },
|
|
76
75
|
licenseCheck: {
|
|
@@ -146,8 +145,15 @@ function getDefaultConfig() {
|
|
|
146
145
|
kotlin: { enabled: true },
|
|
147
146
|
diffSmell: { enabled: true },
|
|
148
147
|
prBody: { enabled: true, minLength: 20, requireTicket: true },
|
|
149
|
-
duplicate: {
|
|
150
|
-
|
|
148
|
+
duplicate: {
|
|
149
|
+
enabled: true,
|
|
150
|
+
minLines: 5,
|
|
151
|
+
minTokens: 50,
|
|
152
|
+
ignore: constants_1.DUPLICATE_IGNORE_DEFAULTS,
|
|
153
|
+
formats: constants_1.DUPLICATE_CODE_FORMATS,
|
|
154
|
+
},
|
|
155
|
+
dependency: { enabled: true, ignore: [] },
|
|
156
|
+
deadCode: { enabled: true, ignoreFiles: [] },
|
|
151
157
|
commitlint: {
|
|
152
158
|
enabled: true,
|
|
153
159
|
types: [
|
|
@@ -174,7 +180,3 @@ function getDefaultConfig() {
|
|
|
174
180
|
},
|
|
175
181
|
};
|
|
176
182
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Export config for external use
|
|
179
|
-
*/
|
|
180
|
-
exports.DEFAULT_CONFIG = getDefaultConfig();
|
|
@@ -24,6 +24,12 @@ exports.deadCodeCheck = {
|
|
|
24
24
|
}
|
|
25
25
|
const bin = (0, utils_1.resolvePackageBin)('ts-unused-exports', 'bin/ts-unused-exports');
|
|
26
26
|
try {
|
|
27
|
+
// Run the full analysis unfiltered: ignore patterns are applied to the
|
|
28
|
+
// *report* below, not passed to ts-unused-exports' own `--ignoreFiles`.
|
|
29
|
+
// That flag drops files from analysis entirely, so a file's imports stop
|
|
30
|
+
// counting as usage — ignoring a barrel or entry point would then cascade
|
|
31
|
+
// and flag everything it re-exports. Filtering the output instead keeps
|
|
32
|
+
// every usage edge intact and only hides the exempted files' own reports.
|
|
27
33
|
const result = await (0, execa_1.execa)(process.execPath, [bin, tsConfigPath], {
|
|
28
34
|
cwd: ctx.cwd,
|
|
29
35
|
reject: false,
|
|
@@ -33,14 +39,31 @@ exports.deadCodeCheck = {
|
|
|
33
39
|
utils_1.logger.info('[Dead Code]: ✅ No unused exports found');
|
|
34
40
|
return (0, types_1.pass)();
|
|
35
41
|
}
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
const ignore = compileIgnorePatterns(ctx.config.deadCode?.ignoreFiles);
|
|
43
|
+
// ts-unused-exports prints one `path: sym1, sym2` line per file, preceded
|
|
44
|
+
// by a `N modules with unused exports` summary line we skip.
|
|
45
|
+
const entries = output
|
|
46
|
+
.split('\n')
|
|
47
|
+
.map(line => line.trim().match(/^(.+\.[cm]?tsx?): (.+)$/))
|
|
48
|
+
.filter((match) => match !== null)
|
|
49
|
+
.map(match => ({
|
|
50
|
+
file: match[1],
|
|
51
|
+
symbols: match[2]
|
|
52
|
+
.split(',')
|
|
53
|
+
.map(sym => sym.trim())
|
|
54
|
+
.filter(Boolean),
|
|
55
|
+
}))
|
|
56
|
+
.filter(entry => !ignore.some(re => re.test(entry.file)));
|
|
57
|
+
if (entries.length === 0) {
|
|
58
|
+
utils_1.logger.info('[Dead Code]: ✅ No unused exports found');
|
|
59
|
+
return (0, types_1.pass)();
|
|
60
|
+
}
|
|
61
|
+
const fileCount = entries.length;
|
|
62
|
+
const exportCount = entries.reduce((sum, entry) => sum + entry.symbols.length, 0);
|
|
42
63
|
utils_1.logger.warn(`[Dead Code]: ⚠️ ${exportCount} unused export(s) across ${fileCount} file(s):`);
|
|
43
|
-
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
utils_1.logger.warn(`${entry.file}: ${entry.symbols.join(', ')}`);
|
|
66
|
+
}
|
|
44
67
|
return (0, types_1.warn)(`${exportCount} unused export(s) in ${fileCount} file(s)`);
|
|
45
68
|
}
|
|
46
69
|
catch (err) {
|
|
@@ -49,3 +72,18 @@ exports.deadCodeCheck = {
|
|
|
49
72
|
}
|
|
50
73
|
},
|
|
51
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Compile `deadCode.ignoreFiles` regex sources, skipping any that fail to parse
|
|
77
|
+
* (a bad pattern warns rather than aborting the whole check).
|
|
78
|
+
*/
|
|
79
|
+
function compileIgnorePatterns(patterns) {
|
|
80
|
+
return (patterns ?? []).filter(Boolean).flatMap(pattern => {
|
|
81
|
+
try {
|
|
82
|
+
return [new RegExp(pattern)];
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
utils_1.logger.warn(`[Dead Code]: ⚠️ Ignoring invalid ignoreFiles pattern: ${pattern}`);
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -13,6 +13,8 @@ exports.dependencyCheck = {
|
|
|
13
13
|
name: 'Dependencies',
|
|
14
14
|
phase: 'blocking',
|
|
15
15
|
applies(ctx) {
|
|
16
|
+
if (ctx.config.dependency?.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) {
|
|
@@ -25,8 +27,16 @@ exports.dependencyCheck = {
|
|
|
25
27
|
catch {
|
|
26
28
|
return (0, types_1.skip)('depcheck unavailable');
|
|
27
29
|
}
|
|
30
|
+
// Dependency names/globs to skip, configured in pr-checkmate.json. Passed via
|
|
31
|
+
// --ignores so a single pr-checkmate.json is the source of truth; depcheck's
|
|
32
|
+
// CLI --ignores overrides any .depcheckrc, so we only pass it when non-empty
|
|
33
|
+
// (letting a client's own .depcheckrc still apply when nothing is configured).
|
|
34
|
+
const ignore = ctx.config.dependency?.ignore ?? [];
|
|
35
|
+
const args = [depcheckBin, '--json'];
|
|
36
|
+
if (ignore.length > 0)
|
|
37
|
+
args.push(`--ignores=${ignore.join(',')}`);
|
|
28
38
|
// reject:false — depcheck exits non-zero when it finds issues but still emits JSON on stdout.
|
|
29
|
-
const { stdout } = await (0, execa_1.execa)(process.execPath,
|
|
39
|
+
const { stdout } = await (0, execa_1.execa)(process.execPath, args, {
|
|
30
40
|
cwd: ctx.cwd,
|
|
31
41
|
reject: false,
|
|
32
42
|
});
|
|
@@ -7,9 +7,15 @@ 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
9
|
const execa_1 = require("execa");
|
|
10
|
+
const constants_1 = require("../../config/constants");
|
|
10
11
|
const utils_1 = require("../../utils");
|
|
11
12
|
const delta_1 = require("../../utils/delta");
|
|
12
13
|
const types_1 = require("../types");
|
|
14
|
+
// Always excluded regardless of client config — scanning these never yields
|
|
15
|
+
// meaningful production duplication. Config files (eslint/*.config.*) are data,
|
|
16
|
+
// not logic, and are commonly shipped in two formats (e.g. .eslintrc + flat
|
|
17
|
+
// config), so their repetition is expected rather than a code smell.
|
|
18
|
+
const BASE_IGNORE = ['node_modules/**', 'dist/**', '.git/**', ...constants_1.CONFIG_FILE_PATTERNS];
|
|
13
19
|
// jscpd v5 appends promotional/funding lines after its report. Strip them so
|
|
14
20
|
// they never reach the client's terminal when running our package.
|
|
15
21
|
const JSCPD_PROMO_MARKERS = [
|
|
@@ -44,6 +50,14 @@ exports.duplicateCheck = {
|
|
|
44
50
|
const srcPath = node_path_1.default.join(ctx.cwd, 'src');
|
|
45
51
|
const targetPaths = changedFiles ?? (node_fs_1.default.existsSync(srcPath) ? [srcPath] : [ctx.cwd]);
|
|
46
52
|
const jscpdBin = (0, utils_1.resolvePackageBin)('jscpd', 'run-jscpd.js');
|
|
53
|
+
// Client-configurable exclusions (pr-checkmate.json `duplicate.ignore`),
|
|
54
|
+
// defaulting to test files/folders, appended to the always-on base ignores.
|
|
55
|
+
const configuredIgnore = ctx.config.duplicate?.ignore ?? constants_1.DUPLICATE_IGNORE_DEFAULTS;
|
|
56
|
+
const ignore = [...BASE_IGNORE, ...configuredIgnore].join(',');
|
|
57
|
+
// Client-configurable formats (pr-checkmate.json `duplicate.formats`),
|
|
58
|
+
// defaulting to source-code formats so data files (yaml/json/markdown) are
|
|
59
|
+
// not scanned. Clients can add them back explicitly.
|
|
60
|
+
const formats = (ctx.config.duplicate?.formats ?? constants_1.DUPLICATE_CODE_FORMATS).join(',');
|
|
47
61
|
try {
|
|
48
62
|
const result = await (0, execa_1.execa)(process.execPath, [
|
|
49
63
|
jscpdBin,
|
|
@@ -53,8 +67,10 @@ exports.duplicateCheck = {
|
|
|
53
67
|
String(minTokens),
|
|
54
68
|
'--reporters',
|
|
55
69
|
'console',
|
|
70
|
+
'--format',
|
|
71
|
+
formats,
|
|
56
72
|
'--ignore',
|
|
57
|
-
|
|
73
|
+
ignore,
|
|
58
74
|
...targetPaths,
|
|
59
75
|
], { cwd: ctx.cwd, reject: false });
|
|
60
76
|
const output = stripJscpdPromo([result.stdout, result.stderr].filter(Boolean).join('\n'));
|
|
@@ -9,7 +9,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const utils_1 = require("../../utils");
|
|
10
10
|
const targets_1 = require("../targets");
|
|
11
11
|
const types_1 = require("../types");
|
|
12
|
-
const
|
|
12
|
+
const ruff_shared_1 = require("./ruff-shared");
|
|
13
13
|
/**
|
|
14
14
|
* Formats changed Python files with Ruff's formatter (WASM, no Python/pip needed).
|
|
15
15
|
* Read-only in check mode (`warn` when files differ from formatted output); rewrites
|
|
@@ -24,13 +24,12 @@ exports.pythonFormatCheck = {
|
|
|
24
24
|
ctx.languages.includes('python'));
|
|
25
25
|
},
|
|
26
26
|
async run(ctx) {
|
|
27
|
-
const targets = await (0, targets_1.resolveTargetFiles)(ctx, PY_GLOBS);
|
|
27
|
+
const targets = await (0, targets_1.resolveTargetFiles)(ctx, ruff_shared_1.PY_GLOBS);
|
|
28
28
|
if (targets === null)
|
|
29
29
|
return (0, types_1.skip)('git unavailable');
|
|
30
30
|
if (targets.length === 0)
|
|
31
31
|
return (0, types_1.pass)('no Python files changed');
|
|
32
|
-
const
|
|
33
|
-
const workspace = new Workspace(Workspace.defaultSettings(), PositionEncoding.Utf16);
|
|
32
|
+
const workspace = (0, ruff_shared_1.createRuffWorkspace)();
|
|
34
33
|
let unformatted = 0;
|
|
35
34
|
for (const rel of targets) {
|
|
36
35
|
const abs = node_path_1.default.join(ctx.cwd, rel);
|
|
@@ -9,7 +9,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const utils_1 = require("../../utils");
|
|
10
10
|
const targets_1 = require("../targets");
|
|
11
11
|
const types_1 = require("../types");
|
|
12
|
-
const
|
|
12
|
+
const ruff_shared_1 = require("./ruff-shared");
|
|
13
13
|
/**
|
|
14
14
|
* Lints changed Python files with Ruff, bundled as a self-contained WASM module
|
|
15
15
|
* (`@astral-sh/ruff-wasm-nodejs`) so it runs on a bare Node image with no Python
|
|
@@ -26,13 +26,12 @@ exports.pythonLintCheck = {
|
|
|
26
26
|
ctx.languages.includes('python'));
|
|
27
27
|
},
|
|
28
28
|
async run(ctx) {
|
|
29
|
-
const targets = await (0, targets_1.resolveTargetFiles)(ctx, PY_GLOBS);
|
|
29
|
+
const targets = await (0, targets_1.resolveTargetFiles)(ctx, ruff_shared_1.PY_GLOBS);
|
|
30
30
|
if (targets === null)
|
|
31
31
|
return (0, types_1.skip)('git unavailable');
|
|
32
32
|
if (targets.length === 0)
|
|
33
33
|
return (0, types_1.pass)('no Python files changed');
|
|
34
|
-
const
|
|
35
|
-
const workspace = new Workspace(Workspace.defaultSettings(), PositionEncoding.Utf16);
|
|
34
|
+
const workspace = (0, ruff_shared_1.createRuffWorkspace)();
|
|
36
35
|
let totalIssues = 0;
|
|
37
36
|
let filesWithIssues = 0;
|
|
38
37
|
for (const rel of targets) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type RuffModule = typeof import('@astral-sh/ruff-wasm-nodejs');
|
|
2
|
+
type RuffWorkspace = InstanceType<RuffModule['Workspace']>;
|
|
3
|
+
export declare const PY_GLOBS: string[];
|
|
4
|
+
/**
|
|
5
|
+
* Instantiate a Ruff WASM workspace with default settings. Shared by the Ruff
|
|
6
|
+
* lint and format checks so their setup stays identical, and kept as a function
|
|
7
|
+
* (not a module-level singleton) so the WASM module loads only when a check runs.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createRuffWorkspace(): RuffWorkspace;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PY_GLOBS = void 0;
|
|
4
|
+
exports.createRuffWorkspace = createRuffWorkspace;
|
|
5
|
+
exports.PY_GLOBS = ['*.py'];
|
|
6
|
+
/**
|
|
7
|
+
* Instantiate a Ruff WASM workspace with default settings. Shared by the Ruff
|
|
8
|
+
* lint and format checks so their setup stays identical, and kept as a function
|
|
9
|
+
* (not a module-level singleton) so the WASM module loads only when a check runs.
|
|
10
|
+
*/
|
|
11
|
+
function createRuffWorkspace() {
|
|
12
|
+
const { Workspace, PositionEncoding } = require('@astral-sh/ruff-wasm-nodejs');
|
|
13
|
+
return new Workspace(Workspace.defaultSettings(), PositionEncoding.Utf16);
|
|
14
|
+
}
|
package/dist/core/reporters.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { CheckReport
|
|
1
|
+
import type { CheckReport } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Emit the report through the selected channel.
|
|
4
4
|
* none: nothing · stdout: console table · github: table + upsert PR comment.
|
|
5
5
|
*/
|
|
6
6
|
export declare function report(kind: 'none' | 'stdout' | 'github', result: CheckReport): Promise<void>;
|
|
7
|
-
export type { CheckResult };
|
package/dist/core/run-checks.js
CHANGED
|
@@ -54,7 +54,12 @@ function errMessage(err) {
|
|
|
54
54
|
async function runOne(check, ctx, collector) {
|
|
55
55
|
try {
|
|
56
56
|
if (!(await check.applies(ctx))) {
|
|
57
|
-
|
|
57
|
+
// A check that doesn't apply is irrelevant to this project/run — e.g. a
|
|
58
|
+
// language-specific check (SwiftLint, ktlint, Ruff, C++) in a repo of a
|
|
59
|
+
// different language, or a check disabled in config. Omit it from the report
|
|
60
|
+
// entirely rather than listing it as "not applicable": in a single-language
|
|
61
|
+
// repo those rows are pure noise and inflate the skipped count. Runtime skips
|
|
62
|
+
// from run() (e.g. "no relevant files changed") are still reported.
|
|
58
63
|
return;
|
|
59
64
|
}
|
|
60
65
|
const outcome = await check.run(ctx);
|
package/dist/index.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export { runChecks, buildContext, REGISTRY } from './core';
|
|
|
7
7
|
export { pass, warn, fail, skip, defineCheck } from './core';
|
|
8
8
|
export type { Check, CheckContext, CheckOutcome, CheckReport, CheckResult, CheckStatus, Language, Phase, ReporterFn, ReporterKind, RunOptions, } from './core';
|
|
9
9
|
export { getSourcePath, getPackageConfigPath, hasLocalConfig } from './config';
|
|
10
|
+
export type { PRCheckMateConfig } from './interfaces';
|
package/dist/init.d.ts
CHANGED
package/dist/init.js
CHANGED
|
@@ -3,14 +3,13 @@ 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 = void 0;
|
|
7
6
|
exports.init = init;
|
|
8
7
|
const fs_1 = __importDefault(require("fs"));
|
|
9
8
|
const path_1 = __importDefault(require("path"));
|
|
10
9
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
10
|
const config_1 = require("./config");
|
|
12
11
|
const utils_1 = require("./utils");
|
|
13
|
-
|
|
12
|
+
const CONFIG_FILE = path_1.default.resolve(process.cwd(), 'pr-checkmate.json');
|
|
14
13
|
/**
|
|
15
14
|
* Default configuration structure with customization options
|
|
16
15
|
*/
|
|
@@ -60,6 +59,18 @@ const DEFAULT_CONFIG = {
|
|
|
60
59
|
enabled: true,
|
|
61
60
|
minLines: 5,
|
|
62
61
|
minTokens: 50,
|
|
62
|
+
// Test files/folders are excluded by default; edit to customise.
|
|
63
|
+
ignore: config_1.DUPLICATE_IGNORE_DEFAULTS,
|
|
64
|
+
// Only source-code formats are scanned. Data formats (yaml, json, markdown)
|
|
65
|
+
// are intentionally absent — add them here to detect duplication in them too.
|
|
66
|
+
formats: config_1.DUPLICATE_CODE_FORMATS,
|
|
67
|
+
},
|
|
68
|
+
// Dependency usage check (depcheck)
|
|
69
|
+
dependency: {
|
|
70
|
+
enabled: true,
|
|
71
|
+
// Dependency names/globs to skip (e.g. CLI-only tools invoked as binaries,
|
|
72
|
+
// which depcheck can't see as imports and would report as unused).
|
|
73
|
+
ignore: [],
|
|
63
74
|
},
|
|
64
75
|
documentation: config_1.documentation,
|
|
65
76
|
};
|
|
@@ -135,7 +146,7 @@ async function createConfig(root) {
|
|
|
135
146
|
sourcePath,
|
|
136
147
|
languages,
|
|
137
148
|
};
|
|
138
|
-
fs_1.default.writeFileSync(
|
|
149
|
+
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
139
150
|
utils_1.logger.info(`[init]: ✅ Created pr-checkmate.json with sourcePath: ${sourcePath}`);
|
|
140
151
|
utils_1.logger.info(`[init]: 💡 You can now customize ESLint rules, Prettier settings,
|
|
141
152
|
and cspell words in pr-checkmate.json`);
|
|
@@ -146,7 +157,7 @@ async function createConfig(root) {
|
|
|
146
157
|
async function updateConfig(root) {
|
|
147
158
|
utils_1.logger.info('[init]: pr-checkmate.json already exists — updating it.');
|
|
148
159
|
try {
|
|
149
|
-
const raw = fs_1.default.readFileSync(
|
|
160
|
+
const raw = fs_1.default.readFileSync(CONFIG_FILE, 'utf-8');
|
|
150
161
|
const json = JSON.parse(raw);
|
|
151
162
|
const languages = await (0, utils_1.detectLanguages)(root);
|
|
152
163
|
utils_1.logger.info(`[init]: 🔍 Detected languages: ${languages.length ? languages.join(', ') : 'none'}`);
|
|
@@ -164,7 +175,7 @@ async function updateConfig(root) {
|
|
|
164
175
|
prBody: { ...DEFAULT_CONFIG.prBody, ...(json.prBody || {}) },
|
|
165
176
|
duplicate: { ...DEFAULT_CONFIG.duplicate, ...(json.duplicate || {}) },
|
|
166
177
|
};
|
|
167
|
-
fs_1.default.writeFileSync(
|
|
178
|
+
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2));
|
|
168
179
|
utils_1.logger.info('[init]: 🔧 Updated pr-checkmate.json with customization options.');
|
|
169
180
|
utils_1.logger.info('[init]: 💡 You can now add custom ESLint rules, cspell words, and more!');
|
|
170
181
|
}
|
|
@@ -177,7 +188,7 @@ async function updateConfig(root) {
|
|
|
177
188
|
*/
|
|
178
189
|
async function init() {
|
|
179
190
|
const root = process.cwd();
|
|
180
|
-
if (fs_1.default.existsSync(
|
|
191
|
+
if (fs_1.default.existsSync(CONFIG_FILE)) {
|
|
181
192
|
await updateConfig(root);
|
|
182
193
|
}
|
|
183
194
|
else {
|
|
@@ -72,6 +72,31 @@ export interface PRCheckMateConfig {
|
|
|
72
72
|
enabled?: boolean;
|
|
73
73
|
minLines?: number;
|
|
74
74
|
minTokens?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Glob patterns excluded from duplicate detection, in addition to the always-on
|
|
77
|
+
* node_modules/dist/.git ignores. Defaults to test files/folders
|
|
78
|
+
* (see DUPLICATE_IGNORE_DEFAULTS). Setting this replaces the default list.
|
|
79
|
+
*/
|
|
80
|
+
ignore?: string[];
|
|
81
|
+
/**
|
|
82
|
+
* jscpd formats to scan. Defaults to source-code formats only
|
|
83
|
+
* (see DUPLICATE_CODE_FORMATS) — data formats like `yaml`, `json` and
|
|
84
|
+
* `markdown` are intentionally NOT scanned, since their repetition is rarely
|
|
85
|
+
* meaningful duplication. Add them back (e.g. `["typescript", "yaml"]`) if you
|
|
86
|
+
* do want to detect duplication in those files. Setting this replaces the list.
|
|
87
|
+
*/
|
|
88
|
+
formats?: string[];
|
|
89
|
+
};
|
|
90
|
+
dependency?: {
|
|
91
|
+
enabled?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Dependency names to exclude from the unused/missing check (depcheck).
|
|
94
|
+
* Supports globs, e.g. "@types/*". Use for packages that are invoked only as
|
|
95
|
+
* CLI binaries or referenced from config — depcheck sees no `import` for them
|
|
96
|
+
* and would otherwise report them as unused. Passed to depcheck's `--ignores`,
|
|
97
|
+
* which takes precedence over any `.depcheckrc` file.
|
|
98
|
+
*/
|
|
99
|
+
ignore?: string[];
|
|
75
100
|
};
|
|
76
101
|
commitlint?: {
|
|
77
102
|
enabled?: boolean;
|
|
@@ -97,33 +122,20 @@ export interface PRCheckMateConfig {
|
|
|
97
122
|
};
|
|
98
123
|
deadCode?: {
|
|
99
124
|
enabled?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Regex sources matched against reported file paths; matching files are
|
|
127
|
+
* dropped from the dead-code report. Use to exempt intentional public
|
|
128
|
+
* surface — a package entry point (`src/index.ts`) or re-export barrels
|
|
129
|
+
* whose exports are consumed by external installers, not within the repo.
|
|
130
|
+
* Applied to the report (not ts-unused-exports' own `--ignoreFiles`), so it
|
|
131
|
+
* never removes a file from analysis and cannot cascade onto other files.
|
|
132
|
+
*/
|
|
133
|
+
ignoreFiles?: string[];
|
|
100
134
|
};
|
|
101
135
|
licenseCheck?: {
|
|
102
136
|
allowPackages?: string[];
|
|
103
137
|
allowLicenses?: string[];
|
|
104
138
|
};
|
|
105
139
|
}
|
|
106
|
-
export interface CheckmateConfig {
|
|
107
|
-
skipLint?: boolean;
|
|
108
|
-
skipDeps?: boolean;
|
|
109
|
-
skipFormat?: boolean;
|
|
110
|
-
skipSpell?: boolean;
|
|
111
|
-
skipSecurity?: boolean;
|
|
112
|
-
skipNpmAudit?: boolean;
|
|
113
|
-
skipCircularDeps?: boolean;
|
|
114
|
-
skipLicense?: boolean;
|
|
115
|
-
skipPrSize?: boolean;
|
|
116
|
-
skipPrTitle?: boolean;
|
|
117
|
-
skipOutdated?: boolean;
|
|
118
|
-
skipMarkdown?: boolean;
|
|
119
|
-
skipTypecheck?: boolean;
|
|
120
|
-
skipDiffSmell?: boolean;
|
|
121
|
-
skipPrBody?: boolean;
|
|
122
|
-
skipDuplicate?: boolean;
|
|
123
|
-
skipDiffSecurity?: boolean;
|
|
124
|
-
skipSensitiveFiles?: boolean;
|
|
125
|
-
skipDeadCode?: boolean;
|
|
126
|
-
autoCommit?: boolean;
|
|
127
|
-
}
|
|
128
140
|
export type { CheckStatus, CheckResult } from '../utils/result-collector';
|
|
129
141
|
export type { Language } from '../utils/detect-language';
|
|
@@ -3,7 +3,6 @@ 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.copyConfigs = copyConfigs;
|
|
7
6
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
8
|
const utils_1 = require("../utils");
|
package/dist/utils/own-deps.js
CHANGED
|
@@ -19,15 +19,19 @@ function readDependencyNames(pkgDir) {
|
|
|
19
19
|
return [];
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Walk up from `startDir` (inclusive) toward the filesystem root, returning the
|
|
24
|
+
* first directory whose package.json declares `name === expectedName`, or null.
|
|
25
|
+
* Broken/missing package.json files are skipped rather than thrown.
|
|
26
|
+
*/
|
|
27
|
+
function findPackageRootByName(startDir, expectedName) {
|
|
28
|
+
let dir = startDir;
|
|
25
29
|
while (dir !== node_path_1.default.dirname(dir)) {
|
|
26
30
|
const pkgJsonPath = node_path_1.default.join(dir, PACKAGE_JSON);
|
|
27
31
|
if (node_fs_1.default.existsSync(pkgJsonPath)) {
|
|
28
32
|
try {
|
|
29
33
|
const pkg = JSON.parse(node_fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
|
|
30
|
-
if (pkg.name ===
|
|
34
|
+
if (pkg.name === expectedName)
|
|
31
35
|
return dir;
|
|
32
36
|
}
|
|
33
37
|
catch { }
|
|
@@ -36,6 +40,10 @@ function findOwnPackageRoot() {
|
|
|
36
40
|
}
|
|
37
41
|
return null;
|
|
38
42
|
}
|
|
43
|
+
/** Walk up from this module until we find pr-checkmate's own package root. */
|
|
44
|
+
function findOwnPackageRoot() {
|
|
45
|
+
return findPackageRootByName(__dirname, OWN_PACKAGE_NAME);
|
|
46
|
+
}
|
|
39
47
|
/**
|
|
40
48
|
* Resolve a dependency's install directory by name, starting the search from
|
|
41
49
|
* `fromDir`. Relies on Node's upward node_modules walk so hoisted packages are
|
|
@@ -50,19 +58,8 @@ function resolvePackageDir(name, fromDir) {
|
|
|
50
58
|
// Fallback for packages whose exports map hides ./package.json: resolve the
|
|
51
59
|
// entry point and walk up to the package's own root.
|
|
52
60
|
try {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const pkgJsonPath = node_path_1.default.join(dir, PACKAGE_JSON);
|
|
56
|
-
if (node_fs_1.default.existsSync(pkgJsonPath)) {
|
|
57
|
-
try {
|
|
58
|
-
const pkg = JSON.parse(node_fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
|
|
59
|
-
if (pkg.name === name)
|
|
60
|
-
return dir;
|
|
61
|
-
}
|
|
62
|
-
catch { }
|
|
63
|
-
}
|
|
64
|
-
dir = node_path_1.default.dirname(dir);
|
|
65
|
-
}
|
|
61
|
+
const entryDir = node_path_1.default.dirname(require.resolve(name, { paths: [fromDir] }));
|
|
62
|
+
return findPackageRootByName(entryDir, name);
|
|
66
63
|
}
|
|
67
64
|
catch { }
|
|
68
65
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pr-checkmate",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.4",
|
|
4
4
|
"description": "Automated PR quality checks: linting, formatting, dependency analysis, and spellcheck",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-actions",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"lint": "eslint \"src/**/*.{ts,tsx}\" --fix",
|
|
47
47
|
"prettier": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
48
48
|
"spellcheck": "cspell '**/*.{ts,tsx,js,jsx,md,json}' --no-progress",
|
|
49
|
+
"docs": "typedoc",
|
|
49
50
|
"scan:secrets": "gitleaks-secret-scanner --diff-mode ci --html-report gitleaks-report.html",
|
|
50
51
|
"test": "echo 'Tests coming soon'",
|
|
51
52
|
"security-scan": "npx pr-checkmate security",
|
|
@@ -99,6 +100,7 @@
|
|
|
99
100
|
"typescript": "^6.0.3"
|
|
100
101
|
},
|
|
101
102
|
"devDependencies": {
|
|
102
|
-
"standard-version": "^9.5.0"
|
|
103
|
+
"standard-version": "^9.5.0",
|
|
104
|
+
"typedoc": "^0.28.20"
|
|
103
105
|
}
|
|
104
106
|
}
|
package/dist/config/config.d.ts
DELETED
package/dist/config/config.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SOURCE_PATH = exports.config = void 0;
|
|
7
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
-
const constants_1 = require("./constants");
|
|
9
|
-
exports.config = node_fs_1.default.existsSync(constants_1.CONFIG_FILE)
|
|
10
|
-
? JSON.parse(node_fs_1.default.readFileSync(constants_1.CONFIG_FILE, 'utf-8'))
|
|
11
|
-
: { sourcePath: 'src' };
|
|
12
|
-
exports.SOURCE_PATH = exports.config.sourcePath;
|