codelaw 0.0.0-stage → 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.
- package/LICENSE +23 -0
- package/README.md +49 -2
- package/bin/codelaw.js +19 -0
- package/codelaw.schema.json +255 -0
- package/index.d.ts +101 -0
- package/index.js +93 -0
- package/package.json +50 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arpit Arya
|
|
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.
|
|
22
|
+
|
|
23
|
+
SPDX-License-Identifier: MIT
|
package/README.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
-
#
|
|
1
|
+
# codelaw
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A linter and formatter whose rules are Markdown files — for JavaScript,
|
|
4
|
+
TypeScript, Python, JSON, YAML, TOML, Markdown, CSS and HTML, alone or mixed.
|
|
5
|
+
|
|
6
|
+
**One engine, two registries, identical output.** The same native binary ships
|
|
7
|
+
as `codelaw` on npm and on PyPI; neither needs the other.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
| your repo | engine | rules for its languages |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Node | `npm i -D codelaw` | `npx codelaw init` adds the `@codelaw/rules-*` packs |
|
|
14
|
+
| Python | `uv add --dev codelaw` or `pip install codelaw` | `codelaw init` adds the `codelaw-rules-*` packs |
|
|
15
|
+
|
|
16
|
+
`codelaw` installed alone lints nothing until a rule pack is installed — it
|
|
17
|
+
says so (`codelaw/no-rules`).
|
|
18
|
+
|
|
19
|
+
**Rule packs:** `js` · `html` · `css` · `python` · `data` — on npm as
|
|
20
|
+
`@codelaw/rules-<name>`, on PyPI as `codelaw-rules-<name>`.
|
|
21
|
+
|
|
22
|
+
## Use
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
codelaw check # lint the project
|
|
26
|
+
codelaw fix # apply the safe fixes
|
|
27
|
+
codelaw check --format json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Programmatic API** — runs the bundled binary and returns its JSON report:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import { check, fix } from "codelaw";
|
|
34
|
+
const report = check(["src"]);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import codelaw
|
|
39
|
+
report = codelaw.check(["src"])
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Platforms
|
|
43
|
+
|
|
44
|
+
macOS arm64 and x64 · Linux x64 and arm64, glibc and musl · Windows x64 and
|
|
45
|
+
arm64. Any other platform fails with an error naming these — codelaw never
|
|
46
|
+
compiles from source at install time.
|
|
47
|
+
|
|
48
|
+
## Licence
|
|
49
|
+
|
|
50
|
+
MIT — <https://github.com/arpitarya/codelaw>
|
package/bin/codelaw.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `codelaw` command on npm: run the platform binary with the same
|
|
3
|
+
// arguments, stdio and exit code (SR-PACKAGES decision 3).
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { binaryPath } from "../index.js";
|
|
6
|
+
|
|
7
|
+
let bin;
|
|
8
|
+
try {
|
|
9
|
+
bin = binaryPath();
|
|
10
|
+
} catch (e) {
|
|
11
|
+
console.error(e.message);
|
|
12
|
+
process.exit(2);
|
|
13
|
+
}
|
|
14
|
+
const r = spawnSync(bin, process.argv.slice(2), { stdio: "inherit" });
|
|
15
|
+
if (r.error) {
|
|
16
|
+
console.error(`codelaw: could not run ${bin}: ${r.error.message}`);
|
|
17
|
+
process.exit(2);
|
|
18
|
+
}
|
|
19
|
+
process.exit(r.status ?? 2);
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/arpitarya/codelaw/codelaw.schema.json",
|
|
4
|
+
"title": "codelaw configuration",
|
|
5
|
+
"description": "codelaw.toml, [tool.codelaw] in pyproject.toml, or \"codelaw\" in package.json (SR-CONFIG). Every key names the one record that defines it in x-codelaw-record.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"definitions": {
|
|
9
|
+
"globs": {
|
|
10
|
+
"type": "array",
|
|
11
|
+
"items": { "type": "string" },
|
|
12
|
+
"description": "Globs relative to the folder of the config that declares them."
|
|
13
|
+
},
|
|
14
|
+
"size": {
|
|
15
|
+
"description": "Bytes, or a string such as \"1 MiB\" or \"512MB\".",
|
|
16
|
+
"oneOf": [
|
|
17
|
+
{ "type": "integer", "minimum": 0 },
|
|
18
|
+
{ "type": "string", "pattern": "^\\s*[0-9]+\\s*(([KkMmGg][Ii]?)?[Bb])?\\s*$" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"duration": {
|
|
22
|
+
"description": "Seconds, or a string such as \"5s\" or \"500ms\".",
|
|
23
|
+
"oneOf": [
|
|
24
|
+
{ "type": "integer", "minimum": 0 },
|
|
25
|
+
{ "type": "string", "pattern": "^\\s*[0-9]+\\s*(ms|s)\\s*$" }
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"severity": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["error", "warn", "info", "off"]
|
|
31
|
+
},
|
|
32
|
+
"ruleSetting": {
|
|
33
|
+
"description": "A severity, or a severity and options.",
|
|
34
|
+
"oneOf": [
|
|
35
|
+
{ "$ref": "#/definitions/severity" },
|
|
36
|
+
{
|
|
37
|
+
"type": "object",
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"properties": {
|
|
40
|
+
"severity": { "$ref": "#/definitions/severity" },
|
|
41
|
+
"options": { "type": "object" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"rules": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"description": "Severity and options per rule id (`<namespace>/<name>`).",
|
|
49
|
+
"additionalProperties": { "$ref": "#/definitions/ruleSetting" }
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"properties": {
|
|
53
|
+
"extends": {
|
|
54
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
55
|
+
"description": "Presets: `codelaw:<namespace>/<preset>`, or team packs as `npm:`, `pypi:` or `path:`. Root config only.",
|
|
56
|
+
"type": "array",
|
|
57
|
+
"items": { "type": "string", "pattern": "^(codelaw|npm|pypi|path):" }
|
|
58
|
+
},
|
|
59
|
+
"languages": {
|
|
60
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
61
|
+
"description": "The languages checked; all of them when absent. The innermost config that sets it wins.",
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"enum": ["javascript", "jsx", "typescript", "tsx", "python", "json", "yaml", "toml", "markdown", "css", "html"]
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"include": { "x-codelaw-record": "SR-CONFIG", "$ref": "#/definitions/globs" },
|
|
69
|
+
"exclude": { "x-codelaw-record": "SR-CONFIG", "$ref": "#/definitions/globs" },
|
|
70
|
+
"rules_dir": {
|
|
71
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
72
|
+
"description": "The local rules folder; `.codelaw/rules` by default. Root config only.",
|
|
73
|
+
"type": "string"
|
|
74
|
+
},
|
|
75
|
+
"rules": { "x-codelaw-record": "SR-CONFIG", "$ref": "#/definitions/rules" },
|
|
76
|
+
"overrides": {
|
|
77
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
78
|
+
"description": "Per-glob rule settings, applied in file order after [rules].",
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"required": ["files"],
|
|
84
|
+
"properties": {
|
|
85
|
+
"files": { "$ref": "#/definitions/globs" },
|
|
86
|
+
"exclude": { "$ref": "#/definitions/globs" },
|
|
87
|
+
"rules": { "$ref": "#/definitions/rules" }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"root": {
|
|
92
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
93
|
+
"description": "Make this folder a separate project with its own graph and baseline.",
|
|
94
|
+
"type": "boolean"
|
|
95
|
+
},
|
|
96
|
+
"requires": {
|
|
97
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
98
|
+
"description": "A version range, e.g. \">=0.4\"; an older codelaw refuses to run.",
|
|
99
|
+
"type": "string"
|
|
100
|
+
},
|
|
101
|
+
"preview": {
|
|
102
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
103
|
+
"description": "Run preview rules (SR-RULE-PACKS decision 9). Root config only.",
|
|
104
|
+
"type": "boolean"
|
|
105
|
+
},
|
|
106
|
+
"allow_pack_fixers": {
|
|
107
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
108
|
+
"description": "Packs whose external fixers may run (SR-RULE-PACKS decision 12). Root config only.",
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": { "type": "string" }
|
|
111
|
+
},
|
|
112
|
+
"files": {
|
|
113
|
+
"x-codelaw-record": "SR-ARCHITECTURE",
|
|
114
|
+
"description": "Discovery, encoding and size (SR-ARCHITECTURE decisions 7 and 10). Root config only.",
|
|
115
|
+
"type": "object",
|
|
116
|
+
"additionalProperties": false,
|
|
117
|
+
"properties": {
|
|
118
|
+
"follow_symlinks": { "type": "boolean", "description": "Follow symlinks during discovery; off by default." },
|
|
119
|
+
"generated_markers": { "type": "array", "items": { "type": "string" }, "description": "Markers besides `@generated` that mark a file generated." },
|
|
120
|
+
"lint_generated": { "type": "boolean", "description": "Check generated files too; off by default." },
|
|
121
|
+
"max_file_size": { "$ref": "#/definitions/size", "description": "Larger files are skipped; 1 MiB by default." }
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"cache": {
|
|
125
|
+
"x-codelaw-record": "SR-CACHE",
|
|
126
|
+
"description": "The result cache (SR-CACHE decisions 3, 6 and 9). Root config only.",
|
|
127
|
+
"type": "object",
|
|
128
|
+
"additionalProperties": false,
|
|
129
|
+
"properties": {
|
|
130
|
+
"enabled": { "type": "boolean", "description": "On by default; `--no-cache` turns it off for one run." },
|
|
131
|
+
"dir": { "type": "string", "description": "`.codelaw/cache` by default; `CODELAW_CACHE_DIR` overrides it." },
|
|
132
|
+
"max_size": { "$ref": "#/definitions/size", "description": "512 MB by default." }
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"fix": {
|
|
136
|
+
"x-codelaw-record": "SR-ARCHITECTURE",
|
|
137
|
+
"description": "The fix pipeline (SR-ARCHITECTURE decision 18). Root config only.",
|
|
138
|
+
"type": "object",
|
|
139
|
+
"additionalProperties": false,
|
|
140
|
+
"properties": {
|
|
141
|
+
"external_timeout": { "$ref": "#/definitions/duration", "description": "Per file, for an external fixer; 5 s by default." }
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"lint": {
|
|
145
|
+
"x-codelaw-record": "SR-LINTER",
|
|
146
|
+
"description": "The linter (SR-LINTER decision 3). Root config only.",
|
|
147
|
+
"type": "object",
|
|
148
|
+
"additionalProperties": false,
|
|
149
|
+
"properties": {
|
|
150
|
+
"tagged_templates": { "type": "boolean", "description": "Lint css`…` and html`…` tagged templates as CSS and HTML; off by default." }
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"markdown": {
|
|
154
|
+
"x-codelaw-record": "SR-CONFIG",
|
|
155
|
+
"description": "Markdown (L3 decision 8). Root config only.",
|
|
156
|
+
"type": "object",
|
|
157
|
+
"additionalProperties": false,
|
|
158
|
+
"properties": {
|
|
159
|
+
"lint_code_blocks": { "x-codelaw-record": "SR-LAW-3", "type": "boolean", "description": "Lint fenced code blocks with their own language's rules; off by default." }
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"format": {
|
|
163
|
+
"x-codelaw-record": "SR-FORMATTER",
|
|
164
|
+
"x-codelaw-validated": false,
|
|
165
|
+
"description": "The formatter (SR-FORMATTER). Its keys are validated once the formatter is built.",
|
|
166
|
+
"type": "object"
|
|
167
|
+
},
|
|
168
|
+
"graph": {
|
|
169
|
+
"x-codelaw-record": "SR-PROJECT-GRAPH",
|
|
170
|
+
"x-codelaw-validated": false,
|
|
171
|
+
"description": "The project graph (SR-PROJECT-GRAPH). Its keys are validated once the graph is built.",
|
|
172
|
+
"type": "object"
|
|
173
|
+
},
|
|
174
|
+
"baseline": {
|
|
175
|
+
"x-codelaw-record": "SR-BASELINE",
|
|
176
|
+
"x-codelaw-validated": false,
|
|
177
|
+
"description": "The baseline (SR-BASELINE). Its keys are validated once the baseline is built.",
|
|
178
|
+
"type": "object"
|
|
179
|
+
},
|
|
180
|
+
"deprecation": {
|
|
181
|
+
"x-codelaw-record": "SR-BASELINE",
|
|
182
|
+
"description": "The policy of a symbol marked deprecated in code (JSDoc `@deprecated`, PEP 702) that `.codelaw/deprecations.toml` does not list (SR-BASELINE decision 6). Root config only.",
|
|
183
|
+
"type": "object",
|
|
184
|
+
"additionalProperties": false,
|
|
185
|
+
"properties": {
|
|
186
|
+
"until": {
|
|
187
|
+
"description": "The deadline, YYYY-MM-DD: after it every use is an error.",
|
|
188
|
+
"type": "string",
|
|
189
|
+
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
|
|
190
|
+
},
|
|
191
|
+
"warn_from": {
|
|
192
|
+
"description": "From this date, YYYY-MM-DD, a grandfathered use is a warning.",
|
|
193
|
+
"type": "string",
|
|
194
|
+
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
|
|
195
|
+
},
|
|
196
|
+
"on_touch": {
|
|
197
|
+
"description": "What a grandfathered use becomes when its file is touched.",
|
|
198
|
+
"enum": ["error", "warn", "keep"]
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"adapters": {
|
|
203
|
+
"x-codelaw-record": "SR-LINTER",
|
|
204
|
+
"description": "Optional external linters run by `check` and `fix` (SR-LINTER decision 2). Root config only.",
|
|
205
|
+
"type": "object",
|
|
206
|
+
"additionalProperties": false,
|
|
207
|
+
"properties": {
|
|
208
|
+
"enabled": {
|
|
209
|
+
"type": "array",
|
|
210
|
+
"items": { "enum": ["html-validate", "oxlint", "ruff", "stylelint"] },
|
|
211
|
+
"uniqueItems": true,
|
|
212
|
+
"description": "The adapters to run when installed; oxlint and Ruff when unset, none when empty."
|
|
213
|
+
},
|
|
214
|
+
"timeout": { "$ref": "#/definitions/duration", "description": "Per run of an adapter; 60 s by default." }
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
"agents": {
|
|
218
|
+
"x-codelaw-record": "SR-AGENT-SURFACES",
|
|
219
|
+
"description": "Agent surfaces (SR-AGENT-SURFACES decision 6): the agents `codelaw sync-agents` writes files for.",
|
|
220
|
+
"type": "object",
|
|
221
|
+
"additionalProperties": false,
|
|
222
|
+
"properties": {
|
|
223
|
+
"targets": {
|
|
224
|
+
"type": "array",
|
|
225
|
+
"items": { "enum": ["claude", "cowork", "copilot", "codex", "kiro"] },
|
|
226
|
+
"uniqueItems": true,
|
|
227
|
+
"description": "The agents whose files `codelaw sync-agents` writes; none by default, and then no agent file exists."
|
|
228
|
+
},
|
|
229
|
+
"command": {
|
|
230
|
+
"type": "string",
|
|
231
|
+
"minLength": 1,
|
|
232
|
+
"description": "How hooks and MCP registrations start codelaw; detected from the repo when unset (`npx --no-install codelaw`, `uv run codelaw` or `codelaw`)."
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
"daemon": {
|
|
237
|
+
"x-codelaw-record": "SR-ARCHITECTURE",
|
|
238
|
+
"description": "The opt-in warm daemon (SR-ARCHITECTURE decision 22). Root config only.",
|
|
239
|
+
"type": "object",
|
|
240
|
+
"additionalProperties": false,
|
|
241
|
+
"properties": {
|
|
242
|
+
"idle_timeout": { "$ref": "#/definitions/duration", "description": "The daemon exits after this long without a request; 30 minutes (1800 s) by default." }
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
"lsp": {
|
|
246
|
+
"x-codelaw-record": "SR-ARCHITECTURE",
|
|
247
|
+
"description": "Warm processes' memory bound (SR-ARCHITECTURE decision 24). Root config only.",
|
|
248
|
+
"type": "object",
|
|
249
|
+
"additionalProperties": false,
|
|
250
|
+
"properties": {
|
|
251
|
+
"tree_cache": { "type": "integer", "minimum": 0, "description": "How many closed files' syntax trees a warm process keeps, most recently touched first; open files always keep theirs. 256 by default; 0 keeps none." }
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Types for the codelaw npm API (SR-PACKAGES decision 3). Each call runs the
|
|
2
|
+
// bundled binary and returns its `--format json` report unchanged.
|
|
3
|
+
|
|
4
|
+
export type Severity = "error" | "warn" | "info";
|
|
5
|
+
export type FixClass = "auto" | "suggest" | "manual";
|
|
6
|
+
|
|
7
|
+
export interface Position { line: number; column: number; offset: number }
|
|
8
|
+
export interface Range { start: Position; end: Position }
|
|
9
|
+
export interface TextEdit { range: Range; text: string }
|
|
10
|
+
|
|
11
|
+
export interface Diagnostic {
|
|
12
|
+
rule: string;
|
|
13
|
+
severity: Severity;
|
|
14
|
+
file: string;
|
|
15
|
+
range: Range;
|
|
16
|
+
message: string;
|
|
17
|
+
fix: { class: FixClass; edits: TextEdit[]; steps: string[]; note: string | null } | null;
|
|
18
|
+
source: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CheckReport {
|
|
23
|
+
schema_version: number;
|
|
24
|
+
codelaw_version: string;
|
|
25
|
+
summary: {
|
|
26
|
+
files_checked: number;
|
|
27
|
+
files_skipped: number;
|
|
28
|
+
errors: number;
|
|
29
|
+
warnings: number;
|
|
30
|
+
infos: number;
|
|
31
|
+
fixable: number;
|
|
32
|
+
suggestions: number;
|
|
33
|
+
internal_errors: number;
|
|
34
|
+
};
|
|
35
|
+
diagnostics: Diagnostic[];
|
|
36
|
+
skipped: unknown[];
|
|
37
|
+
warnings: unknown[];
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Options {
|
|
42
|
+
/** `--lang`: only these languages. */
|
|
43
|
+
lang?: string[];
|
|
44
|
+
/** `--rule`: only these rules. */
|
|
45
|
+
rule?: string[];
|
|
46
|
+
/** `--threads`. */
|
|
47
|
+
threads?: number;
|
|
48
|
+
/** `--no-cache`. */
|
|
49
|
+
noCache?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface FixOptions extends Options {
|
|
53
|
+
/** `--unsafe`: apply `suggest` fixes too. */
|
|
54
|
+
unsafe?: boolean;
|
|
55
|
+
/** `--dry-run`: compute the fixes, write nothing. */
|
|
56
|
+
dryRun?: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface FormatOptions extends Options {
|
|
60
|
+
/** `--check`: report what would be formatted, write nothing. */
|
|
61
|
+
check?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface FixReport extends CheckReport {
|
|
65
|
+
/** Each changed file, the fixes applied per rule, and whether it was written. */
|
|
66
|
+
fixed: { file: string; applied: Record<string, number>; passes: number; written: boolean }[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface FormatReport extends CheckReport {
|
|
70
|
+
check: boolean;
|
|
71
|
+
/** Each file whose layout changed; `written` once the disk holds it. */
|
|
72
|
+
formatted: { file: string; written: boolean }[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** One rule as `rules --for` shows it (SR-CLI-MCP decision 7). */
|
|
76
|
+
export interface RuleCard {
|
|
77
|
+
id: string;
|
|
78
|
+
title: string;
|
|
79
|
+
severity: Severity | "off";
|
|
80
|
+
fix: FixClass;
|
|
81
|
+
/** `local`, or the pack the rule comes from. */
|
|
82
|
+
source: string;
|
|
83
|
+
preview: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface RulesReport {
|
|
87
|
+
schema_version: number;
|
|
88
|
+
codelaw_version: string;
|
|
89
|
+
/** The file asked about; `null` in a listing of every rule. */
|
|
90
|
+
for: string | null;
|
|
91
|
+
rules: RuleCard[];
|
|
92
|
+
[key: string]: unknown;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const PLATFORMS: readonly string[];
|
|
96
|
+
export function platformKey(): string;
|
|
97
|
+
export function binaryPath(): string;
|
|
98
|
+
export function check(paths?: string[], options?: Options): CheckReport;
|
|
99
|
+
export function fix(paths?: string[], options?: FixOptions): FixReport;
|
|
100
|
+
export function format(paths?: string[], options?: FormatOptions): FormatReport;
|
|
101
|
+
export function rulesFor(path: string): RulesReport;
|
package/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// codelaw on npm: find the platform binary and run it (SR-PACKAGES decision 3).
|
|
2
|
+
// No dependencies; the binary is one of the eight optionalDependencies
|
|
3
|
+
// `@codelaw/cli-<os>-<arch>`, of which npm installs exactly one.
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
|
|
9
|
+
/** The eight platforms codelaw ships a binary for (L6 decision 6). */
|
|
10
|
+
export const PLATFORMS = Object.freeze([
|
|
11
|
+
"darwin-arm64",
|
|
12
|
+
"darwin-x64",
|
|
13
|
+
"linux-x64-gnu",
|
|
14
|
+
"linux-arm64-gnu",
|
|
15
|
+
"linux-x64-musl",
|
|
16
|
+
"linux-arm64-musl",
|
|
17
|
+
"win32-x64",
|
|
18
|
+
"win32-arm64",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
function libc() {
|
|
22
|
+
// glibc reports its runtime version; musl reports none.
|
|
23
|
+
const header = process.report?.getReport?.().header ?? {};
|
|
24
|
+
return header.glibcVersionRuntime ? "gnu" : "musl";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** This machine's platform key, e.g. `linux-x64-gnu`. */
|
|
28
|
+
export function platformKey() {
|
|
29
|
+
const base = `${process.platform}-${process.arch}`;
|
|
30
|
+
return process.platform === "linux" ? `${base}-${libc()}` : base;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The absolute path of the codelaw binary for this machine. Throws on an unsupported platform (L6 decision 7). */
|
|
34
|
+
export function binaryPath() {
|
|
35
|
+
if (process.env.CODELAW_BINARY) return process.env.CODELAW_BINARY;
|
|
36
|
+
const key = platformKey();
|
|
37
|
+
if (!PLATFORMS.includes(key)) {
|
|
38
|
+
throw new Error(`codelaw has no binary for ${key}; supported: ${PLATFORMS.join(", ")}`);
|
|
39
|
+
}
|
|
40
|
+
const exe = process.platform === "win32" ? "codelaw.exe" : "codelaw";
|
|
41
|
+
try {
|
|
42
|
+
return require.resolve(`@codelaw/cli-${key}/${exe}`);
|
|
43
|
+
} catch {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`codelaw: @codelaw/cli-${key} is not installed. It is an optional dependency of codelaw — ` +
|
|
46
|
+
`reinstall without --no-optional / --omit=optional.`,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function run(args) {
|
|
52
|
+
const r = spawnSync(binaryPath(), args, { encoding: "utf8", maxBuffer: 1 << 30 });
|
|
53
|
+
if (r.error) throw r.error;
|
|
54
|
+
// 0: clean, 1: diagnostics over the threshold; 2: the run could not start.
|
|
55
|
+
if (r.status !== 0 && r.status !== 1) {
|
|
56
|
+
throw new Error(`codelaw ${args[0]} failed (exit ${r.status}): ${r.stderr.trim()}`);
|
|
57
|
+
}
|
|
58
|
+
return JSON.parse(r.stdout);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function common(o = {}) {
|
|
62
|
+
const a = [];
|
|
63
|
+
if (o.lang?.length) a.push("--lang", o.lang.join(","));
|
|
64
|
+
if (o.rule?.length) a.push("--rule", o.rule.join(","));
|
|
65
|
+
if (o.threads != null) a.push("--threads", String(o.threads));
|
|
66
|
+
if (o.noCache) a.push("--no-cache");
|
|
67
|
+
return a;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** `codelaw check --format json`; returns the report. */
|
|
71
|
+
export function check(paths = [], options = {}) {
|
|
72
|
+
return run(["check", "--format", "json", ...common(options), "--", ...paths]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** `codelaw fix --format json`; returns the report. */
|
|
76
|
+
export function fix(paths = [], options = {}) {
|
|
77
|
+
const a = ["fix", "--format", "json", ...common(options)];
|
|
78
|
+
if (options.unsafe) a.push("--unsafe");
|
|
79
|
+
if (options.dryRun) a.push("--dry-run");
|
|
80
|
+
return run([...a, "--", ...paths]);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** `codelaw format --format json` (`--check`: write nothing); returns the report. */
|
|
84
|
+
export function format(paths = [], options = {}) {
|
|
85
|
+
const a = ["format", "--format", "json", ...common(options)];
|
|
86
|
+
if (options.check) a.push("--check");
|
|
87
|
+
return run([...a, "--", ...paths]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** `codelaw rules --for <path> --format json`; returns the rules that apply to the file, with their severity. */
|
|
91
|
+
export function rulesFor(path) {
|
|
92
|
+
return run(["rules", "--for", path, "--format", "json"]);
|
|
93
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codelaw",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A linter and formatter whose rules are Markdown files",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/arpitarya/codelaw.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/arpitarya/codelaw",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"codelaw": "bin/codelaw.js"
|
|
14
|
+
},
|
|
15
|
+
"main": "index.js",
|
|
16
|
+
"types": "index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./index.d.ts",
|
|
20
|
+
"default": "./index.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json",
|
|
23
|
+
"./codelaw.schema.json": "./codelaw.schema.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin/",
|
|
27
|
+
"index.js",
|
|
28
|
+
"index.d.ts",
|
|
29
|
+
"codelaw.schema.json",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=22"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"linter",
|
|
37
|
+
"formatter",
|
|
38
|
+
"eslint",
|
|
39
|
+
"ruff",
|
|
40
|
+
"prettier"
|
|
41
|
+
],
|
|
42
|
+
"optionalDependencies": {
|
|
43
|
+
"@codelaw/cli-darwin-arm64": "0.1.0",
|
|
44
|
+
"@codelaw/cli-darwin-x64": "0.1.0",
|
|
45
|
+
"@codelaw/cli-linux-x64-gnu": "0.1.0",
|
|
46
|
+
"@codelaw/cli-linux-arm64-gnu": "0.1.0",
|
|
47
|
+
"@codelaw/cli-linux-x64-musl": "0.1.0",
|
|
48
|
+
"@codelaw/cli-linux-arm64-musl": "0.1.0",
|
|
49
|
+
"@codelaw/cli-win32-x64": "0.1.0",
|
|
50
|
+
"@codelaw/cli-win32-arm64": "0.1.0"
|
|
51
|
+
}
|
|
52
|
+
}
|