@amritk/lint 0.5.1 → 0.5.3
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 +18 -10
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -193,7 +193,7 @@ A ruleset is a plain object (authored as YAML, JSON, or a JS module):
|
|
|
193
193
|
|
|
194
194
|
| Field | Description |
|
|
195
195
|
| --- | --- |
|
|
196
|
-
| `rules` | Map of `name → rule`. A rule has `given` (one or more JSONPath expressions), `then` (a function to run, or a list), `severity` (`error`/`warn`/`info`/`hint`/`off`), and optional `message`, `description`, `formats`, `recommended`. |
|
|
196
|
+
| `rules` | Map of `name → rule`. A rule has `given` (one or more JSONPath expressions), `then` (a function to run, or a list), `severity` (`error`/`warn`/`info`/`hint`/`off`), and optional `message`, `description`, `formats`, `recommended`, `resolved` (default `true`; `false` runs the rule against the document as written, before `$ref` dereferencing), and `documentationUrl`. |
|
|
197
197
|
| `then` | `{ function, field?, functionOptions? }` — `field` narrows the match to a child (`@key` targets the property name). |
|
|
198
198
|
| `extends` | A ruleset (or list) to inherit rules from: a file path or npm package. `[target, 'recommended' \| 'all' \| 'off']` controls what it contributes. |
|
|
199
199
|
| `functions` / `functionsDir` | Custom functions to load by name (default dir `functions/`). |
|
|
@@ -230,7 +230,7 @@ Anything outside that grammar is a ruleset error (`createRuleset` throws and nam
|
|
|
230
230
|
| `resolveNamedRuleset(name, basePath?, options?)` | Resolve an `extends` reference (file path or npm package) to its definition. |
|
|
231
231
|
| `builtinFunctions` | The registry of built-in rule functions. |
|
|
232
232
|
|
|
233
|
-
The engine internals (`createDocument`, `lint`, `query`, `validateRuleset`, `parseWithPointers`, `createFixPlugin`, `DiagnosticSeverity
|
|
233
|
+
The engine internals (`createDocument`, `lint`, `lintWithResult`, `query`, `validateRuleset`, `parseWithPointers`, `createFixPlugin`, …) are re-exported from the package root for advanced use; `DiagnosticSeverity` and the rule/diagnostic types (`IDiagnostic`, `RulesetDefinition`, `IRuleDefinition`, …) live on the `@amritk/lint/types` subpath.
|
|
234
234
|
|
|
235
235
|
---
|
|
236
236
|
|
|
@@ -259,7 +259,7 @@ const findings = await lint(spec, { ruleset })
|
|
|
259
259
|
| `oasFixers` | Auto-fixers for the mechanically-repairable OpenAPI rules (pass to `fixDocument` alongside a built OpenAPI ruleset). |
|
|
260
260
|
| `loadOasSchema(version)` | Lazily load one OpenAPI version's official structural meta-schema (`'2.0'` / `'3.0'` / `'3.1'` / `'3.2'`), vendored as raw `.json` from `spec.openapis.org` (3.0/3.1/3.2 verbatim; 2.0 with its external draft-04 metaschema refs inlined). See [`schemas/README.md`](./src/rules/openapi/schemas/README.md). |
|
|
261
261
|
|
|
262
|
-
The structural rules validate against the **official `spec.openapis.org` meta-schemas, vendored as raw `.json`** ([`schemas/`](./src/rules/openapi/schemas/)). 3.0/3.1/3.2 are byte-for-byte verbatim; only 2.0 differs (its external draft-04 metaschema refs are inlined, since the offline interpreter never fetches remote refs). OpenAPI 3.1/3.2 express Schema Objects as JSON Schema 2020-12 via a local `$dynamicRef`/`$dynamicAnchor`, which `@amritk/runtime-validators` resolves natively — so the whole document envelope is validated against the official schema with no bundling or dialect engine, while Schema Object internals stay permissive.
|
|
262
|
+
The structural rules validate against the **official `spec.openapis.org` meta-schemas, vendored as raw `.json`** ([`schemas/`](./src/rules/openapi/schemas/)). 3.0/3.1/3.2 are byte-for-byte verbatim; only 2.0 differs (its external draft-04 metaschema refs are inlined, since the offline interpreter never fetches remote refs, and its top-level `id`/`$schema` keys are dropped). OpenAPI 3.1/3.2 express Schema Objects as JSON Schema 2020-12 via a local `$dynamicRef`/`$dynamicAnchor`, which `@amritk/runtime-validators` resolves natively — so the whole document envelope is validated against the official schema with no bundling or dialect engine, while Schema Object internals stay permissive.
|
|
263
263
|
|
|
264
264
|
`$ref` resolution stays the caller's job: the preset doesn't pull in a resolver, so for rules that need the dereferenced document (`resolved: true`) pass a `resolve` function to the core `lintWithResult` (for example wrapping [`@amritk/resolve-refs`](../resolve-refs)). The `mjst lint` CLI already wires one up.
|
|
265
265
|
|
|
@@ -300,13 +300,21 @@ Structural validation runs **once per document, against the document as written*
|
|
|
300
300
|
|
|
301
301
|
## Benchmarks
|
|
302
302
|
|
|
303
|
-
The `bench/` suite pits `@amritk/lint` head-to-head against **[Spectral](https://github.com/stoplightio/spectral)** — the OpenAPI linter this package is modelled on (hence the `spectral:oas` alias) — over the real-world specs the test suite lints: Swagger's petstore, the DigitalOcean API, and the OpenAI API (~17 KB to ~2.8 MB, spanning a small config and a genuinely large document). Both do the same job: **parse → dereference internal `$ref`s → run their recommended OpenAPI ruleset** (mjst dereferences in memory with [`@amritk/resolve-refs`](../resolve-refs), exactly as the CLI does; Spectral uses its own default resolver).
|
|
303
|
+
The `bench/` suite pits `@amritk/lint` head-to-head against **[Spectral](https://github.com/stoplightio/spectral)** — the OpenAPI linter this package is modelled on (hence the `spectral:oas` alias) — over the real-world specs the test suite lints: Swagger's petstore, the DigitalOcean API, and the OpenAI API (~17 KB to ~2.8 MB, spanning a small config and a genuinely large document). Both do the same job: **parse → dereference internal `$ref`s → run their recommended OpenAPI ruleset** (mjst dereferences in memory with [`@amritk/resolve-refs`](../resolve-refs), exactly as the CLI does; Spectral uses its own default resolver). Medians of three runs on each runtime, one machine (Linux x64, a 4-vCPU cloud box, Bun 1.4.0 and Node 26.8.1 — your hardware will differ, run `bun run bench` or `bun run bench:node` yourself):
|
|
304
304
|
|
|
305
|
-
| document | size | mjst | Spectral | speedup | findings (mjst / Spectral) |
|
|
306
|
-
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
307
|
-
| petstore (Swagger) | 17 KB | ~
|
|
308
|
-
|
|
|
309
|
-
|
|
|
305
|
+
| document | size | runtime | mjst | Spectral | speedup | findings (mjst / Spectral) |
|
|
306
|
+
| --- | ---: | --- | ---: | ---: | ---: | ---: |
|
|
307
|
+
| petstore (Swagger) | 17 KB | Bun | ~4 ms | ~87 ms | **~21×** | 2 / 2 |
|
|
308
|
+
| petstore (Swagger) | 17 KB | Node | ~5 ms | ~50 ms | **~9.5×** | 2 / 2 |
|
|
309
|
+
| digitalocean | 105 KB | Bun | ~25 ms | ~318 ms | **~13×** | 2411 / 4319 |
|
|
310
|
+
| digitalocean | 105 KB | Node | ~23 ms | ~276 ms | **~12×** | 2411 / 4319 |
|
|
311
|
+
| openai | 2.8 MB | Bun | ~0.65 s | ~7.9 s | **~12×** | 587 / 474 |
|
|
312
|
+
| openai | 2.8 MB | Node | ~0.75 s | ~5.5 s | **~7.3×** | 587 / 474 |
|
|
313
|
+
|
|
314
|
+
The lead is smaller on Node throughout, and for the same reason in every row:
|
|
315
|
+
Spectral runs materially faster on V8 than on JavaScriptCore — a third quicker
|
|
316
|
+
on the OpenAI spec — while this linter is close to even between the two. The
|
|
317
|
+
ratio is the thing that moves, not our side of it.
|
|
310
318
|
|
|
311
319
|
An earlier revision of this table reported the OpenAI row as mjst-only, because
|
|
312
320
|
Spectral's JSONPath engine (`nimma`) threw on that spec under Bun. It no longer
|
|
@@ -316,7 +324,7 @@ runtime-specific and may come back.
|
|
|
316
324
|
|
|
317
325
|
Each `lint` figure is the mean wall time of one whole pass — **every rule, not a subset** — dominated by real work: JSONPath matching, the rule functions, and the dereference pass. A fresh document is parsed on every iteration on both sides, matching how the tools are actually called. The finding counts differ because the two rulesets are not byte-identical (different rule implementations and `$ref` resolution), so this is a **throughput** comparison rather than a correctness parity check — but on petstore both land on the same two findings.
|
|
318
326
|
|
|
319
|
-
**Assembling the ruleset** is timed separately, because a process pays it once and then lints many documents: `createOpenApiRuleset` (compiling every rule's JSONPath and wiring up functions and format detectors) measures **~0.07 ms
|
|
327
|
+
**Assembling the ruleset** is timed separately, because a process pays it once and then lints many documents: `createOpenApiRuleset` (compiling every rule's JSONPath and wiring up functions and format detectors) measures **~0.07 ms** on Bun and **~0.06 ms** on Node, versus **~0.26 ms** and **~0.24 ms** for `new Spectral()` + `setRuleset(oas)`. The benchmark warms up before timing and reports the mean over a fixed time budget; micro-benchmark figures vary by machine and runtime.
|
|
320
328
|
|
|
321
329
|
---
|
|
322
330
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amritk/lint",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "A fast, format-agnostic JSON/YAML style-guide linter with JSON Schema and custom rules.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -44,8 +44,10 @@
|
|
|
44
44
|
"prepublishOnly": "node ../../scripts/check-publishable.mjs",
|
|
45
45
|
"types:check": "tsgo -p . --noEmit",
|
|
46
46
|
"test": "NODE_ENV=production vitest run --root ../.. packages/lint/",
|
|
47
|
-
"prebench": "bun run --filter='@amritk/runtime-validators' --filter='@amritk/yaml' --filter='@amritk/resolve-refs' build",
|
|
48
|
-
"bench": "bun run ./bench/run.ts"
|
|
47
|
+
"prebench": "bun run build && bun run --filter='@amritk/runtime-validators' --filter='@amritk/yaml' --filter='@amritk/resolve-refs' build",
|
|
48
|
+
"bench": "bun run ./bench/run.ts",
|
|
49
|
+
"prebench:node": "bun run build && bun run --filter='@amritk/runtime-validators' --filter='@amritk/yaml' --filter='@amritk/resolve-refs' build",
|
|
50
|
+
"bench:node": "node ./bench/run.ts"
|
|
49
51
|
},
|
|
50
52
|
"exports": {
|
|
51
53
|
"./package.json": "./package.json",
|
|
@@ -67,7 +69,7 @@
|
|
|
67
69
|
}
|
|
68
70
|
},
|
|
69
71
|
"dependencies": {
|
|
70
|
-
"@amritk/runtime-validators": "^0.
|
|
72
|
+
"@amritk/runtime-validators": "^0.13.1",
|
|
71
73
|
"@amritk/yaml": "^0.7.2",
|
|
72
74
|
"jsonc-parser": "^3.3.1"
|
|
73
75
|
},
|