unguard 0.2.0 → 0.4.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 +113 -0
- package/bin/unguard.mjs +2 -79
- package/dist/chunk-DYY4VK66.js +1105 -0
- package/dist/chunk-DYY4VK66.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +79 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/package.json +25 -16
- package/rulepacks/ts/rule-tests/__snapshots__/no-any-cast-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/no-double-negation-coercion-snapshot.yml +0 -26
- package/rulepacks/ts/rule-tests/__snapshots__/no-empty-catch-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/no-explicit-any-annotation-snapshot.yml +0 -20
- package/rulepacks/ts/rule-tests/__snapshots__/no-implicit-falsy-check-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/no-inline-type-in-params-snapshot.yml +0 -32
- package/rulepacks/ts/rule-tests/__snapshots__/no-logical-or-fallback-snapshot.yml +0 -100
- package/rulepacks/ts/rule-tests/__snapshots__/no-loose-nullish-check-snapshot.yml +0 -30
- package/rulepacks/ts/rule-tests/__snapshots__/no-non-null-assertion-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/no-null-ternary-normalization-snapshot.yml +0 -58
- package/rulepacks/ts/rule-tests/__snapshots__/no-nullish-coalescing-snapshot.yml +0 -20
- package/rulepacks/ts/rule-tests/__snapshots__/no-optional-call-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/no-optional-element-access-snapshot.yml +0 -8
- package/rulepacks/ts/rule-tests/__snapshots__/no-optional-property-access-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/no-redundant-existence-guard-snapshot.yml +0 -30
- package/rulepacks/ts/rule-tests/__snapshots__/no-redundant-optional-with-default-snapshot.yml +0 -12
- package/rulepacks/ts/rule-tests/__snapshots__/no-strict-nullish-check-snapshot.yml +0 -58
- package/rulepacks/ts/rule-tests/__snapshots__/no-ts-ignore-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/prefer-default-param-value-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/__snapshots__/prefer-required-param-with-guard-snapshot.yml +0 -14
- package/rulepacks/ts/rule-tests/no-any-cast-test.yml +0 -7
- package/rulepacks/ts/rule-tests/no-double-negation-coercion-test.yml +0 -9
- package/rulepacks/ts/rule-tests/no-empty-catch-test.yml +0 -7
- package/rulepacks/ts/rule-tests/no-explicit-any-annotation-test.yml +0 -9
- package/rulepacks/ts/rule-tests/no-implicit-falsy-check-test.yml +0 -7
- package/rulepacks/ts/rule-tests/no-inline-type-in-params-test.yml +0 -9
- package/rulepacks/ts/rule-tests/no-logical-or-fallback-test.yml +0 -13
- package/rulepacks/ts/rule-tests/no-loose-nullish-check-test.yml +0 -8
- package/rulepacks/ts/rule-tests/no-non-null-assertion-test.yml +0 -7
- package/rulepacks/ts/rule-tests/no-null-ternary-normalization-test.yml +0 -9
- package/rulepacks/ts/rule-tests/no-nullish-coalescing-test.yml +0 -8
- package/rulepacks/ts/rule-tests/no-optional-call-test.yml +0 -7
- package/rulepacks/ts/rule-tests/no-optional-element-access-test.yml +0 -5
- package/rulepacks/ts/rule-tests/no-optional-property-access-test.yml +0 -6
- package/rulepacks/ts/rule-tests/no-redundant-existence-guard-test.yml +0 -7
- package/rulepacks/ts/rule-tests/no-redundant-optional-with-default-test.yml +0 -6
- package/rulepacks/ts/rule-tests/no-strict-nullish-check-test.yml +0 -9
- package/rulepacks/ts/rule-tests/no-ts-ignore-test.yml +0 -7
- package/rulepacks/ts/rule-tests/prefer-default-param-value-test.yml +0 -7
- package/rulepacks/ts/rule-tests/prefer-required-param-with-guard-test.yml +0 -7
- package/rulepacks/ts/rules/no-any-cast.yml +0 -10
- package/rulepacks/ts/rules/no-double-negation-coercion.yml +0 -6
- package/rulepacks/ts/rules/no-empty-catch.yml +0 -8
- package/rulepacks/ts/rules/no-explicit-any-annotation.yml +0 -11
- package/rulepacks/ts/rules/no-implicit-falsy-check.yml +0 -8
- package/rulepacks/ts/rules/no-inline-type-in-params.yml +0 -11
- package/rulepacks/ts/rules/no-logical-or-fallback.yml +0 -13
- package/rulepacks/ts/rules/no-loose-nullish-check.yml +0 -13
- package/rulepacks/ts/rules/no-non-null-assertion.yml +0 -6
- package/rulepacks/ts/rules/no-null-ternary-normalization.yml +0 -18
- package/rulepacks/ts/rules/no-nullish-coalescing.yml +0 -6
- package/rulepacks/ts/rules/no-optional-call.yml +0 -6
- package/rulepacks/ts/rules/no-optional-element-access.yml +0 -6
- package/rulepacks/ts/rules/no-optional-property-access.yml +0 -6
- package/rulepacks/ts/rules/no-redundant-existence-guard.yml +0 -12
- package/rulepacks/ts/rules/no-redundant-optional-with-default.yml +0 -8
- package/rulepacks/ts/rules/no-strict-nullish-check.yml +0 -13
- package/rulepacks/ts/rules/no-ts-ignore.yml +0 -7
- package/rulepacks/ts/rules/prefer-default-param-value.yml +0 -18
- package/rulepacks/ts/rules/prefer-required-param-with-guard.yml +0 -18
- package/rulepacks/ts/sgconfig.yml +0 -6
- package/rulepacks/ts/utils/is-literal.yml +0 -12
- package/rulepacks/ts/utils/is-nullish.yml +0 -6
- package/rulepacks/tsx/rule-tests/__snapshots__/no-any-cast-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/no-double-negation-coercion-snapshot.yml +0 -26
- package/rulepacks/tsx/rule-tests/__snapshots__/no-empty-catch-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/no-explicit-any-annotation-snapshot.yml +0 -20
- package/rulepacks/tsx/rule-tests/__snapshots__/no-implicit-falsy-check-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/no-inline-type-in-params-snapshot.yml +0 -32
- package/rulepacks/tsx/rule-tests/__snapshots__/no-logical-or-fallback-snapshot.yml +0 -100
- package/rulepacks/tsx/rule-tests/__snapshots__/no-loose-nullish-check-snapshot.yml +0 -30
- package/rulepacks/tsx/rule-tests/__snapshots__/no-non-null-assertion-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/no-null-ternary-normalization-snapshot.yml +0 -58
- package/rulepacks/tsx/rule-tests/__snapshots__/no-nullish-coalescing-snapshot.yml +0 -20
- package/rulepacks/tsx/rule-tests/__snapshots__/no-optional-call-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/no-optional-element-access-snapshot.yml +0 -8
- package/rulepacks/tsx/rule-tests/__snapshots__/no-optional-property-access-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/no-redundant-existence-guard-snapshot.yml +0 -30
- package/rulepacks/tsx/rule-tests/__snapshots__/no-redundant-optional-with-default-snapshot.yml +0 -12
- package/rulepacks/tsx/rule-tests/__snapshots__/no-strict-nullish-check-snapshot.yml +0 -58
- package/rulepacks/tsx/rule-tests/__snapshots__/no-ts-ignore-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/prefer-default-param-value-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/__snapshots__/prefer-required-param-with-guard-snapshot.yml +0 -14
- package/rulepacks/tsx/rule-tests/no-any-cast-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/no-double-negation-coercion-test.yml +0 -9
- package/rulepacks/tsx/rule-tests/no-empty-catch-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/no-explicit-any-annotation-test.yml +0 -9
- package/rulepacks/tsx/rule-tests/no-implicit-falsy-check-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/no-inline-type-in-params-test.yml +0 -9
- package/rulepacks/tsx/rule-tests/no-logical-or-fallback-test.yml +0 -13
- package/rulepacks/tsx/rule-tests/no-loose-nullish-check-test.yml +0 -8
- package/rulepacks/tsx/rule-tests/no-non-null-assertion-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/no-null-ternary-normalization-test.yml +0 -9
- package/rulepacks/tsx/rule-tests/no-nullish-coalescing-test.yml +0 -8
- package/rulepacks/tsx/rule-tests/no-optional-call-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/no-optional-element-access-test.yml +0 -5
- package/rulepacks/tsx/rule-tests/no-optional-property-access-test.yml +0 -6
- package/rulepacks/tsx/rule-tests/no-redundant-existence-guard-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/no-redundant-optional-with-default-test.yml +0 -6
- package/rulepacks/tsx/rule-tests/no-strict-nullish-check-test.yml +0 -9
- package/rulepacks/tsx/rule-tests/no-ts-ignore-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/prefer-default-param-value-test.yml +0 -7
- package/rulepacks/tsx/rule-tests/prefer-required-param-with-guard-test.yml +0 -7
- package/rulepacks/tsx/rules/no-any-cast.yml +0 -7
- package/rulepacks/tsx/rules/no-double-negation-coercion.yml +0 -7
- package/rulepacks/tsx/rules/no-empty-catch.yml +0 -8
- package/rulepacks/tsx/rules/no-explicit-any-annotation.yml +0 -12
- package/rulepacks/tsx/rules/no-implicit-falsy-check.yml +0 -8
- package/rulepacks/tsx/rules/no-inline-type-in-params.yml +0 -11
- package/rulepacks/tsx/rules/no-logical-or-fallback.yml +0 -14
- package/rulepacks/tsx/rules/no-loose-nullish-check.yml +0 -13
- package/rulepacks/tsx/rules/no-non-null-assertion.yml +0 -6
- package/rulepacks/tsx/rules/no-null-ternary-normalization.yml +0 -19
- package/rulepacks/tsx/rules/no-nullish-coalescing.yml +0 -7
- package/rulepacks/tsx/rules/no-optional-call.yml +0 -7
- package/rulepacks/tsx/rules/no-optional-element-access.yml +0 -7
- package/rulepacks/tsx/rules/no-optional-property-access.yml +0 -7
- package/rulepacks/tsx/rules/no-redundant-existence-guard.yml +0 -12
- package/rulepacks/tsx/rules/no-redundant-optional-with-default.yml +0 -9
- package/rulepacks/tsx/rules/no-strict-nullish-check.yml +0 -14
- package/rulepacks/tsx/rules/no-ts-ignore.yml +0 -8
- package/rulepacks/tsx/rules/prefer-default-param-value.yml +0 -43
- package/rulepacks/tsx/rules/prefer-required-param-with-guard.yml +0 -24
- package/rulepacks/tsx/sgconfig.yml +0 -6
- package/rulepacks/tsx/utils/is-literal.yml +0 -12
- package/rulepacks/tsx/utils/is-nullish.yml +0 -6
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# unguard
|
|
2
|
+
|
|
3
|
+
Unguard your code. Defend agains overdefensive AI-generated code.
|
|
4
|
+
|
|
5
|
+
Built on [oxc-parser](https://github.com/nicolo-ribaudo/oxc-parser-js).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g unguard
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
or simply
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx unguard
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
unguard src/
|
|
23
|
+
unguard src/ --strict # treat warnings as errors (CI)
|
|
24
|
+
unguard src/ --filter no-any-cast # run a single rule
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Add `unguard` to your lint check.
|
|
28
|
+
|
|
29
|
+
## Current Rules
|
|
30
|
+
|
|
31
|
+
### Type system evasion
|
|
32
|
+
|
|
33
|
+
| Rule | What it catches |
|
|
34
|
+
|------|----------------|
|
|
35
|
+
| `no-any-cast` | `x as any` |
|
|
36
|
+
| `no-explicit-any-annotation` | `param: any`, `const x: any` |
|
|
37
|
+
| `no-type-assertion` | `x as unknown as T` |
|
|
38
|
+
| `no-ts-ignore` | `@ts-ignore` / `@ts-expect-error` |
|
|
39
|
+
|
|
40
|
+
### Defensive code
|
|
41
|
+
|
|
42
|
+
| Rule | What it catches |
|
|
43
|
+
|------|----------------|
|
|
44
|
+
| `no-optional-property-access` | `obj?.prop` |
|
|
45
|
+
| `no-optional-element-access` | `obj?.[key]` |
|
|
46
|
+
| `no-optional-call` | `fn?.()` |
|
|
47
|
+
| `no-nullish-coalescing` | `x ?? fallback` |
|
|
48
|
+
| `no-logical-or-fallback` | `x \|\| fallback` |
|
|
49
|
+
| `no-null-ternary-normalization` | `x == null ? fallback : x` |
|
|
50
|
+
| `no-non-null-assertion` | `x!` |
|
|
51
|
+
| `no-double-negation-coercion` | `!!value` |
|
|
52
|
+
| `no-redundant-existence-guard` | `obj && obj.prop` |
|
|
53
|
+
|
|
54
|
+
### Error handling
|
|
55
|
+
|
|
56
|
+
| Rule | What it catches |
|
|
57
|
+
|------|----------------|
|
|
58
|
+
| `no-empty-catch` | `catch {}` with no body |
|
|
59
|
+
| `no-catch-return` | `catch { return fallback }` without rethrowing |
|
|
60
|
+
| `no-error-rewrap` | `throw new Error(e.message)` without `{ cause: e }` |
|
|
61
|
+
|
|
62
|
+
### Interface design
|
|
63
|
+
|
|
64
|
+
| Rule | What it catches |
|
|
65
|
+
|------|----------------|
|
|
66
|
+
| `no-inline-type-in-params` | `fn(opts: { a: string; b: number })` |
|
|
67
|
+
| `prefer-default-param-value` | Optional param reassigned with `??` in the body |
|
|
68
|
+
| `prefer-required-param-with-guard` | `arg?: T` followed by `if (!arg) throw` |
|
|
69
|
+
|
|
70
|
+
### Cross-file analysis
|
|
71
|
+
|
|
72
|
+
| Rule | What it catches |
|
|
73
|
+
|------|----------------|
|
|
74
|
+
| `duplicate-type-declaration` | Same type shape in multiple files |
|
|
75
|
+
| `duplicate-type-name` | Same exported type name, different shapes |
|
|
76
|
+
| `duplicate-function-declaration` | Same function body in multiple files |
|
|
77
|
+
| `duplicate-function-name` | Same exported function name, different bodies |
|
|
78
|
+
| `optional-arg-always-used` | Optional param provided at every call site |
|
|
79
|
+
| `explicit-null-arg` | `fn(null)` / `fn(undefined)` to project functions |
|
|
80
|
+
|
|
81
|
+
### Imports
|
|
82
|
+
|
|
83
|
+
| Rule | What it catches |
|
|
84
|
+
|------|----------------|
|
|
85
|
+
| `no-dynamic-import` | `import("./module")` |
|
|
86
|
+
|
|
87
|
+
## Annotations
|
|
88
|
+
|
|
89
|
+
Comments near flagged lines appear in the output as context:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// intentional escape hatch for untyped AST access
|
|
93
|
+
type AnyNode = Record<string, any>;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```txt
|
|
97
|
+
file.ts:2:31 warning Explicit `any` annotation ... (intentional escape hatch for untyped AST access)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## API
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { scan } from "unguard";
|
|
104
|
+
|
|
105
|
+
const result = await scan({ paths: ["src/"] });
|
|
106
|
+
for (const d of result.diagnostics) {
|
|
107
|
+
console.log(`${d.file}:${d.line} [${d.ruleId}] ${d.message}`);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
MIT
|
package/bin/unguard.mjs
CHANGED
|
@@ -1,80 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import crossSpawn from "cross-spawn";
|
|
6
|
-
|
|
7
|
-
const binDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const packageRoot = path.resolve(binDir, "..");
|
|
9
|
-
const localBinDir = path.join(packageRoot, "node_modules", ".bin");
|
|
10
|
-
|
|
11
|
-
const rulepacks = [
|
|
12
|
-
{
|
|
13
|
-
configPath: path.join(packageRoot, "rulepacks", "ts", "sgconfig.yml"),
|
|
14
|
-
globs: ["**/*.ts", "**/*.cts", "**/*.mts"],
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
configPath: path.join(packageRoot, "rulepacks", "tsx", "sgconfig.yml"),
|
|
18
|
-
globs: ["**/*.tsx"],
|
|
19
|
-
},
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
const rawArgs = process.argv.slice(2);
|
|
23
|
-
const firstArg = rawArgs[0];
|
|
24
|
-
|
|
25
|
-
if (firstArg === "-h" || firstArg === "--help") {
|
|
26
|
-
console.log(`unguard: data-shape AST checker
|
|
27
|
-
|
|
28
|
-
Usage:
|
|
29
|
-
unguard scan [paths...] [ast-grep scan options]
|
|
30
|
-
unguard scan [paths...] --strict
|
|
31
|
-
unguard [paths...] [ast-grep scan options]
|
|
32
|
-
|
|
33
|
-
Examples:
|
|
34
|
-
unguard scan src
|
|
35
|
-
unguard scan src --filter no-loose-nullish-check
|
|
36
|
-
unguard scan src --strict
|
|
37
|
-
unguard src --strict
|
|
38
|
-
`);
|
|
39
|
-
process.exit(0);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const userArgs = firstArg === "scan" ? rawArgs.slice(1) : rawArgs;
|
|
43
|
-
const strictMode = userArgs.includes("--strict");
|
|
44
|
-
const forwardedArgs = userArgs.filter((a) => a !== "--strict");
|
|
45
|
-
|
|
46
|
-
const envPath = process.env.PATH
|
|
47
|
-
? `${localBinDir}${path.delimiter}${process.env.PATH}`
|
|
48
|
-
: localBinDir;
|
|
49
|
-
|
|
50
|
-
let finalStatus = 0;
|
|
51
|
-
for (const rulepack of rulepacks) {
|
|
52
|
-
const scanArgs = ["scan", "--config", rulepack.configPath, ...forwardedArgs];
|
|
53
|
-
for (const glob of rulepack.globs) {
|
|
54
|
-
scanArgs.push("--globs", glob);
|
|
55
|
-
}
|
|
56
|
-
if (strictMode) {
|
|
57
|
-
scanArgs.push("--error");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const result = crossSpawn.sync("ast-grep", scanArgs, {
|
|
61
|
-
stdio: "inherit",
|
|
62
|
-
env: { ...process.env, PATH: envPath },
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
if (result.error) {
|
|
66
|
-
if (result.error.code === "ENOENT") {
|
|
67
|
-
console.error(
|
|
68
|
-
"ast-grep binary not found. Run `npm install` in this package or install @ast-grep/cli globally.",
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
console.error(result.error.message);
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if ((result.status ?? 0) !== 0) {
|
|
76
|
-
finalStatus = result.status ?? 1;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
process.exit(finalStatus);
|
|
2
|
+
import { main } from "../dist/cli.js";
|
|
3
|
+
main(process.argv).then((code) => process.exit(code));
|