dep-up-surgeon 2.2.1 → 2.2.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 +47 -2
- package/dist/cli/doctor.d.ts +52 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +616 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/doctorCommand.d.ts +2 -0
- package/dist/cli/doctorCommand.d.ts.map +1 -0
- package/dist/cli/doctorCommand.js +71 -0
- package/dist/cli/doctorCommand.js.map +1 -0
- package/dist/cli/doctorRenderer.d.ts +21 -0
- package/dist/cli/doctorRenderer.d.ts.map +1 -0
- package/dist/cli/doctorRenderer.js +79 -0
- package/dist/cli/doctorRenderer.js.map +1 -0
- package/dist/cli/report.d.ts +2 -0
- package/dist/cli/report.d.ts.map +1 -1
- package/dist/cli/report.js +4 -0
- package/dist/cli/report.js.map +1 -1
- package/dist/cli.js +14 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/upgrader.d.ts +18 -6
- package/dist/core/upgrader.d.ts.map +1 -1
- package/dist/core/upgrader.js +56 -11
- package/dist/core/upgrader.js.map +1 -1
- package/dist/core/workspaces.d.ts +22 -0
- package/dist/core/workspaces.d.ts.map +1 -1
- package/dist/core/workspaces.js +52 -0
- package/dist/core/workspaces.js.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/concurrency.d.ts +36 -0
- package/dist/utils/concurrency.d.ts.map +1 -1
- package/dist/utils/concurrency.js +45 -0
- package/dist/utils/concurrency.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -62,7 +62,8 @@ dep-up-surgeon [options]
|
|
|
62
62
|
| `--workspaces-only` | Like `--workspaces` but **skips** the root `package.json`. Only workspace members are traversed. |
|
|
63
63
|
| `--workspace <names>` | Comma-separated workspace member **names** (the `name` field from each child `package.json`) to traverse. Pass `root` to also include the root. Example: `--workspace "@org/core,@org/web,root"`. Unknown names produce a friendly error listing the known members. |
|
|
64
64
|
| `--install-mode <mode>` | Workspace install strategy. **`root`** (default) always runs `<mgr> install` from the workspace root after every mutation — the safest option, supported by every package manager. **`filtered`** rewrites per-child installs to their workspace-scoped form: **npm 7+** uses `npm install --workspace <name>`, **pnpm** uses `pnpm install --filter <name>`, **yarn berry (v2+) with `@yarnpkg/plugin-workspace-tools`** uses `yarn workspaces focus <name>`, and **yarn classic / berry without the plugin** falls back to a full root install with a one-time warning explaining the upgrade path. The capability is auto-detected at startup (yarn version + plugin probe) and reported as `project.yarnMajorVersion` + `project.yarnSupportsFocus` in `--json`. Only meaningful with `--workspaces` / `--workspaces-only` / `--workspace <names>`. |
|
|
65
|
-
| `--concurrency <n>` | Maximum number of workspace targets to traverse in parallel (1–16; default `1`). Higher values overlap registry **scan + plan** phases across targets while a shared mutex keeps **install + validation strictly serialized** — the workspace lockfile is shared, so concurrent installs would corrupt it. The default in-process registry cache also deduplicates `pacote.manifest` / `pacote.packument` calls across targets, so even at concurrency `1` you get a speedup when the same dep appears in many workspaces. **Requires `--json`** so per-target log lines don't interleave; non-JSON mode silently downgrades to `1` with a warning. |
|
|
65
|
+
| `--concurrency <n>` | Maximum number of workspace targets to traverse in parallel (1–16; default `1`). Higher values overlap registry **scan + plan** phases across targets while a shared mutex keeps **install + validation strictly serialized** — the workspace lockfile is shared, so concurrent installs would corrupt it. The default in-process registry cache also deduplicates `pacote.manifest` / `pacote.packument` calls across targets, so even at concurrency `1` you get a speedup when the same dep appears in many workspaces. **Requires `--json`** so per-target log lines don't interleave; non-JSON mode silently downgrades to `1` with a warning. In an **isolated-lockfile** monorepo (pnpm `shared-workspace-lockfile=false`, or every workspace member shipping its own lockfile) installs + validation are ALSO run in parallel — see **Parallel installs** below. |
|
|
66
|
+
| `--no-parallel-installs` | Force installs + validation to stay serialized even when an isolated-lockfile monorepo is detected. Useful when debugging a flaky install step (parallel installs mask the ordering) or when a per-workspace postinstall script touches shared state outside its workspace. |
|
|
66
67
|
| `--retry-failed` | Read `.dep-up-surgeon.last-run.json` from the previous run and only re-attempt entries that failed for **non-terminal** reasons (`install`, `validation-conflicts`, `versions`, `unknown`). Successful upgrades + terminal failures (`peer`, `validation-script`) from the last run are added to the ignore list automatically. See **Persisted last-run report** below. |
|
|
67
68
|
| `--no-persist-report` | Do **not** write `.dep-up-surgeon.last-run.json` after the run. By default the structured report is written next to the workspace root for `--retry-failed` and CI consumers. |
|
|
68
69
|
| `--summary <format>` | Write a human-friendly summary of the run as `md` (default) or `html`. Destination is `$GITHUB_STEP_SUMMARY` if set (appended), otherwise `--summary-file <path>`, otherwise `./dep-up-surgeon-summary.<ext>`. |
|
|
@@ -362,6 +363,50 @@ Where it shows up:
|
|
|
362
363
|
npx dep-up-surgeon --security-only --apply-overrides --fix-lockfile --summary md
|
|
363
364
|
```
|
|
364
365
|
|
|
366
|
+
### Doctor subcommand (`dep-up-surgeon doctor`)
|
|
367
|
+
|
|
368
|
+
`doctor` is a **read-only** diagnostic that answers one question: "is this project in good shape for an upgrade pass right now?". Run it before trusting an upgrade loop (or as a CI pre-check); it never mutates anything. Output is a **traffic-light report** — green/yellow/red per check with a remediation hint on anything non-green.
|
|
369
|
+
|
|
370
|
+
What it checks, in order (stable IDs for `--json` consumers):
|
|
371
|
+
|
|
372
|
+
1. **`node-version`** — current Node satisfies `engines.node` (if set). Red when a mismatched Node would tear down peer-dep resolution in ways that look like CVE-driven failures later.
|
|
373
|
+
2. **`manager`** — a single package manager was resolved cleanly. Yellow when multiple lockfiles coexist or the tool had to fall back to the `npm` default without any signal.
|
|
374
|
+
3. **`lockfile`** — the lockfile is parseable. Yellow on npm v1 shape (upgrades to v2 recommended); red on unreadable / corrupt files.
|
|
375
|
+
4. **`workspace-coherence`** — declared workspace members resolve on disk with their own `package.json`.
|
|
376
|
+
5. **`policy`** — `.dep-up-surgeon.policy.{yaml,json}` (when present) parses without warnings.
|
|
377
|
+
6. **`preflight-validator`** — your `<mgr> test` / `<mgr> run build` (or `--validate <cmd>`) passes right now, before any upgrade. Red here means the project is broken **before** the upgrade loop — fix that first or every failure downstream will look like a regression.
|
|
378
|
+
7. **`peer-deps`** — existing peer / missing dep warnings (via `npm ls --all`, `pnpm install --frozen-lockfile --offline`, or `yarn check`). Catches "already broken before you touched it" cases.
|
|
379
|
+
8. **`audit`** — `<mgr> audit` dry-run with severity breakdown. Red on any high/critical advisory, yellow on low/moderate.
|
|
380
|
+
9. **`stale-transitives`** — up to 100 transitives scanned against registry `latest`; yellow when any are more than a minor or a full major behind. Informational (never red); run `--fix-lockfile` to clean up the easy ones.
|
|
381
|
+
|
|
382
|
+
Exit codes:
|
|
383
|
+
|
|
384
|
+
- `0` — all checks green (or yellow-only without `--strict`)
|
|
385
|
+
- `1` — any yellow under `--strict`
|
|
386
|
+
- `2` — any red
|
|
387
|
+
|
|
388
|
+
Options are focused (no entanglement with the 70+ upgrade-flow flags):
|
|
389
|
+
|
|
390
|
+
| Option | Description |
|
|
391
|
+
|--------|-------------|
|
|
392
|
+
| `--json` | Emit the full `DoctorReport` as JSON on stdout instead of the human format. |
|
|
393
|
+
| `--strict` | Treat yellow checks as failures (exit 1 instead of 0). Use for CI gates. |
|
|
394
|
+
| `--no-validate` | Skip the pre-flight validator check. |
|
|
395
|
+
| `--validate <cmd>` | Override the validator command used by the pre-flight check. |
|
|
396
|
+
| `--skip-audit` | Skip the audit dry-run. Use for air-gapped CI / offline dev. |
|
|
397
|
+
| `--skip-peer-scan` | Skip the peer-dep scan (slow on huge trees). |
|
|
398
|
+
| `--skip-stale-scan` | Skip the registry-backed stale-transitive scan. |
|
|
399
|
+
| `--package-manager <mgr>` | Override detected manager: `auto`, `npm`, `pnpm`, `yarn`. |
|
|
400
|
+
| `--cwd <path>` | Run against a different directory. |
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
# Quick CI pre-check
|
|
404
|
+
npx dep-up-surgeon doctor --strict --json
|
|
405
|
+
|
|
406
|
+
# Local "should I trust the upgrade loop?" check
|
|
407
|
+
npx dep-up-surgeon doctor
|
|
408
|
+
```
|
|
409
|
+
|
|
365
410
|
### Auto-opening a PR (`--open-pr`)
|
|
366
411
|
|
|
367
412
|
When you've already paid the cost of running `--git-commit --git-branch`, `--open-pr` closes the loop by pushing the branch and opening a GitHub pull request via the [GitHub CLI (`gh`)](https://cli.github.com/). Uses your existing `gh auth`; the tool handles nothing sensitive.
|
|
@@ -397,7 +442,7 @@ npx dep-up-surgeon --workspaces --summary md \
|
|
|
397
442
|
- **yarn berry without the plugin** → falls back to a full root install with a one-time warning telling you the exact `yarn plugin import` command to fix it
|
|
398
443
|
|
|
399
444
|
The yarn capability is auto-probed at startup (`yarn --version` + `yarn workspaces focus --help`) and surfaced as `project.yarnMajorVersion` and `project.yarnSupportsFocus` in `--json`. The mode actually used is recorded as `installMode` in the report, and the exact filtered command appears under `failed[].install.command` when an upgrade rolls back.
|
|
400
|
-
- **Parallel target traversal (`--concurrency <n>`).** With more than one target, pass `--concurrency 4` (or up to `16`) to run target **scans + plans** concurrently. Registry IO (`pacote.manifest` / `pacote.packument`) is the slow part of each engine pass and is fully parallel-safe — overlapping it across targets gives a real wall-clock speedup on monorepos with many workspaces. **
|
|
445
|
+
- **Parallel target traversal (`--concurrency <n>`).** With more than one target, pass `--concurrency 4` (or up to `16`) to run target **scans + plans** concurrently. Registry IO (`pacote.manifest` / `pacote.packument`) is the slow part of each engine pass and is fully parallel-safe — overlapping it across targets gives a real wall-clock speedup on monorepos with many workspaces. In a **shared-lockfile** monorepo (the common case) installs and validations stay serialized under a keyed async mutex because they all touch the same root lockfile and `node_modules`; running them in parallel would corrupt the lockfile. In an **isolated-lockfile** monorepo (pnpm `shared-workspace-lockfile=false`, or every workspace member shipping its own lockfile) the installs and validations ALSO run in parallel — the keyed mutex keys off each target's install directory, so same-dir operations still serialize while different-dir operations unlock. The detection is automatic and surfaced as `project.isolatedLockfiles` + `parallelInstalls: true` in `--json`; pass `--no-parallel-installs` to force the old serialized behavior. An in-process registry cache (always on) also deduplicates fetches so the same dependency name in many workspaces only hits the network once. The effective concurrency is reported as `concurrency` in `--json` output. Parallelism requires `--json`; non-JSON mode silently downgrades to `1` to keep per-target log lines legible.
|
|
401
446
|
|
|
402
447
|
The detected manager + members are surfaced under `project` in `--json` output:
|
|
403
448
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { PackageManager } from '../core/workspaces.js';
|
|
2
|
+
export type DoctorStatus = 'green' | 'yellow' | 'red';
|
|
3
|
+
export interface DoctorCheck {
|
|
4
|
+
/** Stable id — used as the JSON key so consumers can branch on it reliably. */
|
|
5
|
+
id: string;
|
|
6
|
+
/** Short label shown in the human-readable output. */
|
|
7
|
+
label: string;
|
|
8
|
+
status: DoctorStatus;
|
|
9
|
+
/** One-line human summary of the outcome. */
|
|
10
|
+
message: string;
|
|
11
|
+
/** Optional remediation hint shown under the message for non-green entries. */
|
|
12
|
+
hint?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Free-form structured payload included in `--json` output. Kept check-specific so the human
|
|
15
|
+
* renderer can stay dumb and downstream consumers can parse what they care about.
|
|
16
|
+
*/
|
|
17
|
+
data?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface DoctorReport {
|
|
20
|
+
cwd: string;
|
|
21
|
+
toolVersion: string;
|
|
22
|
+
/** Per-check results in stable order. */
|
|
23
|
+
checks: DoctorCheck[];
|
|
24
|
+
/** Aggregate — worst status across all checks. */
|
|
25
|
+
overall: DoctorStatus;
|
|
26
|
+
/** Count of checks per status. */
|
|
27
|
+
counts: Record<DoctorStatus, number>;
|
|
28
|
+
}
|
|
29
|
+
export interface RunDoctorOptions {
|
|
30
|
+
cwd: string;
|
|
31
|
+
toolVersion: string;
|
|
32
|
+
/** When true, skip the pre-flight validator even if a command is configured. */
|
|
33
|
+
skipValidator?: boolean;
|
|
34
|
+
/** User-provided validator command (overrides the default `<mgr> test` fallback). */
|
|
35
|
+
validatorCommand?: string;
|
|
36
|
+
/** When true, skip `<mgr> audit` (air-gapped CI, offline dev). */
|
|
37
|
+
skipAudit?: boolean;
|
|
38
|
+
/** When true, skip `<mgr> ls --all` (slow on huge trees). */
|
|
39
|
+
skipPeerScan?: boolean;
|
|
40
|
+
/** When true, skip the registry-backed stale-transitive scan. */
|
|
41
|
+
skipStaleScan?: boolean;
|
|
42
|
+
/** Override package manager (mirrors the top-level `--package-manager` flag). */
|
|
43
|
+
manager?: PackageManager | 'auto';
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Public entry point. Runs every enabled check in sequence (checks are cheap enough that
|
|
47
|
+
* serial keeps the log predictable; we don't gain anything by racing them). Never throws —
|
|
48
|
+
* a check that explodes returns `red` with the error as the `message` so downstream renderers
|
|
49
|
+
* still see a complete report.
|
|
50
|
+
*/
|
|
51
|
+
export declare function runDoctor(opts: RunDoctorOptions): Promise<DoctorReport>;
|
|
52
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,uBAAuB,CAAC;AAUzE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,EAAE,EAAE,MAAM,CAAC;IACX,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,kDAAkD;IAClD,OAAO,EAAE,YAAY,CAAC;IACtB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iFAAiF;IACjF,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkC7E"}
|