@avinashchby/aireview 0.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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/bin/aireview.js +2 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +79 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config.d.ts +4 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/config.js +78 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/fixer/index.d.ts +4 -0
  13. package/dist/fixer/index.d.ts.map +1 -0
  14. package/dist/fixer/index.js +54 -0
  15. package/dist/fixer/index.js.map +1 -0
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +7 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/parsers/index.d.ts +8 -0
  21. package/dist/parsers/index.d.ts.map +1 -0
  22. package/dist/parsers/index.js +47 -0
  23. package/dist/parsers/index.js.map +1 -0
  24. package/dist/parsers/python-parser.d.ts +4 -0
  25. package/dist/parsers/python-parser.d.ts.map +1 -0
  26. package/dist/parsers/python-parser.js +235 -0
  27. package/dist/parsers/python-parser.js.map +1 -0
  28. package/dist/parsers/typescript-parser.d.ts +4 -0
  29. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  30. package/dist/parsers/typescript-parser.js +300 -0
  31. package/dist/parsers/typescript-parser.js.map +1 -0
  32. package/dist/reporters/ci-reporter.d.ts +4 -0
  33. package/dist/reporters/ci-reporter.d.ts.map +1 -0
  34. package/dist/reporters/ci-reporter.js +49 -0
  35. package/dist/reporters/ci-reporter.js.map +1 -0
  36. package/dist/reporters/index.d.ts +6 -0
  37. package/dist/reporters/index.d.ts.map +1 -0
  38. package/dist/reporters/index.js +15 -0
  39. package/dist/reporters/index.js.map +1 -0
  40. package/dist/reporters/json-reporter.d.ts +4 -0
  41. package/dist/reporters/json-reporter.d.ts.map +1 -0
  42. package/dist/reporters/json-reporter.js +8 -0
  43. package/dist/reporters/json-reporter.js.map +1 -0
  44. package/dist/reporters/text-reporter.d.ts +4 -0
  45. package/dist/reporters/text-reporter.d.ts.map +1 -0
  46. package/dist/reporters/text-reporter.js +110 -0
  47. package/dist/reporters/text-reporter.js.map +1 -0
  48. package/dist/rules/confidence-patterns.d.ts +4 -0
  49. package/dist/rules/confidence-patterns.d.ts.map +1 -0
  50. package/dist/rules/confidence-patterns.js +186 -0
  51. package/dist/rules/confidence-patterns.js.map +1 -0
  52. package/dist/rules/engine.d.ts +19 -0
  53. package/dist/rules/engine.d.ts.map +1 -0
  54. package/dist/rules/engine.js +58 -0
  55. package/dist/rules/engine.js.map +1 -0
  56. package/dist/rules/error-handling.d.ts +4 -0
  57. package/dist/rules/error-handling.d.ts.map +1 -0
  58. package/dist/rules/error-handling.js +162 -0
  59. package/dist/rules/error-handling.js.map +1 -0
  60. package/dist/rules/hallucinated-apis.d.ts +4 -0
  61. package/dist/rules/hallucinated-apis.d.ts.map +1 -0
  62. package/dist/rules/hallucinated-apis.js +196 -0
  63. package/dist/rules/hallucinated-apis.js.map +1 -0
  64. package/dist/rules/index.d.ts +4 -0
  65. package/dist/rules/index.d.ts.map +1 -0
  66. package/dist/rules/index.js +27 -0
  67. package/dist/rules/index.js.map +1 -0
  68. package/dist/rules/phantom-imports.d.ts +4 -0
  69. package/dist/rules/phantom-imports.d.ts.map +1 -0
  70. package/dist/rules/phantom-imports.js +300 -0
  71. package/dist/rules/phantom-imports.js.map +1 -0
  72. package/dist/rules/placeholder-code.d.ts +4 -0
  73. package/dist/rules/placeholder-code.d.ts.map +1 -0
  74. package/dist/rules/placeholder-code.js +113 -0
  75. package/dist/rules/placeholder-code.js.map +1 -0
  76. package/dist/rules/security-antipatterns.d.ts +4 -0
  77. package/dist/rules/security-antipatterns.d.ts.map +1 -0
  78. package/dist/rules/security-antipatterns.js +174 -0
  79. package/dist/rules/security-antipatterns.js.map +1 -0
  80. package/dist/rules/type-safety.d.ts +4 -0
  81. package/dist/rules/type-safety.d.ts.map +1 -0
  82. package/dist/rules/type-safety.js +148 -0
  83. package/dist/rules/type-safety.js.map +1 -0
  84. package/dist/scanner/discovery.d.ts +3 -0
  85. package/dist/scanner/discovery.d.ts.map +1 -0
  86. package/dist/scanner/discovery.js +76 -0
  87. package/dist/scanner/discovery.js.map +1 -0
  88. package/dist/scanner/git-diff.d.ts +8 -0
  89. package/dist/scanner/git-diff.d.ts.map +1 -0
  90. package/dist/scanner/git-diff.js +58 -0
  91. package/dist/scanner/git-diff.js.map +1 -0
  92. package/dist/scanner/index.d.ts +4 -0
  93. package/dist/scanner/index.d.ts.map +1 -0
  94. package/dist/scanner/index.js +110 -0
  95. package/dist/scanner/index.js.map +1 -0
  96. package/dist/types.d.ts +150 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +3 -0
  99. package/dist/types.js.map +1 -0
  100. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Avinash Chaubey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # aireview
2
+
3
+ **Catch what your AI missed.** Static analysis for LLM-generated code -- no API keys, no cloud, no cost.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/aireview.svg)](https://www.npmjs.com/package/aireview)
6
+ [![license](https://img.shields.io/npm/l/aireview.svg)](https://github.com/avinashchaubey/aireview/blob/main/LICENSE)
7
+ [![node](https://img.shields.io/node/v/aireview.svg)](https://nodejs.org)
8
+
9
+ ```bash
10
+ npx aireview .
11
+ ```
12
+
13
+ ```
14
+ src/api.ts (confidence: 42%)
15
+ ✗ 3:1 'openai-functions' is a commonly hallucinated package [phantom-imports]
16
+ | import { createFunction } from 'openai-functions';
17
+
18
+ ✗ 14:5 'fs.readFileAsync' does not exist [hallucinated-apis]
19
+ | const data = await fs.readFileAsync('config.json');
20
+ Fix: Use 'fs.promises.readFile'
21
+
22
+ ✗ 22:0 eval() is a code injection vector [security-antipatterns]
23
+ | const result = eval(userInput);
24
+
25
+ ⚠ 28:1 Hedging comment: "adjust as needed" [confidence-patterns]
26
+ | // adjust as needed for your use case
27
+
28
+ ---
29
+ Scanned 12 files in 38ms
30
+ Found 3 errors, 1 warning
31
+ ```
32
+
33
+ ## Why this exists
34
+
35
+ LLMs write confident-looking code that compiles, passes a glance review, and breaks in production. The failure modes are predictable:
36
+
37
+ - **Phantom imports** -- packages that sound right but don't exist on npm/PyPI
38
+ - **Hallucinated APIs** -- `fs.readFileAsync()`, `array.flatten()`, `dict.has_key()` -- methods that were never real or were removed years ago
39
+ - **Placeholder stubs** -- empty function bodies, `// TODO` comments, `throw new Error("Not implemented")` hidden behind working-looking signatures
40
+ - **Security holes** -- `eval()`, SQL string concatenation, hardcoded API keys -- patterns LLMs reproduce from training data without understanding the risk
41
+ - **Swallowed errors** -- `catch(e) {}`, bare `except:`, `.catch(() => {})` -- silent failure modes that make debugging impossible
42
+
43
+ These patterns are hard to catch in code review because they look intentional. `aireview` knows the specific shapes of LLM mistakes and flags them before they ship.
44
+
45
+ **Zero API calls.** Pure AST parsing and pattern matching. Runs in milliseconds, works offline, costs nothing.
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ npx aireview . # run without installing
51
+ npm install -g aireview # or install globally
52
+ ```
53
+
54
+ Requires Node.js >= 18.
55
+
56
+ ## Usage
57
+
58
+ ```bash
59
+ aireview . # scan current directory
60
+ aireview src/api.ts # scan a specific file
61
+ aireview src/ lib/ # scan multiple paths
62
+ aireview --diff # scan staged git changes
63
+ aireview --diff HEAD~1 # scan last commit
64
+ aireview --ci # CI mode: exit 1 if errors found
65
+ aireview --format json # JSON output for tooling
66
+ aireview --fix # auto-fix safe issues
67
+ aireview --severity error # only errors, skip warnings/info
68
+ aireview --ignore phantom-imports # skip specific rules
69
+ ```
70
+
71
+ ## Detection rules
72
+
73
+ | Rule | Catches | Severity |
74
+ |------|---------|----------|
75
+ | `phantom-imports` | Imports of packages not in your dependency file, known hallucinated package names | warning/error |
76
+ | `hallucinated-apis` | `fs.readFileAsync()`, `array.flatten()`, `new Buffer()`, `dict.has_key()`, 30+ more | error |
77
+ | `placeholder-code` | TODO/FIXME, empty functions, `NotImplementedError`, `// ...` elisions | warning/error |
78
+ | `confidence-patterns` | Generic variable names (`data`, `result`, `temp`), hedging comments, inconsistent style | info/warning |
79
+ | `security-antipatterns` | `eval()`, `new Function()`, SQL injection, hardcoded secrets, disabled TLS | error |
80
+ | `type-safety` | `any` overuse, `as any` casts, `@ts-ignore`, `@ts-nocheck`, loose equality | warning/error |
81
+ | `error-handling` | Empty catch blocks, catch-only-logs, bare `except:`, missing `.catch()` | error/warning |
82
+
83
+ ## Configuration
84
+
85
+ Create `.aireviewrc.json` in your project root:
86
+
87
+ ```json
88
+ {
89
+ "rules": {
90
+ "phantom-imports": "error",
91
+ "hallucinated-apis": "error",
92
+ "placeholder-code": "warn",
93
+ "confidence-patterns": "off",
94
+ "security-antipatterns": "error",
95
+ "type-safety": "warn",
96
+ "error-handling": "error"
97
+ },
98
+ "ignore": ["*.test.ts", "*.spec.js"]
99
+ }
100
+ ```
101
+
102
+ Or add an `"aireview"` key to your `package.json`.
103
+
104
+ ## GitHub Actions
105
+
106
+ ```yaml
107
+ name: AI Code Review
108
+ on: [pull_request]
109
+
110
+ jobs:
111
+ aireview:
112
+ runs-on: ubuntu-latest
113
+ steps:
114
+ - uses: actions/checkout@v4
115
+ with:
116
+ fetch-depth: 0
117
+
118
+ - uses: actions/setup-node@v4
119
+ with:
120
+ node-version: '20'
121
+
122
+ - name: Run aireview
123
+ run: npx aireview --diff origin/main --ci
124
+ ```
125
+
126
+ Findings appear as inline annotations on the PR diff. Use `--format json` to pipe into other tools.
127
+
128
+ ## Programmatic API
129
+
130
+ ```typescript
131
+ import { scan } from 'aireview';
132
+
133
+ const result = await scan({
134
+ paths: ['src/'],
135
+ severity: 'warning',
136
+ ignore: ['confidence-patterns'],
137
+ });
138
+
139
+ for (const file of result.files) {
140
+ console.log(`${file.filePath}: ${file.confidenceScore}% confidence`);
141
+ for (const finding of file.findings) {
142
+ console.log(` ${finding.line}:${finding.column} ${finding.message}`);
143
+ }
144
+ }
145
+ ```
146
+
147
+ ## Supported languages
148
+
149
+ - JavaScript (`.js`, `.jsx`) -- TypeScript compiler API
150
+ - TypeScript (`.ts`, `.tsx`) -- TypeScript compiler API
151
+ - Python (`.py`) -- regex-based parser (no native dependencies)
152
+
153
+ Designed for extensibility. Add a language by implementing a parser that returns `ParserResult` and registering rules.
154
+
155
+ ## License
156
+
157
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/cli.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const commander_1 = require("commander");
4
+ const index_js_1 = require("./scanner/index.js");
5
+ const index_js_2 = require("./reporters/index.js");
6
+ const index_js_3 = require("./fixer/index.js");
7
+ const config_js_1 = require("./config.js");
8
+ /** Create and configure the CLI program. */
9
+ function createProgram() {
10
+ const program = new commander_1.Command();
11
+ program
12
+ .name('aireview')
13
+ .description('Static analysis tool that detects LLM hallucination patterns in code')
14
+ .version('0.1.0')
15
+ .argument('[paths...]', 'paths to scan', ['.'])
16
+ .option('--diff [ref]', 'scan git diff (staged if no ref)')
17
+ .option('--ci', 'CI mode with GitHub Actions annotations')
18
+ .option('--format <format>', 'output format (text or json)', 'text')
19
+ .option('--fix', 'auto-fix issues where possible')
20
+ .option('--severity <level>', 'minimum severity to report (error, warning, info)', 'info')
21
+ .option('--ignore <rules>', 'comma-separated rule IDs to skip')
22
+ .option('--config <path>', 'path to config file')
23
+ .action(runScan);
24
+ return program;
25
+ }
26
+ /** Main scan action handler. */
27
+ async function runScan(paths, opts) {
28
+ const config = await (0, config_js_1.loadConfig)(opts.config);
29
+ const options = buildScanOptions(paths, opts, config);
30
+ const result = await (0, index_js_1.scan)(options);
31
+ if (opts.fix) {
32
+ const fixCount = await (0, index_js_3.applyFixes)(result);
33
+ if (fixCount > 0) {
34
+ console.log(`Applied ${fixCount} fixes.`);
35
+ }
36
+ }
37
+ const format = validateFormat(opts.format);
38
+ const reporter = (0, index_js_2.getReporter)(format, opts.ci ?? false);
39
+ reporter(result);
40
+ if (result.errorCount > 0 && opts.ci) {
41
+ process.exitCode = 1;
42
+ }
43
+ }
44
+ /** Build ScanOptions from CLI args and config. */
45
+ function buildScanOptions(paths, opts, config) {
46
+ const ignoreRules = opts.ignore
47
+ ? opts.ignore.split(',').map((s) => s.trim())
48
+ : [];
49
+ return {
50
+ paths: paths.length > 0 ? paths : ['.'],
51
+ diff: opts.diff,
52
+ ci: opts.ci,
53
+ format: validateFormat(opts.format),
54
+ fix: opts.fix,
55
+ severity: validateSeverity(opts.severity),
56
+ ignore: [...ignoreRules, ...(config.ignore ?? [])],
57
+ config: opts.config,
58
+ };
59
+ }
60
+ /** Validate and return a format option. */
61
+ function validateFormat(format) {
62
+ if (format === 'json')
63
+ return 'json';
64
+ return 'text';
65
+ }
66
+ /** Validate and return a severity option. */
67
+ function validateSeverity(severity) {
68
+ if (severity === 'error' || severity === 'warning' || severity === 'info') {
69
+ return severity;
70
+ }
71
+ return 'info';
72
+ }
73
+ /** Entry point. */
74
+ const program = createProgram();
75
+ program.parseAsync(process.argv).catch((err) => {
76
+ console.error('Fatal error:', err instanceof Error ? err.message : String(err));
77
+ process.exitCode = 1;
78
+ });
79
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AireviewConfig } from './types.js';
2
+ /** Load aireview configuration from file or defaults. */
3
+ export declare function loadConfig(configPath?: string): Promise<AireviewConfig>;
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AASjD,yDAAyD;AACzD,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAgB7E"}
package/dist/config.js ADDED
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadConfig = loadConfig;
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_path_1 = require("node:path");
6
+ const node_fs_1 = require("node:fs");
7
+ const CONFIG_FILENAME = '.aireviewrc.json';
8
+ const DEFAULT_CONFIG = {
9
+ rules: {},
10
+ ignore: [],
11
+ languages: ['javascript', 'typescript', 'python'],
12
+ };
13
+ /** Load aireview configuration from file or defaults. */
14
+ async function loadConfig(configPath) {
15
+ if (configPath) {
16
+ return mergeWithDefaults(await readConfigFile(configPath));
17
+ }
18
+ const found = await findConfigFile(process.cwd());
19
+ if (found) {
20
+ return mergeWithDefaults(await readConfigFile(found));
21
+ }
22
+ const pkgConfig = await loadFromPackageJson(process.cwd());
23
+ if (pkgConfig) {
24
+ return mergeWithDefaults(pkgConfig);
25
+ }
26
+ return { ...DEFAULT_CONFIG };
27
+ }
28
+ /** Read and parse a config file. */
29
+ async function readConfigFile(path) {
30
+ try {
31
+ const content = await (0, promises_1.readFile)(path, 'utf-8');
32
+ return JSON.parse(content);
33
+ }
34
+ catch {
35
+ return {};
36
+ }
37
+ }
38
+ /** Walk up directories looking for .aireviewrc.json. */
39
+ async function findConfigFile(startDir) {
40
+ let dir = startDir;
41
+ const root = (0, node_path_1.dirname)(dir);
42
+ for (let i = 0; i < 20; i++) {
43
+ const candidate = (0, node_path_1.join)(dir, CONFIG_FILENAME);
44
+ if ((0, node_fs_1.existsSync)(candidate))
45
+ return candidate;
46
+ const parent = (0, node_path_1.dirname)(dir);
47
+ if (parent === dir || parent === root)
48
+ break;
49
+ dir = parent;
50
+ }
51
+ return null;
52
+ }
53
+ /** Check package.json for an "aireview" config key. */
54
+ async function loadFromPackageJson(startDir) {
55
+ const pkgPath = (0, node_path_1.join)(startDir, 'package.json');
56
+ if (!(0, node_fs_1.existsSync)(pkgPath))
57
+ return null;
58
+ try {
59
+ const content = await (0, promises_1.readFile)(pkgPath, 'utf-8');
60
+ const pkg = JSON.parse(content);
61
+ if (pkg['aireview'] && typeof pkg['aireview'] === 'object') {
62
+ return pkg['aireview'];
63
+ }
64
+ }
65
+ catch {
66
+ // Ignore parse errors
67
+ }
68
+ return null;
69
+ }
70
+ /** Merge a partial config with defaults. */
71
+ function mergeWithDefaults(partial) {
72
+ return {
73
+ rules: { ...DEFAULT_CONFIG.rules, ...partial.rules },
74
+ ignore: partial.ignore ?? DEFAULT_CONFIG.ignore,
75
+ languages: partial.languages ?? DEFAULT_CONFIG.languages,
76
+ };
77
+ }
78
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ScanResult } from '../types.js';
2
+ /** Apply auto-fixes for findings that have a replacement. Returns count of fixes applied. */
3
+ export declare function applyFixes(result: ScanResult): Promise<number>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixer/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,aAAa,CAAC;AAEvD,6FAA6F;AAC7F,wBAAsB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAYpE"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyFixes = applyFixes;
4
+ const promises_1 = require("node:fs/promises");
5
+ /** Apply auto-fixes for findings that have a replacement. Returns count of fixes applied. */
6
+ async function applyFixes(result) {
7
+ let totalFixed = 0;
8
+ for (const file of result.files) {
9
+ const fixable = getFixableFindings(file.findings);
10
+ if (fixable.length === 0)
11
+ continue;
12
+ const fixed = await applyFixesToFile(file.filePath, fixable);
13
+ totalFixed += fixed;
14
+ }
15
+ return totalFixed;
16
+ }
17
+ /** Get findings that have a fix with a replacement, sorted bottom-up. */
18
+ function getFixableFindings(findings) {
19
+ return findings
20
+ .filter((f) => f.fix?.replacement !== undefined)
21
+ .sort((a, b) => b.line - a.line);
22
+ }
23
+ /** Apply fixes to a single file, processing from bottom to top. */
24
+ async function applyFixesToFile(filePath, findings) {
25
+ let source;
26
+ try {
27
+ source = await (0, promises_1.readFile)(filePath, 'utf-8');
28
+ }
29
+ catch {
30
+ return 0;
31
+ }
32
+ const lines = source.split('\n');
33
+ let applied = 0;
34
+ for (const finding of findings) {
35
+ if (!finding.fix?.replacement === undefined)
36
+ continue;
37
+ const lineIdx = finding.line - 1;
38
+ if (lineIdx < 0 || lineIdx >= lines.length)
39
+ continue;
40
+ const replacement = finding.fix.replacement;
41
+ lines[lineIdx] = applyLineReplacement(lines[lineIdx], finding.column - 1, finding.fix.endColumn ? finding.fix.endColumn - 1 : undefined, replacement);
42
+ applied++;
43
+ }
44
+ if (applied > 0) {
45
+ await (0, promises_1.writeFile)(filePath, lines.join('\n'), 'utf-8');
46
+ }
47
+ return applied;
48
+ }
49
+ /** Apply a replacement to a specific position within a line. */
50
+ function applyLineReplacement(line, startCol, endCol, replacement) {
51
+ const end = endCol ?? line.length;
52
+ return line.slice(0, startCol) + replacement + line.slice(end);
53
+ }
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fixer/index.ts"],"names":[],"mappings":";;AAIA,gCAYC;AAhBD,+CAAuD;AAGvD,6FAA6F;AACtF,KAAK,UAAU,UAAU,CAAC,MAAkB;IACjD,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEnC,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7D,UAAU,IAAI,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,yEAAyE;AACzE,SAAS,kBAAkB,CAAC,QAAmB;IAC7C,OAAO,QAAQ;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,SAAS,CAAC;SAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,mEAAmE;AACnE,KAAK,UAAU,gBAAgB,CAC7B,QAAgB,EAChB,QAAmB;IAEnB,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,KAAK,SAAS;YAAE,SAAS;QACtD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;QACjC,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM;YAAE,SAAS;QAErD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAI,CAAC,WAAY,CAAC;QAC9C,KAAK,CAAC,OAAO,CAAC,GAAG,oBAAoB,CACnC,KAAK,CAAC,OAAO,CAAC,EACd,OAAO,CAAC,MAAM,GAAG,CAAC,EAClB,OAAO,CAAC,GAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAC/D,WAAW,CACZ,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAA,oBAAS,EAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gEAAgE;AAChE,SAAS,oBAAoB,CAC3B,IAAY,EACZ,QAAgB,EAChB,MAA0B,EAC1B,WAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAClC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Programmatic API for aireview. */
2
+ export { scan } from './scanner/index.js';
3
+ export type { Severity, RuleCategory, Language, FixSuggestion, Finding, FileResult, ScanResult, ScanOptions, ParsedImport, FunctionCall, FunctionDecl, Comment, TypeAnnotation, CatchBlock, StringLiteral, ParserResult, Rule, RuleContext, AireviewConfig, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,OAAO,EACP,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scan = void 0;
4
+ /** Programmatic API for aireview. */
5
+ var index_js_1 = require("./scanner/index.js");
6
+ Object.defineProperty(exports, "scan", { enumerable: true, get: function () { return index_js_1.scan; } });
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qCAAqC;AACrC,+CAA0C;AAAjC,gGAAA,IAAI,OAAA"}
@@ -0,0 +1,8 @@
1
+ import type { ParserResult, Language } from '../types.js';
2
+ /** Get the supported file extensions. */
3
+ export declare function getSupportedExtensions(): string[];
4
+ /** Determine the language of a file by its extension. */
5
+ export declare function getLanguage(filePath: string): Language | null;
6
+ /** Parse a source file into a structured ParserResult. */
7
+ export declare function parseFile(source: string, filePath: string): ParserResult;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAoB1D,yCAAyC;AACzC,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD;AAED,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAG7D;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAOxE"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSupportedExtensions = getSupportedExtensions;
4
+ exports.getLanguage = getLanguage;
5
+ exports.parseFile = parseFile;
6
+ const typescript_parser_js_1 = require("./typescript-parser.js");
7
+ const python_parser_js_1 = require("./python-parser.js");
8
+ /** Map of file extensions to their parser functions. */
9
+ const PARSER_MAP = {
10
+ '.ts': typescript_parser_js_1.parseTypeScript,
11
+ '.tsx': typescript_parser_js_1.parseTypeScript,
12
+ '.js': typescript_parser_js_1.parseTypeScript,
13
+ '.jsx': typescript_parser_js_1.parseTypeScript,
14
+ '.py': python_parser_js_1.parsePython,
15
+ };
16
+ /** Map of file extensions to their language identifier. */
17
+ const LANGUAGE_MAP = {
18
+ '.ts': 'typescript',
19
+ '.tsx': 'typescript',
20
+ '.js': 'javascript',
21
+ '.jsx': 'javascript',
22
+ '.py': 'python',
23
+ };
24
+ /** Get the supported file extensions. */
25
+ function getSupportedExtensions() {
26
+ return Object.keys(PARSER_MAP);
27
+ }
28
+ /** Determine the language of a file by its extension. */
29
+ function getLanguage(filePath) {
30
+ const ext = getExtension(filePath);
31
+ return LANGUAGE_MAP[ext] ?? null;
32
+ }
33
+ /** Parse a source file into a structured ParserResult. */
34
+ function parseFile(source, filePath) {
35
+ const ext = getExtension(filePath);
36
+ const parser = PARSER_MAP[ext];
37
+ if (!parser) {
38
+ throw new Error(`Unsupported file extension: ${ext}`);
39
+ }
40
+ return parser(source, filePath);
41
+ }
42
+ /** Extract the file extension from a path. */
43
+ function getExtension(filePath) {
44
+ const match = filePath.match(/\.[^.]+$/);
45
+ return match ? match[0] : '';
46
+ }
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":";;AAuBA,wDAEC;AAGD,kCAGC;AAGD,8BAOC;AAzCD,iEAAyD;AACzD,yDAAiD;AAGjD,wDAAwD;AACxD,MAAM,UAAU,GAAuE;IACrF,KAAK,EAAE,sCAAe;IACtB,MAAM,EAAE,sCAAe;IACvB,KAAK,EAAE,sCAAe;IACtB,MAAM,EAAE,sCAAe;IACvB,KAAK,EAAE,8BAAW;CACnB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,YAAY,GAA6B;IAC7C,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF,yCAAyC;AACzC,SAAgB,sBAAsB;IACpC,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC;AAED,yDAAyD;AACzD,SAAgB,WAAW,CAAC,QAAgB;IAC1C,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC;AAED,0DAA0D;AAC1D,SAAgB,SAAS,CAAC,MAAc,EAAE,QAAgB;IACxD,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,8CAA8C;AAC9C,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ParserResult } from '../types.js';
2
+ /** Parse a Python source file using regex-based extraction. */
3
+ export declare function parsePython(source: string, filePath: string): ParserResult;
4
+ //# sourceMappingURL=python-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/python-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAOV,YAAY,EAEb,MAAM,aAAa,CAAC;AAErB,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAc1E"}