dep-up-surgeon 2.2.3 → 2.2.4
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 +74 -1
- package/dist/cli/overrideFlow.d.ts +15 -2
- package/dist/cli/overrideFlow.d.ts.map +1 -1
- package/dist/cli/overrideFlow.js +2 -0
- package/dist/cli/overrideFlow.js.map +1 -1
- package/dist/cli/summary.d.ts.map +1 -1
- package/dist/cli/summary.js +13 -3
- package/dist/cli/summary.js.map +1 -1
- package/dist/cli/undo.d.ts +105 -0
- package/dist/cli/undo.d.ts.map +1 -0
- package/dist/cli/undo.js +410 -0
- package/dist/cli/undo.js.map +1 -0
- package/dist/cli/undoCommand.d.ts +2 -0
- package/dist/cli/undoCommand.d.ts.map +1 -0
- package/dist/cli/undoCommand.js +101 -0
- package/dist/cli/undoCommand.js.map +1 -0
- package/dist/cli.js +40 -24
- package/dist/cli.js.map +1 -1
- package/dist/config/loadConfig.d.ts +64 -0
- package/dist/config/loadConfig.d.ts.map +1 -1
- package/dist/config/loadConfig.js +200 -1
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/types.d.ts +7 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/cli/undo.js
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implementation of the `dep-up-surgeon undo` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* Given a `.dep-up-surgeon.last-run.json` report (the one written next to every CLI run,
|
|
5
|
+
* unless `--no-persist-report`), this module computes a reverse pass that:
|
|
6
|
+
*
|
|
7
|
+
* 1. Reverts `package.json` dependency ranges back to the `from` values recorded for each
|
|
8
|
+
* successful upgrade (root + every workspace target).
|
|
9
|
+
* 2. Drops override pins that this run added and, when the attempt recorded a `previous`
|
|
10
|
+
* value, restores the previous pin (i.e. if the advisory/manual pin REPLACED an
|
|
11
|
+
* existing override, we don't silently delete the original).
|
|
12
|
+
* 3. Runs `<manager> install` so the lockfile reconverges to the reverted ranges.
|
|
13
|
+
* 4. Runs the validator (unless `--no-validate`) so the operator knows the project builds
|
|
14
|
+
* with the reverted versions before they commit the undo.
|
|
15
|
+
*
|
|
16
|
+
* Safety contract:
|
|
17
|
+
* - If `package.json` has drifted since the recorded run (e.g. another upgrade changed the
|
|
18
|
+
* range), we **skip** that row with `reason: 'drifted'`. We never rewrite a range the
|
|
19
|
+
* user moved out from under us.
|
|
20
|
+
* - If the recorded run was `dryRun`, there's nothing to undo — we return a no-op report.
|
|
21
|
+
* - The module does not know how to restore a lockfile snapshot; instead it asks the
|
|
22
|
+
* manager to reinstall from the reverted `package.json`, which is the guarantee we
|
|
23
|
+
* actually want. A future extension can layer on a lockfile-hash check.
|
|
24
|
+
*
|
|
25
|
+
* Everything heavy (install, validator) is injected via `opts.installer` / `opts.runValidator`
|
|
26
|
+
* so unit tests can exercise the reverse pass without network / process calls.
|
|
27
|
+
*/
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
import fs from 'fs-extra';
|
|
30
|
+
import { readOverrides, removeOverrideFromFile, applyOverrideInMemory, } from '../utils/overrides.js';
|
|
31
|
+
import { runInstall } from '../utils/npm.js';
|
|
32
|
+
import { log } from '../utils/logger.js';
|
|
33
|
+
import { LAST_RUN_FILENAME, loadLastRunReport } from './lastRun.js';
|
|
34
|
+
const DEP_SECTIONS = [
|
|
35
|
+
'dependencies',
|
|
36
|
+
'devDependencies',
|
|
37
|
+
'peerDependencies',
|
|
38
|
+
'optionalDependencies',
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Run the full reverse pass. Returns a structured `UndoResult` describing what was reverted,
|
|
42
|
+
* what was skipped, and the outcome of the post-reverse install + validator. Never throws on
|
|
43
|
+
* recoverable errors — skipped / failed items are recorded on the result.
|
|
44
|
+
*/
|
|
45
|
+
export async function runUndo(opts) {
|
|
46
|
+
const file = opts.file ? path.resolve(opts.cwd, opts.file) : path.join(opts.cwd, LAST_RUN_FILENAME);
|
|
47
|
+
const persisted = opts.file
|
|
48
|
+
? await readPersisted(file)
|
|
49
|
+
: await loadLastRunReport(opts.cwd);
|
|
50
|
+
if (!persisted) {
|
|
51
|
+
throw new Error(`undo: no run report found at ${file}. Pass --file <path> to point at a specific ` +
|
|
52
|
+
`${LAST_RUN_FILENAME}, or re-run dep-up-surgeon so it writes one.`);
|
|
53
|
+
}
|
|
54
|
+
if (persisted.dryRun) {
|
|
55
|
+
if (!opts.json) {
|
|
56
|
+
log.info(`undo: the recorded run was a dry-run; nothing to revert.`);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
sourceFile: file,
|
|
60
|
+
noop: true,
|
|
61
|
+
reverts: [],
|
|
62
|
+
overrides: [],
|
|
63
|
+
installs: [],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const manager = opts.manager ?? persisted.project?.manager ?? 'npm';
|
|
67
|
+
const targets = buildTargetMap(persisted, opts.cwd);
|
|
68
|
+
const reverts = [];
|
|
69
|
+
const overrides = [];
|
|
70
|
+
// ---- 1. Revert dep ranges ------------------------------------------------
|
|
71
|
+
const editedTargets = new Set();
|
|
72
|
+
for (const row of persisted.upgraded ?? []) {
|
|
73
|
+
if (!row.success || row.skipped)
|
|
74
|
+
continue;
|
|
75
|
+
const workspace = row.workspace ?? 'root';
|
|
76
|
+
const target = targets.get(workspace) ?? targets.get('root');
|
|
77
|
+
if (!target) {
|
|
78
|
+
reverts.push({
|
|
79
|
+
name: row.name,
|
|
80
|
+
workspace,
|
|
81
|
+
ok: false,
|
|
82
|
+
skipped: true,
|
|
83
|
+
reason: 'target-missing',
|
|
84
|
+
detail: `no target cwd found for workspace "${workspace}"`,
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!row.from) {
|
|
89
|
+
reverts.push({
|
|
90
|
+
name: row.name,
|
|
91
|
+
workspace,
|
|
92
|
+
ok: false,
|
|
93
|
+
skipped: true,
|
|
94
|
+
reason: 'no-from',
|
|
95
|
+
detail: 'upgrade row did not record a `from` value',
|
|
96
|
+
...(row.to ? { to: row.to } : {}),
|
|
97
|
+
});
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const revert = await revertDepRange(target.packageJson, row.name, row.from, row.to);
|
|
101
|
+
reverts.push({
|
|
102
|
+
name: row.name,
|
|
103
|
+
workspace,
|
|
104
|
+
from: row.from,
|
|
105
|
+
...(row.to ? { to: row.to } : {}),
|
|
106
|
+
...(revert.section ? { section: revert.section } : {}),
|
|
107
|
+
ok: revert.ok,
|
|
108
|
+
skipped: !revert.ok,
|
|
109
|
+
...(revert.reason ? { reason: revert.reason } : {}),
|
|
110
|
+
...(revert.detail ? { detail: revert.detail } : {}),
|
|
111
|
+
});
|
|
112
|
+
if (revert.ok && !opts.planOnly) {
|
|
113
|
+
await fs.writeJson(target.packageJson, revert.pkg, { spaces: 2 });
|
|
114
|
+
editedTargets.add(target.cwd);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// ---- 2. Drop / restore overrides ----------------------------------------
|
|
118
|
+
for (const att of persisted.overrides?.attempts ?? []) {
|
|
119
|
+
if (!att.ok || att.skipped)
|
|
120
|
+
continue;
|
|
121
|
+
const pkgJson = targets.get('root')?.packageJson ?? path.join(opts.cwd, 'package.json');
|
|
122
|
+
if (!(await fs.pathExists(pkgJson))) {
|
|
123
|
+
overrides.push({
|
|
124
|
+
name: att.name,
|
|
125
|
+
ok: false,
|
|
126
|
+
skipped: true,
|
|
127
|
+
reason: 'missing-package-json',
|
|
128
|
+
detail: pkgJson,
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const chain = att.chain && att.chain.length > 0 ? [...att.chain] : [att.name];
|
|
133
|
+
let result;
|
|
134
|
+
if (att.previous && att.previous !== att.applied) {
|
|
135
|
+
// Restore the pre-existing pin rather than deleting outright. This is the case where
|
|
136
|
+
// --apply-overrides REPLACED an existing override (e.g. we bumped 1.2.3 → 1.3.0); undo
|
|
137
|
+
// should put 1.2.3 back, not leave the transitive floating.
|
|
138
|
+
if (opts.planOnly) {
|
|
139
|
+
result = {
|
|
140
|
+
name: att.name,
|
|
141
|
+
chain,
|
|
142
|
+
...(att.applied ? { applied: att.applied } : {}),
|
|
143
|
+
previous: att.previous,
|
|
144
|
+
ok: true,
|
|
145
|
+
skipped: false,
|
|
146
|
+
reason: 'restored-previous',
|
|
147
|
+
detail: `would restore ${att.previous}`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const entry = { name: chain[chain.length - 1], range: att.previous };
|
|
152
|
+
if (chain.length > 1)
|
|
153
|
+
entry.parentChain = chain.slice(0, -1);
|
|
154
|
+
// Undo deliberately bypasses `applyOverrideToFile`'s "skip if existing >= target"
|
|
155
|
+
// semantics — a revert is allowed to move the pin backwards; that's literally the
|
|
156
|
+
// whole point. We call `applyOverrideInMemory` directly and write the result.
|
|
157
|
+
const pkg = (await fs.readJson(pkgJson));
|
|
158
|
+
const next = applyOverrideInMemory(pkg, manager, entry);
|
|
159
|
+
await fs.writeJson(pkgJson, next, { spaces: 2 });
|
|
160
|
+
editedTargets.add(opts.cwd);
|
|
161
|
+
result = {
|
|
162
|
+
name: att.name,
|
|
163
|
+
chain,
|
|
164
|
+
...(att.applied ? { applied: att.applied } : {}),
|
|
165
|
+
previous: att.previous,
|
|
166
|
+
ok: true,
|
|
167
|
+
skipped: false,
|
|
168
|
+
reason: 'restored-previous',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
if (opts.planOnly) {
|
|
174
|
+
result = {
|
|
175
|
+
name: att.name,
|
|
176
|
+
chain,
|
|
177
|
+
...(att.applied ? { applied: att.applied } : {}),
|
|
178
|
+
ok: true,
|
|
179
|
+
skipped: false,
|
|
180
|
+
reason: 'dropped',
|
|
181
|
+
detail: 'would drop',
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const removed = await removeOverrideFromFile(pkgJson, manager, { chain });
|
|
186
|
+
if (removed.removed) {
|
|
187
|
+
editedTargets.add(opts.cwd);
|
|
188
|
+
result = {
|
|
189
|
+
name: att.name,
|
|
190
|
+
chain,
|
|
191
|
+
...(att.applied ? { applied: att.applied } : {}),
|
|
192
|
+
ok: true,
|
|
193
|
+
skipped: false,
|
|
194
|
+
reason: 'dropped',
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
result = {
|
|
199
|
+
name: att.name,
|
|
200
|
+
chain,
|
|
201
|
+
...(att.applied ? { applied: att.applied } : {}),
|
|
202
|
+
ok: false,
|
|
203
|
+
skipped: true,
|
|
204
|
+
reason: 'not-present',
|
|
205
|
+
...(removed.reason ? { detail: removed.reason } : {}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
overrides.push(result);
|
|
211
|
+
}
|
|
212
|
+
// ---- 3. Post-reverse install --------------------------------------------
|
|
213
|
+
const installs = [];
|
|
214
|
+
if (!opts.planOnly && !opts.skipInstall && editedTargets.size > 0) {
|
|
215
|
+
const installer = opts.installer ?? runInstall;
|
|
216
|
+
for (const targetCwd of editedTargets) {
|
|
217
|
+
const r = await installer(targetCwd, manager, {});
|
|
218
|
+
const row = {
|
|
219
|
+
cwd: targetCwd,
|
|
220
|
+
ok: r.ok,
|
|
221
|
+
...(r.command ? { command: r.command } : {}),
|
|
222
|
+
...(typeof r.exitCode === 'number' ? { exitCode: r.exitCode } : {}),
|
|
223
|
+
...(r.output ? { lastLines: tail(r.output, 40) } : {}),
|
|
224
|
+
};
|
|
225
|
+
installs.push(row);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// ---- 4. Post-reverse validator ------------------------------------------
|
|
229
|
+
let validation;
|
|
230
|
+
if (!opts.planOnly && !opts.skipValidator && installs.every((r) => r.ok)) {
|
|
231
|
+
if (opts.runValidator) {
|
|
232
|
+
validation = await opts.runValidator();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
sourceFile: file,
|
|
237
|
+
noop: false,
|
|
238
|
+
reverts,
|
|
239
|
+
overrides,
|
|
240
|
+
installs,
|
|
241
|
+
...(validation ? { validation } : {}),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
async function readPersisted(file) {
|
|
245
|
+
if (!(await fs.pathExists(file))) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
return (await fs.readJson(file));
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Map workspace label → `{ cwd, packageJson }`. Falls back to the run's `cwd` when no
|
|
257
|
+
* targets block was persisted (single-root run).
|
|
258
|
+
*/
|
|
259
|
+
function buildTargetMap(persisted, invokedAt) {
|
|
260
|
+
const map = new Map();
|
|
261
|
+
const targets = persisted.targets ?? [];
|
|
262
|
+
if (targets.length === 0) {
|
|
263
|
+
const rootCwd = persisted.cwd ?? invokedAt;
|
|
264
|
+
map.set('root', {
|
|
265
|
+
cwd: rootCwd,
|
|
266
|
+
packageJson: path.join(rootCwd, 'package.json'),
|
|
267
|
+
});
|
|
268
|
+
return map;
|
|
269
|
+
}
|
|
270
|
+
for (const t of targets) {
|
|
271
|
+
map.set(t.label, { cwd: t.cwd, packageJson: t.packageJson });
|
|
272
|
+
}
|
|
273
|
+
if (!map.has('root')) {
|
|
274
|
+
const rootCwd = persisted.cwd ?? invokedAt;
|
|
275
|
+
map.set('root', {
|
|
276
|
+
cwd: rootCwd,
|
|
277
|
+
packageJson: path.join(rootCwd, 'package.json'),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
return map;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Revert `name` back to `from` in whichever dep section currently holds it. Returns the
|
|
284
|
+
* modified `pkg` object alongside metadata about what section we touched. If the current
|
|
285
|
+
* range doesn't match the recorded `to`, we skip with `drifted` — the user modified the
|
|
286
|
+
* range out from under us and rewriting would be destructive.
|
|
287
|
+
*
|
|
288
|
+
* We do NOT assert the recorded `from` matches the version before the run; the run itself
|
|
289
|
+
* wrote it, so treating its `from` value as authoritative is exactly what the user wants.
|
|
290
|
+
*/
|
|
291
|
+
async function revertDepRange(packageJson, name, from, to) {
|
|
292
|
+
if (!(await fs.pathExists(packageJson))) {
|
|
293
|
+
return { ok: false, reason: 'missing', detail: `${packageJson} not found` };
|
|
294
|
+
}
|
|
295
|
+
const pkg = (await fs.readJson(packageJson));
|
|
296
|
+
for (const section of DEP_SECTIONS) {
|
|
297
|
+
const sec = pkg[section];
|
|
298
|
+
if (!sec || typeof sec !== 'object')
|
|
299
|
+
continue;
|
|
300
|
+
const map = sec;
|
|
301
|
+
if (!(name in map))
|
|
302
|
+
continue;
|
|
303
|
+
const current = typeof map[name] === 'string' ? map[name] : undefined;
|
|
304
|
+
if (to && current !== undefined && current !== to) {
|
|
305
|
+
// The recorded run landed on `to` but the current file holds something else — another
|
|
306
|
+
// run (or a human edit) changed it. Bail out of this row; undo is about REVERSING this
|
|
307
|
+
// specific run, not about steamrolling later history.
|
|
308
|
+
return {
|
|
309
|
+
ok: false,
|
|
310
|
+
reason: 'drifted',
|
|
311
|
+
detail: `current \`${section}.${name}\` is "${current}" but the run recorded "${to}"; leaving as-is`,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
map[name] = from;
|
|
315
|
+
pkg[section] = map;
|
|
316
|
+
return { ok: true, pkg, section };
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
ok: false,
|
|
320
|
+
reason: 'missing',
|
|
321
|
+
detail: `${name} not found in any dep section of ${path.basename(packageJson)}`,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Render a human-readable summary of an `UndoResult`. Used by the CLI when `--json` is not
|
|
326
|
+
* set; tests render the JSON directly.
|
|
327
|
+
*/
|
|
328
|
+
export function renderUndoHuman(result) {
|
|
329
|
+
const lines = [];
|
|
330
|
+
lines.push(`undo: replayed ${path.basename(result.sourceFile)}`);
|
|
331
|
+
if (result.noop) {
|
|
332
|
+
lines.push(' nothing to revert (recorded run was a dry-run)');
|
|
333
|
+
return lines.join('\n');
|
|
334
|
+
}
|
|
335
|
+
const reverted = result.reverts.filter((r) => r.ok);
|
|
336
|
+
const skipped = result.reverts.filter((r) => !r.ok);
|
|
337
|
+
const droppedOverrides = result.overrides.filter((r) => r.ok);
|
|
338
|
+
const skippedOverrides = result.overrides.filter((r) => !r.ok);
|
|
339
|
+
lines.push(` ${reverted.length} dep range(s) reverted, ${skipped.length} skipped`);
|
|
340
|
+
for (const r of reverted) {
|
|
341
|
+
const ws = r.workspace === 'root' ? '' : ` [${r.workspace}]`;
|
|
342
|
+
lines.push(` - ${r.name}${ws}: ${r.to ?? '?'} → ${r.from}`);
|
|
343
|
+
}
|
|
344
|
+
for (const r of skipped) {
|
|
345
|
+
const ws = r.workspace === 'root' ? '' : ` [${r.workspace}]`;
|
|
346
|
+
lines.push(` ~ ${r.name}${ws}: skipped (${r.reason}${r.detail ? ` — ${r.detail}` : ''})`);
|
|
347
|
+
}
|
|
348
|
+
if (result.overrides.length > 0) {
|
|
349
|
+
lines.push(` ${droppedOverrides.length} override(s) dropped, ${skippedOverrides.length} skipped`);
|
|
350
|
+
for (const o of droppedOverrides) {
|
|
351
|
+
const label = o.chain && o.chain.length > 1 ? o.chain.join('>') : o.name;
|
|
352
|
+
lines.push(` - ${label}: ${o.reason}${o.previous ? ` (${o.applied} → ${o.previous})` : ` (dropped ${o.applied ?? '?'})`}`);
|
|
353
|
+
}
|
|
354
|
+
for (const o of skippedOverrides) {
|
|
355
|
+
const label = o.chain && o.chain.length > 1 ? o.chain.join('>') : o.name;
|
|
356
|
+
lines.push(` ~ ${label}: skipped (${o.reason}${o.detail ? ` — ${o.detail}` : ''})`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
for (const inst of result.installs) {
|
|
360
|
+
lines.push(` install @ ${inst.cwd}: ${inst.ok ? 'ok' : `failed (exit ${inst.exitCode ?? '?'})`}`);
|
|
361
|
+
}
|
|
362
|
+
if (result.validation) {
|
|
363
|
+
lines.push(` validator: ${result.validation.ok ? 'ok' : 'failed'}`);
|
|
364
|
+
}
|
|
365
|
+
return lines.join('\n');
|
|
366
|
+
}
|
|
367
|
+
/** Take the last `n` lines of multi-line text, preserving order. */
|
|
368
|
+
function tail(text, n) {
|
|
369
|
+
const lines = text.split(/\r?\n/);
|
|
370
|
+
return lines.slice(-n).join('\n');
|
|
371
|
+
}
|
|
372
|
+
/** True when the reverse pass succeeded end-to-end (reverts, installs, validator). */
|
|
373
|
+
export function undoSucceeded(result) {
|
|
374
|
+
if (result.noop)
|
|
375
|
+
return true;
|
|
376
|
+
if (result.installs.some((i) => !i.ok))
|
|
377
|
+
return false;
|
|
378
|
+
if (result.validation && !result.validation.ok)
|
|
379
|
+
return false;
|
|
380
|
+
// Skipped revert rows are soft failures — the user knows about them — so we still return
|
|
381
|
+
// true so `--undo` can exit 0 when everything else is clean. The JSON report surfaces the
|
|
382
|
+
// per-row `skipped` so CI bots can be stricter if they care.
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Verify a persisted run's overrides weren't already partially undone by a subsequent run.
|
|
387
|
+
* Exported so callers can cheaply check state before running the full reverse pass (e.g. a
|
|
388
|
+
* `--undo --dry-run` mode).
|
|
389
|
+
*/
|
|
390
|
+
export async function checkOverridesStillPresent(persisted, manager, cwd) {
|
|
391
|
+
const pkgJson = path.join(cwd, 'package.json');
|
|
392
|
+
if (!(await fs.pathExists(pkgJson)))
|
|
393
|
+
return { present: 0, missing: 0 };
|
|
394
|
+
const pkg = (await fs.readJson(pkgJson));
|
|
395
|
+
const read = readOverrides(pkg, manager);
|
|
396
|
+
let present = 0;
|
|
397
|
+
let missing = 0;
|
|
398
|
+
for (const att of persisted.overrides?.attempts ?? []) {
|
|
399
|
+
if (!att.ok || att.skipped)
|
|
400
|
+
continue;
|
|
401
|
+
const chain = att.chain && att.chain.length > 0 ? att.chain : [att.name];
|
|
402
|
+
const hit = read.entries.find((e) => e.chain.length === chain.length && e.chain.every((seg, i) => seg === chain[i]));
|
|
403
|
+
if (hit)
|
|
404
|
+
present++;
|
|
405
|
+
else
|
|
406
|
+
missing++;
|
|
407
|
+
}
|
|
408
|
+
return { present, missing };
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=undo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undo.js","sourceRoot":"","sources":["../../src/cli/undo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undoCommand.d.ts","sourceRoot":"","sources":["../../src/cli/undoCommand.ts"],"names":[],"mappings":"AAeA,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsHnF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated entry point for `dep-up-surgeon undo`. Like `doctor`, this subcommand has its
|
|
3
|
+
* own commander program because `undo` only needs a tiny subset of the main flow's options,
|
|
4
|
+
* and threading it as a flag would force every upgrade-time option to grow a guard.
|
|
5
|
+
*
|
|
6
|
+
* Exit-code contract:
|
|
7
|
+
* - reverse pass succeeded (or noop) → 0
|
|
8
|
+
* - persisted run file not found / can't be parsed → 2
|
|
9
|
+
* - install or validator failed during the reverse pass → 1
|
|
10
|
+
*/
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
import { log } from '../utils/logger.js';
|
|
14
|
+
import { renderUndoHuman, runUndo, undoSucceeded } from './undo.js';
|
|
15
|
+
export async function runUndoCommand(argv, version) {
|
|
16
|
+
const cmd = new Command();
|
|
17
|
+
cmd
|
|
18
|
+
.name('dep-up-surgeon undo')
|
|
19
|
+
.description('Reverse the most recent `dep-up-surgeon` run using `.dep-up-surgeon.last-run.json`. ' +
|
|
20
|
+
'Reverts `package.json` dep ranges to their `from` values, drops override pins this ' +
|
|
21
|
+
'run added (or restores the previous pin when the run replaced an existing one), ' +
|
|
22
|
+
'runs a fresh `<manager> install`, then runs the validator so you see green/red before ' +
|
|
23
|
+
'you commit the revert. Skips rows whose current `package.json` value has drifted from ' +
|
|
24
|
+
'the recorded `to`, so another run\'s changes are never clobbered. Pair with `--json` ' +
|
|
25
|
+
'for machine-readable output in CI.')
|
|
26
|
+
.version(version)
|
|
27
|
+
.option('--file <path>', 'Use a specific run report instead of `.dep-up-surgeon.last-run.json` in cwd. Useful when ' +
|
|
28
|
+
'the directory has been cleaned up or you want to replay a report from a CI artifact.')
|
|
29
|
+
.option('--json', 'Emit the structured `UndoResult` as JSON on stdout instead of the human format.', false)
|
|
30
|
+
.option('--dry-run', 'Compute the reverse plan and print it, but do not touch `package.json`, do not run install, do not run the validator.', false)
|
|
31
|
+
.option('--no-validate', 'Skip the post-reverse validator. Use when the project has no test/build script or when you ' +
|
|
32
|
+
'only care that the dep ranges rolled back cleanly.')
|
|
33
|
+
.option('--validate <cmd>', 'Run this command as the post-reverse validator (same semantics as the upgrade flow\'s `--validate`).')
|
|
34
|
+
.option('--skip-install', 'Skip the post-reverse `<manager> install`. Only use when you plan to run install yourself ' +
|
|
35
|
+
'(e.g. in a follow-up CI step) — the lockfile will otherwise diverge from the reverted `package.json`.', false)
|
|
36
|
+
.option('--package-manager <mgr>', 'Override the manager recorded in the run report (auto / npm / pnpm / yarn).', 'auto')
|
|
37
|
+
.option('--cwd <path>', 'Run the undo against this directory instead of the current one.');
|
|
38
|
+
// Strip the `undo` dispatch token the same way `doctor` does.
|
|
39
|
+
const forwarded = [argv[0], argv[1], ...argv.slice(3)];
|
|
40
|
+
cmd.parse(forwarded);
|
|
41
|
+
const opts = cmd.opts();
|
|
42
|
+
const cwd = opts.cwd ? path.resolve(process.cwd(), opts.cwd) : process.cwd();
|
|
43
|
+
const skipValidator = opts.validate === false;
|
|
44
|
+
const validatorCommand = typeof opts.validate === 'string' ? opts.validate : undefined;
|
|
45
|
+
try {
|
|
46
|
+
// Build a validator closure that mirrors the main flow's behavior: if the user passed a
|
|
47
|
+
// command we shell that out; otherwise `validateProject` auto-detects test / build. This
|
|
48
|
+
// keeps `--validate "my-cmd"` working identically across `upgrade`, `doctor`, and `undo`.
|
|
49
|
+
const runValidator = async () => {
|
|
50
|
+
if (skipValidator)
|
|
51
|
+
return { ok: true };
|
|
52
|
+
try {
|
|
53
|
+
const { validateProject } = await import('../core/validator.js');
|
|
54
|
+
const fs = await import('fs-extra');
|
|
55
|
+
const pkg = await fs.default.readJson(path.join(cwd, 'package.json'));
|
|
56
|
+
const manager = opts.packageManager && opts.packageManager !== 'auto'
|
|
57
|
+
? opts.packageManager
|
|
58
|
+
: 'npm';
|
|
59
|
+
const vr = await validateProject(cwd, pkg, {
|
|
60
|
+
...(validatorCommand ? { command: validatorCommand, source: 'cli' } : {}),
|
|
61
|
+
manager,
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
ok: vr.ok,
|
|
65
|
+
...(vr.command ? { command: vr.command } : {}),
|
|
66
|
+
...(vr.output ? { lastLines: vr.output } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Validator crash != project broken for undo's purposes — report ok so we don't
|
|
71
|
+
// exit 1 purely because the validator harness itself errored. The reverse pass has
|
|
72
|
+
// already written the correct ranges; the operator can run their tests manually.
|
|
73
|
+
return { ok: true };
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const result = await runUndo({
|
|
77
|
+
cwd,
|
|
78
|
+
...(opts.file ? { file: opts.file } : {}),
|
|
79
|
+
...(opts.packageManager && opts.packageManager !== 'auto'
|
|
80
|
+
? { manager: opts.packageManager }
|
|
81
|
+
: {}),
|
|
82
|
+
...(opts.dryRun ? { planOnly: true } : {}),
|
|
83
|
+
...(opts.skipInstall ? { skipInstall: true } : {}),
|
|
84
|
+
...(skipValidator ? { skipValidator: true } : {}),
|
|
85
|
+
...(skipValidator ? {} : { runValidator }),
|
|
86
|
+
...(opts.json ? { json: true } : {}),
|
|
87
|
+
});
|
|
88
|
+
if (opts.json) {
|
|
89
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
process.stdout.write(renderUndoHuman(result) + '\n');
|
|
93
|
+
}
|
|
94
|
+
process.exit(undoSucceeded(result) ? 0 : 1);
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
log.error(`undo failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
98
|
+
process.exit(2);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=undoCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undoCommand.js","sourceRoot":"","sources":["../../src/cli/undoCommand.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import chalk from 'chalk';
|
|
|
5
5
|
import fs from 'fs-extra';
|
|
6
6
|
import { program } from 'commander';
|
|
7
7
|
import prompts from 'prompts';
|
|
8
|
-
import { appendIgnoreToRc, loadConfig, mergeIgnoreLists, resolveValidateOptions, } from './config/loadConfig.js';
|
|
8
|
+
import { appendIgnoreToRc, loadConfig, mergeIgnoreLists, mergeOverrideSources, resolveValidateOptions, } from './config/loadConfig.js';
|
|
9
9
|
import { buildStructuredReport, printStructuredCliSummary } from './cli/report.js';
|
|
10
10
|
import { computeRetryFailedIgnores, LAST_RUN_FILENAME, loadLastRunReport, persistLastRunReport, } from './cli/lastRun.js';
|
|
11
11
|
import { resolveSummaryDestination, writeSummary } from './cli/summary.js';
|
|
@@ -122,6 +122,14 @@ async function main() {
|
|
|
122
122
|
await runDoctorCommand(process.argv, version);
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
|
+
// `undo` reads `.dep-up-surgeon.last-run.json` and reverses the last run (dep ranges +
|
|
126
|
+
// overrides + reinstall + validate). Same early-dispatch pattern as `doctor` so the
|
|
127
|
+
// subcommand doesn't inherit the upgrade flow's 70+ options.
|
|
128
|
+
if (process.argv[2] === 'undo') {
|
|
129
|
+
const { runUndoCommand } = await import('./cli/undoCommand.js');
|
|
130
|
+
await runUndoCommand(process.argv, version);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
125
133
|
program
|
|
126
134
|
.name('dep-up-surgeon')
|
|
127
135
|
.description('Upgrade npm dependencies one-by-one with install + test/build validation and rollback on failure.')
|
|
@@ -197,6 +205,12 @@ async function main() {
|
|
|
197
205
|
}
|
|
198
206
|
const config = await loadConfig(cwd);
|
|
199
207
|
const ignore = mergeIgnoreLists(config.ignore, opts.ignore);
|
|
208
|
+
for (const w of config.warnings ?? []) {
|
|
209
|
+
log.warn(`rc: ${w}`);
|
|
210
|
+
}
|
|
211
|
+
if ((config.overrides?.length ?? 0) > 0 && !jsonOutput) {
|
|
212
|
+
log.info(`rc: loaded ${config.overrides.length} override pin${config.overrides.length === 1 ? '' : 's'} from .dep-up-surgeonrc (will run through the same install + validator + rollback cycle as --apply-overrides)`);
|
|
213
|
+
}
|
|
200
214
|
// ---- Load .dep-up-surgeon.policy.{yaml,json} ----
|
|
201
215
|
const { loadPolicy } = await import('./config/policy.js');
|
|
202
216
|
const policyResult = await loadPolicy(cwd);
|
|
@@ -571,32 +585,34 @@ async function main() {
|
|
|
571
585
|
// Runs AFTER enrichments so we have the final `upgraded` list, and BEFORE the summary so
|
|
572
586
|
// the summary writer + JSON consumers see `report.overrides`. `--override` works
|
|
573
587
|
// standalone (no --security-only required); `--apply-overrides` still needs an audit.
|
|
574
|
-
const
|
|
588
|
+
const hasCliOverrides = Array.isArray(opts.override) && opts.override.length > 0;
|
|
589
|
+
const hasRcOverrides = (config.overrides?.length ?? 0) > 0;
|
|
590
|
+
const hasManualOverrides = hasCliOverrides || hasRcOverrides;
|
|
575
591
|
const wantsAdvisoryOverrides = Boolean(opts.applyOverrides);
|
|
576
592
|
if ((wantsAdvisoryOverrides || hasManualOverrides) && !dryRun) {
|
|
577
|
-
//
|
|
578
|
-
//
|
|
579
|
-
//
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
593
|
+
// Merge rc-sourced + CLI selectors. The merger dedupes by chain (CLI wins on conflict),
|
|
594
|
+
// normalizes selector strings, and surfaces malformed CLI entries as warnings — but NOT
|
|
595
|
+
// as a fatal error, because we still want the valid rc entries to apply even when the
|
|
596
|
+
// user typo'd one `--override` flag.
|
|
597
|
+
const merged = mergeOverrideSources(config.overrides, opts.override);
|
|
598
|
+
for (const w of merged.warnings) {
|
|
599
|
+
log.warn(w);
|
|
600
|
+
}
|
|
601
|
+
const manualOverrides = merged.entries.map((e) => {
|
|
602
|
+
const spec = {
|
|
603
|
+
chain: e.chain,
|
|
604
|
+
range: e.range,
|
|
605
|
+
};
|
|
606
|
+
if (e.source)
|
|
607
|
+
spec.source = e.source;
|
|
608
|
+
if (e.reason)
|
|
609
|
+
spec.reason = e.reason;
|
|
610
|
+
return spec;
|
|
611
|
+
});
|
|
612
|
+
const effectivelyHasManual = manualOverrides.length > 0;
|
|
613
|
+
if (wantsAdvisoryOverrides &&
|
|
598
614
|
(!opts.securityOnly || !auditResult || auditResult.advisories.length === 0) &&
|
|
599
|
-
!
|
|
615
|
+
!effectivelyHasManual) {
|
|
600
616
|
if (!jsonOutput) {
|
|
601
617
|
log.warn('--apply-overrides requires --security-only with at least one audit advisory; skipping.');
|
|
602
618
|
}
|