slop-police 0.3.0 → 0.3.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 +13 -11
- package/lib/runner.js +1 -8
- package/lib/testing.d.ts +5 -9
- package/lib/testing.js +4 -6
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -6,17 +6,19 @@
|
|
|
6
6
|
A type-aware TypeScript linter for the dead code and needless indirection AI agents leave behind.
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
```sh
|
|
10
|
+
pnpm add slop-police
|
|
11
|
+
# or
|
|
12
|
+
npm i slop-police
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Run it with `pnpm exec slop-police` or `npx slop-police`.
|
|
14
16
|
|
|
15
17
|
Example output:
|
|
16
18
|
|
|
17
19
|
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
deck-store.ts:42:3 error unused-methods Method DeckStore.reset is never used
|
|
21
|
+
links.ts:30:3 error unused-object-keys links.privacyPolicy is never read
|
|
20
22
|
|
|
21
23
|
2 errors, 0 warnings
|
|
22
24
|
```
|
|
@@ -270,7 +272,7 @@ export const noRepeatedUrl = defineRule({
|
|
|
270
272
|
});
|
|
271
273
|
```
|
|
272
274
|
|
|
273
|
-
Test rules with `lint` from `slop-police/testing`, which runs a rule alone on a source string (or on files
|
|
275
|
+
Test rules with `lint` from `slop-police/testing`, which runs a rule alone on a source string (as `index.ts`) or on files (an object of paths to contents) in a strict TypeScript project:
|
|
274
276
|
|
|
275
277
|
```ts
|
|
276
278
|
import { lint } from "slop-police/testing";
|
|
@@ -278,12 +280,12 @@ import { noDirectFetch } from "./slop-rules.ts";
|
|
|
278
280
|
|
|
279
281
|
test("no-direct-fetch", () => {
|
|
280
282
|
expect(lint(noDirectFetch, `fetch("/users");`)).toEqual([
|
|
281
|
-
{ line: 1, column: 1, message: "Use the API client instead of fetch()" },
|
|
283
|
+
{ file: "index.ts", line: 1, column: 1, message: "Use the API client instead of fetch()" },
|
|
282
284
|
]);
|
|
283
285
|
});
|
|
284
286
|
```
|
|
285
287
|
|
|
286
|
-
Plugins need the npm launcher (`npx slop-police` or `pnpm exec slop-police`), which runs them in Node while the linter serves ASTs and types.
|
|
288
|
+
Plugins need the npm launcher (`npx slop-police` or `pnpm exec slop-police`), which runs them in Node while the linter serves ASTs and types. Published plugin packages must ship JavaScript, since Node doesn't run TypeScript from `node_modules`.
|
|
287
289
|
|
|
288
290
|
## Ignoring findings
|
|
289
291
|
|
|
@@ -303,7 +305,7 @@ For `no-placeholder-comment`, put the ignore comment on the line directly above
|
|
|
303
305
|
|
|
304
306
|
## Requirements
|
|
305
307
|
|
|
306
|
-
macOS or Linux on arm64 or x64 (on Windows, use WSL). The linter bundles its own TypeScript 7 compiler, so your tsconfigs need to work with TypeScript 7.
|
|
308
|
+
macOS or Linux on arm64 or x64 (on Windows, use WSL), and Node.js 22.18 or later. The linter bundles its own TypeScript 7 compiler, so your tsconfigs need to work with TypeScript 7.
|
|
307
309
|
|
|
308
310
|
## License
|
|
309
311
|
|
package/lib/runner.js
CHANGED
|
@@ -38,7 +38,7 @@ async function loadPlugins(root, plugins) {
|
|
|
38
38
|
try {
|
|
39
39
|
exports = await import(resolvePlugin(root, plugin));
|
|
40
40
|
} catch (error) {
|
|
41
|
-
throw new LintError(`Unable to load plugin ${plugin}: ${error.message}
|
|
41
|
+
throw new LintError(`Unable to load plugin ${plugin}: ${error.message}`, 2);
|
|
42
42
|
}
|
|
43
43
|
const found = Object.values(exports).flat().filter(isRule);
|
|
44
44
|
if (found.length === 0) {
|
|
@@ -62,13 +62,6 @@ function resolvePlugin(root, plugin) {
|
|
|
62
62
|
return pathToFileURL(createRequire(path.join(root, "package.json")).resolve(plugin)).href;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
function loadHint(error, plugin) {
|
|
66
|
-
if (error.code === "ERR_UNKNOWN_FILE_EXTENSION" && /\.[cm]?tsx?$/.test(plugin)) {
|
|
67
|
-
return " (TypeScript plugins need Node.js 22.18 or later)";
|
|
68
|
-
}
|
|
69
|
-
return "";
|
|
70
|
-
}
|
|
71
|
-
|
|
72
65
|
// lint runs the built-in rules enabled in root's config in the binary and the
|
|
73
66
|
// enabled ones among rules here, and returns the binary's report: {results,
|
|
74
67
|
// output, exitCode}. It throws a LintError when the run fails.
|
package/lib/testing.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Rule, RuleOptions } from "./index.js";
|
|
2
2
|
|
|
3
3
|
export interface Finding {
|
|
4
|
+
/** The path relative to the project: index.ts for a source string. */
|
|
5
|
+
file: string;
|
|
4
6
|
/** 1-based. */
|
|
5
7
|
line: number;
|
|
6
8
|
/** 1-based, in UTF-16 code units. */
|
|
@@ -8,14 +10,8 @@ export interface Finding {
|
|
|
8
10
|
message: string;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
/** Runs rule alone on source, as index.ts in a strict TypeScript project. */
|
|
12
|
-
export declare function lint(rule: Rule<any>, source: string, options?: RuleOptions): Finding[];
|
|
13
13
|
/**
|
|
14
|
-
* Runs rule alone on files (paths to contents), in
|
|
15
|
-
* unless files has a tsconfig.json.
|
|
14
|
+
* Runs rule alone on source (as index.ts) or on files (paths to contents), in
|
|
15
|
+
* a strict TypeScript project unless files has a tsconfig.json.
|
|
16
16
|
*/
|
|
17
|
-
export declare function lint(
|
|
18
|
-
rule: Rule<any>,
|
|
19
|
-
files: Record<string, string>,
|
|
20
|
-
options?: RuleOptions,
|
|
21
|
-
): (Finding & { file: string })[];
|
|
17
|
+
export declare function lint(rule: Rule<any>, source: string | Record<string, string>, options?: RuleOptions): Finding[];
|
package/lib/testing.js
CHANGED
|
@@ -17,9 +17,9 @@ const tsconfig = {
|
|
|
17
17
|
include: ["**/*.ts", "**/*.tsx"],
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
// lint runs rule alone on source (index.ts) or on files (paths to
|
|
21
|
-
// with a default strict tsconfig.json unless one is given) and
|
|
22
|
-
//
|
|
20
|
+
// lint runs rule alone on source (as index.ts) or on files (paths to
|
|
21
|
+
// contents, with a default strict tsconfig.json unless one is given) and
|
|
22
|
+
// returns its findings.
|
|
23
23
|
export function lint(rule, source, options) {
|
|
24
24
|
const files = typeof source === "string" ? { "index.ts": source } : source;
|
|
25
25
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "slop-police-test-"));
|
|
@@ -31,9 +31,7 @@ export function lint(rule, source, options) {
|
|
|
31
31
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
32
32
|
fs.writeFileSync(file, content);
|
|
33
33
|
}
|
|
34
|
-
return lintWithRules(findBinary(), root, [rule]).results.map(({ file, line, column, message }) =>
|
|
35
|
-
typeof source === "string" ? { line, column, message } : { file, line, column, message },
|
|
36
|
-
);
|
|
34
|
+
return lintWithRules(findBinary(), root, [rule]).results.map(({ file, line, column, message }) => ({ file, line, column, message }));
|
|
37
35
|
} finally {
|
|
38
36
|
fs.rmSync(root, { recursive: true, force: true });
|
|
39
37
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slop-police",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Type-aware TypeScript linter for the dead code and needless indirection AI agents leave behind",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"engines": {
|
|
41
|
-
"node": ">=18"
|
|
41
|
+
"node": ">=22.18"
|
|
42
42
|
},
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"slop-police-darwin-arm64": "0.3.
|
|
45
|
-
"slop-police-darwin-x64": "0.3.
|
|
46
|
-
"slop-police-linux-arm64": "0.3.
|
|
47
|
-
"slop-police-linux-x64": "0.3.
|
|
44
|
+
"slop-police-darwin-arm64": "0.3.1",
|
|
45
|
+
"slop-police-darwin-x64": "0.3.1",
|
|
46
|
+
"slop-police-linux-arm64": "0.3.1",
|
|
47
|
+
"slop-police-linux-x64": "0.3.1"
|
|
48
48
|
}
|
|
49
49
|
}
|