@hublo/sentinel 1.5.0-alpha.8 → 1.5.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/README.md +9 -7
- package/dist/bin/sentinel.js +61 -16
- package/dist/{chunk-KLEXJFJ6.js → chunk-43HQ6BVJ.js} +61 -15
- package/dist/{chunk-YQRDKWSH.js → chunk-IL5PPLXE.js} +11 -1
- package/dist/chunk-IL5PPLXE.js.map +1 -0
- package/dist/chunk-MOELAQPC.js +10365 -0
- package/dist/chunk-WBDBRGLV.js +214 -0
- package/dist/chunk-WBDBRGLV.js.map +1 -0
- package/dist/{chunk-AMCGMLPS.js → chunk-Y57KA4QS.js} +2 -2
- package/dist/index.d.ts +28 -1
- package/dist/index.js +4 -4
- package/dist/roles/build/nest/toolchain.js +68 -18
- package/dist/roles/build/nest/toolchain.js.map +1 -1
- package/dist/roles/static-analysis/config.d.ts +15 -1
- package/dist/roles/static-analysis/config.js +1 -1
- package/dist/roles/test/setup/jest-parity.js +2 -2
- package/dist/roles/test/setup/workspace-entry.js +2 -2
- package/dist/{validate-AWWMBSH5.js → validate-FRMENKHM.js} +2 -2
- package/docs/bundle-analysis-spec.md +272 -0
- package/docs/sql-verification-study.md +401 -0
- package/docs/static-analysis-adoption.md +285 -0
- package/docs/static-analysis-study.md +824 -18
- package/docs/typescript-adoption.md +1 -1
- package/docs/typescript-traces.md +27 -12
- package/docs/using-sentinel.md +22 -12
- package/docs/validating-a-change.md +185 -0
- package/lint/nest.json +98 -18
- package/lint/node.json +83 -3
- package/lint/react-lib.json +121 -31
- package/lint/react.json +101 -2
- package/package.json +27 -6
- package/plugins/hublo/no-palette-common.js +76 -0
- package/plugins/hublo/no-regex-lookbehind.js +70 -0
- package/plugins/hublo/require-reload-document.js +70 -0
- package/plugins/hublo.js +20 -145
- package/plugins/sonar-cognitive.js +108 -0
- package/dist/chunk-DKLQYGPI.js +0 -6466
- package/dist/chunk-EDFIVLUA.js +0 -100
- package/dist/chunk-EDFIVLUA.js.map +0 -1
- package/dist/chunk-YQRDKWSH.js.map +0 -1
- /package/dist/{chunk-AMCGMLPS.js.map → chunk-Y57KA4QS.js.map} +0 -0
|
@@ -147,7 +147,7 @@ $ sentinel --run --typescript --json --max-diagnostics 1
|
|
|
147
147
|
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
148
148
|
| `target(s) not available yet: --test` | only wired types run; `--help` lists what is available now vs planned |
|
|
149
149
|
| `preset is ambiguous, detected "react" ... also found sails` | a mixed stack; pass `--preset` to be explicit |
|
|
150
|
-
| `sentinel requires Node >=
|
|
150
|
+
| `sentinel requires Node >= 24.15` | run sentinel with a modern Node via `fnm`/`nvm`; the project's own Node is untouched |
|
|
151
151
|
| fresh version will not install (`minimumReleaseAge`) | `--init` allow-lists sentinel automatically when the root uses the gate; if you adopted by hand, add the package to `minimumReleaseAgeExclude` (or `--config.minimumReleaseAge=0`) until it ages |
|
|
152
152
|
| a translation-singleton test goes red after adopting a front module | `--init` handles this automatically when the root runs more than one TypeScript: adopting re-resolves pnpm and can duplicate a package with an optional, type-only `typescript` peer (e.g. i18next); `--init` pins that peer so it collapses to one instance |
|
|
153
153
|
|
|
@@ -1072,7 +1072,7 @@ $ sentinel --report --typescript --max-diagnostics 3.9 --module bff-admin
|
|
|
1072
1072
|
$ sentinel --init --dry-run
|
|
1073
1073
|
dry run: no files written
|
|
1074
1074
|
wrote .oxlintrc.json extending ./node_modules/@hublo/sentinel/lint/nest.json (@hublo/sentinel@<version>)
|
|
1075
|
-
|
|
1075
|
+
20 rule(s) not enforced by this preset (17 jest, 1 no-barrel-files, 1 core, 1 vitest). Run --inspect --lint for each rule and why.
|
|
1076
1076
|
run `pnpm install`, then `pnpm run lint`
|
|
1077
1077
|
|
|
1078
1078
|
create .oxlintrc.json
|
|
@@ -1156,7 +1156,7 @@ $ sentinel --init --dry-run
|
|
|
1156
1156
|
build: no Vite config in this module, so there is nothing to point at sentinel. This role moves an existing config's imports; it does not introduce a bundler. If this module builds another way (38 services here build through `@nx/webpack`), the build role does not apply to it.
|
|
1157
1157
|
test: this module has no test and no jest leftovers, so there is nothing to do here.
|
|
1158
1158
|
dry run: no files written
|
|
1159
|
-
added the three `static-analysis` scripts and static-analysis.config.mjs; declare this module's entry points
|
|
1159
|
+
added the three `static-analysis` scripts and static-analysis.config.mjs; declare this module's entry points there, everything else comes from the role
|
|
1160
1160
|
|
|
1161
1161
|
create static-analysis.config.mjs
|
|
1162
1162
|
+ import { defineStaticAnalysis } from '@hublo/sentinel/static-analysis'
|
|
@@ -1168,17 +1168,32 @@ $ sentinel --init --dry-run
|
|
|
1168
1168
|
+ // the patterns sentinel ships, never replacing them.
|
|
1169
1169
|
+ entry: [],
|
|
1170
1170
|
+
|
|
1171
|
-
+ //
|
|
1172
|
-
+ //
|
|
1173
|
-
+
|
|
1174
|
-
+
|
|
1175
|
-
+ //
|
|
1176
|
-
+ //
|
|
1177
|
-
+ //
|
|
1171
|
+
+ // ---------------------------------------------------------------------------------------------
|
|
1172
|
+
+ // What this module can move, with the role's value today. A setting you leave out keeps that
|
|
1173
|
+
+ // value; a setting you write REPLACES it, including inside a list. Anything you set is printed
|
|
1174
|
+
+ // under "measured with" in the report and marked `(module)`, because two modules measured with
|
|
1175
|
+
+ // different settings can no longer be compared.
|
|
1176
|
+
+ //
|
|
1177
|
+
+ // ignore 19 patterns
|
|
1178
|
+
+ // languages javascript, typescript, jsx, tsx, css, scss
|
|
1179
|
+
+ // duplication.minTokens 50
|
|
1180
|
+
+ // duplication.minLines 5
|
|
1181
|
+
+ // duplication.tests 3 patterns
|
|
1182
|
+
+ // deadCode.minConfidence 60
|
|
1183
|
+
+ // deadCode.categories unused-file, unused-export, unused-symbol, unused-import
|
|
1184
|
+
+ // graph.resolution 1
|
|
1185
|
+
+ //
|
|
1186
|
+
+ // A list shown as a count is not copyable, and replacing one means writing back what you keep,
|
|
1187
|
+
+ // so read the values in full with:
|
|
1188
|
+
+ //
|
|
1189
|
+
+ // pnpm exec sentinel --inspect --static-analysis --json
|
|
1190
|
+
+ //
|
|
1191
|
+
+ // duplication.kinds: only `exact` is supported: any other kind overlaps it and double-counts
|
|
1192
|
+
+ // tools: sentinel's own passthrough to the tool underneath; a module never names the vendor
|
|
1178
1193
|
+ //
|
|
1179
|
-
+ //
|
|
1180
|
-
+ //
|
|
1181
|
-
+ //
|
|
1194
|
+
+ // overrides: {
|
|
1195
|
+
+ // duplication: { minTokens: 100 },
|
|
1196
|
+
+ // },
|
|
1182
1197
|
+ })
|
|
1183
1198
|
|
|
1184
1199
|
update package.json
|
package/docs/using-sentinel.md
CHANGED
|
@@ -4,9 +4,10 @@ The commands, what an adopted module ends up looking like, and how versions move
|
|
|
4
4
|
migrating a module see [`lint-adoption.md`](lint-adoption.md),
|
|
5
5
|
[`format-adoption.md`](format-adoption.md),
|
|
6
6
|
[`typescript-adoption.md`](typescript-adoption.md),
|
|
7
|
-
[`build-adoption.md`](build-adoption.md)
|
|
8
|
-
[`test-adoption.md`](test-adoption.md)
|
|
9
|
-
|
|
7
|
+
[`build-adoption.md`](build-adoption.md),
|
|
8
|
+
[`test-adoption.md`](test-adoption.md) and
|
|
9
|
+
[`static-analysis-adoption.md`](static-analysis-adoption.md). The reference gate `--test` runs a
|
|
10
|
+
migration against is in `test-adoption.md`, not the static-analysis page.
|
|
10
11
|
|
|
11
12
|
## The grid
|
|
12
13
|
|
|
@@ -22,18 +23,25 @@ sentinel --run # no target -> every wired tar
|
|
|
22
23
|
Read it by target, since that is what you pick first. `--report` and `--status` are deprecated
|
|
23
24
|
everywhere (`--run --json` and `--inspect` answer them), and `--migrate` is refused everywhere.
|
|
24
25
|
|
|
25
|
-
| Target
|
|
26
|
-
|
|
|
27
|
-
| `--lint`
|
|
28
|
-
| `--format`
|
|
29
|
-
| `--typescript`
|
|
30
|
-
| `--build`
|
|
31
|
-
| `--dev`
|
|
32
|
-
| `--test`
|
|
26
|
+
| Target | `--init` writes | `--run` does | `--inspect` shows |
|
|
27
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
28
|
+
| `--lint` | stub + scripts + nx metadata, removes the ESLint config and the module's ESLint deps, then autofixes once | lints; `--fix` autofixes in the same pass | rule count, what is disabled or downgraded and **why**, drift |
|
|
29
|
+
| `--format` | materializes the preset + scripts + nx metadata, removes the Prettier config and deps, then formats once | **checks**; `--fix` writes | effective options, every departure from the standard and why |
|
|
30
|
+
| `--typescript` | writes/extends the tsconfig + `typecheck` script | typechecks | resolved options, what is deferred, drift |
|
|
31
|
+
| `--build` | points the module's Vite config at sentinel's toolchain + scripts + nx metadata | builds | runner, config file, whose Vite, how many overrides, adoption |
|
|
32
|
+
| `--dev` | adopts the BUILD too: one plan writes both `build` and `serve` | serves; long-running, so never swept by an unqualified `--run` | refuses, and sends you to `--inspect --build`: it is that config |
|
|
33
|
+
| `--test` | the Vitest config + scripts + nx metadata, and migrates every spec file | runs Vitest | runner, which configs were found, adoption state, drift |
|
|
34
|
+
| `--static-analysis` | the config stub + three scripts + nx metadata, and ignores the report directory at the repository root | measures and reports; never exits non-zero on a finding | runner, config file, resolved settings, what this module moved |
|
|
33
35
|
|
|
34
36
|
`--json` works for every verb, and stdout carries **only** the envelope, so `| jq` always
|
|
35
37
|
parses. `--dry-run` applies to `--init` and writes nothing.
|
|
36
38
|
|
|
39
|
+
`--output <shape>` is different, and only a role that WRITES a report reads it: `console` is the
|
|
40
|
+
default and writes no file, `html` is the page you open and send, `json` is for CI and for a
|
|
41
|
+
script, `markdown` is the six lines a workflow posts on a pull request. Today `--static-analysis`
|
|
42
|
+
is the role that has them. ⚠️ `--output html` pays a graph layout the other three skip, which is
|
|
43
|
+
fine for a page somebody opens and wrong for a commit hook.
|
|
44
|
+
|
|
37
45
|
**`--validate` is a verb of its own**, and the proof of a migration lives there rather than on
|
|
38
46
|
`--init` or `--run`. Run before a migration it records what the module does today; run after, it
|
|
39
47
|
compares by test NAME and refuses a run that lost one or invented one. What separates it from
|
|
@@ -100,7 +108,9 @@ These options can weaken a check as easily as strengthen it, and `--run` is what
|
|
|
100
108
|
|
|
101
109
|
## What a fully adopted module looks like
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
Five files once a module has adopted every role, and none of them holds a rule. The fifth is
|
|
112
|
+
`static-analysis.config.mjs`, which holds the only thing that role asks a team to declare: the files
|
|
113
|
+
that run although nothing imports them.
|
|
104
114
|
|
|
105
115
|
```jsonc
|
|
106
116
|
// .oxlintrc.json — the rules come from the preset; the ignores must be here, because oxlint
|
|
@@ -132,3 +132,188 @@ package that looks missing.
|
|
|
132
132
|
what a module looks like once you have thought about it. Measured on the real monorepo: 22 of 37
|
|
133
133
|
Nest services have none at all. A change that looked complete against 64 test files refused the
|
|
134
134
|
majority of the migration, and only a sweep over every real module found it.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## The static analysis role's validation matrix, 19 October 2026
|
|
139
|
+
|
|
140
|
+
Re-run from scratch because **53 commits landed on the role since 13 October**, and three of them
|
|
141
|
+
added an AXIS the earlier matrix has no column for: the `markdown` recap, `--output` taking a list,
|
|
142
|
+
and a front whose build produced no files. A matrix that does not grow with the tool is a claim of
|
|
143
|
+
coverage that stopped being true.
|
|
144
|
+
|
|
145
|
+
39 cells, six real modules, one log per cell.
|
|
146
|
+
|
|
147
|
+
### output shape × module, from the module's own directory
|
|
148
|
+
|
|
149
|
+
| | console | json | html | markdown |
|
|
150
|
+
| --------------------------------- | ------- | ---- | ---- | -------- |
|
|
151
|
+
| `console`, react with a build | 0 | 0 | 0 | 0 |
|
|
152
|
+
| `host-admin`, react with NO build | 0 | 0 | 0 | 0 |
|
|
153
|
+
| `institution`, nest | 0 | 0 | 0 | 0 |
|
|
154
|
+
| `hr-management`, svelte | 0 | 0 | 0 | 0 |
|
|
155
|
+
| `libs/front/components`, library | 0 | 0 | 0 | 0 |
|
|
156
|
+
| `libs/nest/auth`, nest library | 0 | 0 | 0 | 0 |
|
|
157
|
+
|
|
158
|
+
⭐ The second row is new and it earned its place: the two defects found this week both live there.
|
|
159
|
+
A front that declares a build and produced no files is not a front without a bundle, and the role
|
|
160
|
+
said the same sentence to both until it was pointed at one.
|
|
161
|
+
|
|
162
|
+
### `--output` taking a LIST, which did not exist on 13 October
|
|
163
|
+
|
|
164
|
+
| | exit | files written |
|
|
165
|
+
| -------------------- | ---: | ---------------------------------- |
|
|
166
|
+
| `html,json` | 0 | html, json, svg |
|
|
167
|
+
| `json,html` | 0 | html, json, svg, same as above |
|
|
168
|
+
| `json,json` | 0 | **json only**, the duplicate drops |
|
|
169
|
+
| `markdown,html,json` | 0 | html, json, md, svg |
|
|
170
|
+
|
|
171
|
+
### from the workspace ROOT rather than the module
|
|
172
|
+
|
|
173
|
+
| | exit |
|
|
174
|
+
| ---------------------------------------------- | ---: |
|
|
175
|
+
| `--run --static-analysis --module console` | 0 |
|
|
176
|
+
| `--run --static-analysis --module institution` | 0 |
|
|
177
|
+
| `--inspect --static-analysis --json` | 0 |
|
|
178
|
+
|
|
179
|
+
### the forms that must REFUSE
|
|
180
|
+
|
|
181
|
+
| | exit | what it says |
|
|
182
|
+
| ------------------- | ----: | ------------------------------------------------------------------ |
|
|
183
|
+
| `--output pdf` | **1** | `unknown --output "pdf" (known: console, json, html, markdown; …)` |
|
|
184
|
+
| `--output html,pdf` | **1** | the same, naming the whole list it was given |
|
|
185
|
+
| `--output ,` | **1** | an empty list refuses rather than falling back to the console |
|
|
186
|
+
| `--module <absent>` | **1** | `sentinel: module "…" not found in the workspace` |
|
|
187
|
+
|
|
188
|
+
⚠️ The first cell is where the earlier matrix had gone stale: it answered `known: console, json,
|
|
189
|
+
html`, and `markdown` had been shippable for days.
|
|
190
|
+
|
|
191
|
+
### ⭐ What the matrix proves, beyond an exit code
|
|
192
|
+
|
|
193
|
+
| invariant | result |
|
|
194
|
+
| --------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
195
|
+
| json, markdown and html report the SAME figures | **174 figures compared, 0 disagreement** |
|
|
196
|
+
| a list writes one file per shape, and a repeat writes one | held on both modules |
|
|
197
|
+
| a list costs ONE measurement, not one per shape | `console` 6.4 s in three runs, **2.6 s** in one; `institution` 10.9 s against **6.3 s** |
|
|
198
|
+
|
|
199
|
+
The third one is why `--output` learned to take a list: the measurement is the whole cost of this
|
|
200
|
+
role and rendering is under a second, so asking for the page and the recap used to pay for the
|
|
201
|
+
analysis twice.
|
|
202
|
+
|
|
203
|
+
### ⚠️ The bench lied twice before it told the truth
|
|
204
|
+
|
|
205
|
+
Both times it would have been reported as a defect of the role:
|
|
206
|
+
|
|
207
|
+
| what the bench did | what it would have claimed |
|
|
208
|
+
| ------------------------------------------------------------- | -------------------------- |
|
|
209
|
+
| a character class that swallowed the newline, reading `0\n>` | one figure disagreeing |
|
|
210
|
+
| comparing `29 entries` from the recap with `29` from the page | **150 disagreements** |
|
|
211
|
+
|
|
212
|
+
Comparing the NUMBER rather than the string is what made the invariant mean something. An
|
|
213
|
+
instrument is validated before its measurement is believed, and a matrix that reports a defect of
|
|
214
|
+
itself is the most expensive kind.
|
|
215
|
+
|
|
216
|
+
### What this matrix does NOT cover, said so nobody assumes it does
|
|
217
|
+
|
|
218
|
+
- `--init --static-analysis`: it WRITES, and this matrix runs against a shared tree. Covered by the
|
|
219
|
+
adoption pull requests and the e2e suite.
|
|
220
|
+
- a module that has ADOPTED the role, for the same reason: no module on this branch carries a
|
|
221
|
+
`static-analysis.config.mjs`. The four adoption pull requests are where that axis lives.
|
|
222
|
+
- `--ci`, which needs a diff against a base to mean anything. The pull-request recap covers it, on
|
|
223
|
+
three probe pull requests of 1, 2 and 5 modules.
|
|
224
|
+
- the `node` and `tools` presets: no module of either carries the evidence the branches react to.
|
|
225
|
+
|
|
226
|
+
## The static analysis role's validation matrix, 13 October 2026
|
|
227
|
+
|
|
228
|
+
A matrix is a claim of coverage, so a partial one is worse than none: everyone then believes the
|
|
229
|
+
thing was checked. The axes are the tool's, not a sample of them.
|
|
230
|
+
|
|
231
|
+
**Run on real modules, never on fixtures.** The branches that break are reached by what a real
|
|
232
|
+
module carries, a `.svelte` file, a module with no `src/`, a library whose reachability is decided
|
|
233
|
+
outside it. A synthetic temp module cannot reach them, so running it a thousand times proves
|
|
234
|
+
nothing. Logs: one per cell.
|
|
235
|
+
|
|
236
|
+
### verb × output shape × preset, from the module's own directory
|
|
237
|
+
|
|
238
|
+
| | console | json | html | `--inspect` | `--inspect --json` |
|
|
239
|
+
| ----------------------- | ------- | ---- | ---- | ----------- | ------------------ |
|
|
240
|
+
| `console`, react | 0 | 0 | 0 | 0 | 0 |
|
|
241
|
+
| `contract`, nest | 0 | 0 | 0 | 0 | 0 |
|
|
242
|
+
| `hr-management`, svelte | 0 | 0 | 0 | 0 | 0 |
|
|
243
|
+
|
|
244
|
+
### the module states that take a different path
|
|
245
|
+
|
|
246
|
+
| | | exit |
|
|
247
|
+
| ---------------- | -------------------------------------------------------- | ---: |
|
|
248
|
+
| `network` | a module that has NOT adopted | 0 |
|
|
249
|
+
| `libs/nest/auth` | a library, whose dead code is decided outside the module | 0 |
|
|
250
|
+
| `libs/nest/auth` | `--inspect` on the same | 0 |
|
|
251
|
+
|
|
252
|
+
### from the workspace ROOT rather than the module
|
|
253
|
+
|
|
254
|
+
| | exit |
|
|
255
|
+
| ------------------------------------------- | ---: |
|
|
256
|
+
| `--run --static-analysis --module console` | 0 |
|
|
257
|
+
| `--run --static-analysis --module contract` | 0 |
|
|
258
|
+
| `--inspect --static-analysis --json` | 0 |
|
|
259
|
+
|
|
260
|
+
### the forms that must REFUSE, and what they say
|
|
261
|
+
|
|
262
|
+
| | exit | message |
|
|
263
|
+
| --------------------------------- | ----: | ----------------------------------------------------- |
|
|
264
|
+
| `--output pdf` | **1** | `unknown --output "pdf" (known: console, json, html)` |
|
|
265
|
+
| `--module ce-module-n-existe-pas` | **1** | `sentinel: module "…" not found in the workspace` |
|
|
266
|
+
|
|
267
|
+
### ⭐ What the matrix actually proves, beyond an exit code
|
|
268
|
+
|
|
269
|
+
An exit code is a smoke test. Two invariants were checked by comparing the sorted figure lines of
|
|
270
|
+
each run, as a hash:
|
|
271
|
+
|
|
272
|
+
| invariant | result |
|
|
273
|
+
| -------------------------------------------------------------------------- | ----------------------------------- |
|
|
274
|
+
| the three output shapes report the SAME figures | identical on react, nest and svelte |
|
|
275
|
+
| a module measured from its own directory and from the root with `--module` | **identical** |
|
|
276
|
+
|
|
277
|
+
The second one matters because the two paths resolve the module differently, and a report that
|
|
278
|
+
changed with the caller's working directory would make every figure uncomparable.
|
|
279
|
+
|
|
280
|
+
### Two timings the cells show, neither of them a defect
|
|
281
|
+
|
|
282
|
+
| | first run of a session | run again |
|
|
283
|
+
| --------------------------------------- | ---------------------: | ------------: |
|
|
284
|
+
| `console` from its own directory | 22 188 ms | **2 648 ms** |
|
|
285
|
+
| `console` from the root with `--module` | 45 046 ms | **18 374 ms** |
|
|
286
|
+
|
|
287
|
+
**The first cell of a session pays for the consumer index**, the one scan of the workspace that
|
|
288
|
+
decides a library's reachability; every cell after it reads the cache. Reading the first number as
|
|
289
|
+
the role's cost is the mistake this table exists to prevent.
|
|
290
|
+
|
|
291
|
+
**From the root costs about 16 seconds more, whatever the module**, warm: 18.4 s against 2.6 s on
|
|
292
|
+
react, 17.9 s on nest. The root form resolves the workspace before it can target one module. It is
|
|
293
|
+
the right form for CI and the wrong one for a developer in a loop, and the adoption guide says to
|
|
294
|
+
run the script from the module.
|
|
295
|
+
|
|
296
|
+
### What this matrix does NOT cover, said so nobody assumes it does
|
|
297
|
+
|
|
298
|
+
- `--init --static-analysis` on a module that has never adopted. Covered by the adoption branch and
|
|
299
|
+
by the e2e suite, not re-run here, because it WRITES and this matrix runs against a shared tree.
|
|
300
|
+
- `--ci` (affected only), which needs a diff against a base to mean anything.
|
|
301
|
+
- the `node` and `tools` presets: no module of either carries the evidence the branches react to,
|
|
302
|
+
so the cells would be green without proving anything.
|
|
303
|
+
- a module whose oxlint binary cannot be resolved. The role reports "not measured" there rather than
|
|
304
|
+
zero, and that path is covered by a unit test instead.
|
|
305
|
+
|
|
306
|
+
### Beside it: the whole-repository sweep, same day
|
|
307
|
+
|
|
308
|
+
| | modules | exit 0 | defects |
|
|
309
|
+
| -------------------------- | ------: | ------: | ------: |
|
|
310
|
+
| `apps/front` | 5 | 5 | 0 |
|
|
311
|
+
| `apps/nest` + `apps/cloud` | 241 | 241 | 0 |
|
|
312
|
+
| `libs` | 150 | 150 | 0 |
|
|
313
|
+
| **total** | **396** | **396** | **0** |
|
|
314
|
+
|
|
315
|
+
⚠️ The sweep found no defect in the role and two in what the role was SAYING: a help line claiming
|
|
316
|
+
the gauge and the graph read the same population, false for any module with a stylesheet, and the
|
|
317
|
+
same line again on `apps/cloud/interop`, where a bare `staffea` in the repository's `.gitignore`
|
|
318
|
+
hides 34 tracked files from every tool that consumes gitignore patterns. Both are corrected; the
|
|
319
|
+
second is monorepo #22358.
|
package/lint/nest.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"plugins": [
|
|
4
4
|
"typescript",
|
|
5
5
|
"jest",
|
|
6
|
+
"vitest",
|
|
6
7
|
"import",
|
|
7
8
|
"unicorn",
|
|
8
9
|
"oxc",
|
|
@@ -93,27 +94,27 @@
|
|
|
93
94
|
"prefer-inline": true
|
|
94
95
|
}
|
|
95
96
|
],
|
|
96
|
-
"jest/expect-expect": "
|
|
97
|
-
"jest/no-alias-methods": "
|
|
98
|
-
"jest/no-commented-out-tests": "
|
|
97
|
+
"jest/expect-expect": "off",
|
|
98
|
+
"jest/no-alias-methods": "off",
|
|
99
|
+
"jest/no-commented-out-tests": "off",
|
|
99
100
|
"jest/no-deprecated-functions": "error",
|
|
100
|
-
"jest/no-disabled-tests": "
|
|
101
|
+
"jest/no-disabled-tests": "off",
|
|
101
102
|
"jest/no-done-callback": "error",
|
|
102
103
|
"jest/no-export": "error",
|
|
103
|
-
"jest/no-focused-tests": "
|
|
104
|
-
"jest/no-identical-title": "
|
|
105
|
-
"jest/no-interpolation-in-snapshots": "
|
|
104
|
+
"jest/no-focused-tests": "off",
|
|
105
|
+
"jest/no-identical-title": "off",
|
|
106
|
+
"jest/no-interpolation-in-snapshots": "off",
|
|
106
107
|
"jest/no-jasmine-globals": "error",
|
|
107
|
-
"jest/no-mocks-import": "
|
|
108
|
-
"jest/no-standalone-expect": "
|
|
109
|
-
"jest/no-test-prefixes": "
|
|
110
|
-
"jest/prefer-to-be": "
|
|
111
|
-
"jest/prefer-to-contain": "
|
|
112
|
-
"jest/prefer-to-have-length": "
|
|
113
|
-
"jest/valid-describe-callback": "
|
|
114
|
-
"jest/valid-expect": "
|
|
115
|
-
"jest/valid-expect-in-promise": "
|
|
116
|
-
"jest/valid-title": "
|
|
108
|
+
"jest/no-mocks-import": "off",
|
|
109
|
+
"jest/no-standalone-expect": "off",
|
|
110
|
+
"jest/no-test-prefixes": "off",
|
|
111
|
+
"jest/prefer-to-be": "off",
|
|
112
|
+
"jest/prefer-to-contain": "off",
|
|
113
|
+
"jest/prefer-to-have-length": "off",
|
|
114
|
+
"jest/valid-describe-callback": "off",
|
|
115
|
+
"jest/valid-expect": "off",
|
|
116
|
+
"jest/valid-expect-in-promise": "off",
|
|
117
|
+
"jest/valid-title": "off",
|
|
117
118
|
"no-async-promise-executor": "error",
|
|
118
119
|
"no-case-declarations": "error",
|
|
119
120
|
"no-compare-neg-zero": "error",
|
|
@@ -347,12 +348,91 @@
|
|
|
347
348
|
{
|
|
348
349
|
"requireStringLiterals": false
|
|
349
350
|
}
|
|
350
|
-
]
|
|
351
|
+
],
|
|
352
|
+
"vitest/expect-expect": "warn",
|
|
353
|
+
"vitest/no-alias-methods": "error",
|
|
354
|
+
"vitest/no-commented-out-tests": "warn",
|
|
355
|
+
"vitest/no-conditional-expect": "warn",
|
|
356
|
+
"vitest/no-disabled-tests": "warn",
|
|
357
|
+
"vitest/no-focused-tests": "error",
|
|
358
|
+
"vitest/no-identical-title": "error",
|
|
359
|
+
"vitest/no-interpolation-in-snapshots": "error",
|
|
360
|
+
"vitest/no-mocks-import": "error",
|
|
361
|
+
"vitest/no-standalone-expect": "error",
|
|
362
|
+
"vitest/no-test-prefixes": "error",
|
|
363
|
+
"vitest/prefer-to-be": "error",
|
|
364
|
+
"vitest/prefer-to-contain": "error",
|
|
365
|
+
"vitest/prefer-to-have-length": "error",
|
|
366
|
+
"vitest/require-mock-type-parameters": "off",
|
|
367
|
+
"vitest/require-to-throw-message": "warn",
|
|
368
|
+
"vitest/valid-describe-callback": "error",
|
|
369
|
+
"vitest/valid-expect": "warn",
|
|
370
|
+
"vitest/valid-expect-in-promise": "error",
|
|
371
|
+
"vitest/valid-title": "error",
|
|
372
|
+
"vitest/warn-todo": "warn"
|
|
351
373
|
},
|
|
352
374
|
"jsPlugins": [
|
|
353
375
|
{
|
|
354
376
|
"name": "nx",
|
|
355
377
|
"specifier": "@nx/eslint-plugin"
|
|
356
378
|
}
|
|
379
|
+
],
|
|
380
|
+
"overrides": [
|
|
381
|
+
{
|
|
382
|
+
"files": [
|
|
383
|
+
"**/*.test.ts",
|
|
384
|
+
"**/*.test.tsx",
|
|
385
|
+
"**/*.spec.ts",
|
|
386
|
+
"**/*.spec.tsx",
|
|
387
|
+
"**/*.integration-spec.ts",
|
|
388
|
+
"**/*.e2e-spec.ts"
|
|
389
|
+
],
|
|
390
|
+
"rules": {
|
|
391
|
+
"no-restricted-properties": [
|
|
392
|
+
"warn",
|
|
393
|
+
{
|
|
394
|
+
"object": "Math",
|
|
395
|
+
"property": "random",
|
|
396
|
+
"message": "No Math.random() in a test: use a deterministic fixture, or stub the random source."
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
"object": "Date",
|
|
400
|
+
"property": "now",
|
|
401
|
+
"message": "No Date.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"object": "performance",
|
|
405
|
+
"property": "now",
|
|
406
|
+
"message": "No performance.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"object": "process",
|
|
410
|
+
"property": "hrtime",
|
|
411
|
+
"message": "No process.hrtime in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"object": "crypto",
|
|
415
|
+
"property": "randomUUID",
|
|
416
|
+
"message": "No crypto.randomUUID() in a test: use a fixed id, or stub the random source."
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
"object": "crypto",
|
|
420
|
+
"property": "getRandomValues",
|
|
421
|
+
"message": "No crypto.getRandomValues() in a test: use a fixed buffer, or stub the random source."
|
|
422
|
+
}
|
|
423
|
+
],
|
|
424
|
+
"no-restricted-globals": [
|
|
425
|
+
"warn",
|
|
426
|
+
{
|
|
427
|
+
"name": "setTimeout",
|
|
428
|
+
"message": "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"name": "setInterval",
|
|
432
|
+
"message": "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
433
|
+
}
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
}
|
|
357
437
|
]
|
|
358
438
|
}
|
package/lint/node.json
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
3
3
|
"plugins": [
|
|
4
4
|
"typescript",
|
|
5
|
-
"oxc"
|
|
5
|
+
"oxc",
|
|
6
|
+
"vitest"
|
|
6
7
|
],
|
|
7
8
|
"categories": {
|
|
8
9
|
"correctness": "off",
|
|
@@ -47,6 +48,85 @@
|
|
|
47
48
|
"typescript/no-wrapper-object-types": "error",
|
|
48
49
|
"typescript/prefer-as-const": "error",
|
|
49
50
|
"typescript/prefer-namespace-keyword": "error",
|
|
50
|
-
"typescript/triple-slash-reference": "error"
|
|
51
|
-
|
|
51
|
+
"typescript/triple-slash-reference": "error",
|
|
52
|
+
"vitest/expect-expect": "warn",
|
|
53
|
+
"vitest/no-alias-methods": "warn",
|
|
54
|
+
"vitest/no-commented-out-tests": "warn",
|
|
55
|
+
"vitest/no-conditional-expect": "warn",
|
|
56
|
+
"vitest/no-disabled-tests": "warn",
|
|
57
|
+
"vitest/no-focused-tests": "warn",
|
|
58
|
+
"vitest/no-identical-title": "warn",
|
|
59
|
+
"vitest/no-interpolation-in-snapshots": "warn",
|
|
60
|
+
"vitest/no-mocks-import": "warn",
|
|
61
|
+
"vitest/no-standalone-expect": "warn",
|
|
62
|
+
"vitest/no-test-prefixes": "warn",
|
|
63
|
+
"vitest/prefer-to-be": "warn",
|
|
64
|
+
"vitest/prefer-to-contain": "warn",
|
|
65
|
+
"vitest/prefer-to-have-length": "warn",
|
|
66
|
+
"vitest/require-mock-type-parameters": "off",
|
|
67
|
+
"vitest/require-to-throw-message": "warn",
|
|
68
|
+
"vitest/valid-describe-callback": "warn",
|
|
69
|
+
"vitest/valid-expect": "warn",
|
|
70
|
+
"vitest/valid-expect-in-promise": "warn",
|
|
71
|
+
"vitest/valid-title": "warn",
|
|
72
|
+
"vitest/warn-todo": "warn"
|
|
73
|
+
},
|
|
74
|
+
"overrides": [
|
|
75
|
+
{
|
|
76
|
+
"files": [
|
|
77
|
+
"**/*.test.ts",
|
|
78
|
+
"**/*.test.tsx",
|
|
79
|
+
"**/*.spec.ts",
|
|
80
|
+
"**/*.spec.tsx",
|
|
81
|
+
"**/*.integration-spec.ts",
|
|
82
|
+
"**/*.e2e-spec.ts"
|
|
83
|
+
],
|
|
84
|
+
"rules": {
|
|
85
|
+
"no-restricted-properties": [
|
|
86
|
+
"warn",
|
|
87
|
+
{
|
|
88
|
+
"object": "Math",
|
|
89
|
+
"property": "random",
|
|
90
|
+
"message": "No Math.random() in a test: use a deterministic fixture, or stub the random source."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"object": "Date",
|
|
94
|
+
"property": "now",
|
|
95
|
+
"message": "No Date.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"object": "performance",
|
|
99
|
+
"property": "now",
|
|
100
|
+
"message": "No performance.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"object": "process",
|
|
104
|
+
"property": "hrtime",
|
|
105
|
+
"message": "No process.hrtime in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"object": "crypto",
|
|
109
|
+
"property": "randomUUID",
|
|
110
|
+
"message": "No crypto.randomUUID() in a test: use a fixed id, or stub the random source."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"object": "crypto",
|
|
114
|
+
"property": "getRandomValues",
|
|
115
|
+
"message": "No crypto.getRandomValues() in a test: use a fixed buffer, or stub the random source."
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"no-restricted-globals": [
|
|
119
|
+
"warn",
|
|
120
|
+
{
|
|
121
|
+
"name": "setTimeout",
|
|
122
|
+
"message": "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "setInterval",
|
|
126
|
+
"message": "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
]
|
|
52
132
|
}
|