pr-checkmate 1.0.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/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright Β© 2025 Mybono.
2
+ All rights reserved.
3
+
4
+ This software and associated documentation files (the β€œSoftware”) are the exclusive property of the copyright holder.
5
+
6
+ Permission is hereby NOT granted to any person or entity to copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, or use the Software in any manner, unless an explicit written permission is provided by the copyright holder.
7
+
8
+ Any unauthorized use, modification, reproduction, or distribution of the Software is strictly prohibited and may result in civil and criminal penalties.
9
+
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # πŸ” PR CheckMate
2
+
3
+ > **PR CheckMate** is a public npm package for automating Pull Request checks. It helps teams maintain code quality by validating linting, formatting, dependency changes, and spelling before merging to the main branch.
4
+
5
+ ---
6
+
7
+ ## ⚑ Why PR CheckMate?
8
+
9
+ When a PR is opened, it's essential that the code follows project standards. PR CheckMate automatically checks:
10
+
11
+ * βœ… **Linting** β€” TypeScript/JavaScript code compliance with ESLint rules
12
+ * βœ… **Prettier Auto-Format** β€” automatically formats code and commits changes if needed
13
+ * βœ… **Dependency Changes** β€” checks for updates in `package.json`/`package-lock.json` and warns about potential risks
14
+ * βœ… **Spellcheck** β€” checks spelling in code, documentation, and JSON files using `cspell`
15
+
16
+ ---
17
+
18
+ ## πŸ›  How It Works
19
+
20
+ ### 1. Install via npm
21
+
22
+ ```bash
23
+ npm install --save-dev pr_checkmate
24
+ ```
25
+
26
+ ### 2. Run as a CLI command
27
+
28
+ ```bash
29
+ npx pr-checks <job>
30
+ ```
31
+
32
+ **`<job>` options:**
33
+
34
+ | Job | Description |
35
+ |-----|-------------|
36
+ | `lint` | Lint code using ESLint |
37
+ | `prettier` | Format code with Prettier and push changes |
38
+ | `deps` | Check for dependency changes |
39
+ | `spellcheck` | Run spellcheck on source and documentation |
40
+
41
+ ### 3. Use in GitHub Actions
42
+
43
+ Automatically check PRs by adding to your workflow:
44
+
45
+ ```yaml
46
+ jobs:
47
+ pr-checks:
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - uses: actions/setup-node@v3
52
+ with:
53
+ node-version: 20
54
+ - run: npm ci
55
+ - run: npx pr-checks lint
56
+ - run: npx pr-checks prettier
57
+ - run: npx pr-checks deps
58
+ - run: npx pr-checks spellcheck
59
+ ```
60
+
61
+ ---
62
+
63
+ ## 🧰 Tech Stack
64
+
65
+ * **Node.js 20** β€” executes scripts
66
+ * **TypeScript** β€” fully typed code
67
+ * **ESLint + @typescript-eslint** β€” code linting
68
+ * **Prettier** β€” auto-formatting
69
+ * **cspell** β€” spellchecking
70
+ * **execa** β€” running CLI commands from Node.js
71
+
72
+ ---
73
+
74
+ ## πŸ“¦ Features
75
+
76
+ * βœ… Works locally and in CI/CD pipelines (GitHub Actions, GitLab CI, etc.)
77
+ * βœ… Uses a built-in `logger` for console output
78
+ * βœ… Automatically detects the current Git branch and pushes commits after auto-formatting
79
+ * βœ… Self-contained package β€” no external environment variables required
80
+
81
+ ---
82
+
83
+ ## πŸ’» Example Usage in Node.js
84
+
85
+ ```javascript
86
+ import {
87
+ runLint,
88
+ runDependencyCheck,
89
+ runPrettier,
90
+ runSpellcheck
91
+ } from 'pr_checkmate';
92
+
93
+ async function runAllChecks() {
94
+ await runLint();
95
+ await runPrettier();
96
+ await runDependencyCheck();
97
+ await runSpellcheck();
98
+ }
99
+
100
+ runAllChecks();
101
+ ```
102
+
103
+ ---
104
+
105
+ ## πŸ“œ License
106
+
107
+ LicenseRef Proprietary Β© 2025
package/dist/index.js ADDED
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * PR CheckMate - Automated PR quality checks
4
+ *
5
+ * @module pr-checkmate
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.logger = exports.runSpellcheck = exports.runPrettier = exports.runDependencyCheck = exports.runLint = void 0;
42
+ exports.runAllChecks = runAllChecks;
43
+ exports.runChecks = runChecks;
44
+ var lint_1 = require("./scripts/lint");
45
+ Object.defineProperty(exports, "runLint", { enumerable: true, get: function () { return lint_1.runLint; } });
46
+ var dependency_check_1 = require("./scripts/dependency-check");
47
+ Object.defineProperty(exports, "runDependencyCheck", { enumerable: true, get: function () { return dependency_check_1.runDependencyCheck; } });
48
+ var prettier_autoformat_1 = require("./scripts/prettier-autoformat");
49
+ Object.defineProperty(exports, "runPrettier", { enumerable: true, get: function () { return prettier_autoformat_1.runPrettier; } });
50
+ var spellcheck_1 = require("./scripts/spellcheck");
51
+ Object.defineProperty(exports, "runSpellcheck", { enumerable: true, get: function () { return spellcheck_1.runSpellcheck; } });
52
+ var utils_1 = require("./utils");
53
+ Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return utils_1.logger; } });
54
+ /**
55
+ * Run all checks sequentially
56
+ * @returns Promise that resolves when all checks complete
57
+ */
58
+ async function runAllChecks() {
59
+ const { runLint } = await Promise.resolve().then(() => __importStar(require('./scripts/lint')));
60
+ const { runDependencyCheck } = await Promise.resolve().then(() => __importStar(require('./scripts/dependency-check')));
61
+ const { runPrettier } = await Promise.resolve().then(() => __importStar(require('./scripts/prettier-autoformat')));
62
+ const { runSpellcheck } = await Promise.resolve().then(() => __importStar(require('./scripts/spellcheck')));
63
+ await runLint();
64
+ await runDependencyCheck();
65
+ await runSpellcheck();
66
+ await runPrettier(); // Last to commit any fixes
67
+ }
68
+ /**
69
+ * Run checks based on configuration
70
+ */
71
+ async function runChecks(config = {}) {
72
+ const { runLint } = await Promise.resolve().then(() => __importStar(require('./scripts/lint')));
73
+ const { runDependencyCheck } = await Promise.resolve().then(() => __importStar(require('./scripts/dependency-check')));
74
+ const { runPrettier } = await Promise.resolve().then(() => __importStar(require('./scripts/prettier-autoformat')));
75
+ const { runSpellcheck } = await Promise.resolve().then(() => __importStar(require('./scripts/spellcheck')));
76
+ if (!config.skipLint)
77
+ await runLint();
78
+ if (!config.skipDeps)
79
+ await runDependencyCheck();
80
+ if (!config.skipSpell)
81
+ await runSpellcheck();
82
+ if (!config.skipFormat && config.autoCommit)
83
+ await runPrettier();
84
+ }
@@ -0,0 +1,33 @@
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.runDependencyCheck = runDependencyCheck;
7
+ const utils_1 = require("../utils");
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ /**
10
+ * Check for changes in dependency files using CHANGED_FILES env variable.
11
+ */
12
+ // export async function runDependencyCheck(): Promise<void> {
13
+ // try {
14
+ // const changedFiles = process.env.CHANGED_FILES ?? '';
15
+ // if (/package.*\.json/.test(changedFiles)) {
16
+ // logger.warn('[runDependencyCheck]: ⚠️ Dependencies changed!');
17
+ // } else {
18
+ // logger.log('[runDependencyCheck]: βœ… No dependency changes detected.');
19
+ // }
20
+ // } catch (err: unknown) {
21
+ // const errorMessage = err instanceof Error ? err.message : String(err);
22
+ // logger.error('[runDependencyCheck]: ❌ Dependency check failed:', errorMessage);
23
+ // throw err;
24
+ // }
25
+ // }
26
+ async function runDependencyCheck() {
27
+ utils_1.logger.info('Checking dependencies...');
28
+ if (!node_fs_1.default.existsSync('package.json')) {
29
+ utils_1.logger.warn('No package.json β€” skipping');
30
+ return;
31
+ }
32
+ utils_1.logger.info('Dependencies OK');
33
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const lint_1 = require("./lint");
4
+ const dependency_check_1 = require("./dependency-check");
5
+ const prettier_autoformat_1 = require("./prettier-autoformat");
6
+ const spellcheck_1 = require("./spellcheck");
7
+ const utils_1 = require("../utils");
8
+ /**
9
+ * CLI entry point for PR CheckMate.
10
+ *
11
+ * Usage:
12
+ * npx pr-checks <job>
13
+ *
14
+ * Available jobs:
15
+ * all - Run ESLint + Dependency check + Prettier + spellcheck
16
+ * lint - Run ESLint
17
+ * deps - Check for dependency changes
18
+ * prettier - Run Prettier auto-format
19
+ * spellcheck - Run cspell spellcheck
20
+ */
21
+ const job = process.argv[2];
22
+ async function runJob(jobName) {
23
+ switch (jobName) {
24
+ case 'all':
25
+ await (0, lint_1.runLint)();
26
+ await (0, dependency_check_1.runDependencyCheck)();
27
+ await (0, prettier_autoformat_1.runPrettier)();
28
+ await (0, spellcheck_1.runSpellcheck)();
29
+ break;
30
+ case 'lint':
31
+ await (0, lint_1.runLint)();
32
+ break;
33
+ case 'deps':
34
+ await (0, dependency_check_1.runDependencyCheck)();
35
+ break;
36
+ case 'prettier':
37
+ await (0, prettier_autoformat_1.runPrettier)();
38
+ break;
39
+ case 'spellcheck':
40
+ await (0, spellcheck_1.runSpellcheck)();
41
+ break;
42
+ default:
43
+ utils_1.logger.log('[runJob]: Available jobs: lint, deps, prettier, spellcheck');
44
+ }
45
+ }
46
+ runJob(job).catch(err => {
47
+ const message = err instanceof Error ? err.message : String(err);
48
+ throw new Error(`[runJob]: ❌ CLI execution failed: ${message}`);
49
+ });
@@ -0,0 +1,41 @@
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.runLint = runLint;
7
+ const execa_1 = require("execa");
8
+ const utils_1 = require("../utils");
9
+ const node_fs_1 = __importDefault(require("node:fs"));
10
+ // /**
11
+ // * Run ESLint on the project.
12
+ // */
13
+ // export async function runLint(): Promise<void> {
14
+ // try {
15
+ // logger.info('[runLint]: Running ESLint...');
16
+ // // Run ESLint
17
+ // await execa('npm', ['run', 'lint'], { stdio: 'inherit' });
18
+ // logger.log('[runLint]: βœ… ESLint passed successfully.');
19
+ // } catch (err: unknown) {
20
+ // const errorMessage = err instanceof Error ? err.message : String(err);
21
+ // logger.warn(`[runLint]: ⚠️ ESLint found issues: ${errorMessage}`);
22
+ // // Don't throw - allow process to continue
23
+ // }
24
+ // }
25
+ async function runLint() {
26
+ utils_1.logger.info('Running ESLint...');
27
+ const hasLocalConfig = node_fs_1.default.existsSync('eslint.config.mjs') ||
28
+ node_fs_1.default.existsSync('.eslintrc.js') ||
29
+ node_fs_1.default.existsSync('.eslintrc.json');
30
+ const args = hasLocalConfig
31
+ ? ['eslint', '.', '--ext', '.ts,.tsx', '--fix']
32
+ : ['eslint', 'src', '--ext', '.ts', '--fix'];
33
+ try {
34
+ await (0, execa_1.execa)('npx', args, { stdio: 'inherit' });
35
+ utils_1.logger.info('ESLint passed');
36
+ }
37
+ catch (err) {
38
+ utils_1.logger.warn('ESLint issues found');
39
+ throw err;
40
+ }
41
+ }
@@ -0,0 +1,43 @@
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.runPrettier = runPrettier;
7
+ const execa_1 = require("execa");
8
+ const utils_1 = require("../utils");
9
+ const node_fs_1 = __importDefault(require("node:fs"));
10
+ /**
11
+ * Run Prettier formatting inside container.
12
+ * Git commit/push is done on the runner, not in Docker.
13
+ */
14
+ // export async function runPrettier(): Promise<void> {
15
+ // try {
16
+ // logger.info('[runPrettier]: Running Prettier auto-format...');
17
+ // await execa('npm', ['run', 'prettier'], { stdio: 'inherit' });
18
+ // logger.log(
19
+ // '[runPrettier]: βœ… Prettier formatting completed (no git operations inside container)',
20
+ // );
21
+ // } catch (err: unknown) {
22
+ // const errorMessage = err instanceof Error ? err.message : String(err);
23
+ // logger.error('[runPrettier]: ❌ Prettier failed:', errorMessage);
24
+ // throw err;
25
+ // }
26
+ // }
27
+ async function runPrettier() {
28
+ utils_1.logger.info('Running Prettier...');
29
+ const hasConfig = node_fs_1.default.existsSync('.prettierrc') ||
30
+ node_fs_1.default.existsSync('.prettierrc.json') ||
31
+ node_fs_1.default.existsSync('prettier.config.js');
32
+ const pattern = hasConfig ? '.' : 'src';
33
+ try {
34
+ await (0, execa_1.execa)('npx', ['prettier', '--write', `${pattern}/**/*`], {
35
+ stdio: 'inherit',
36
+ });
37
+ utils_1.logger.info('Prettier completed');
38
+ }
39
+ catch (err) {
40
+ utils_1.logger.error('Prettier failed');
41
+ throw err;
42
+ }
43
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSpellcheck = runSpellcheck;
4
+ const execa_1 = require("execa");
5
+ const utils_1 = require("../utils");
6
+ /**
7
+ * Run spellcheck on the project using cspell.
8
+ */
9
+ // export async function runSpellcheck(): Promise<void> {
10
+ // try {
11
+ // logger.info('[runSpellcheck]: Running spellcheck...');
12
+ // await execa('npx', ['cspell', '**/*.{ts,tsx,js,jsx,md,json}', '--no-progress'], {
13
+ // stdio: 'inherit',
14
+ // });
15
+ // logger.log('[runSpellcheck]: βœ… Spellcheck passed successfully.');
16
+ // } catch (err: unknown) {
17
+ // const errorMessage = err instanceof Error ? err.message : String(err);
18
+ // logger.warn(`[runSpellcheck]: ⚠️ Spellcheck found errors: ${errorMessage}`);
19
+ // // Don't throw - allow process to continue
20
+ // }
21
+ // }
22
+ async function runSpellcheck() {
23
+ utils_1.logger.info('Running spellcheck...');
24
+ try {
25
+ await (0, execa_1.execa)('npx', ['cspell', '**/*'], { stdio: 'inherit' });
26
+ utils_1.logger.info('Spellcheck passed');
27
+ }
28
+ catch (err) {
29
+ utils_1.logger.warn('Spellcheck found issues');
30
+ throw err;
31
+ }
32
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./logger"), exports);
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
4
+ class Logger {
5
+ constructor() {
6
+ this.logs = [];
7
+ this.levelOrder = {
8
+ error: 0,
9
+ warn: 1,
10
+ info: 2,
11
+ log: 2,
12
+ debug: 3,
13
+ };
14
+ this.currentLevel = 'info';
15
+ }
16
+ getTimestamp() {
17
+ return new Date().toISOString();
18
+ }
19
+ shouldLog(level) {
20
+ return this.levelOrder[level] <= this.levelOrder[this.currentLevel];
21
+ }
22
+ colorize(level, message) {
23
+ const colors = {
24
+ error: '\x1b[31m', // red
25
+ warn: '\x1b[33m', // yellow
26
+ info: '\x1b[32m', // green
27
+ log: '\x1b[37m', // white
28
+ debug: '\x1b[36m', // cyan
29
+ };
30
+ const reset = '\x1b[0m';
31
+ return `${colors[level]}${message}${reset}`;
32
+ }
33
+ logMessage(level, message, error) {
34
+ if (!this.shouldLog(level))
35
+ return;
36
+ const timestamp = this.getTimestamp();
37
+ const fullMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}` +
38
+ (error instanceof Error ? `\n${error.stack}` : '');
39
+ this.logs.push(fullMessage);
40
+ /* eslint-disable-next-line no-console */
41
+ console.log(this.colorize(level, fullMessage));
42
+ }
43
+ log(msg) {
44
+ this.logMessage('log', msg);
45
+ }
46
+ info(msg) {
47
+ this.logMessage('info', msg);
48
+ }
49
+ warn(msg) {
50
+ this.logMessage('warn', msg);
51
+ }
52
+ error(msg, err) {
53
+ this.logMessage('error', msg, err);
54
+ }
55
+ debug(msg) {
56
+ this.logMessage('debug', msg);
57
+ }
58
+ getLogs() {
59
+ return this.logs;
60
+ }
61
+ clear() {
62
+ this.logs = [];
63
+ }
64
+ }
65
+ exports.logger = new Logger();
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "pr-checkmate",
3
+ "version": "1.0.0",
4
+ "description": "Automated PR quality checks: linting, formatting, dependency analysis, and spellcheck",
5
+ "keywords": [
6
+ "github-actions",
7
+ "pull-request",
8
+ "ci-cd",
9
+ "eslint",
10
+ "prettier",
11
+ "code-quality",
12
+ "automation"
13
+ ],
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "bin": {
17
+ "pr-checkmate": "./dist/scripts/index.js"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "check": "npm run build && npm run lint && npm run prettier && npm run spellcheck",
26
+ "build": "npm run clean && tsc",
27
+ "prepublishOnly": "npm run build",
28
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
29
+ "prettier": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
30
+ "spellcheck": "cspell '**/*.{ts,tsx,js,jsx,md,json}' --no-progress",
31
+ "test": "echo 'Tests coming soon'",
32
+ "clean": "rm -rf dist"
33
+ },
34
+ "engines": {
35
+ "node": ">=18.0.0",
36
+ "npm": ">=8.0.0"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/YOUR_USERNAME/pr-checkmate.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/YOUR_USERNAME/pr-checkmate/issues"
44
+ },
45
+ "homepage": "https://github.com/YOUR_USERNAME/pr-checkmate#readme",
46
+ "author": "Your Name <your.email@example.com>",
47
+ "license": "LicenseRef-Proprietary",
48
+ "devDependencies": {
49
+ "@typescript-eslint/eslint-plugin": "^8.47.0",
50
+ "@typescript-eslint/parser": "^8.47.0",
51
+ "eslint": "^9.39.1",
52
+ "eslint-config-prettier": "^9.1.2",
53
+ "eslint-plugin-import": "^2.29.0",
54
+ "eslint-plugin-prettier": "^5.5.4",
55
+ "prettier": "^3.6.2",
56
+ "ts-node": "^10.9.1",
57
+ "typescript": "^5.2.0",
58
+ "cspell": "^6.30.0",
59
+ "execa": "^7.1.0"
60
+ },
61
+ "dependencies": {
62
+ "dotenv": "^17.2.3"
63
+ },
64
+ "peerDependencies": {
65
+ "eslint": ">=8.0.0",
66
+ "prettier": ">=3.0.0"
67
+ }
68
+ }