@hublo/sentinel 1.3.0 → 1.4.0-alpha.2
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 +8 -4
- package/dist/bin/sentinel.d.ts +0 -1
- package/dist/bin/sentinel.js +22 -8
- package/dist/chunk-2XLX6PFR.js +132 -0
- package/dist/chunk-3TDUIKVQ.js +178 -0
- package/dist/{chunk-676GBPMS.js → chunk-4UIZJ3TR.js} +3399 -549
- package/dist/chunk-CPCUPK4J.js +70 -0
- package/dist/chunk-NX4GHIHF.js +25 -0
- package/dist/chunk-PWV3BMDA.js +15 -0
- package/dist/chunk-WLFE5RUU.js +264 -0
- package/dist/index.js +2 -1
- package/dist/roles/build/nest/toolchain.d.ts +4 -36
- package/dist/roles/build/nest/toolchain.js +10 -178
- package/dist/roles/build/nest/toolchain.js.map +1 -0
- package/dist/roles/build/toolchain.js.map +1 -0
- package/dist/roles/test/nest/toolchain.d.ts +29 -0
- package/dist/roles/test/nest/toolchain.js +289 -0
- package/dist/roles/test/nest/toolchain.js.map +1 -0
- package/dist/roles/test/react/toolchain.d.ts +62 -0
- package/dist/roles/test/react/toolchain.js +5 -0
- package/dist/roles/test/react/toolchain.js.map +1 -0
- package/dist/roles/test/setup/mock-extended.d.ts +46 -0
- package/dist/roles/test/setup/mock-extended.js +65 -0
- package/dist/roles/test/setup/mock-extended.js.map +1 -0
- package/dist/roles/test/setup/msw-lifecycle.d.ts +16 -0
- package/dist/roles/test/setup/msw-lifecycle.js +12 -0
- package/dist/roles/test/setup/msw-lifecycle.js.map +1 -0
- package/dist/roles/test/setup/msw-server.d.ts +3 -0
- package/dist/roles/test/setup/msw-server.js +10 -0
- package/dist/roles/test/setup/msw-server.js.map +1 -0
- package/dist/roles/test/setup/nest.d.ts +2 -0
- package/dist/roles/test/setup/nest.js +159 -0
- package/dist/roles/test/setup/nest.js.map +1 -0
- package/dist/roles/test/setup/workspace-entry.d.ts +2 -0
- package/dist/roles/test/setup/workspace-entry.js +8 -0
- package/dist/roles/test/setup/workspace-entry.js.map +1 -0
- package/dist/tsconfig-aliases-Ce6axdJ4.d.ts +36 -0
- package/docs/.gitkeep +0 -0
- package/docs/build-adoption.md +521 -0
- package/docs/format-adoption.md +321 -0
- package/docs/lint-adoption.md +290 -0
- package/docs/performance.md +49 -0
- package/docs/test-adoption.md +175 -0
- package/docs/typescript-adoption.md +184 -0
- package/docs/typescript-traces.md +798 -0
- package/docs/using-sentinel.md +180 -0
- package/docs/validating-a-change.md +101 -0
- package/package.json +32 -5
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Using sentinel
|
|
2
|
+
|
|
3
|
+
The commands, what an adopted module ends up looking like, and how versions move. For
|
|
4
|
+
migrating a module see [`lint-adoption.md`](lint-adoption.md),
|
|
5
|
+
[`format-adoption.md`](format-adoption.md),
|
|
6
|
+
[`typescript-adoption.md`](typescript-adoption.md) and
|
|
7
|
+
[`build-adoption.md`](build-adoption.md).
|
|
8
|
+
|
|
9
|
+
## The grid
|
|
10
|
+
|
|
11
|
+
A command is **verb + target + location**.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
sentinel --run --lint # in a module dir -> that module
|
|
15
|
+
sentinel --run --lint --module bff-admin # from the root -> one module
|
|
16
|
+
sentinel --run --ci # from the root -> affected only
|
|
17
|
+
sentinel --run # no target -> every wired target
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| Verb | `--lint` | `--format` | `--typescript` |
|
|
21
|
+
| ----------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
|
22
|
+
| `--init` | stub + scripts + nx cache metadata, removes the ESLint config and the module's ESLint deps, then runs oxlint's autofix once | materializes the preset + scripts + nx cache metadata, removes the Prettier config and deps, then formats the module once | writes/extends the tsconfig + `typecheck` script |
|
|
23
|
+
| `--run` | lints; `--fix` autofixes in the same pass | **checks**; `--fix` writes | typechecks |
|
|
24
|
+
| `--inspect` | rule count, what is disabled or downgraded and **why**, adoption, drift | effective options, every option that departs from the standard and why, adoption, drift | resolved options, what is deferred, adoption, drift |
|
|
25
|
+
| `--report` | error and warning counts with a per-rule breakdown | how many files are unformatted, and which | error counts |
|
|
26
|
+
| `--status` | deprecated, `--inspect` answers this and more | same | same |
|
|
27
|
+
| `--migrate` | planned, refused for now | same | same |
|
|
28
|
+
|
|
29
|
+
`--json` works for every verb, and stdout carries **only** the envelope, so `| jq` always
|
|
30
|
+
parses. `--dry-run` applies to `--init` and writes nothing.
|
|
31
|
+
|
|
32
|
+
`--init` is the one verb that targets exactly **one** module. Adopting everything at once
|
|
33
|
+
would be a big-bang; migration is meant to be gradual and per-team.
|
|
34
|
+
|
|
35
|
+
## When a role has nothing to do here
|
|
36
|
+
|
|
37
|
+
Adoption is per role, not per module, and a role declines when **its own tool** has nothing to
|
|
38
|
+
read. Run in `apps/front/maintenance`, which is a static `index.html`, a stylesheet and an SVG:
|
|
39
|
+
|
|
40
|
+
```console
|
|
41
|
+
$ sentinel --init
|
|
42
|
+
lint: no file oxlint can read (looked for .js, .mjs, .cjs, .jsx, .ts, ...), so there is
|
|
43
|
+
nothing to lint here. Other roles may still apply: the formatter reads markdown,
|
|
44
|
+
YAML, HTML and CSS too.
|
|
45
|
+
typescript: no TypeScript here (looked for .ts, .mts, .cts, .tsx), so there is nothing
|
|
46
|
+
for tsc to check.
|
|
47
|
+
wrote .oxfmtrc.json
|
|
48
|
+
...
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Two roles decline, the formatter adopts, and the command **exits 0**. Nothing failed: the
|
|
52
|
+
module simply is what it is. "Not a TypeScript project" would have been the wrong question,
|
|
53
|
+
since oxfmt has real work in exactly that module.
|
|
54
|
+
|
|
55
|
+
Declining matters for the numbers as much as the tidiness. A lint config written for a module
|
|
56
|
+
with nothing to lint reports as covered on the migration page, forever, while checking an
|
|
57
|
+
empty set.
|
|
58
|
+
|
|
59
|
+
The check names what it looked for, so you can disagree with it. It searches the whole module
|
|
60
|
+
rather than assuming `src/` (code lives in `lib/`, `scripts/` and at the root here too), stops
|
|
61
|
+
at the first match, and never descends into `node_modules` or build output: 0.1ms on a
|
|
62
|
+
4210-file module, 47ms in the pathological case where nothing matches anywhere.
|
|
63
|
+
|
|
64
|
+
## Asking the tool your own question
|
|
65
|
+
|
|
66
|
+
Everything after `--` goes to the underlying tool, on `--run` only, with one target named:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
sentinel --run --typescript -- --noImplicitAny # what would this deferred rule cost?
|
|
70
|
+
sentinel --run --lint -- --deny-warnings # what would zero warnings take?
|
|
71
|
+
sentinel --run --lint --fix -- src/a.ts src/b.ts # only these files (what a commit hook wants)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
A trailing argument is a **file** when it exists on disk, and a tool **option** otherwise.
|
|
75
|
+
That is why `-- -D no-console` still works: `no-console` is not a file.
|
|
76
|
+
|
|
77
|
+
A run carrying your own options says so on stderr and marks itself in the `--json` envelope.
|
|
78
|
+
These options can weaken a check as easily as strengthen it, and `--run` is what CI calls.
|
|
79
|
+
|
|
80
|
+
## What a fully adopted module looks like
|
|
81
|
+
|
|
82
|
+
Four files, and none of them holds a rule.
|
|
83
|
+
|
|
84
|
+
```jsonc
|
|
85
|
+
// .oxlintrc.json — the rules come from the preset; the ignores must be here, because oxlint
|
|
86
|
+
// does not inherit them through `extends`
|
|
87
|
+
{
|
|
88
|
+
"extends": ["./node_modules/@hublo/sentinel/oxlint/react.json"],
|
|
89
|
+
"ignorePatterns": ["**/dist/**", "**/node_modules/**", "..."],
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```jsonc
|
|
94
|
+
// .oxfmtrc.json — MATERIALIZED, because oxfmt has no `extends` and ignores the key silently.
|
|
95
|
+
// `$sentinel.local` names the options this module deliberately owns; a re-init keeps exactly
|
|
96
|
+
// those and refreshes the rest.
|
|
97
|
+
{
|
|
98
|
+
"$sentinel": { "preset": "base", "version": "1.1.0", "local": ["printWidth"] },
|
|
99
|
+
"printWidth": 100,
|
|
100
|
+
"semi": false,
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```jsonc
|
|
105
|
+
// tsconfig.json — composes the repo base with the sentinel preset
|
|
106
|
+
{
|
|
107
|
+
"extends": ["../../tsconfig.base.json", "@hublo/sentinel/tsconfig/react"],
|
|
108
|
+
"include": ["src"],
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```jsonc
|
|
113
|
+
// package.json
|
|
114
|
+
{
|
|
115
|
+
"scripts": {
|
|
116
|
+
// `lint` checks BOTH, the way `prettier --check . && eslint .` used to. In the :fix pair
|
|
117
|
+
// the formatter runs LAST, because the linter's autofix rewrites code.
|
|
118
|
+
"lint": "sentinel --run --lint && sentinel --run --format",
|
|
119
|
+
"lint:fix": "sentinel --run --lint --fix && sentinel --run --format --fix",
|
|
120
|
+
"format": "sentinel --run --format",
|
|
121
|
+
"format:fix": "sentinel --run --format --fix",
|
|
122
|
+
"typecheck": "sentinel --run --typescript",
|
|
123
|
+
},
|
|
124
|
+
"devDependencies": { "@hublo/sentinel": "1.1.0" },
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The `nx` block carries what only nx needs: which inputs invalidate the cache. **Not the
|
|
129
|
+
command.** `pnpm run lint` has to work whatever orchestrates the module, so nx must not be the
|
|
130
|
+
only thing that knows how to check it; nx infers the target from the script, which it does
|
|
131
|
+
even when the module also has a `project.json`.
|
|
132
|
+
|
|
133
|
+
```jsonc
|
|
134
|
+
// package.json, continued
|
|
135
|
+
"nx": {
|
|
136
|
+
"targets": {
|
|
137
|
+
"lint": { "cache": true, "inputs": ["default", "{projectRoot}/.oxlintrc.json"] },
|
|
138
|
+
"format": { "cache": true, "inputs": ["default", "{projectRoot}/.oxfmtrc.json"] },
|
|
139
|
+
// the writer is never cached: a cache hit would change nothing and leave the files
|
|
140
|
+
// unformatted while nx reports success
|
|
141
|
+
"format:fix": { "cache": false },
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
And **`--init` removes that role's target from `project.json`**, leaving every other target
|
|
147
|
+
alone. Each adoption decouples one more thing from nx: the command moves to the script, the
|
|
148
|
+
caching moves to the manifest, and `project.json` shrinks. Declaring the inputs is not
|
|
149
|
+
tidiness, it is the point: without them the inferred target inherits `targetDefaults`, and in
|
|
150
|
+
this repo the lint default pins the cache to the ROOT eslint config, a file an adopted module
|
|
151
|
+
no longer uses.
|
|
152
|
+
|
|
153
|
+
And one line, added by adoption, in the workspace root's `.prettierignore`, so the root
|
|
154
|
+
formatter stops competing for a module that now formats itself.
|
|
155
|
+
|
|
156
|
+
## Versions, and moving between them
|
|
157
|
+
|
|
158
|
+
An adopting module pins an exact version:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
"devDependencies": { "@hublo/sentinel": "1.1.0-alpha.5" }
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
That pin is what makes a preset change **reviewable**: it lands in one module's PR, run by
|
|
165
|
+
that module's team, rather than arriving everywhere at once on an unrelated install.
|
|
166
|
+
|
|
167
|
+
How a change reaches modules depends on the role, and the difference is not cosmetic:
|
|
168
|
+
|
|
169
|
+
- **lint and typescript** commit a stub that `extends` a file inside the package, so a preset
|
|
170
|
+
change arrives with the new version: bump, install, done.
|
|
171
|
+
- **format** materializes the values, because oxfmt has no `extends`. A preset change reaches
|
|
172
|
+
nobody until someone re-runs `sentinel --init --format` in that module.
|
|
173
|
+
|
|
174
|
+
`sentinel --inspect --format` from the root reports which modules are behind, so the gap is
|
|
175
|
+
visible. Closing it in one action is [issue #17](https://github.com/hublo/sentinel/issues/17);
|
|
176
|
+
today it is one command per module.
|
|
177
|
+
|
|
178
|
+
**Upgrading:** bump the pin, `pnpm install`, then `sentinel --init` in the module and commit
|
|
179
|
+
what changes. `--init` is idempotent, so on a version that changed nothing relevant it reports
|
|
180
|
+
nothing to change.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Validating a change
|
|
2
|
+
|
|
3
|
+
How a change to sentinel is proven before it ships, and the traps that made each step necessary.
|
|
4
|
+
|
|
5
|
+
Everything here was learned the expensive way. None of it is theory.
|
|
6
|
+
|
|
7
|
+
- [The rule everything follows](#the-rule-everything-follows)
|
|
8
|
+
- [Phase 0: prove the premise](#phase-0-prove-the-premise)
|
|
9
|
+
- [Phase 1: measure the output](#phase-1-measure-the-output)
|
|
10
|
+
- [Traps that report success](#traps-that-report-success)
|
|
11
|
+
- [What CI does not cover](#what-ci-does-not-cover)
|
|
12
|
+
|
|
13
|
+
## The rule everything follows
|
|
14
|
+
|
|
15
|
+
> A check must not be satisfiable by **doing nothing**.
|
|
16
|
+
|
|
17
|
+
Ask what your check would report if the step it verifies never ran. If the answer is "success",
|
|
18
|
+
the check is decoration.
|
|
19
|
+
|
|
20
|
+
This is not abstract. A test asserting `plan().operations` is empty passed for a week on a code
|
|
21
|
+
path that returned early and wrote nothing, while the thing it was supposed to guarantee (that
|
|
22
|
+
re-running changes nothing on disk) was broken in the other direction.
|
|
23
|
+
|
|
24
|
+
## Phase 0: prove the premise
|
|
25
|
+
|
|
26
|
+
**Before** any expensive measurement, prove you are measuring the right thing. A perfect method
|
|
27
|
+
pointed at the wrong object gives a perfectly wrong answer, and nothing in the result says so.
|
|
28
|
+
|
|
29
|
+
For the build role that is one command:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
sentinel --inspect --build # conformant, or the drift named
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
It reports the seven things a half-adoption is missing. Every one of them shipped at least once.
|
|
36
|
+
|
|
37
|
+
The cost of skipping this: a sweep once reported "36 of 36 contracts identical" on a branch where
|
|
38
|
+
34 of the services still built with **webpack**. The method was sound. The premise was not, and the
|
|
39
|
+
only reason it surfaced was an unrelated error message mentioning webpack.
|
|
40
|
+
|
|
41
|
+
## Phase 1: measure the output
|
|
42
|
+
|
|
43
|
+
For a Nest service, the acceptance test is its committed OpenAPI contract:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
echo '{"corrompu":true}' > libs/api-types/service-<x>/src/service-<x>.swagger.json
|
|
47
|
+
NX_CACHE_DIRECTORY=$(mktemp -d) nx run <x>:generate-swagger-file --skip-nx-cache
|
|
48
|
+
git diff --exit-code -- libs/api-types/service-<x>/
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Three things in there are load-bearing:
|
|
52
|
+
|
|
53
|
+
- **overwrite the contract first.** An untouched file is byte-identical to the committed one, so
|
|
54
|
+
without this "identical" can mean "nothing ran".
|
|
55
|
+
- **an empty `NX_CACHE_DIRECTORY`** kills the local cache.
|
|
56
|
+
- **`--skip-nx-cache`** disconnects the remote one.
|
|
57
|
+
|
|
58
|
+
Neither cache flag alone is enough, and neither name says what it does: `--skip-nx-cache` only
|
|
59
|
+
disconnects Nx Cloud, and `--no-cache` only stops **writing**. Measured: with either alone, nx
|
|
60
|
+
restored a cached contract over the corrupted file and reported success without building.
|
|
61
|
+
|
|
62
|
+
For a front app the equivalent is the output count:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
rm -rf apps/front/<x>/.output && nx run <x>:build # note the file count
|
|
66
|
+
rm -rf apps/front/<x>/.output && nx run <x>:build # cache hit: same count restored?
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`console` once restored **0 of 464** files from a green cache hit. Its image runs `pnpm` rather
|
|
70
|
+
than nx, so the one caller that would have failed never used the cache.
|
|
71
|
+
|
|
72
|
+
## Traps that report success
|
|
73
|
+
|
|
74
|
+
| Trap | What it looks like | What closes it |
|
|
75
|
+
| --------------------------- | ------------------------------- | -------------------------------------------------------------------------- |
|
|
76
|
+
| An untouched file | "identical", forever | overwrite it with garbage first |
|
|
77
|
+
| `--skip-nx-cache` | a cold run | it only disconnects Nx Cloud |
|
|
78
|
+
| `--no-cache` | a cold run | it only stops **writing** to the cache |
|
|
79
|
+
| A clock reading vs an mtime | passes locally, fails in CI | stamp from the same filesystem |
|
|
80
|
+
| A stale cache entry | a hit that restores nothing | `nx reset`; entries predating a module's `outputs` restore nothing forever |
|
|
81
|
+
| `"$var:generate-x"` in zsh | a task name that does not exist | brace it: `"${var}:generate-x"` — `:g` is a zsh modifier |
|
|
82
|
+
|
|
83
|
+
The last one is the only one that lies toward FAILURE, which makes it visible but sends you
|
|
84
|
+
hunting for causes elsewhere. It produced several "failures" that were only quoting.
|
|
85
|
+
|
|
86
|
+
## What CI does not cover
|
|
87
|
+
|
|
88
|
+
**The build only runs at deploy time.** Neither PR CI nor a local `nx build` exercises the image,
|
|
89
|
+
so a regression there is invisible until a deploy. Two of five defects on one release were only
|
|
90
|
+
visible on env4, which is why env4 is in the definition of done.
|
|
91
|
+
|
|
92
|
+
**Prisma clients** need `pnpm prisma:gen:*` before a local Nest build, or resolution fails on a
|
|
93
|
+
package that looks missing.
|
|
94
|
+
|
|
95
|
+
**Front configs are executed**, so their environment variables must exist wherever you build:
|
|
96
|
+
`host-admin` and `career` stop on a missing `VITE_BRAND_ID` before a single file is bundled.
|
|
97
|
+
|
|
98
|
+
**Fixtures are not modules.** Every fixture in this repo writes a `package.json`, because that is
|
|
99
|
+
what a module looks like once you have thought about it. Measured on the real monorepo: 22 of 37
|
|
100
|
+
Nest services have none at all. A change that looked complete against 64 test files refused the
|
|
101
|
+
majority of the migration, and only a sweep over every real module found it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0-alpha.2",
|
|
4
4
|
"description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,26 +49,52 @@
|
|
|
49
49
|
"./test/react": {
|
|
50
50
|
"types": "./dist/roles/test/react/toolchain.d.ts",
|
|
51
51
|
"import": "./dist/roles/test/react/toolchain.js"
|
|
52
|
+
},
|
|
53
|
+
"./test/nest": {
|
|
54
|
+
"types": "./dist/roles/test/nest/toolchain.d.ts",
|
|
55
|
+
"import": "./dist/roles/test/nest/toolchain.js"
|
|
56
|
+
},
|
|
57
|
+
"./test/setup/nest": {
|
|
58
|
+
"types": "./dist/roles/test/setup/nest.d.ts",
|
|
59
|
+
"import": "./dist/roles/test/setup/nest.js"
|
|
60
|
+
},
|
|
61
|
+
"./test/msw": {
|
|
62
|
+
"types": "./dist/roles/test/setup/msw-server.d.ts",
|
|
63
|
+
"import": "./dist/roles/test/setup/msw-server.js"
|
|
64
|
+
},
|
|
65
|
+
"./test/setup/msw-lifecycle": {
|
|
66
|
+
"types": "./dist/roles/test/setup/msw-lifecycle.d.ts",
|
|
67
|
+
"import": "./dist/roles/test/setup/msw-lifecycle.js"
|
|
68
|
+
},
|
|
69
|
+
"./test/setup/workspace": {
|
|
70
|
+
"types": "./dist/roles/test/setup/workspace-entry.d.ts",
|
|
71
|
+
"import": "./dist/roles/test/setup/workspace-entry.js"
|
|
52
72
|
}
|
|
53
73
|
},
|
|
54
74
|
"files": [
|
|
55
75
|
"dist",
|
|
76
|
+
"docs",
|
|
56
77
|
"lint",
|
|
57
78
|
"oxlint",
|
|
58
79
|
"plugins",
|
|
59
|
-
"!dist/**/*.map"
|
|
80
|
+
"!dist/**/*.map",
|
|
81
|
+
"dist/roles/**/*.map"
|
|
60
82
|
],
|
|
61
83
|
"dependencies": {
|
|
62
84
|
"@nx/eslint-plugin": "23.0.1",
|
|
63
85
|
"@tailwindcss/vite": "4.1.18",
|
|
64
86
|
"@vitejs/plugin-react": "6.0.1",
|
|
87
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
65
88
|
"commander": "^13.0.0",
|
|
89
|
+
"dotenv-flow": "4.1.0",
|
|
66
90
|
"eslint-plugin-jest-dom": "5.5.0",
|
|
67
91
|
"eslint-plugin-no-barrel-files": "1.2.1",
|
|
68
92
|
"eslint-plugin-react-refresh": "0.4.19",
|
|
69
93
|
"eslint-plugin-storybook": "10.3.5",
|
|
70
94
|
"eslint-plugin-styled-components-a11y": "2.2.0",
|
|
95
|
+
"jsdom": "^24.1.3",
|
|
71
96
|
"jsonc-parser": "^3.3.1",
|
|
97
|
+
"msw": "1.3.3",
|
|
72
98
|
"nitro": "3.0.260415-beta",
|
|
73
99
|
"oxc-parser": "0.147.0",
|
|
74
100
|
"oxfmt": "0.63.0",
|
|
@@ -77,7 +103,8 @@
|
|
|
77
103
|
"typescript": "5.9.3",
|
|
78
104
|
"vite": "8.2.2",
|
|
79
105
|
"vite-plugin-svgr": "5.2.0",
|
|
80
|
-
"vitest": "4.1.4"
|
|
106
|
+
"vitest": "4.1.4",
|
|
107
|
+
"vitest-mock-extended": "5.1.1"
|
|
81
108
|
},
|
|
82
109
|
"devDependencies": {
|
|
83
110
|
"@hublo/sentinel": "link:.",
|
|
@@ -110,10 +137,10 @@
|
|
|
110
137
|
"nx": ">= 21"
|
|
111
138
|
},
|
|
112
139
|
"peerDependenciesMeta": {
|
|
113
|
-
"nx": {
|
|
140
|
+
"@nx/js": {
|
|
114
141
|
"optional": true
|
|
115
142
|
},
|
|
116
|
-
"
|
|
143
|
+
"nx": {
|
|
117
144
|
"optional": true
|
|
118
145
|
}
|
|
119
146
|
},
|