habit-hooks-typescript 1.0.0__tar.gz
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.
- habit_hooks_typescript-1.0.0/.gitignore +20 -0
- habit_hooks_typescript-1.0.0/PKG-INFO +5 -0
- habit_hooks_typescript-1.0.0/docs/typescript-plugin.spec.md +178 -0
- habit_hooks_typescript-1.0.0/package-lock.json +2048 -0
- habit_hooks_typescript-1.0.0/package.json +13 -0
- habit_hooks_typescript-1.0.0/pyproject.toml +16 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/__init__.py +1 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/config.toml +4 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/eslint.config.mjs +49 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/guides/non-null-assertion.md +11 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/knip.json +5 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/sensors/comment.js +78 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/sensors/comment.toml +1 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/sensors/eslint.toml +34 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/sensors/knip.js +58 -0
- habit_hooks_typescript-1.0.0/src/habit_hooks_typescript/sensors/knip.toml +1 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Per-plugin Node tool deps (installed via npm ci; see plugins/*/package.json)
|
|
2
|
+
node_modules/
|
|
3
|
+
dist
|
|
4
|
+
coverage
|
|
5
|
+
.DS_Store
|
|
6
|
+
.idea
|
|
7
|
+
.claude-channel/
|
|
8
|
+
*.tgz
|
|
9
|
+
*.log
|
|
10
|
+
.vscode/
|
|
11
|
+
.venv/
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.pyc
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.spec-runs/
|
|
16
|
+
|
|
17
|
+
/ruff.toml
|
|
18
|
+
|
|
19
|
+
# Workflow orchestration script (run from ~/.claude, never a repo deliverable)
|
|
20
|
+
.claude/workflows-build-overnight.js
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# The typescript plugin โ acceptance
|
|
2
|
+
|
|
3
|
+
The typescript plugin runs its sensors through the real `habit-sensors` pipeline.
|
|
4
|
+
These cases run the **actual** tools (`eslint`, `knip`, and a `ts-morph` comment
|
|
5
|
+
scan) against a fixture with a known smell and assert the canonical finding comes
|
|
6
|
+
out, mapped to the smell keys in [smell-vocabulary.md](smell-vocabulary.md).
|
|
7
|
+
|
|
8
|
+
`habit-sensors` is the installed CLI. The Node tools live in the typescript
|
|
9
|
+
plugin's own `node_modules` (`plugins/typescript/node_modules`). The intro
|
|
10
|
+
symlinks that into each case as `./node_modules` and puts its `.bin` on `PATH`
|
|
11
|
+
once โ the shipped `eslint.config.mjs` and `knip` resolve their plugin deps
|
|
12
|
+
through the normal `node_modules` walk (ESM `import` ignores `NODE_PATH`, which
|
|
13
|
+
is why we symlink rather than set it), and `ts-morph`'s `require` resolves the
|
|
14
|
+
same way. The cases share `finding.jq` to project each finding down to the
|
|
15
|
+
asserted fields.
|
|
16
|
+
|
|
17
|
+
๐.habit-hooks/config.toml
|
|
18
|
+
```toml
|
|
19
|
+
plugins = ["typescript"]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
๐package.json
|
|
23
|
+
```json
|
|
24
|
+
{ "name": "demo", "version": "0.0.0" }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
๐finding.jq
|
|
28
|
+
```jq
|
|
29
|
+
sort_by(.smell)[]
|
|
30
|
+
| {
|
|
31
|
+
smell,
|
|
32
|
+
language,
|
|
33
|
+
key: (.issues[0].key | sub(".*/"; "")),
|
|
34
|
+
line: .issues[0].details.line,
|
|
35
|
+
source: .issues[0].details.source
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ln -s ../../plugins/typescript/node_modules node_modules
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
โ๏ธPATH
|
|
44
|
+
```text
|
|
45
|
+
$PWD/node_modules/.bin:$PATH
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## eslint adapter maps rule IDs to canonical smells
|
|
49
|
+
|
|
50
|
+
The `eslint` adapter runs eslint with the shipped flat config and a jq transform
|
|
51
|
+
in its command flattens the per-file `messages[]`, remaps each rule ID to a
|
|
52
|
+
canonical smell, and groups one finding per smell, stamping `source:
|
|
53
|
+
"eslint:<rule>"` on each issue. The config caps `max-params` at 3, so a
|
|
54
|
+
four-parameter function trips `max-params` โ `too-many-parameters`.
|
|
55
|
+
|
|
56
|
+
๐eslint.config.mjs @plugins/typescript/src/habit_hooks_typescript/eslint.config.mjs
|
|
57
|
+
|
|
58
|
+
๐src/billing.ts
|
|
59
|
+
```typescript
|
|
60
|
+
export function charge(a: number, b: number, c: number, d: number): number {
|
|
61
|
+
return a + b + c + d;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
๐.habit-hooks/config.toml
|
|
66
|
+
```toml
|
|
67
|
+
plugins = ["typescript"]
|
|
68
|
+
|
|
69
|
+
[sensors.knip]
|
|
70
|
+
disabled = true
|
|
71
|
+
|
|
72
|
+
[sensors.comment]
|
|
73
|
+
disabled = true
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
habit-sensors --all | jq -f finding.jq
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
๐ฅ๏ธ โ
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"smell": "too-many-parameters",
|
|
84
|
+
"language": "typescript",
|
|
85
|
+
"key": "billing.ts",
|
|
86
|
+
"line": 1,
|
|
87
|
+
"source": "eslint:max-params"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## knip sensor maps an unused export to unused-export
|
|
92
|
+
|
|
93
|
+
The `knip` sensor runs knip with the shipped `knip.json`, accepts its 0/1 exit
|
|
94
|
+
codes, and shapes each typed issue array into a finding โ `exports` โ
|
|
95
|
+
`unused-export`, one issue per symbol keyed by the symbol name. `helper.ts`
|
|
96
|
+
exports `neverUsed`, which nothing imports.
|
|
97
|
+
|
|
98
|
+
๐knip.json @plugins/typescript/src/habit_hooks_typescript/knip.json
|
|
99
|
+
|
|
100
|
+
๐src/cli.ts
|
|
101
|
+
```typescript
|
|
102
|
+
import { used } from "./helper";
|
|
103
|
+
|
|
104
|
+
used();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
๐src/helper.ts
|
|
108
|
+
```typescript
|
|
109
|
+
export function used(): void {}
|
|
110
|
+
|
|
111
|
+
export function neverUsed(): void {}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
๐.habit-hooks/config.toml
|
|
115
|
+
```toml
|
|
116
|
+
plugins = ["typescript"]
|
|
117
|
+
|
|
118
|
+
[sensors.eslint]
|
|
119
|
+
disabled = true
|
|
120
|
+
|
|
121
|
+
[sensors.comment]
|
|
122
|
+
disabled = true
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
habit-sensors --all | jq '.[] | {smell, language, key: .issues[0].key, file: .issues[0].details.file, source: .issues[0].details.source}'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
๐ฅ๏ธ โ
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"smell": "unused-export",
|
|
133
|
+
"language": "typescript",
|
|
134
|
+
"key": "neverUsed",
|
|
135
|
+
"file": "src/helper.ts",
|
|
136
|
+
"source": "knip:exports"
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## comment sensor maps a non-essential comment to non-essential-comment
|
|
141
|
+
|
|
142
|
+
The `comment` sensor scans the scoped files with ts-morph and reports comments
|
|
143
|
+
the reader could work out from the code, shaping each into a
|
|
144
|
+
`non-essential-comment` finding with `source: "comment:non-essential"`.
|
|
145
|
+
|
|
146
|
+
๐src/util.ts
|
|
147
|
+
```typescript
|
|
148
|
+
export function add(a: number, b: number): number {
|
|
149
|
+
// this comment restates what the code already says clearly
|
|
150
|
+
return a + b;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
๐.habit-hooks/config.toml
|
|
155
|
+
```toml
|
|
156
|
+
plugins = ["typescript"]
|
|
157
|
+
|
|
158
|
+
[sensors.eslint]
|
|
159
|
+
disabled = true
|
|
160
|
+
|
|
161
|
+
[sensors.knip]
|
|
162
|
+
disabled = true
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
habit-sensors --all | jq -f finding.jq
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
๐ฅ๏ธ โ
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"smell": "non-essential-comment",
|
|
173
|
+
"language": "typescript",
|
|
174
|
+
"key": "util.ts",
|
|
175
|
+
"line": 2,
|
|
176
|
+
"source": "comment:non-essential"
|
|
177
|
+
}
|
|
178
|
+
```
|