@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.
Files changed (94) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +165 -271
  3. package/dist/checks/fix-folderization.d.ts.map +1 -1
  4. package/dist/checks/fix-folderization.js +8 -14
  5. package/dist/checks/fix-folderization.js.map +1 -1
  6. package/dist/checks/index.d.ts +4 -3
  7. package/dist/checks/index.d.ts.map +1 -1
  8. package/dist/checks/index.js +107 -76
  9. package/dist/checks/index.js.map +1 -1
  10. package/dist/checks/rule-slugs.d.ts +15 -0
  11. package/dist/checks/rule-slugs.d.ts.map +1 -0
  12. package/dist/checks/rule-slugs.js +62 -0
  13. package/dist/checks/rule-slugs.js.map +1 -0
  14. package/dist/checks/rules/dry.d.ts +7 -0
  15. package/dist/checks/rules/dry.d.ts.map +1 -0
  16. package/dist/checks/rules/dry.js +913 -0
  17. package/dist/checks/rules/dry.js.map +1 -0
  18. package/dist/checks/rules/folderize-compound-files.d.ts.map +1 -1
  19. package/dist/checks/rules/folderize-compound-files.js +0 -1
  20. package/dist/checks/rules/folderize-compound-files.js.map +1 -1
  21. package/dist/checks/rules/max-file-lines.d.ts.map +1 -1
  22. package/dist/checks/rules/max-file-lines.js +0 -1
  23. package/dist/checks/rules/max-file-lines.js.map +1 -1
  24. package/dist/checks/rules/max-function-lines.d.ts.map +1 -1
  25. package/dist/checks/rules/max-function-lines.js +0 -1
  26. package/dist/checks/rules/max-function-lines.js.map +1 -1
  27. package/dist/checks/types.d.ts +49 -26
  28. package/dist/checks/types.d.ts.map +1 -1
  29. package/dist/cli/run-cli.d.ts.map +1 -1
  30. package/dist/cli/run-cli.js +22 -31
  31. package/dist/cli/run-cli.js.map +1 -1
  32. package/dist/cli.d.ts.map +1 -1
  33. package/dist/cli.js +2 -3
  34. package/dist/cli.js.map +1 -1
  35. package/dist/config/index.d.ts +1 -1
  36. package/dist/config/index.d.ts.map +1 -1
  37. package/dist/config/index.js +122 -16
  38. package/dist/config/index.js.map +1 -1
  39. package/dist/config/normalize-check-options.d.ts +2 -2
  40. package/dist/config/normalize-check-options.d.ts.map +1 -1
  41. package/dist/config/normalize-check-options.js +6 -2
  42. package/dist/config/normalize-check-options.js.map +1 -1
  43. package/dist/config/normalize-rule-options.d.ts +9 -9
  44. package/dist/config/normalize-rule-options.d.ts.map +1 -1
  45. package/dist/config/normalize-rule-options.js +58 -15
  46. package/dist/config/normalize-rule-options.js.map +1 -1
  47. package/dist/config/normalize-sync-imports-options.d.ts.map +1 -1
  48. package/dist/config/normalize-sync-imports-options.js +8 -12
  49. package/dist/config/normalize-sync-imports-options.js.map +1 -1
  50. package/dist/imports/aliases.d.ts.map +1 -1
  51. package/dist/imports/aliases.js +6 -2
  52. package/dist/imports/aliases.js.map +1 -1
  53. package/dist/imports/check-sync-imports.d.ts.map +1 -1
  54. package/dist/imports/check-sync-imports.js +18 -2
  55. package/dist/imports/check-sync-imports.js.map +1 -1
  56. package/dist/imports/sync-imports.d.ts.map +1 -1
  57. package/dist/imports/sync-imports.js +23 -18
  58. package/dist/imports/sync-imports.js.map +1 -1
  59. package/dist/imports/types.d.ts +12 -6
  60. package/dist/imports/types.d.ts.map +1 -1
  61. package/dist/index.d.ts +5 -5
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +1 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/run.d.ts +15 -18
  66. package/dist/run.d.ts.map +1 -1
  67. package/dist/run.js +9 -38
  68. package/dist/run.js.map +1 -1
  69. package/dist/runtime/orchestrate.d.ts +2 -3
  70. package/dist/runtime/orchestrate.d.ts.map +1 -1
  71. package/dist/runtime/orchestrate.js +0 -10
  72. package/dist/runtime/orchestrate.js.map +1 -1
  73. package/dist/runtime/runtime-imports-sync.d.ts +12 -3
  74. package/dist/runtime/runtime-imports-sync.d.ts.map +1 -1
  75. package/dist/runtime/runtime-imports-sync.js +34 -32
  76. package/dist/runtime/runtime-imports-sync.js.map +1 -1
  77. package/dist/runtime/tsconfig-paths.d.ts +1 -1
  78. package/dist/runtime/tsconfig-paths.d.ts.map +1 -1
  79. package/dist/runtime/tsconfig-paths.js +1 -1
  80. package/dist/runtime/tsconfig-paths.js.map +1 -1
  81. package/dist/shared/constants.d.ts +1 -2
  82. package/dist/shared/constants.d.ts.map +1 -1
  83. package/dist/shared/constants.js +1 -2
  84. package/dist/shared/constants.js.map +1 -1
  85. package/dist/shared/discipline-types.d.ts +3 -6
  86. package/dist/shared/discipline-types.d.ts.map +1 -1
  87. package/dist/shared/logging.d.ts.map +1 -1
  88. package/dist/shared/logging.js +25 -39
  89. package/dist/shared/logging.js.map +1 -1
  90. package/dist/shared/utils.d.ts +2 -1
  91. package/dist/shared/utils.d.ts.map +1 -1
  92. package/dist/shared/utils.js +14 -1
  93. package/dist/shared/utils.js.map +1 -1
  94. 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, structural fixes, and import syncing for Bun and Node.js projects.
3
+ Configurable repository discipline checks and rule-driven fixes for Bun and Node.js projects.
4
4
 
5
- `@trebired/code-discipline` is intentionally focused. It helps you keep a source tree disciplined without turning into a full linter, formatter, or build system.
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: Bun 1+ and Node.js 18+.
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 sync
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
- The CLI auto-discovers a config module in the current project root. Supported default names:
34
+ Top-level `sync` is gone.
36
35
 
37
- - `discipline.config.mjs`
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 check --config ./discipline.config.mjs
39
+ code-discipline fix sync-imports
48
40
  ```
49
41
 
50
- Typical `package.json` scripts can now stay direct and generic:
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
- Command responsibilities stay clean:
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
- - `syncImports` rewrites imports and `tsconfig.json` only when `syncImports.fix` is `true`
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
- ## Simple Runtime API
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
- For app startup or scripts, you can now use one package-owned entrypoint instead of hand-rolling mode dispatch in app code.
64
+ `tb.code-discipline.ts` is the recommended default.
77
65
 
78
- ```ts
79
- import { codeDiscipline } from "@trebired/code-discipline";
66
+ You can still point at an explicit module path:
80
67
 
81
- const result = await codeDiscipline({
82
- mode: "check",
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
- `mode: "startup"` is a convenience alias for sync-oriented startup flows:
72
+ Legacy config filenames are no longer auto-discovered, but they still work when passed explicitly with `--config`.
98
73
 
99
- ```ts
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
- await codeDiscipline({
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 { createCodeDiscipline } from "@trebired/code-discipline";
79
+ import { defineCodeDisciplineConfig } from "@trebired/code-discipline";
123
80
 
124
- const discipline = createCodeDiscipline({
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
- ## Generic Lifecycle Hooks
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
- - `lifecycle.beforeRun(context)`
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
- The hook context includes:
215
-
216
- - `mode`
217
- - `projectRoot`
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
- Use `tsconfigPaths` when a project needs temporary normalization of `compilerOptions.paths` before discipline runs.
139
+ Rules use kebab-case public slugs:
225
140
 
226
- ```js
227
- export default {
228
- tsconfigPaths: {
229
- normalize: "relative-dot-prefix",
230
- restoreAfterRun: true,
231
- },
232
- };
233
- ```
141
+ - `max-file-lines`
142
+ - `max-function-lines`
143
+ - `folderize-compound-files`
144
+ - `sync-imports`
145
+ - `dry`
234
146
 
235
- Supported normalization modes:
147
+ `fix` only accepts fixable rules. Trying to run `code-discipline fix max-function-lines` fails clearly.
236
148
 
237
- - `"relative-dot-prefix"`: turns `src/x.ts` into `./src/x.ts`
238
- - `"strip-dot-prefix"`: turns `./src/x.ts` into `src/x.ts`
239
- - `"none"`: disables the helper
149
+ ## Runtime API
240
150
 
241
- `restoreAfterRun: true` restores the original `tsconfig.json` after read-oriented runs so the normalization can stay package-owned instead of living in shell wrappers.
151
+ The package-owned runtime dispatcher now has two modes only:
242
152
 
243
- ## Optional Package Imports Sync
153
+ - `check`
154
+ - `fix`
244
155
 
245
- Use `runtimeImportsSync` when a project wants `package.json#imports` mirrored from `tsconfig.compilerOptions.paths`.
156
+ ```ts
157
+ import { codeDiscipline } from "@trebired/code-discipline";
246
158
 
247
- ```js
248
- export default {
249
- runtimeImportsSync: {
250
- enabled: true,
251
- source: "tsconfig.paths",
252
- target: "package.json.imports",
253
- aliasPrefix: "#",
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
- Behavior:
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 { checkCodeDiscipline } from "@trebired/code-discipline";
177
+ import { createCodeDiscipline } from "@trebired/code-discipline";
270
178
 
271
- const result = await checkCodeDiscipline({
272
- projectRoot: "/repo",
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
- severity: "error",
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
- Result shape:
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
- ```ts
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
- `ok` becomes `false` only when at least one returned violation has `severity: "error"`.
204
+ ### `maxFileLines`
322
205
 
323
- ## Function Length
206
+ Reports files whose total line count exceeds `max`.
324
207
 
325
- `maxFunctionLines` reports function-like declarations whose total span exceeds a configured limit.
208
+ ### `maxFunctionLines`
326
209
 
327
- - function declarations
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
- Violations include the function name when available, plus `startLine` and `endLine` details.
212
+ ### `folderizeCompoundFiles`
335
213
 
336
- ## Folderization
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
- `folderizeCompoundFiles` is structural. It does not depend on configured suffix lists.
216
+ ### `syncImports`
339
217
 
340
- Same-directory groups:
218
+ Validates and optionally fixes:
341
219
 
342
- ```txt
343
- src/api/user_route.ts
344
- src/api/user_schema.ts
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
- suggest:
224
+ Example targeted CLI usage:
349
225
 
350
- ```txt
351
- src/api/user/route.ts
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
- Repeated folder-prefix files are also detected:
230
+ ### `dry`
357
231
 
358
- ```txt
359
- src/api/user/user_route.ts
360
- ```
232
+ Registers canonical helper functions and reports exact normalized duplicates.
233
+
234
+ The first version is intentionally conservative:
361
235
 
362
- suggests:
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
- ```txt
365
- src/api/user/route.ts
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
- `check` only reports these candidates.
259
+ Supported canonical helper exports:
369
260
 
370
- `fix` may apply them only when `folderizeCompoundFiles.fix` is `true`, and it rewrites affected relative imports after the move.
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
- ## Import Sync
265
+ ## Lifecycle Hooks
373
266
 
374
- `syncImports()` and `code-discipline sync` use the same severity-aware config shape.
267
+ Hooks remain package-owned and generic:
375
268
 
376
- ```ts
377
- import { syncImports } from "@trebired/code-discipline";
269
+ - `beforeRun(context)`
270
+ - `afterRun(context, result)`
271
+ - `beforeMode(context)`
272
+ - `afterMode(context, result)`
378
273
 
379
- const result = await syncImports({
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
- Behavior:
276
+ - `mode`
277
+ - `projectRoot`
278
+ - `configPath`
279
+ - `config`
280
+ - mutable `state`
391
281
 
392
- - `fix: false` reports alias/import drift as violations
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
- `syncImports()` keeps its operational result fields and also returns `errors`, `warnings`, and `violations`.
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
- ## Logging
293
+ Available modes:
400
294
 
401
- When you provide a logger, discipline results are emitted through it. Trebired-style loggers are supported directly, and the package falls back safely when no logger is provided.
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
- The default/common logger adaptation path is powered by `@trebired/logger-adapter`, while `logging.adapter(event)` remains available when you want exact control over the emitted event shape.
299
+ ## Advanced Helpers
404
300
 
405
- ## Public API
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
- The package also exports the public TypeScript types for severity, rule config, results, violations, alias strategies, logging adapters, and source scan rows.
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,CAUzB;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,CA6ElC;AAED,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,CAAC"}
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
- errors: 0,
164
+ violationCount: 0,
168
165
  moved_files: 0,
169
166
  rewritten_files: 0,
170
167
  rewritten_imports: 0,
171
- warnings,
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
- discipline: {
179
- errors,
180
- warnings,
181
- },
175
+ violationCount: violations.length,
182
176
  });
183
177
  return {
184
- ok: errors === 0,
185
- errors,
178
+ ok: false,
179
+ violationCount: violations.length,
186
180
  moved_files: 0,
187
181
  rewritten_files: 0,
188
182
  rewritten_imports: 0,
189
- warnings,
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
- errors: 0,
203
+ violationCount: 0,
210
204
  moved_files: movedFiles,
211
205
  rewritten_files: rewriteState.rewrittenFiles,
212
206
  rewritten_imports: rewriteState.rewrittenImports,
213
- warnings: 0,
207
+ ruleResults: {},
214
208
  violations: [],
215
209
  };
216
210
  }