commit-cop 1.0.0 → 1.1.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.
Files changed (74) hide show
  1. package/README.md +98 -20
  2. package/dist/checks/binaryFileCheck.d.ts +3 -0
  3. package/dist/checks/binaryFileCheck.d.ts.map +1 -0
  4. package/dist/checks/binaryFileCheck.js +53 -0
  5. package/dist/checks/binaryFileCheck.js.map +1 -0
  6. package/dist/checks/debuggerCheck.d.ts +3 -0
  7. package/dist/checks/debuggerCheck.d.ts.map +1 -0
  8. package/dist/checks/debuggerCheck.js +28 -0
  9. package/dist/checks/debuggerCheck.js.map +1 -0
  10. package/dist/checks/generatedFolderCheck.d.ts.map +1 -1
  11. package/dist/checks/generatedFolderCheck.js +7 -2
  12. package/dist/checks/generatedFolderCheck.js.map +1 -1
  13. package/dist/checks/junkFileCheck.d.ts +3 -0
  14. package/dist/checks/junkFileCheck.d.ts.map +1 -0
  15. package/dist/checks/junkFileCheck.js +30 -0
  16. package/dist/checks/junkFileCheck.js.map +1 -0
  17. package/dist/checks/lockfileDriftCheck.d.ts +3 -0
  18. package/dist/checks/lockfileDriftCheck.d.ts.map +1 -0
  19. package/dist/checks/lockfileDriftCheck.js +32 -0
  20. package/dist/checks/lockfileDriftCheck.js.map +1 -0
  21. package/dist/checks/mergeConflictCheck.d.ts +3 -0
  22. package/dist/checks/mergeConflictCheck.d.ts.map +1 -0
  23. package/dist/checks/mergeConflictCheck.js +33 -0
  24. package/dist/checks/mergeConflictCheck.js.map +1 -0
  25. package/dist/checks/secretCheck.d.ts.map +1 -1
  26. package/dist/checks/secretCheck.js +15 -4
  27. package/dist/checks/secretCheck.js.map +1 -1
  28. package/dist/checks/sensitiveFilenameCheck.d.ts +3 -0
  29. package/dist/checks/sensitiveFilenameCheck.d.ts.map +1 -0
  30. package/dist/checks/sensitiveFilenameCheck.js +41 -0
  31. package/dist/checks/sensitiveFilenameCheck.js.map +1 -0
  32. package/dist/checks/utils.d.ts +9 -0
  33. package/dist/checks/utils.d.ts.map +1 -0
  34. package/dist/checks/utils.js +48 -0
  35. package/dist/checks/utils.js.map +1 -0
  36. package/dist/index.js +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/scanner.d.ts.map +1 -1
  39. package/dist/scanner.js +14 -2
  40. package/dist/scanner.js.map +1 -1
  41. package/package.json +6 -5
  42. package/src/brand.ts +3 -0
  43. package/src/checks/binaryFileCheck.ts +64 -0
  44. package/src/checks/consoleLogCheck.ts +3 -2
  45. package/src/checks/debuggerCheck.ts +33 -0
  46. package/src/checks/envFileCheck.ts +3 -2
  47. package/src/checks/focusedTestCheck.ts +2 -2
  48. package/src/checks/generatedFolderCheck.ts +13 -5
  49. package/src/checks/junkFileCheck.ts +40 -0
  50. package/src/checks/largeFileCheck.ts +2 -2
  51. package/src/checks/localHostCheck.ts +2 -2
  52. package/src/checks/lockfileDriftCheck.ts +40 -0
  53. package/src/checks/mergeConflictCheck.ts +41 -0
  54. package/src/checks/secretCheck.ts +33 -17
  55. package/src/checks/sensitiveFilenameCheck.ts +51 -0
  56. package/src/checks/utils.ts +62 -0
  57. package/src/fix/debugCode.ts +74 -0
  58. package/src/fix/focusedTests.ts +26 -0
  59. package/src/fix/gitignore.ts +108 -0
  60. package/src/fix/junkFiles.ts +16 -0
  61. package/src/fix/lockfile.ts +23 -0
  62. package/src/fix/matchers.ts +141 -0
  63. package/src/fix/runFix.ts +96 -0
  64. package/src/fix/unstage.ts +25 -0
  65. package/src/fix/utils.ts +50 -0
  66. package/src/git.ts +2 -1
  67. package/src/hook.ts +98 -0
  68. package/src/index.ts +45 -27
  69. package/src/reporter.ts +70 -30
  70. package/src/runScan.ts +35 -0
  71. package/src/scanner.ts +19 -4
  72. package/src/types.ts +5 -0
  73. package/test.ts +5 -1
  74. package/testing.ts +3 -0
package/README.md CHANGED
@@ -1,36 +1,112 @@
1
- # CommitClean
1
+ # Commit Cop
2
2
 
3
- CommitClean is a pre-commit safety checker that scans your **staged files** and warns you about common mistakes before they get pushed to GitHub.
3
+ Commit Cop is a pre-commit safety checker that scans your **staged files** and warns you about common mistakes before they get pushed to GitHub.
4
4
 
5
5
  Built for students, hackathons, and dev teams who want practical guardrails—not just formatting checks.
6
6
 
7
+ > **Commit Cop** (`commit-cop`) — catch bad commits before they hit GitHub.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install commit-cop
13
+ ```
14
+
15
+ ### Run automatically on every commit (recommended)
16
+
17
+ From your Git repo:
18
+
19
+ ```bash
20
+ npx commit-cop install
21
+ ```
22
+
23
+ This adds a pre-commit hook. After that, **Commit Cop runs whenever you `git commit`**. If it finds errors, the commit is blocked.
24
+
25
+ Treat warnings as errors in the hook:
26
+
27
+ ```bash
28
+ npx commit-cop install --strict
29
+ ```
30
+
31
+ Remove the hook:
32
+
33
+ ```bash
34
+ npx commit-cop uninstall
35
+ ```
36
+
37
+ ### Run manually
38
+
39
+ Scan staged changes once:
40
+
41
+ ```bash
42
+ npx commit-cop
43
+ ```
44
+
45
+ Treat warnings as errors:
46
+
47
+ ```bash
48
+ npx commit-cop --strict
49
+ ```
50
+
51
+ Allow `console.log` in staged code (skips the console.log check):
52
+
53
+ ```bash
54
+ npx commit-cop --allow-console-log
55
+ ```
56
+
57
+ ## Auto-fix (work in progress)
58
+
59
+ `wip-fix` is a placeholder command name that applies common repo fixes. More fixes may be added over time.
60
+
61
+ ```bash
62
+ npx commit-cop wip-fix
63
+ ```
64
+
65
+ By default, `wip-fix` does **not** remove `console.log` lines. Pass `--fix-console-log` to include that fix. `debugger` lines are still removed from staged files.
66
+
67
+ ```bash
68
+ npx commit-cop wip-fix --fix-console-log
69
+ ```
70
+
71
+ | Check | Fix |
72
+ | --- | --- |
73
+ | Generated folders / env files | Adds missing `.gitignore` entries (`.env`, `node_modules/`, `dist/`, `build/`, `.next/`, `coverage/`, junk patterns) |
74
+ | Focused tests | Replaces `test.only`, `it.only`, `describe.only` in test/spec files |
75
+ | Debug logs | Removes standalone `console.log(...)` from **staged** JS/TS files only with `--fix-console-log` |
76
+ | Debugger | Always removes standalone `debugger` lines from **staged** JS/TS files |
77
+ | Junk files | Deletes `.DS_Store`, `Thumbs.db`, swap/backup files found on disk |
78
+ | Env / sensitive / generated / junk / binary / large (staged) | Runs `git restore --staged` on matching staged files |
79
+ | Lockfile drift | Runs `npm install` when `package-lock.json` is missing or older than `package.json` |
80
+ | Merge conflicts, secrets, localhost | **Manual only** — reported at the end; not auto-fixed |
81
+
82
+ Review all changes before committing. `wip-fix` may run `npm install` and unstaging commands against your Git index.
83
+
7
84
  ## What it checks
8
85
 
9
86
  | Check | Severity | What it catches |
10
87
  | --- | --- | --- |
88
+ | Merge conflicts | Error | `<<<<<<<`, `=======`, `>>>>>>>` markers left in code |
11
89
  | Environment files | Error | `.env`, `.env.local`, and other `.env.*` files |
12
- | Generated folders | Error | `node_modules/`, `dist/`, `build/`, `.next/`, `coverage/` |
13
- | Secrets | Error | API keys, JWT secrets, database URLs, and similar patterns |
90
+ | Sensitive filenames | Error | Keys, certs, `credentials.json`, `.npmrc`, and similar |
91
+ | Generated folders | Error | `node_modules/`, `dist/`, `build/`, `.next/`, `coverage/` (including nested paths) |
92
+ | Secrets | Error | API keys, GitHub/AWS/Stripe tokens, JWT secrets, database URLs |
14
93
  | Focused tests | Error | `test.only`, `it.only`, `describe.only` left in test files |
15
- | Debug logs | Warning | `console.log` in staged JS/TS code |
94
+ | Debug logs | Warning | `console.log` in staged JS/TS code (skip with `--allow-console-log`) |
95
+ | Debugger statements | Warning | `debugger` in staged JS/TS code |
16
96
  | Localhost URLs | Warning | Hardcoded `localhost` or `127.0.0.1` URLs |
97
+ | Junk files | Warning | `.DS_Store`, `Thumbs.db`, swap/backup files |
98
+ | Lockfile drift | Warning | `package.json` staged without `package-lock.json` (or vice versa) |
17
99
  | Large files | Warning | Staged files over 5 MB |
100
+ | Binary files | Warning | `.zip`, `.exe`, `.mp4`, and other non-text files |
18
101
 
19
102
  Errors block the commit. Warnings are reported but do not block unless you use `--strict`.
20
103
 
21
- ## Usage
22
-
23
- Run inside a Git repository with staged changes:
104
+ ## Local development
24
105
 
25
106
  ```bash
26
107
  npm install
27
- npm run commitclean
28
- ```
29
-
30
- Treat warnings as errors:
31
-
32
- ```bash
33
- npm run commitclean -- --strict
108
+ npm run commit-cop
109
+ npm run commit-cop -- wip-fix
34
110
  ```
35
111
 
36
112
  Build and run the compiled CLI:
@@ -44,19 +120,21 @@ npm start
44
120
 
45
121
  ```
46
122
  src/
47
- index.ts CLI entry point
123
+ index.ts CLI entry point (scan + wip-fix subcommand)
48
124
  git.ts Reads staged files from Git
49
125
  scanner.ts Runs all checks
50
126
  reporter.ts Prints the report
51
127
  types.ts Shared types
52
128
  checks/ One file per check
129
+ fix/ Auto-fix helpers used by wip-fix
53
130
  ```
54
131
 
55
132
  Each check implements the same interface: receive staged files, return findings with a message and suggested fix.
56
133
 
57
134
  ## How it works
58
135
 
59
- 1. Read staged file paths with `git diff --cached --name-only`
60
- 2. Run every check in `src/checks/`
61
- 3. Print a summary with file locations and fix suggestions
62
- 4. Exit with code `1` if errors are found (or warnings in strict mode)
136
+ 1. Install the hook with `npx commit-cop install` (or run manually)
137
+ 2. Read staged file paths with `git diff --cached --name-only`
138
+ 3. Run every check in `src/checks/`
139
+ 4. Print a summary with file locations and fix suggestions
140
+ 5. Exit with code `1` if errors are found (or warnings in strict mode), which blocks the commit
@@ -0,0 +1,3 @@
1
+ import type { Check } from "../types.js";
2
+ export declare const binaryFileCheck: Check;
3
+ //# sourceMappingURL=binaryFileCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binaryFileCheck.d.ts","sourceRoot":"","sources":["../../src/checks/binaryFileCheck.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AA0BlD,eAAO,MAAM,eAAe,EAAE,KAoC7B,CAAC"}
@@ -0,0 +1,53 @@
1
+ import fs from "node:fs";
2
+ import { getBaseName } from "./utils.js";
3
+ const binaryExtensions = new Set([
4
+ ".zip",
5
+ ".exe",
6
+ ".dll",
7
+ ".mp4",
8
+ ".mov",
9
+ ".sqlite",
10
+ ".db",
11
+ ]);
12
+ function hasNullBytes(file) {
13
+ const buffer = fs.readFileSync(file);
14
+ const sampleSize = Math.min(buffer.length, 8192);
15
+ for (let index = 0; index < sampleSize; index += 1) {
16
+ if (buffer[index] === 0) {
17
+ return true;
18
+ }
19
+ }
20
+ return false;
21
+ }
22
+ export const binaryFileCheck = {
23
+ name: "binary-file-check",
24
+ async run(context) {
25
+ const findings = [];
26
+ for (const file of context.stagedFiles) {
27
+ if (!fs.existsSync(file))
28
+ continue;
29
+ const baseName = getBaseName(file);
30
+ const extension = baseName.includes(".")
31
+ ? baseName.slice(baseName.lastIndexOf(".")).toLowerCase()
32
+ : "";
33
+ let isBinary = binaryExtensions.has(extension);
34
+ try {
35
+ isBinary ||= hasNullBytes(file);
36
+ }
37
+ catch {
38
+ continue;
39
+ }
40
+ if (isBinary) {
41
+ findings.push({
42
+ severity: "warning",
43
+ checkName: this.name,
44
+ file,
45
+ message: "Binary or non-text file is staged.",
46
+ suggestion: "Remove it from the commit or store it outside Git (e.g. Git LFS).",
47
+ });
48
+ }
49
+ }
50
+ return findings;
51
+ },
52
+ };
53
+ //# sourceMappingURL=binaryFileCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binaryFileCheck.js","sourceRoot":"","sources":["../../src/checks/binaryFileCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,SAAS;IACT,KAAK;CACN,CAAC,CAAC;AAEH,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEjD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACnD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAU;IACpC,IAAI,EAAE,mBAAmB;IAEzB,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS;YAEnC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;gBACtC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;gBACzD,CAAC,CAAC,EAAE,CAAC;YAEP,IAAI,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAE/C,IAAI,CAAC;gBACH,QAAQ,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,IAAI;oBACJ,OAAO,EAAE,oCAAoC;oBAC7C,UAAU,EACR,mEAAmE;iBACtE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Check } from "../types.js";
2
+ export declare const debuggerCheck: Check;
3
+ //# sourceMappingURL=debuggerCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debuggerCheck.d.ts","sourceRoot":"","sources":["../../src/checks/debuggerCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,aAAa,EAAE,KA4B3B,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { isCodeFile, readFileLines } from "./utils.js";
2
+ export const debuggerCheck = {
3
+ name: "debugger-check",
4
+ async run(context) {
5
+ const findings = [];
6
+ for (const file of context.stagedFiles) {
7
+ if (!isCodeFile(file))
8
+ continue;
9
+ const lines = readFileLines(file);
10
+ if (!lines)
11
+ continue;
12
+ lines.forEach((line, index) => {
13
+ if (/\bdebugger\b/.test(line)) {
14
+ findings.push({
15
+ severity: "warning",
16
+ checkName: this.name,
17
+ file,
18
+ line: index + 1,
19
+ message: "debugger statement found in staged code.",
20
+ suggestion: "Remove debugger statements before committing.",
21
+ });
22
+ }
23
+ });
24
+ }
25
+ return findings;
26
+ },
27
+ };
28
+ //# sourceMappingURL=debuggerCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debuggerCheck.js","sourceRoot":"","sources":["../../src/checks/debuggerCheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,CAAC,MAAM,aAAa,GAAU;IAClC,IAAI,EAAE,gBAAgB;IAEtB,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS;YAEhC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9B,QAAQ,CAAC,IAAI,CAAC;wBACZ,QAAQ,EAAE,SAAS;wBACnB,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,IAAI;wBACJ,IAAI,EAAE,KAAK,GAAG,CAAC;wBACf,OAAO,EAAE,0CAA0C;wBACnD,UAAU,EAAE,+CAA+C;qBAC5D,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"generatedFolderCheck.d.ts","sourceRoot":"","sources":["../../src/checks/generatedFolderCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAUlD,eAAO,MAAM,oBAAoB,EAAE,KA0BlC,CAAC"}
1
+ {"version":3,"file":"generatedFolderCheck.d.ts","sourceRoot":"","sources":["../../src/checks/generatedFolderCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAkBlD,eAAO,MAAM,oBAAoB,EAAE,KA0BlC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { normalizePath } from "./utils.js";
1
2
  const blockedFolders = [
2
3
  "node_modules/",
3
4
  "dist/",
@@ -5,13 +6,17 @@ const blockedFolders = [
5
6
  ".next/",
6
7
  "coverage/",
7
8
  ];
9
+ function matchesBlockedFolder(normalizedPath, folder) {
10
+ return (normalizedPath.startsWith(folder) ||
11
+ normalizedPath.includes(`/${folder}`));
12
+ }
8
13
  export const generatedFolderCheck = {
9
14
  name: "generated-folder-check",
10
15
  async run(context) {
11
16
  const findings = [];
12
17
  for (const file of context.stagedFiles) {
13
- const normalized = file.replaceAll("\\", "/");
14
- const matchedFolder = blockedFolders.find((folder) => normalized.startsWith(folder));
18
+ const normalized = normalizePath(file);
19
+ const matchedFolder = blockedFolders.find((folder) => matchesBlockedFolder(normalized, folder));
15
20
  if (matchedFolder) {
16
21
  findings.push({
17
22
  severity: "error",
@@ -1 +1 @@
1
- {"version":3,"file":"generatedFolderCheck.js","sourceRoot":"","sources":["../../src/checks/generatedFolderCheck.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG;IACrB,eAAe;IACf,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,WAAW;CACZ,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAU;IACzC,IAAI,EAAE,wBAAwB;IAE9B,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAE9C,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACnD,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAC9B,CAAC;YAEF,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,IAAI;oBACJ,OAAO,EAAE,GAAG,aAAa,kEAAkE;oBAC3F,UAAU,EAAE,OAAO,aAAa,gDAAgD,IAAI,EAAE;iBACvF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"generatedFolderCheck.js","sourceRoot":"","sources":["../../src/checks/generatedFolderCheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,cAAc,GAAG;IACrB,eAAe;IACf,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,WAAW;CACZ,CAAC;AAEF,SAAS,oBAAoB,CAAC,cAAsB,EAAE,MAAc;IAClE,OAAO,CACL,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;QACjC,cAAc,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CACtC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAU;IACzC,IAAI,EAAE,wBAAwB;IAE9B,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAEvC,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACnD,oBAAoB,CAAC,UAAU,EAAE,MAAM,CAAC,CACzC,CAAC;YAEF,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,IAAI;oBACJ,OAAO,EAAE,GAAG,aAAa,kEAAkE;oBAC3F,UAAU,EAAE,OAAO,aAAa,gDAAgD,IAAI,EAAE;iBACvF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Check } from "../types.js";
2
+ export declare const junkFileCheck: Check;
3
+ //# sourceMappingURL=junkFileCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"junkFileCheck.d.ts","sourceRoot":"","sources":["../../src/checks/junkFileCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAWlD,eAAO,MAAM,aAAa,EAAE,KA2B3B,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { getBaseName, matchesAnyPattern } from "./utils.js";
2
+ const junkExactNames = new Set([
3
+ ".ds_store",
4
+ "thumbs.db",
5
+ "desktop.ini",
6
+ ]);
7
+ const junkNamePatterns = [/\.swp$/i, /\.bak$/i, /\.tmp$/i, /~$/];
8
+ export const junkFileCheck = {
9
+ name: "junk-file-check",
10
+ async run(context) {
11
+ const findings = [];
12
+ for (const file of context.stagedFiles) {
13
+ const baseName = getBaseName(file);
14
+ const normalizedBaseName = baseName.toLowerCase();
15
+ const isJunk = junkExactNames.has(normalizedBaseName) ||
16
+ matchesAnyPattern(baseName, junkNamePatterns);
17
+ if (isJunk) {
18
+ findings.push({
19
+ severity: "warning",
20
+ checkName: this.name,
21
+ file,
22
+ message: "OS or editor junk file is staged.",
23
+ suggestion: `Run: git restore --staged ${file}`,
24
+ });
25
+ }
26
+ }
27
+ return findings;
28
+ },
29
+ };
30
+ //# sourceMappingURL=junkFileCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"junkFileCheck.js","sourceRoot":"","sources":["../../src/checks/junkFileCheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,WAAW;IACX,WAAW;IACX,aAAa;CACd,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,aAAa,GAAU;IAClC,IAAI,EAAE,iBAAiB;IAEvB,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;YAElD,MAAM,MAAM,GACV,cAAc,CAAC,GAAG,CAAC,kBAAkB,CAAC;gBACtC,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;YAEhD,IAAI,MAAM,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,IAAI;oBACJ,OAAO,EAAE,mCAAmC;oBAC5C,UAAU,EAAE,6BAA6B,IAAI,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Check } from "../types.js";
2
+ export declare const lockfileDriftCheck: Check;
3
+ //# sourceMappingURL=lockfileDriftCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfileDriftCheck.d.ts","sourceRoot":"","sources":["../../src/checks/lockfileDriftCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAOlD,eAAO,MAAM,kBAAkB,EAAE,KA8BhC,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { normalizePath } from "./utils.js";
2
+ function isStaged(stagedFiles, target) {
3
+ return stagedFiles.some((file) => normalizePath(file) === target);
4
+ }
5
+ export const lockfileDriftCheck = {
6
+ name: "lockfile-drift-check",
7
+ async run(context) {
8
+ const findings = [];
9
+ const packageJsonStaged = isStaged(context.stagedFiles, "package.json");
10
+ const lockfileStaged = isStaged(context.stagedFiles, "package-lock.json");
11
+ if (packageJsonStaged && !lockfileStaged) {
12
+ findings.push({
13
+ severity: "warning",
14
+ checkName: this.name,
15
+ file: "package.json",
16
+ message: "package.json is staged but package-lock.json is not.",
17
+ suggestion: "Run npm install and stage package-lock.json.",
18
+ });
19
+ }
20
+ if (lockfileStaged && !packageJsonStaged) {
21
+ findings.push({
22
+ severity: "warning",
23
+ checkName: this.name,
24
+ file: "package-lock.json",
25
+ message: "package-lock.json is staged but package.json is not.",
26
+ suggestion: "Stage package.json or unstage the lockfile.",
27
+ });
28
+ }
29
+ return findings;
30
+ },
31
+ };
32
+ //# sourceMappingURL=lockfileDriftCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfileDriftCheck.js","sourceRoot":"","sources":["../../src/checks/lockfileDriftCheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,SAAS,QAAQ,CAAC,WAAqB,EAAE,MAAc;IACrD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAU;IACvC,IAAI,EAAE,sBAAsB;IAE5B,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;QAE1E,IAAI,iBAAiB,IAAI,CAAC,cAAc,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,SAAS;gBACnB,SAAS,EAAE,IAAI,CAAC,IAAI;gBACpB,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,sDAAsD;gBAC/D,UAAU,EAAE,8CAA8C;aAC3D,CAAC,CAAC;QACL,CAAC;QAED,IAAI,cAAc,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,SAAS;gBACnB,SAAS,EAAE,IAAI,CAAC,IAAI;gBACpB,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,sDAAsD;gBAC/D,UAAU,EAAE,6CAA6C;aAC1D,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Check } from "../types.js";
2
+ export declare const mergeConflictCheck: Check;
3
+ //# sourceMappingURL=mergeConflictCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeConflictCheck.d.ts","sourceRoot":"","sources":["../../src/checks/mergeConflictCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAKlD,eAAO,MAAM,kBAAkB,EAAE,KAkChC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { readFileLines, shouldSkipContentScan } from "./utils.js";
2
+ const conflictMarkers = ["<<<<<<<", "=======", ">>>>>>>"];
3
+ export const mergeConflictCheck = {
4
+ name: "merge-conflict-check",
5
+ async run(context) {
6
+ const findings = [];
7
+ for (const file of context.stagedFiles) {
8
+ if (shouldSkipContentScan(file))
9
+ continue;
10
+ const lines = readFileLines(file);
11
+ if (!lines)
12
+ continue;
13
+ lines.forEach((line, index) => {
14
+ const trimmed = line.trim();
15
+ for (const marker of conflictMarkers) {
16
+ if (trimmed.startsWith(marker)) {
17
+ findings.push({
18
+ severity: "error",
19
+ checkName: this.name,
20
+ file,
21
+ line: index + 1,
22
+ message: "Merge conflict marker found in staged file.",
23
+ suggestion: "Resolve the conflict, remove the markers, and restage the file.",
24
+ });
25
+ return;
26
+ }
27
+ }
28
+ });
29
+ }
30
+ return findings;
31
+ },
32
+ };
33
+ //# sourceMappingURL=mergeConflictCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeConflictCheck.js","sourceRoot":"","sources":["../../src/checks/mergeConflictCheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,kBAAkB,GAAU;IACvC,IAAI,EAAE,sBAAsB;IAE5B,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,qBAAqB,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE1C,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAE5B,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;oBACrC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;wBAC/B,QAAQ,CAAC,IAAI,CAAC;4BACZ,QAAQ,EAAE,OAAO;4BACjB,SAAS,EAAE,IAAI,CAAC,IAAI;4BACpB,IAAI;4BACJ,IAAI,EAAE,KAAK,GAAG,CAAC;4BACf,OAAO,EAAE,6CAA6C;4BACtD,UAAU,EACR,iEAAiE;yBACpE,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"secretCheck.d.ts","sourceRoot":"","sources":["../../src/checks/secretCheck.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAYlD,eAAO,MAAM,WAAW,EAAE,KA8BzB,CAAC"}
1
+ {"version":3,"file":"secretCheck.d.ts","sourceRoot":"","sources":["../../src/checks/secretCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAyBlD,eAAO,MAAM,WAAW,EAAE,KAkCzB,CAAC"}
@@ -1,4 +1,4 @@
1
- import fs from "node:fs";
1
+ import { isCommentLine, isPlaceholderValue, readFileLines, shouldSkipContentScan, } from "./utils.js";
2
2
  const secretPatterns = [
3
3
  /OPENAI_API_KEY\s*=/i,
4
4
  /DATABASE_URL\s*=/i,
@@ -7,17 +7,27 @@ const secretPatterns = [
7
7
  /PRIVATE_KEY\s*=/i,
8
8
  /SECRET_KEY\s*=/i,
9
9
  /sk-[A-Za-z0-9_-]{20,}/,
10
+ /ghp_[A-Za-z0-9]{36,}/,
11
+ /github_pat_[A-Za-z0-9_]+/,
12
+ /AKIA[0-9A-Z]{16}/,
13
+ /sk_live_[A-Za-z0-9]+/,
14
+ /AIza[0-9A-Za-z_-]{35}/,
15
+ /hooks\.slack\.com\/services\//,
16
+ /password\s*=\s*['"][^'"]{8,}['"]/i,
10
17
  ];
11
18
  export const secretCheck = {
12
19
  name: "secret-check",
13
20
  async run(context) {
14
21
  const findings = [];
15
22
  for (const file of context.stagedFiles) {
16
- if (!fs.existsSync(file))
23
+ if (shouldSkipContentScan(file))
24
+ continue;
25
+ const lines = readFileLines(file);
26
+ if (!lines)
17
27
  continue;
18
- const content = fs.readFileSync(file, "utf-8");
19
- const lines = content.split("\n");
20
28
  lines.forEach((line, index) => {
29
+ if (isCommentLine(line) || isPlaceholderValue(line))
30
+ return;
21
31
  for (const pattern of secretPatterns) {
22
32
  if (pattern.test(line)) {
23
33
  findings.push({
@@ -28,6 +38,7 @@ export const secretCheck = {
28
38
  message: "Possible secret found in staged file.",
29
39
  suggestion: "Remove the secret and rotate it if it was already pushed.",
30
40
  });
41
+ return;
31
42
  }
32
43
  }
33
44
  });
@@ -1 +1 @@
1
- {"version":3,"file":"secretCheck.js","sourceRoot":"","sources":["../../src/checks/secretCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzB,MAAM,cAAc,GAAG;IACrB,qBAAqB;IACrB,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;IAClB,iBAAiB;IACjB,uBAAuB;CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,IAAI,EAAE,cAAc;IAEpB,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS;YAEnC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAElC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;oBACrC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC;4BACZ,QAAQ,EAAE,OAAO;4BACjB,SAAS,EAAE,IAAI,CAAC,IAAI;4BACpB,IAAI;4BACJ,IAAI,EAAE,KAAK,GAAG,CAAC;4BACf,OAAO,EAAE,uCAAuC;4BAChD,UAAU,EAAE,2DAA2D;yBACxE,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"secretCheck.js","sourceRoot":"","sources":["../../src/checks/secretCheck.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,cAAc,GAAG;IACrB,qBAAqB;IACrB,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;IAClB,iBAAiB;IACjB,uBAAuB;IACvB,sBAAsB;IACtB,0BAA0B;IAC1B,kBAAkB;IAClB,sBAAsB;IACtB,uBAAuB;IACvB,+BAA+B;IAC/B,mCAAmC;CACpC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,IAAI,EAAE,cAAc;IAEpB,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,qBAAqB,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE1C,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAE5D,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;oBACrC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC;4BACZ,QAAQ,EAAE,OAAO;4BACjB,SAAS,EAAE,IAAI,CAAC,IAAI;4BACpB,IAAI;4BACJ,IAAI,EAAE,KAAK,GAAG,CAAC;4BACf,OAAO,EAAE,uCAAuC;4BAChD,UAAU,EACR,2DAA2D;yBAC9D,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Check } from "../types.js";
2
+ export declare const sensitiveFilenameCheck: Check;
3
+ //# sourceMappingURL=sensitiveFilenameCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitiveFilenameCheck.d.ts","sourceRoot":"","sources":["../../src/checks/sensitiveFilenameCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,aAAa,CAAC;AAmBlD,eAAO,MAAM,sBAAsB,EAAE,KA8BpC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { getBaseName, matchesAnyPattern, normalizePath } from "./utils.js";
2
+ const sensitiveExactNames = new Set([
3
+ "id_rsa",
4
+ "id_ed25519",
5
+ "credentials.json",
6
+ "serviceaccountkey.json",
7
+ ".npmrc",
8
+ ".pypirc",
9
+ ]);
10
+ const sensitiveNamePatterns = [
11
+ /\.pem$/i,
12
+ /\.p12$/i,
13
+ /\.key$/i,
14
+ /^firebase-adminsdk.*\.json$/i,
15
+ ];
16
+ export const sensitiveFilenameCheck = {
17
+ name: "sensitive-filename-check",
18
+ async run(context) {
19
+ const findings = [];
20
+ for (const file of context.stagedFiles) {
21
+ const baseName = getBaseName(file);
22
+ const normalizedBaseName = baseName.toLowerCase();
23
+ const normalizedPath = normalizePath(file).toLowerCase();
24
+ const isSensitive = sensitiveExactNames.has(normalizedBaseName) ||
25
+ matchesAnyPattern(baseName, sensitiveNamePatterns) ||
26
+ normalizedPath.endsWith("/credentials.json") ||
27
+ normalizedPath.includes("serviceaccountkey.json");
28
+ if (isSensitive) {
29
+ findings.push({
30
+ severity: "error",
31
+ checkName: this.name,
32
+ file,
33
+ message: "Sensitive credential file is staged.",
34
+ suggestion: `Run: git restore --staged ${file}`,
35
+ });
36
+ }
37
+ }
38
+ return findings;
39
+ },
40
+ };
41
+ //# sourceMappingURL=sensitiveFilenameCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitiveFilenameCheck.js","sourceRoot":"","sources":["../../src/checks/sensitiveFilenameCheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3E,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,QAAQ;IACR,YAAY;IACZ,kBAAkB;IAClB,wBAAwB;IACxB,QAAQ;IACR,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG;IAC5B,SAAS;IACT,SAAS;IACT,SAAS;IACT,8BAA8B;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAU;IAC3C,IAAI,EAAE,0BAA0B;IAEhC,KAAK,CAAC,GAAG,CAAC,OAAO;QACf,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;YAClD,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAEzD,MAAM,WAAW,GACf,mBAAmB,CAAC,GAAG,CAAC,kBAAkB,CAAC;gBAC3C,iBAAiB,CAAC,QAAQ,EAAE,qBAAqB,CAAC;gBAClD,cAAc,CAAC,QAAQ,CAAC,mBAAmB,CAAC;gBAC5C,cAAc,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;YAEpD,IAAI,WAAW,EAAE,CAAC;gBAChB,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,IAAI;oBACJ,OAAO,EAAE,sCAAsC;oBAC/C,UAAU,EAAE,6BAA6B,IAAI,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare function normalizePath(file: string): string;
2
+ export declare function getBaseName(file: string): string;
3
+ export declare function isCodeFile(file: string): boolean;
4
+ export declare function shouldSkipContentScan(file: string): boolean;
5
+ export declare function readFileLines(file: string): string[] | null;
6
+ export declare function isCommentLine(line: string): boolean;
7
+ export declare function isPlaceholderValue(line: string): boolean;
8
+ export declare function matchesAnyPattern(value: string, patterns: RegExp[]): boolean;
9
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/checks/utils.ts"],"names":[],"mappings":"AAgBA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAQ3D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAET"}
@@ -0,0 +1,48 @@
1
+ import fs from "node:fs";
2
+ const CODE_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx"];
3
+ const SKIP_CONTENT_EXTENSIONS = [".md", ".example", ".sample"];
4
+ const PLACEHOLDER_PATTERNS = [
5
+ /your-api-key/i,
6
+ /changeme/i,
7
+ /xxx+/i,
8
+ /TODO/i,
9
+ /placeholder/i,
10
+ /example/i,
11
+ /replace-me/i,
12
+ ];
13
+ export function normalizePath(file) {
14
+ return file.replaceAll("\\", "/");
15
+ }
16
+ export function getBaseName(file) {
17
+ return normalizePath(file).split("/").pop() ?? "";
18
+ }
19
+ export function isCodeFile(file) {
20
+ return CODE_EXTENSIONS.some((ext) => file.endsWith(ext));
21
+ }
22
+ export function shouldSkipContentScan(file) {
23
+ return SKIP_CONTENT_EXTENSIONS.some((ext) => file.endsWith(ext));
24
+ }
25
+ export function readFileLines(file) {
26
+ if (!fs.existsSync(file))
27
+ return null;
28
+ try {
29
+ return fs.readFileSync(file, "utf-8").split("\n");
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ export function isCommentLine(line) {
36
+ const trimmed = line.trim();
37
+ return (trimmed.startsWith("//") ||
38
+ trimmed.startsWith("#") ||
39
+ trimmed.startsWith("*") ||
40
+ trimmed.startsWith("/*"));
41
+ }
42
+ export function isPlaceholderValue(line) {
43
+ return PLACEHOLDER_PATTERNS.some((pattern) => pattern.test(line));
44
+ }
45
+ export function matchesAnyPattern(value, patterns) {
46
+ return patterns.some((pattern) => pattern.test(value));
47
+ }
48
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/checks/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAEvD,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAE/D,MAAM,oBAAoB,GAAG;IAC3B,eAAe;IACf,WAAW;IACX,OAAO;IACP,OAAO;IACP,cAAc;IACd,UAAU;IACV,aAAa;CACd,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,CACL,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QACxB,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACvB,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACvB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,QAAkB;IAElB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACzD,CAAC"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { runChecks } from "./scanner.js";
5
5
  import { printReport } from "./reporter.js";
6
6
  const program = new Command();
7
7
  program
8
- .name("commitclean")
8
+ .name("commit-cop")
9
9
  .description("Pre-commit safety checker for staged files")
10
10
  .option("--strict", "Treat warnings as errors")
11
11
  .action(async (options) => {