@trebired/code-discipline 1.5.0 → 2.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/CHANGELOG.md +16 -0
- package/README.md +165 -271
- package/dist/checks/fix-folderization.d.ts.map +1 -1
- package/dist/checks/fix-folderization.js +8 -14
- package/dist/checks/fix-folderization.js.map +1 -1
- package/dist/checks/index.d.ts +4 -3
- package/dist/checks/index.d.ts.map +1 -1
- package/dist/checks/index.js +107 -76
- package/dist/checks/index.js.map +1 -1
- package/dist/checks/rule-slugs.d.ts +15 -0
- package/dist/checks/rule-slugs.d.ts.map +1 -0
- package/dist/checks/rule-slugs.js +62 -0
- package/dist/checks/rule-slugs.js.map +1 -0
- package/dist/checks/rules/dry.d.ts +7 -0
- package/dist/checks/rules/dry.d.ts.map +1 -0
- package/dist/checks/rules/dry.js +913 -0
- package/dist/checks/rules/dry.js.map +1 -0
- package/dist/checks/rules/folderize-compound-files.d.ts.map +1 -1
- package/dist/checks/rules/folderize-compound-files.js +0 -1
- package/dist/checks/rules/folderize-compound-files.js.map +1 -1
- package/dist/checks/rules/max-file-lines.d.ts.map +1 -1
- package/dist/checks/rules/max-file-lines.js +0 -1
- package/dist/checks/rules/max-file-lines.js.map +1 -1
- package/dist/checks/rules/max-function-lines.d.ts.map +1 -1
- package/dist/checks/rules/max-function-lines.js +0 -1
- package/dist/checks/rules/max-function-lines.js.map +1 -1
- package/dist/checks/types.d.ts +49 -26
- package/dist/checks/types.d.ts.map +1 -1
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +22 -31
- package/dist/cli/run-cli.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -3
- package/dist/cli.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +122 -16
- package/dist/config/index.js.map +1 -1
- package/dist/config/normalize-check-options.d.ts +2 -2
- package/dist/config/normalize-check-options.d.ts.map +1 -1
- package/dist/config/normalize-check-options.js +6 -2
- package/dist/config/normalize-check-options.js.map +1 -1
- package/dist/config/normalize-rule-options.d.ts +9 -9
- package/dist/config/normalize-rule-options.d.ts.map +1 -1
- package/dist/config/normalize-rule-options.js +58 -15
- package/dist/config/normalize-rule-options.js.map +1 -1
- package/dist/config/normalize-sync-imports-options.d.ts.map +1 -1
- package/dist/config/normalize-sync-imports-options.js +8 -12
- package/dist/config/normalize-sync-imports-options.js.map +1 -1
- package/dist/imports/aliases.d.ts.map +1 -1
- package/dist/imports/aliases.js +6 -2
- package/dist/imports/aliases.js.map +1 -1
- package/dist/imports/check-sync-imports.d.ts.map +1 -1
- package/dist/imports/check-sync-imports.js +18 -2
- package/dist/imports/check-sync-imports.js.map +1 -1
- package/dist/imports/sync-imports.d.ts.map +1 -1
- package/dist/imports/sync-imports.js +23 -18
- package/dist/imports/sync-imports.js.map +1 -1
- package/dist/imports/types.d.ts +12 -6
- package/dist/imports/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +15 -18
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +9 -38
- package/dist/run.js.map +1 -1
- package/dist/runtime/orchestrate.d.ts +2 -3
- package/dist/runtime/orchestrate.d.ts.map +1 -1
- package/dist/runtime/orchestrate.js +0 -10
- package/dist/runtime/orchestrate.js.map +1 -1
- package/dist/runtime/runtime-imports-sync.d.ts +12 -3
- package/dist/runtime/runtime-imports-sync.d.ts.map +1 -1
- package/dist/runtime/runtime-imports-sync.js +34 -32
- package/dist/runtime/runtime-imports-sync.js.map +1 -1
- package/dist/runtime/tsconfig-paths.d.ts +1 -1
- package/dist/runtime/tsconfig-paths.d.ts.map +1 -1
- package/dist/runtime/tsconfig-paths.js +1 -1
- package/dist/runtime/tsconfig-paths.js.map +1 -1
- package/dist/shared/constants.d.ts +1 -2
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +1 -2
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/discipline-types.d.ts +3 -6
- package/dist/shared/discipline-types.d.ts.map +1 -1
- package/dist/shared/logging.d.ts.map +1 -1
- package/dist/shared/logging.js +25 -39
- package/dist/shared/logging.js.map +1 -1
- package/dist/shared/utils.d.ts +2 -1
- package/dist/shared/utils.d.ts.map +1 -1
- package/dist/shared/utils.js +14 -1
- package/dist/shared/utils.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@trebired/code-discipline` will be documented here.
|
|
4
4
|
|
|
5
|
+
## 2.1.0
|
|
6
|
+
|
|
7
|
+
- Removed severity from the public rule config, violation objects, and result summaries.
|
|
8
|
+
- Changed discipline and sync results to report `violationCount` instead of separate `errors` and `warnings`.
|
|
9
|
+
- Simplified CLI output to concise violation lines and short summaries instead of JSON-style payloads.
|
|
10
|
+
- Reduced logger noise by dropping large violation metadata from summary events and only emitting initialization logs when logging is enabled.
|
|
11
|
+
|
|
12
|
+
## 2.0.0
|
|
13
|
+
|
|
14
|
+
- Removed the top-level `code-discipline sync` command and the runtime `sync` / `startup` modes.
|
|
15
|
+
- Changed the package-owned surface to `check` and `fix`, with positional rule selectors such as `code-discipline fix sync-imports`.
|
|
16
|
+
- Changed config auto-discovery to the new `tb.code-discipline.*` filenames and added package-owned TypeScript config loading for Node and Bun.
|
|
17
|
+
- Added the `dry` rule for canonical helper registration, duplicate detection, and full-removal standalone autofix.
|
|
18
|
+
- Moved optional `package.json#imports` syncing under `rules.syncImports.packageJsonImports`.
|
|
19
|
+
- Changed `fixCodeDiscipline()` from a folderization-only mutation path into a rule-ordered fix pipeline with `ruleResults`.
|
|
20
|
+
|
|
5
21
|
## 1.5.0
|
|
6
22
|
|
|
7
23
|
- Added direct config auto-discovery so the CLI can be used as `code-discipline check`, `fix`, and `sync` without mandatory wrapper scripts or `--config` flags.
|
package/README.md
CHANGED
|
@@ -1,411 +1,305 @@
|
|
|
1
1
|
# @trebired/code-discipline
|
|
2
2
|
|
|
3
|
-
Configurable repository discipline checks
|
|
3
|
+
Configurable repository discipline checks and rule-driven fixes for Bun and Node.js projects.
|
|
4
4
|
|
|
5
|
-
`@trebired/code-discipline`
|
|
5
|
+
`@trebired/code-discipline` stays in one lane:
|
|
6
|
+
|
|
7
|
+
- code shape rules such as max lines per file or function
|
|
8
|
+
- structural rules such as folderizing compound files
|
|
9
|
+
- sync rules such as keeping source imports, `tsconfig.json`, and optional `package.json#imports` aligned
|
|
10
|
+
- DRY enforcement against registered canonical helper functions
|
|
11
|
+
|
|
12
|
+
It is not a formatter, linter replacement, or build system.
|
|
6
13
|
|
|
7
14
|
## Install
|
|
8
15
|
|
|
9
|
-
Runtime support:
|
|
16
|
+
Runtime support:
|
|
17
|
+
|
|
18
|
+
- Bun 1+
|
|
19
|
+
- Node.js 18+
|
|
10
20
|
|
|
11
21
|
```sh
|
|
12
22
|
npm install @trebired/code-discipline
|
|
13
23
|
```
|
|
14
24
|
|
|
15
|
-
## Why This Package
|
|
16
|
-
|
|
17
|
-
Some repository rules are not really single-file lint rules. They are about the shape of the tree:
|
|
18
|
-
|
|
19
|
-
- files growing too large
|
|
20
|
-
- functions growing too large
|
|
21
|
-
- compound filenames that want to become folders
|
|
22
|
-
- alias drift between `tsconfig.json` and source imports
|
|
23
|
-
- returning structured policy results that a caller can interpret
|
|
24
|
-
|
|
25
|
-
That is the lane of this package.
|
|
26
|
-
|
|
27
25
|
## Commands
|
|
28
26
|
|
|
29
27
|
```sh
|
|
30
28
|
code-discipline check
|
|
31
|
-
code-discipline
|
|
29
|
+
code-discipline check max-function-lines dry
|
|
32
30
|
code-discipline fix
|
|
31
|
+
code-discipline fix sync-imports dry
|
|
33
32
|
```
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
Top-level `sync` is gone.
|
|
36
35
|
|
|
37
|
-
-
|
|
38
|
-
- `discipline.config.js`
|
|
39
|
-
- `discipline.config.cjs`
|
|
40
|
-
- `code-discipline.config.mjs`
|
|
41
|
-
- `code-discipline.config.js`
|
|
42
|
-
- `code-discipline.config.cjs`
|
|
43
|
-
|
|
44
|
-
You can still override discovery explicitly:
|
|
36
|
+
`sync-imports` is now just another fixable rule, so targeted sync work is done through:
|
|
45
37
|
|
|
46
38
|
```sh
|
|
47
|
-
code-discipline
|
|
39
|
+
code-discipline fix sync-imports
|
|
48
40
|
```
|
|
49
41
|
|
|
50
|
-
Typical `package.json` scripts can
|
|
42
|
+
Typical `package.json` scripts can stay simple:
|
|
51
43
|
|
|
52
44
|
```json
|
|
53
45
|
{
|
|
54
46
|
"scripts": {
|
|
55
47
|
"discipline:check": "code-discipline check",
|
|
56
|
-
"discipline:fix": "code-discipline fix"
|
|
57
|
-
"discipline:sync": "code-discipline sync"
|
|
48
|
+
"discipline:fix": "code-discipline fix"
|
|
58
49
|
}
|
|
59
50
|
}
|
|
60
51
|
```
|
|
61
52
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- `check`: read-only validation and logging
|
|
65
|
-
- `sync`: package-owned synchronization work from config
|
|
66
|
-
- `fix`: configured structural fixes only
|
|
67
|
-
|
|
68
|
-
Mutations stay opt-in:
|
|
53
|
+
## Config
|
|
69
54
|
|
|
70
|
-
|
|
71
|
-
- `runtimeImportsSync` updates `package.json#imports` only when that feature is enabled
|
|
72
|
-
- `fix` applies folderization moves only when `folderizeCompoundFiles.fix` is `true`
|
|
55
|
+
The CLI auto-discovers a top-level config module in this order:
|
|
73
56
|
|
|
74
|
-
|
|
57
|
+
- `tb.code-discipline.ts`
|
|
58
|
+
- `tb.code-discipline.mts`
|
|
59
|
+
- `tb.code-discipline.mjs`
|
|
60
|
+
- `tb.code-discipline.js`
|
|
61
|
+
- `tb.code-discipline.cts`
|
|
62
|
+
- `tb.code-discipline.cjs`
|
|
75
63
|
|
|
76
|
-
|
|
64
|
+
`tb.code-discipline.ts` is the recommended default.
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
import { codeDiscipline } from "@trebired/code-discipline";
|
|
66
|
+
You can still point at an explicit module path:
|
|
80
67
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
projectRoot: process.cwd(),
|
|
84
|
-
rules: {
|
|
85
|
-
maxFileLines: {
|
|
86
|
-
severity: "warning",
|
|
87
|
-
max: 500,
|
|
88
|
-
},
|
|
89
|
-
maxFunctionLines: {
|
|
90
|
-
severity: "warning",
|
|
91
|
-
max: 80,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
});
|
|
68
|
+
```sh
|
|
69
|
+
code-discipline check --config ./discipline.config.mjs
|
|
95
70
|
```
|
|
96
71
|
|
|
97
|
-
|
|
72
|
+
Legacy config filenames are no longer auto-discovered, but they still work when passed explicitly with `--config`.
|
|
98
73
|
|
|
99
|
-
|
|
100
|
-
import { codeDiscipline } from "@trebired/code-discipline";
|
|
74
|
+
Rules are enabled by presence. If a rule object exists under `rules`, it runs.
|
|
101
75
|
|
|
102
|
-
|
|
103
|
-
mode: "startup",
|
|
104
|
-
projectRoot: PROJECT_ROOT,
|
|
105
|
-
logger,
|
|
106
|
-
rules: {
|
|
107
|
-
syncImports: {
|
|
108
|
-
severity: "error",
|
|
109
|
-
fix: true,
|
|
110
|
-
alias: {
|
|
111
|
-
strategy: "relative-path-slug",
|
|
112
|
-
},
|
|
113
|
-
allowRelative: ["./"],
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
If you want to define repo rules once and reuse them, create a bound helper:
|
|
76
|
+
Example `tb.code-discipline.ts`:
|
|
120
77
|
|
|
121
78
|
```ts
|
|
122
|
-
import {
|
|
79
|
+
import { defineCodeDisciplineConfig } from "@trebired/code-discipline";
|
|
123
80
|
|
|
124
|
-
|
|
125
|
-
sourceRoot: "src",
|
|
126
|
-
rules: {
|
|
127
|
-
syncImports: {
|
|
128
|
-
severity: "error",
|
|
129
|
-
fix: true,
|
|
130
|
-
alias: {
|
|
131
|
-
strategy: "relative-path-slug",
|
|
132
|
-
},
|
|
133
|
-
allowRelative: ["./"],
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
await discipline.startup({ projectRoot: PROJECT_ROOT, logger });
|
|
139
|
-
process.exitCode = (await discipline.check({ projectRoot: process.cwd() })).ok ? 0 : 1;
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## Config
|
|
143
|
-
|
|
144
|
-
Rules are enabled by presence. If a rule object exists under `rules`, it runs. If the rule is omitted, it is disabled.
|
|
145
|
-
|
|
146
|
-
`severity` is discipline metadata, not a logger level and not process control. The library never calls `process.exit()` from core APIs. Callers decide what to do with `ok`, `errors`, and `warnings`.
|
|
147
|
-
|
|
148
|
-
Example config module:
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
export default {
|
|
81
|
+
export default defineCodeDisciplineConfig({
|
|
152
82
|
sourceRoot: "src",
|
|
153
83
|
sourceExtensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
154
84
|
excludeDirs: ["node_modules", "dist", ".vite"],
|
|
155
|
-
logging: {
|
|
156
|
-
enabled: true,
|
|
157
|
-
quiet: false,
|
|
158
|
-
},
|
|
159
85
|
tsconfigPaths: {
|
|
160
86
|
normalize: "relative-dot-prefix",
|
|
161
87
|
restoreAfterRun: true,
|
|
162
88
|
},
|
|
163
|
-
runtimeImportsSync: {
|
|
164
|
-
enabled: true,
|
|
165
|
-
source: "tsconfig.paths",
|
|
166
|
-
target: "package.json.imports",
|
|
167
|
-
aliasPrefix: "#",
|
|
168
|
-
},
|
|
169
89
|
lifecycle: {
|
|
170
90
|
async beforeRun(context) {
|
|
171
91
|
context.state.started = true;
|
|
172
92
|
},
|
|
173
|
-
async afterRun(context, result) {
|
|
174
|
-
context.state.finished = result.ok;
|
|
175
|
-
},
|
|
176
93
|
},
|
|
177
94
|
rules: {
|
|
178
95
|
maxFileLines: {
|
|
179
|
-
severity: "warning",
|
|
180
96
|
max: 500,
|
|
181
97
|
},
|
|
182
98
|
maxFunctionLines: {
|
|
183
|
-
severity: "warning",
|
|
184
99
|
max: 80,
|
|
185
100
|
},
|
|
186
101
|
folderizeCompoundFiles: {
|
|
187
|
-
severity: "error",
|
|
188
102
|
fix: true,
|
|
189
103
|
separators: ["_", "-"],
|
|
190
104
|
},
|
|
191
105
|
syncImports: {
|
|
192
|
-
severity: "error",
|
|
193
106
|
fix: true,
|
|
194
107
|
alias: {
|
|
108
|
+
prefix: "#",
|
|
195
109
|
strategy: "relative-path-slug",
|
|
196
110
|
},
|
|
197
111
|
allowRelative: ["./"],
|
|
112
|
+
packageJsonImports: {
|
|
113
|
+
enabled: true,
|
|
114
|
+
aliasPrefix: "#",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
dry: {
|
|
118
|
+
fix: true,
|
|
119
|
+
helpers: [
|
|
120
|
+
{
|
|
121
|
+
from: "./src/shared/to-text.ts",
|
|
122
|
+
exportName: "toText",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
198
125
|
},
|
|
199
126
|
},
|
|
200
|
-
};
|
|
127
|
+
});
|
|
201
128
|
```
|
|
202
129
|
|
|
203
|
-
##
|
|
204
|
-
|
|
205
|
-
If a project needs package-owned preprocessing or postprocessing around discipline commands, use config hooks instead of wrapper scripts.
|
|
206
|
-
|
|
207
|
-
Available hooks:
|
|
130
|
+
## Rule Selectors
|
|
208
131
|
|
|
209
|
-
|
|
210
|
-
- `lifecycle.afterRun(context, result)`
|
|
211
|
-
- `lifecycle.beforeMode(context)`
|
|
212
|
-
- `lifecycle.afterMode(context, result)`
|
|
132
|
+
`check` and `fix` both accept positional rule selectors:
|
|
213
133
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
-
|
|
217
|
-
|
|
218
|
-
- `configPath`
|
|
219
|
-
- `config`
|
|
220
|
-
- mutable `state`
|
|
221
|
-
|
|
222
|
-
## Optional Tsconfig Path Normalization
|
|
134
|
+
```sh
|
|
135
|
+
code-discipline check max-file-lines max-function-lines
|
|
136
|
+
code-discipline fix sync-imports dry
|
|
137
|
+
```
|
|
223
138
|
|
|
224
|
-
|
|
139
|
+
Rules use kebab-case public slugs:
|
|
225
140
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
},
|
|
232
|
-
};
|
|
233
|
-
```
|
|
141
|
+
- `max-file-lines`
|
|
142
|
+
- `max-function-lines`
|
|
143
|
+
- `folderize-compound-files`
|
|
144
|
+
- `sync-imports`
|
|
145
|
+
- `dry`
|
|
234
146
|
|
|
235
|
-
|
|
147
|
+
`fix` only accepts fixable rules. Trying to run `code-discipline fix max-function-lines` fails clearly.
|
|
236
148
|
|
|
237
|
-
|
|
238
|
-
- `"strip-dot-prefix"`: turns `./src/x.ts` into `src/x.ts`
|
|
239
|
-
- `"none"`: disables the helper
|
|
149
|
+
## Runtime API
|
|
240
150
|
|
|
241
|
-
|
|
151
|
+
The package-owned runtime dispatcher now has two modes only:
|
|
242
152
|
|
|
243
|
-
|
|
153
|
+
- `check`
|
|
154
|
+
- `fix`
|
|
244
155
|
|
|
245
|
-
|
|
156
|
+
```ts
|
|
157
|
+
import { codeDiscipline } from "@trebired/code-discipline";
|
|
246
158
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
159
|
+
const result = await codeDiscipline({
|
|
160
|
+
mode: "fix",
|
|
161
|
+
projectRoot: process.cwd(),
|
|
162
|
+
onlyRules: ["sync-imports"],
|
|
163
|
+
rules: {
|
|
164
|
+
syncImports: {
|
|
165
|
+
fix: true,
|
|
166
|
+
alias: {
|
|
167
|
+
strategy: "relative-path-slug",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
254
170
|
},
|
|
255
|
-
};
|
|
171
|
+
});
|
|
256
172
|
```
|
|
257
173
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
- only aliases matching the configured prefix or prefixes are managed
|
|
261
|
-
- unrelated existing `package.json#imports` entries are preserved
|
|
262
|
-
- the feature runs through `code-discipline sync` and `mode: "sync"` / `mode: "startup"`
|
|
263
|
-
|
|
264
|
-
## Checks
|
|
265
|
-
|
|
266
|
-
`checkCodeDiscipline()` is read-only. It never moves files, rewrites imports, or updates `tsconfig.json`.
|
|
174
|
+
You can also bind config once:
|
|
267
175
|
|
|
268
176
|
```ts
|
|
269
|
-
import {
|
|
177
|
+
import { createCodeDiscipline } from "@trebired/code-discipline";
|
|
270
178
|
|
|
271
|
-
const
|
|
272
|
-
|
|
179
|
+
const discipline = createCodeDiscipline({
|
|
180
|
+
sourceRoot: "src",
|
|
273
181
|
rules: {
|
|
274
|
-
maxFileLines: {
|
|
275
|
-
severity: "warning",
|
|
276
|
-
max: 500,
|
|
277
|
-
},
|
|
278
182
|
maxFunctionLines: {
|
|
279
|
-
severity: "warning",
|
|
280
183
|
max: 80,
|
|
281
184
|
},
|
|
282
|
-
folderizeCompoundFiles: {
|
|
283
|
-
severity: "error",
|
|
284
|
-
separators: ["_", "-"],
|
|
285
|
-
},
|
|
286
185
|
syncImports: {
|
|
287
|
-
|
|
288
|
-
fix: false,
|
|
186
|
+
fix: true,
|
|
289
187
|
alias: {
|
|
290
188
|
strategy: "relative-path-slug",
|
|
291
189
|
},
|
|
292
|
-
allowRelative: ["./"],
|
|
293
190
|
},
|
|
294
191
|
},
|
|
295
192
|
});
|
|
193
|
+
|
|
194
|
+
await discipline.fix({
|
|
195
|
+
projectRoot: process.cwd(),
|
|
196
|
+
onlyRules: ["sync-imports"],
|
|
197
|
+
});
|
|
296
198
|
```
|
|
297
199
|
|
|
298
|
-
|
|
200
|
+
Every violation is treated uniformly now. Results expose `ok`, `violationCount`, and `violations`, and the CLI prints concise rule/file/message lines instead of large JSON-style payloads.
|
|
299
201
|
|
|
300
|
-
|
|
301
|
-
type CodeDisciplineSeverity = "error" | "warning";
|
|
302
|
-
|
|
303
|
-
type CodeDisciplineViolation = {
|
|
304
|
-
rule: "max-file-lines" | "max-function-lines" | "folderize-compound-files" | "sync-imports";
|
|
305
|
-
severity: CodeDisciplineSeverity;
|
|
306
|
-
fix: boolean;
|
|
307
|
-
filePath: string;
|
|
308
|
-
message: string;
|
|
309
|
-
details: Record<string, unknown>;
|
|
310
|
-
suggestedPath?: string;
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
type CodeDisciplineResult = {
|
|
314
|
-
ok: boolean;
|
|
315
|
-
errors: number;
|
|
316
|
-
warnings: number;
|
|
317
|
-
violations: CodeDisciplineViolation[];
|
|
318
|
-
};
|
|
319
|
-
```
|
|
202
|
+
## Rules
|
|
320
203
|
|
|
321
|
-
|
|
204
|
+
### `maxFileLines`
|
|
322
205
|
|
|
323
|
-
|
|
206
|
+
Reports files whose total line count exceeds `max`.
|
|
324
207
|
|
|
325
|
-
`maxFunctionLines`
|
|
208
|
+
### `maxFunctionLines`
|
|
326
209
|
|
|
327
|
-
|
|
328
|
-
- function expressions
|
|
329
|
-
- arrow functions
|
|
330
|
-
- class methods
|
|
331
|
-
- constructors
|
|
332
|
-
- getters and setters
|
|
210
|
+
Reports function-like declarations whose total span exceeds `max`.
|
|
333
211
|
|
|
334
|
-
|
|
212
|
+
### `folderizeCompoundFiles`
|
|
335
213
|
|
|
336
|
-
|
|
214
|
+
Detects flat compound names such as `user_route.ts` and can move them into structural folders such as `user/route.ts`.
|
|
337
215
|
|
|
338
|
-
`
|
|
216
|
+
### `syncImports`
|
|
339
217
|
|
|
340
|
-
|
|
218
|
+
Validates and optionally fixes:
|
|
341
219
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
src/api/user_controller.ts
|
|
346
|
-
```
|
|
220
|
+
- `tsconfig.compilerOptions.paths`
|
|
221
|
+
- relative source imports that should become aliases
|
|
222
|
+
- optional `package.json#imports` drift through `packageJsonImports`
|
|
347
223
|
|
|
348
|
-
|
|
224
|
+
Example targeted CLI usage:
|
|
349
225
|
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
src/api/user/schema.ts
|
|
353
|
-
src/api/user/controller.ts
|
|
226
|
+
```sh
|
|
227
|
+
code-discipline fix sync-imports
|
|
354
228
|
```
|
|
355
229
|
|
|
356
|
-
|
|
230
|
+
### `dry`
|
|
357
231
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
232
|
+
Registers canonical helper functions and reports exact normalized duplicates.
|
|
233
|
+
|
|
234
|
+
The first version is intentionally conservative:
|
|
361
235
|
|
|
362
|
-
|
|
236
|
+
- matching is exact normalized structure, not heuristic similarity
|
|
237
|
+
- whitespace, comments, function names, and local identifier names do not matter
|
|
238
|
+
- class/object methods are report-only
|
|
239
|
+
- autofix only runs when the duplicate can be removed completely and replaced by a canonical import
|
|
363
240
|
|
|
364
|
-
|
|
365
|
-
|
|
241
|
+
Canonical helpers are registered by module export reference:
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
dry: {
|
|
245
|
+
fix: true,
|
|
246
|
+
helpers: [
|
|
247
|
+
{
|
|
248
|
+
from: "./src/shared/to-text.ts",
|
|
249
|
+
exportName: "toText",
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
from: "./src/shared/normalize.ts",
|
|
253
|
+
exportName: "default",
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
}
|
|
366
257
|
```
|
|
367
258
|
|
|
368
|
-
|
|
259
|
+
Supported canonical helper exports:
|
|
369
260
|
|
|
370
|
-
|
|
261
|
+
- exported function declarations
|
|
262
|
+
- exported const bindings initialized with function expressions or arrow functions
|
|
263
|
+
- default exports of those function shapes
|
|
371
264
|
|
|
372
|
-
##
|
|
265
|
+
## Lifecycle Hooks
|
|
373
266
|
|
|
374
|
-
|
|
267
|
+
Hooks remain package-owned and generic:
|
|
375
268
|
|
|
376
|
-
|
|
377
|
-
|
|
269
|
+
- `beforeRun(context)`
|
|
270
|
+
- `afterRun(context, result)`
|
|
271
|
+
- `beforeMode(context)`
|
|
272
|
+
- `afterMode(context, result)`
|
|
378
273
|
|
|
379
|
-
|
|
380
|
-
projectRoot: "/repo",
|
|
381
|
-
severity: "error",
|
|
382
|
-
fix: true,
|
|
383
|
-
alias: {
|
|
384
|
-
strategy: "relative-path-slug",
|
|
385
|
-
},
|
|
386
|
-
allowRelative: ["./"],
|
|
387
|
-
});
|
|
388
|
-
```
|
|
274
|
+
The hook context includes:
|
|
389
275
|
|
|
390
|
-
|
|
276
|
+
- `mode`
|
|
277
|
+
- `projectRoot`
|
|
278
|
+
- `configPath`
|
|
279
|
+
- `config`
|
|
280
|
+
- mutable `state`
|
|
391
281
|
|
|
392
|
-
|
|
393
|
-
- `fix: true` rewrites imports and updates `tsconfig.json`
|
|
394
|
-
- `allowRelative: ["./"]` keeps same-folder relative imports
|
|
395
|
-
- upward relative imports can be reported or rewritten through the configured alias policy
|
|
282
|
+
## Tsconfig Path Normalization
|
|
396
283
|
|
|
397
|
-
`
|
|
284
|
+
Use `tsconfigPaths` when a run needs temporary `compilerOptions.paths` normalization:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
tsconfigPaths: {
|
|
288
|
+
normalize: "relative-dot-prefix",
|
|
289
|
+
restoreAfterRun: true,
|
|
290
|
+
}
|
|
291
|
+
```
|
|
398
292
|
|
|
399
|
-
|
|
293
|
+
Available modes:
|
|
400
294
|
|
|
401
|
-
|
|
295
|
+
- `"relative-dot-prefix"` turns `src/x.ts` into `./src/x.ts`
|
|
296
|
+
- `"strip-dot-prefix"` turns `./src/x.ts` into `src/x.ts`
|
|
297
|
+
- `"none"` leaves values unchanged
|
|
402
298
|
|
|
403
|
-
|
|
299
|
+
## Advanced Helpers
|
|
404
300
|
|
|
405
|
-
|
|
301
|
+
Low-level helpers are still exported for advanced tooling:
|
|
406
302
|
|
|
407
|
-
- `codeDiscipline()`
|
|
408
|
-
- `createCodeDiscipline()`
|
|
409
303
|
- `checkCodeDiscipline()`
|
|
410
304
|
- `fixCodeDiscipline()`
|
|
411
305
|
- `syncImports()`
|
|
@@ -416,4 +310,4 @@ The default/common logger adaptation path is powered by `@trebired/logger-adapte
|
|
|
416
310
|
- `restoreTsconfigPaths()`
|
|
417
311
|
- `syncPackageJsonImportsFromTsconfigPaths()`
|
|
418
312
|
|
|
419
|
-
|
|
313
|
+
`syncImports()` remains available as a lower-level helper, but the package CLI no longer exposes a separate `sync` command.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fix-folderization.d.ts","sourceRoot":"","sources":["../../src/checks/fix-folderization.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,oCAAoC,EACrC,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAO7E,KAAK,WAAW,GAAG;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,iBAAS,4BAA4B,CACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,oCAAoC,EAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,uBAAuB,
|
|
1
|
+
{"version":3,"file":"fix-folderization.d.ts","sourceRoot":"","sources":["../../src/checks/fix-folderization.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,oCAAoC,EACrC,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAO7E,KAAK,WAAW,GAAG;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,iBAAS,4BAA4B,CACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,oCAAoC,EAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,uBAAuB,CASzB;AAED,iBAAS,aAAa,CACpB,WAAW,EAAE,iBAAiB,EAAE,EAChC,OAAO,EAAE,oCAAoC,GAC5C;IAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAAC,UAAU,EAAE,uBAAuB,EAAE,CAAA;CAAE,CAqBjE;AAsKD,iBAAe,gBAAgB,CAC7B,WAAW,EAAE,iBAAiB,EAAE,EAChC,OAAO,EAAE,oCAAoC,EAC7C,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CAwElC;AAED,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -8,7 +8,6 @@ import { planFolderizeCompoundFiles } from "./rules/folderize-plan.js";
|
|
|
8
8
|
function createFolderizationViolation(filePath, suggestedPath, options, details) {
|
|
9
9
|
return {
|
|
10
10
|
rule: "folderize-compound-files",
|
|
11
|
-
severity: options.rules.folderizeCompoundFiles?.severity ?? "error",
|
|
12
11
|
fix: options.rules.folderizeCompoundFiles?.fix ?? false,
|
|
13
12
|
filePath,
|
|
14
13
|
message: `file can be grouped under ${suggestedPath}`,
|
|
@@ -156,37 +155,32 @@ async function removeEmptyDirectories(directories) {
|
|
|
156
155
|
}
|
|
157
156
|
async function fixFolderization(sourceFiles, options, logger) {
|
|
158
157
|
const { moves, violations } = buildMovePlan(sourceFiles, options);
|
|
159
|
-
const warnings = violations.filter((violation) => violation.severity === "warning").length;
|
|
160
|
-
const errors = violations.length - warnings;
|
|
161
158
|
if (!options.rules.folderizeCompoundFiles || moves.length === 0) {
|
|
162
159
|
logger.info("fix-folderization-unchanged", "no folderization moves required", {
|
|
163
160
|
moves: 0,
|
|
164
161
|
});
|
|
165
162
|
return {
|
|
166
163
|
ok: true,
|
|
167
|
-
|
|
164
|
+
violationCount: 0,
|
|
168
165
|
moved_files: 0,
|
|
169
166
|
rewritten_files: 0,
|
|
170
167
|
rewritten_imports: 0,
|
|
171
|
-
|
|
168
|
+
ruleResults: {},
|
|
172
169
|
violations: [],
|
|
173
170
|
};
|
|
174
171
|
}
|
|
175
172
|
if (!options.rules.folderizeCompoundFiles.fix) {
|
|
176
173
|
logger.warn("fix-folderization-disabled", "folderization fix is disabled", {
|
|
177
174
|
candidates: moves.length,
|
|
178
|
-
|
|
179
|
-
errors,
|
|
180
|
-
warnings,
|
|
181
|
-
},
|
|
175
|
+
violationCount: violations.length,
|
|
182
176
|
});
|
|
183
177
|
return {
|
|
184
|
-
ok:
|
|
185
|
-
|
|
178
|
+
ok: false,
|
|
179
|
+
violationCount: violations.length,
|
|
186
180
|
moved_files: 0,
|
|
187
181
|
rewritten_files: 0,
|
|
188
182
|
rewritten_imports: 0,
|
|
189
|
-
|
|
183
|
+
ruleResults: {},
|
|
190
184
|
violations,
|
|
191
185
|
};
|
|
192
186
|
}
|
|
@@ -206,11 +200,11 @@ async function fixFolderization(sourceFiles, options, logger) {
|
|
|
206
200
|
});
|
|
207
201
|
return {
|
|
208
202
|
ok: true,
|
|
209
|
-
|
|
203
|
+
violationCount: 0,
|
|
210
204
|
moved_files: movedFiles,
|
|
211
205
|
rewritten_files: rewriteState.rewrittenFiles,
|
|
212
206
|
rewritten_imports: rewriteState.rewrittenImports,
|
|
213
|
-
|
|
207
|
+
ruleResults: {},
|
|
214
208
|
violations: [],
|
|
215
209
|
};
|
|
216
210
|
}
|