@geoql/doctor-core 0.1.0 → 0.1.1
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 +70 -10
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,34 +1,94 @@
|
|
|
1
1
|
# `@geoql/doctor-core`
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> The audit engine behind [`@geoql/vue-doctor`](../vue-doctor) and [`@geoql/nuxt-doctor`](../nuxt-doctor).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This is the library that does the work. The two CLIs are thin `cac` wrappers; everything real lives here: the hybrid scan, scoring, reporters, config loading, and project detection. You usually depend on a CLI, not on this package directly. Reach for `doctor-core` only when you're embedding the audit into your own tool.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
2. **Script pass** — spawns `oxlint` as a subprocess with a generated `.oxlintrc.json` that activates oxlint's built-in `vue` plugin AND a custom `jsPlugins` entry (`@geoql/oxlint-plugin-vue-doctor`).
|
|
7
|
+
## What it does
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
`doctor-core` runs a **hybrid two-pass scan** over a Vue 3 or Nuxt 4 project, as locked in [`docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md):
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
- **Pass 1 — template AST.** Parses `.vue` SFCs with `@vue/compiler-sfc` and walks the template AST in-process. This is the only pass that can see the template, so template-shaped rules (`v-for` missing `:key`, `v-if`/`v-for` on the same node, inline object props in lists) live here.
|
|
12
|
+
- **Pass 2 — script ESTree.** Spawns `oxlint` as a subprocess against a generated `.oxlintrc.json` that turns on oxlint's native `vue` plugin plus the doctor JS plugins (`@geoql/oxlint-plugin-vue-doctor`, `@geoql/oxlint-plugin-nuxt-doctor`). oxlint only hands JS plugins the extracted `<script>`, so all script-level rules run here.
|
|
13
|
+
|
|
14
|
+
Diagnostics from both passes are merged and deduped on `(file, line, column, ruleId)`, then collapsed into a deterministic 0–100 score. Scoring uses fixed severity weights (`error` = 5, `warn` = 2, `info` = 0.5) with √-decay on repeat offenders so one noisy rule can't tank the whole score. Same code in, same score out: no randomness, no config-tunable weights.
|
|
15
|
+
|
|
16
|
+
It also owns the pieces the CLIs surface: the config loader (`doctor.config.ts` via `c12`), project/capability detection used to gate rules, the rule registry, and every reporter format.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npm i @geoql/doctor-core
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Published on [npm](https://www.npmjs.com/package/@geoql/doctor-core) and [JSR](https://jsr.io/@geoql/doctor-core) at `v0.1.0` with provenance. ESM-only. `knip` and `oxlint` are peer dependencies (the dead-code and script passes shell out to them).
|
|
25
|
+
|
|
26
|
+
## API
|
|
27
|
+
|
|
28
|
+
The main entry is `audit()`. It returns a report carrying diagnostics, the numeric score, the score breakdown, detected project info, and a process exit code.
|
|
13
29
|
|
|
14
30
|
```ts
|
|
15
|
-
import { audit } from '@geoql/doctor-core';
|
|
31
|
+
import { audit, format } from '@geoql/doctor-core';
|
|
16
32
|
|
|
17
33
|
const report = await audit({
|
|
18
34
|
rootDir: process.cwd(),
|
|
19
35
|
include: ['**/*.vue', '**/*.ts'],
|
|
36
|
+
exclude: ['node_modules', 'dist', '.nuxt', '.output'],
|
|
20
37
|
failOn: 'error',
|
|
21
38
|
});
|
|
22
39
|
|
|
23
|
-
for (const
|
|
40
|
+
for (const d of report.diagnostics) {
|
|
24
41
|
console.log(
|
|
25
|
-
`${
|
|
42
|
+
`${d.file}:${d.line}:${d.column} ${d.severity} ${d.ruleId}: ${d.message}`,
|
|
26
43
|
);
|
|
27
44
|
}
|
|
45
|
+
|
|
28
46
|
console.log(`Score: ${report.score}/100`);
|
|
47
|
+
console.log(`Exit code: ${report.exitCode}`);
|
|
48
|
+
|
|
49
|
+
// Render any reporter format. `format()` takes a ReporterInput,
|
|
50
|
+
// which you assemble from the report.
|
|
51
|
+
process.stdout.write(
|
|
52
|
+
format(
|
|
53
|
+
{
|
|
54
|
+
toolName: '@geoql/vue-doctor',
|
|
55
|
+
toolVersion: '0.1.0',
|
|
56
|
+
rootDirectory: report.rootDir,
|
|
57
|
+
analyzedFileCount: report.filesScanned,
|
|
58
|
+
elapsedMs: report.elapsedMs,
|
|
59
|
+
diagnostics: report.diagnostics,
|
|
60
|
+
score: report.scoreResult,
|
|
61
|
+
projectInfo: report.projectInfo,
|
|
62
|
+
},
|
|
63
|
+
'agent',
|
|
64
|
+
),
|
|
65
|
+
);
|
|
29
66
|
```
|
|
30
67
|
|
|
31
|
-
|
|
68
|
+
Severity is `error | warn | info` throughout. `failOn` accepts `error | warn | none`.
|
|
69
|
+
|
|
70
|
+
### Key exports
|
|
71
|
+
|
|
72
|
+
| Export | Purpose |
|
|
73
|
+
| ------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
74
|
+
| `audit` | Run the two-pass scan and return the full report. |
|
|
75
|
+
| `format` | Render a report as `agent`, `pretty`, `json`, `json-compact`, `sarif`, or `html`. |
|
|
76
|
+
| `loadDoctorConfig`, `defineConfig`, `mergeCliOverrides` | Load `doctor.config.ts` (via `c12`) and layer CLI overrides on top. |
|
|
77
|
+
| `detectProject` | Detect framework, versions, and capability tokens used to gate rules. |
|
|
78
|
+
| `listRules`, `RULE_REGISTRY`, `loadRuleDoc` | Inspect the rule registry and per-rule docs. |
|
|
79
|
+
| `scoreDiagnostics` | Deterministic 0–100 scoring with the breakdown. |
|
|
80
|
+
| `listChangedFiles` | Resolve diff/staged file scopes for incremental runs. |
|
|
81
|
+
| `encodeAnnotations` | Emit GitHub Actions `::error::` / `::warning::` lines. |
|
|
82
|
+
|
|
83
|
+
Types ship alongside (`AuditConfig`, `AuditReport`, `Diagnostic`, `Severity`, `ReporterFormat`, `ProjectInfo`, `ScoreResult`, and more).
|
|
84
|
+
|
|
85
|
+
## Scope
|
|
86
|
+
|
|
87
|
+
Vue 3 and Nuxt 4 only. Nuxt detection expects the `app/` directory layout with `compatibilityVersion: 4`.
|
|
88
|
+
|
|
89
|
+
## Architecture
|
|
90
|
+
|
|
91
|
+
See [`docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md) for the full two-pass design, the empirical oxlint findings that shaped it, and the canonical `Diagnostic` shape.
|
|
32
92
|
|
|
33
93
|
## License
|
|
34
94
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geoql/doctor-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Audit engine for @geoql/vue-doctor and @geoql/nuxt-doctor. Hybrid two-pass: @vue/compiler-sfc template AST + oxlint subprocess. TypeScript, ESM.",
|
|
6
6
|
"keywords": [
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"picocolors": "^1.1.1",
|
|
52
52
|
"semver": "^7.8.1",
|
|
53
53
|
"tinyglobby": "^0.2.16",
|
|
54
|
-
"@geoql/oxlint-plugin-
|
|
55
|
-
"@geoql/oxlint-plugin-
|
|
54
|
+
"@geoql/oxlint-plugin-vue-doctor": "^0.1.1",
|
|
55
|
+
"@geoql/oxlint-plugin-nuxt-doctor": "0.1.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/node": "^25.9.1",
|