flamerjs 0.1.5 → 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/README.md +72 -32
- package/dist/cli.js +80 -2
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
**A fast sanity checker for AI-assisted codebases.**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/flamerjs)
|
|
8
|
-
[](LICENSE)
|
|
5
|
+
[](https://github.com/dummy3ye/flamer/actions/workflows/ci.yml)
|
|
6
|
+
[](https://codecov.io/gh/dummy3ye/flamer)
|
|
7
|
+
[](https://www.npmjs.com/package/flamerjs)<br>
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://github.com/dummy3ye/flamer/commits/master)
|
|
10
|
+
[](https://github.com/dummy3ye/flamer/stargazers)
|
|
11
|
+
[](https://github.com/dummy3ye/flamer)
|
|
9
12
|
|
|
10
13
|
Flamer scans a repository for the common mistakes that appear when software is
|
|
11
14
|
assembled quickly with AI or other “vibe coding” workflows: unfinished
|
|
@@ -49,68 +52,79 @@ can be used locally, in pull requests, or in CI.
|
|
|
49
52
|
C#, Zig, SQL, notebooks, and additional language profiles.
|
|
50
53
|
- **Stable JSON output:** suitable for CI annotations and other automation.
|
|
51
54
|
- **Single-pass scanning:** files are walked once and content is read once.
|
|
55
|
+
- **Optional native workers:** Rust and C++ workers for isolated file metrics,
|
|
56
|
+
with TypeScript remaining the default engine.
|
|
52
57
|
|
|
53
58
|
## Requirements
|
|
54
59
|
|
|
55
60
|
- Node.js 18 or newer
|
|
56
61
|
- npm
|
|
57
62
|
|
|
63
|
+
The default TypeScript engine needs only Node.js and npm. Native mode additionally
|
|
64
|
+
requires Rust/Cargo for the Rust worker or a C++17 compiler and CMake for the
|
|
65
|
+
C++ worker.
|
|
66
|
+
|
|
58
67
|
## Quick start
|
|
59
68
|
|
|
60
|
-
Run
|
|
69
|
+
Run the published CLI without installing it permanently:
|
|
61
70
|
|
|
62
71
|
```bash
|
|
63
|
-
|
|
64
|
-
npm run build
|
|
65
|
-
node dist/cli.js .
|
|
72
|
+
npx flamerjs .
|
|
66
73
|
```
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
For a project-local installation, add Flamer as a development dependency:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm install --save-dev flamerjs
|
|
79
|
+
npx flamerjs .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or install it globally if you use it across repositories:
|
|
69
83
|
|
|
70
84
|
```bash
|
|
71
85
|
npm install --global flamerjs
|
|
72
86
|
flamerjs .
|
|
73
87
|
```
|
|
74
88
|
|
|
75
|
-
During development, `npm run dev` watches and rebuilds `dist/cli.js`.
|
|
76
89
|
The default output is a colorized terminal summary when run interactively.
|
|
77
90
|
Use `--format json` for automation and machine-readable output.
|
|
78
91
|
|
|
79
92
|
For a human-readable report:
|
|
80
93
|
|
|
81
94
|
```bash
|
|
82
|
-
|
|
95
|
+
flamerjs . --format summary
|
|
83
96
|
```
|
|
84
97
|
|
|
85
98
|
Analyze another repository:
|
|
86
99
|
|
|
87
100
|
```bash
|
|
88
|
-
|
|
101
|
+
flamerjs /path/to/repository --format summary
|
|
89
102
|
```
|
|
90
103
|
|
|
91
104
|
## CLI
|
|
92
105
|
|
|
93
106
|
```text
|
|
94
|
-
|
|
107
|
+
flamerjs [path] [options]
|
|
95
108
|
```
|
|
96
109
|
|
|
97
|
-
| Option
|
|
98
|
-
|
|
|
99
|
-
| `--package, --scope <name>`
|
|
100
|
-
| `--path <dir>`
|
|
101
|
-
| `--format <json\|summary>`
|
|
102
|
-
| `--out <file>`
|
|
103
|
-
| `--fail-on <SEVERITY>`
|
|
104
|
-
| `--max-files <n>`
|
|
105
|
-
| `--commit-limit <n>`
|
|
106
|
-
| `--no-git`
|
|
107
|
-
| `--no-lockfile-warning`
|
|
108
|
-
| `--ignore-dir <name>`
|
|
109
|
-
| `--quiet`
|
|
110
|
-
| `--color`
|
|
111
|
-
| `--no-color`
|
|
112
|
-
| `--
|
|
113
|
-
| `--
|
|
110
|
+
| Option | Description |
|
|
111
|
+
| ------------------------------------- | ----------------------------------------------------------------------------- |
|
|
112
|
+
| `--package, --scope <name>` | Analyze only a named sub-project |
|
|
113
|
+
| `--path <dir>` | Set the repository root; defaults to the current directory |
|
|
114
|
+
| `--format <json\|summary>` | Select JSON or human-readable output; summary is the default |
|
|
115
|
+
| `--out <file>` | Also write the JSON report to a file |
|
|
116
|
+
| `--fail-on <SEVERITY>` | Exit with status 1 at or above `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, or `INFO` |
|
|
117
|
+
| `--max-files <n>` | Limit the number of files scanned |
|
|
118
|
+
| `--commit-limit <n>` | Limit commits inspected by Git checks |
|
|
119
|
+
| `--no-git` | Skip Git analysis |
|
|
120
|
+
| `--no-lockfile-warning` | Suppress the missing-lockfile suggestion |
|
|
121
|
+
| `--ignore-dir <name>` | Ignore an additional directory name; repeatable |
|
|
122
|
+
| `--quiet` | Suppress the human summary |
|
|
123
|
+
| `--color` | Force ANSI colors |
|
|
124
|
+
| `--no-color` | Disable ANSI colors |
|
|
125
|
+
| `--engine <typescript\|native\|auto>` | Select the scan engine; TypeScript is the default |
|
|
126
|
+
| `--list-languages` | List recognized language profiles |
|
|
127
|
+
| `--help` | Show command help |
|
|
114
128
|
|
|
115
129
|
Exit status `0` means the scan completed; findings may still exist. Status `1`
|
|
116
130
|
means `--fail-on` was reached, and status `2` indicates invalid usage or a
|
|
@@ -142,25 +156,51 @@ Findings are sorted by severity. Credential values are always redacted.
|
|
|
142
156
|
|
|
143
157
|
## Development
|
|
144
158
|
|
|
159
|
+
Clone the repository when you want to contribute or work on the scanner itself:
|
|
160
|
+
|
|
145
161
|
```bash
|
|
146
162
|
npm ci
|
|
147
|
-
npm run dev #
|
|
163
|
+
npm run dev # watch and rebuild dist/cli.js
|
|
148
164
|
npm test # run the test suite
|
|
149
165
|
npm run lint
|
|
150
166
|
npm run format:check
|
|
151
167
|
npm run build
|
|
152
168
|
```
|
|
153
169
|
|
|
170
|
+
To run the local build directly:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
node dist/cli.js .
|
|
174
|
+
```
|
|
175
|
+
|
|
154
176
|
The project uses Node.js and npm as its supported development toolchain.
|
|
155
177
|
`package-lock.json` is the canonical dependency lockfile.
|
|
156
178
|
The current test suite contains **175 tests**.
|
|
157
179
|
|
|
180
|
+
### Optional native engine
|
|
181
|
+
|
|
182
|
+
Flamer includes an experimental Rust worker for native file metrics. It is
|
|
183
|
+
disabled by default and does not change findings:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm run native:build
|
|
187
|
+
node dist/cli.js . --engine native
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Use `--engine auto` to fall back to TypeScript when the worker is unavailable.
|
|
191
|
+
The native protocol and worker details are documented in
|
|
192
|
+
[`native/core/README.md`](native/core/README.md).
|
|
193
|
+
|
|
194
|
+
See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the runtime layers,
|
|
195
|
+
worker protocol, engine selection, and native development workflow.
|
|
196
|
+
|
|
158
197
|
## How it works
|
|
159
198
|
|
|
160
199
|
1. Detect the repository layout, languages, and ecosystems.
|
|
161
200
|
2. Walk the tree once and collect file metadata and content-derived signals.
|
|
162
201
|
3. Run isolated analyzers against the collected records.
|
|
163
|
-
4.
|
|
202
|
+
4. Optionally collect native file metrics through the versioned worker protocol.
|
|
203
|
+
5. Sort findings and emit JSON or a concise summary.
|
|
164
204
|
|
|
165
205
|
Analyzers are intentionally factual and conservative. A finding should identify
|
|
166
206
|
something actionable rather than merely express a preference.
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { writeFileSync, existsSync as
|
|
4
|
+
import { writeFileSync, existsSync as existsSync4 } from "fs";
|
|
5
5
|
import { resolve, basename } from "path";
|
|
6
6
|
|
|
7
7
|
// src/util/fs.ts
|
|
@@ -2901,6 +2901,42 @@ var ANALYZERS = [
|
|
|
2901
2901
|
{ id: "systems", label: "Rust / Go / C / C++ / C# / Zig", fn: analyze6 }
|
|
2902
2902
|
];
|
|
2903
2903
|
|
|
2904
|
+
// src/native.ts
|
|
2905
|
+
import { spawnSync } from "child_process";
|
|
2906
|
+
import { existsSync as existsSync3 } from "fs";
|
|
2907
|
+
import { join as join6 } from "path";
|
|
2908
|
+
function nativeWorkerPath(root) {
|
|
2909
|
+
const configured = process.env.FLAMER_CORE;
|
|
2910
|
+
if (configured) return configured;
|
|
2911
|
+
return join6(root, "native", "core", "rust", "target", "release", "flamer-core");
|
|
2912
|
+
}
|
|
2913
|
+
function runNativeMetrics(root, files) {
|
|
2914
|
+
const worker = nativeWorkerPath(root);
|
|
2915
|
+
if (!existsSync3(worker)) {
|
|
2916
|
+
throw new Error(`native worker not found at ${worker}; run npm run native:build`);
|
|
2917
|
+
}
|
|
2918
|
+
const request = JSON.stringify({ protocol: 1, operation: "file_metrics", root, files });
|
|
2919
|
+
const result = spawnSync(worker, { input: `${request}
|
|
2920
|
+
`, encoding: "utf8", timeout: 3e4 });
|
|
2921
|
+
if (result.error) throw new Error(`native worker failed: ${result.error.message}`);
|
|
2922
|
+
if (result.status !== 0) {
|
|
2923
|
+
throw new Error(`native worker exited with status ${result.status}: ${result.stderr.trim()}`);
|
|
2924
|
+
}
|
|
2925
|
+
let response;
|
|
2926
|
+
try {
|
|
2927
|
+
response = JSON.parse(result.stdout);
|
|
2928
|
+
} catch {
|
|
2929
|
+
throw new Error("native worker returned invalid JSON");
|
|
2930
|
+
}
|
|
2931
|
+
if (response.protocol !== 1 || response.operation !== "file_metrics") {
|
|
2932
|
+
throw new Error("native worker returned an incompatible response");
|
|
2933
|
+
}
|
|
2934
|
+
if (!response.ok) {
|
|
2935
|
+
throw new Error(response.errors.map((error) => `${error.path}: ${error.message}`).join("; "));
|
|
2936
|
+
}
|
|
2937
|
+
return response;
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2904
2940
|
// src/cli.ts
|
|
2905
2941
|
var SPEC_VERSION = 1;
|
|
2906
2942
|
function parseArgs(argv) {
|
|
@@ -2918,6 +2954,7 @@ function parseArgs(argv) {
|
|
|
2918
2954
|
listLanguages: false,
|
|
2919
2955
|
help: false,
|
|
2920
2956
|
color: null,
|
|
2957
|
+
engine: "typescript",
|
|
2921
2958
|
ignoreDirs: []
|
|
2922
2959
|
};
|
|
2923
2960
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -2963,6 +3000,14 @@ function parseArgs(argv) {
|
|
|
2963
3000
|
case "--no-color":
|
|
2964
3001
|
opts.color = false;
|
|
2965
3002
|
break;
|
|
3003
|
+
case "--engine":
|
|
3004
|
+
opts.engine = argv[++i] || "typescript";
|
|
3005
|
+
if (!["typescript", "native", "auto"].includes(opts.engine)) {
|
|
3006
|
+
process.stderr.write(`invalid engine: ${opts.engine}
|
|
3007
|
+
`);
|
|
3008
|
+
process.exit(2);
|
|
3009
|
+
}
|
|
3010
|
+
break;
|
|
2966
3011
|
case "--list-languages":
|
|
2967
3012
|
opts.listLanguages = true;
|
|
2968
3013
|
break;
|
|
@@ -3004,6 +3049,8 @@ Options:
|
|
|
3004
3049
|
--quiet suppress the human summary
|
|
3005
3050
|
--color force ANSI colors
|
|
3006
3051
|
--no-color disable ANSI colors
|
|
3052
|
+
--engine <typescript|native|auto>
|
|
3053
|
+
choose the scan engine (default: typescript)
|
|
3007
3054
|
--list-languages print the supported language table
|
|
3008
3055
|
-h, --help show this help
|
|
3009
3056
|
`);
|
|
@@ -3023,7 +3070,7 @@ ${allExtensions().length} file extensions recognized.
|
|
|
3023
3070
|
function run2(opts) {
|
|
3024
3071
|
const started = Date.now();
|
|
3025
3072
|
const root = opts.root;
|
|
3026
|
-
if (!
|
|
3073
|
+
if (!existsSync4(root) || !isDir(root)) {
|
|
3027
3074
|
const err = {
|
|
3028
3075
|
specVersion: SPEC_VERSION,
|
|
3029
3076
|
tool: "flamer",
|
|
@@ -3161,6 +3208,37 @@ function run2(opts) {
|
|
|
3161
3208
|
analyzers: analyzerResults
|
|
3162
3209
|
}
|
|
3163
3210
|
};
|
|
3211
|
+
if (opts.engine !== "typescript") {
|
|
3212
|
+
try {
|
|
3213
|
+
const native = runNativeMetrics(
|
|
3214
|
+
root,
|
|
3215
|
+
scopedFiles.map((file) => file.rel)
|
|
3216
|
+
);
|
|
3217
|
+
report.metadata.native = {
|
|
3218
|
+
engine: "rust",
|
|
3219
|
+
files: native.metrics.files,
|
|
3220
|
+
bytes: native.metrics.bytes,
|
|
3221
|
+
lines: native.metrics.lines,
|
|
3222
|
+
durationMs: native.duration_ms
|
|
3223
|
+
};
|
|
3224
|
+
} catch (error) {
|
|
3225
|
+
const message = error?.message || String(error);
|
|
3226
|
+
if (opts.engine === "native") {
|
|
3227
|
+
findings.push(
|
|
3228
|
+
finding({
|
|
3229
|
+
category: "error",
|
|
3230
|
+
severity: "CRITICAL",
|
|
3231
|
+
title: "Native engine failed",
|
|
3232
|
+
detail: message
|
|
3233
|
+
})
|
|
3234
|
+
);
|
|
3235
|
+
report.findings = sortFindings(findings);
|
|
3236
|
+
report.metadata.native = { engine: "rust", error: message };
|
|
3237
|
+
return { report, exitCode: 2 };
|
|
3238
|
+
}
|
|
3239
|
+
report.metadata.native = { engine: "typescript", fallback: message };
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3164
3242
|
let exitCode = 0;
|
|
3165
3243
|
if (opts.failOn && report.metadata.worst && rank(report.metadata.worst) <= rank(opts.failOn)) {
|
|
3166
3244
|
exitCode = 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flamerjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Language-agnostic code health auditor that walks a repository once and reports what is wrong with it",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsup",
|
|
27
27
|
"dev": "tsup --watch",
|
|
28
|
+
"native:build": "cargo build --release --manifest-path native/core/rust/Cargo.toml",
|
|
29
|
+
"native:test": "cargo test --manifest-path native/core/rust/Cargo.toml",
|
|
28
30
|
"prepublishOnly": "npm run lint && npm run build && npm test",
|
|
29
31
|
"lint": "eslint .",
|
|
30
32
|
"lint:fix": "eslint . --fix",
|