@ripast/cli 0.1.0 → 0.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/dist/cli.mjs +122 -13
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { mkdirSync, readFileSync, renameSync } from "node:fs";
|
|
2
|
-
import { dirname, resolve } from "node:path";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync } from "node:fs";
|
|
2
|
+
import { dirname, relative, resolve } from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import { buildDeclarationTree, buildScanGraph, buildUnusedDeclarations, formatAgentDeclarationTree, formatAgentFileScanHits, formatAgentHits, formatAgentScanHits, formatDeclarationTree, formatFileScanHits, formatHits, formatRegressions, formatScanGraph, formatScanHits, formatUnusedDeclarations, printDiffs, resolveVerifyMode, runCssClassFileScan, runCssClassRename, runCssClassScan, runDelete, runMove, runRename, runRenameFile, runReplace, scan, summarize, writeChanges } from "@ripast/core";
|
|
4
|
+
import { buildDeclarationTree, buildScanGraph, buildUnusedDeclarations, formatAgentDeclarationTree, formatAgentFileScanHits, formatAgentHits, formatAgentScanHits, formatDeclarationTree, formatFileScanHits, formatHits, formatRegressions, formatScanGraph, formatScanHits, formatUnusedDeclarations, printDiffs, resolveVerifyMode, runCssClassFileScan, runCssClassRename, runCssClassScan, runDelete, runMove, runRename, runRenameFile, runReplace, runVueTemplateUnwrap, runVueTemplateWrap, scan, summarize, writeChanges } from "@ripast/core";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
6
6
|
import { agent, isAgent } from "std-env";
|
|
7
7
|
const globArg = {
|
|
@@ -67,6 +67,35 @@ function resolveCliVerifyMode(verify, verifyMode) {
|
|
|
67
67
|
}
|
|
68
68
|
return resolveVerifyMode(verify);
|
|
69
69
|
}
|
|
70
|
+
function recoverSmushedPair(oldArg, newArg) {
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
if (!!oldArg && existsSync(resolve(cwd, oldArg)) && newArg) return {
|
|
73
|
+
old: oldArg,
|
|
74
|
+
new: newArg
|
|
75
|
+
};
|
|
76
|
+
if (!oldArg) return {
|
|
77
|
+
old: oldArg,
|
|
78
|
+
new: newArg
|
|
79
|
+
};
|
|
80
|
+
const candidates = [];
|
|
81
|
+
for (const sep of [
|
|
82
|
+
/\s+/,
|
|
83
|
+
/\s*,\s*/,
|
|
84
|
+
/\s*:\s*/
|
|
85
|
+
]) {
|
|
86
|
+
const parts = oldArg.split(sep).filter(Boolean);
|
|
87
|
+
if (parts.length === 2) candidates.push([parts[0], parts[1]]);
|
|
88
|
+
}
|
|
89
|
+
for (const [a, b] of candidates) if (existsSync(resolve(cwd, a)) && !existsSync(resolve(cwd, b))) return {
|
|
90
|
+
old: a,
|
|
91
|
+
new: b,
|
|
92
|
+
warning: `recovered smushed positional args: treating "${oldArg}" as old="${a}" new="${b}". Quote each path separately next time.`
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
old: oldArg,
|
|
96
|
+
new: newArg
|
|
97
|
+
};
|
|
98
|
+
}
|
|
70
99
|
function resolveExportFilter(raw) {
|
|
71
100
|
if (raw !== "all" && raw !== "exported" && raw !== "local") {
|
|
72
101
|
process.stderr.write(`ripast: --exports must be "all", "exported", or "local".\n`);
|
|
@@ -401,25 +430,37 @@ const renameFileCmd = defineCommand({
|
|
|
401
430
|
tsconfig: { type: "string" },
|
|
402
431
|
apply: applyArg,
|
|
403
432
|
verify: verifyArg,
|
|
433
|
+
verifyMode: verifyModeArg,
|
|
404
434
|
profile: profileArg,
|
|
405
435
|
json: jsonArg
|
|
406
436
|
},
|
|
407
437
|
async run({ args }) {
|
|
408
|
-
const
|
|
438
|
+
const verifyMode = resolveCliVerifyMode(args.verify, args.verifyMode);
|
|
439
|
+
const recovered = recoverSmushedPair(args.old, args.new);
|
|
440
|
+
if (recovered.warning) process.stderr.write(`warning: ${recovered.warning}\n`);
|
|
441
|
+
const r = await runRenameFile(recovered.old, recovered.new, {
|
|
409
442
|
tsconfig: args.tsconfig,
|
|
410
|
-
verify:
|
|
443
|
+
verify: verifyMode
|
|
411
444
|
});
|
|
412
445
|
const apply = !!args.apply;
|
|
413
|
-
const verify =
|
|
446
|
+
const verify = verifyMode !== "none";
|
|
414
447
|
const json = !!args.json;
|
|
415
448
|
const { agentProfile } = resolveProfile(args.profile);
|
|
416
|
-
const
|
|
449
|
+
const selfChangeDisplay = r.selfChange ? {
|
|
450
|
+
path: r.fileMove.to,
|
|
451
|
+
rel: relative(process.cwd(), r.fileMove.to),
|
|
452
|
+
before: r.selfChange.before,
|
|
453
|
+
after: r.selfChange.after
|
|
454
|
+
} : null;
|
|
455
|
+
const displayChanges = selfChangeDisplay ? [selfChangeDisplay, ...r.changes] : r.changes;
|
|
456
|
+
const s = summarize(displayChanges);
|
|
417
457
|
const blockedByRegression = verify && apply && r.regressions.length > 0;
|
|
418
458
|
const wrote = apply && !blockedByRegression;
|
|
419
459
|
if (wrote) {
|
|
420
460
|
writeChanges(r.changes);
|
|
421
461
|
mkdirSync(dirname(r.fileMove.to), { recursive: true });
|
|
422
462
|
renameSync(r.fileMove.from, r.fileMove.to);
|
|
463
|
+
if (selfChangeDisplay) writeChanges([selfChangeDisplay]);
|
|
423
464
|
}
|
|
424
465
|
if (json) {
|
|
425
466
|
process.stdout.write(`${JSON.stringify({
|
|
@@ -429,6 +470,7 @@ const renameFileCmd = defineCommand({
|
|
|
429
470
|
scanned: r.scanned,
|
|
430
471
|
summary: s,
|
|
431
472
|
fileMove: r.fileMove,
|
|
473
|
+
selfChange: r.selfChange,
|
|
432
474
|
changes: r.changes.map((c) => ({
|
|
433
475
|
path: c.rel,
|
|
434
476
|
absolutePath: c.path,
|
|
@@ -444,12 +486,13 @@ const renameFileCmd = defineCommand({
|
|
|
444
486
|
for (const w of r.warnings) process.stderr.write(`warning: ${w}\n`);
|
|
445
487
|
if (agentProfile) {
|
|
446
488
|
process.stdout.write(`${profileHeader()}\n`);
|
|
447
|
-
process.stdout.write(`rename-file: ${
|
|
489
|
+
process.stdout.write(`rename-file: ${recovered.old} -> ${recovered.new}\n`);
|
|
448
490
|
process.stdout.write(`consumers: ${r.changes.length}/${r.scanned}, +${s.linesAdded} -${s.linesRemoved} lines\n`);
|
|
491
|
+
if (selfChangeDisplay) process.stdout.write(`self: rewrote moved file's own relative imports\n`);
|
|
449
492
|
process.stdout.write(`mode: ${apply ? blockedByRegression ? "blocked" : "applied" : "dry-run"}\n`);
|
|
450
|
-
if (
|
|
493
|
+
if (displayChanges.length) {
|
|
451
494
|
process.stdout.write(`files:\n`);
|
|
452
|
-
for (const c of
|
|
495
|
+
for (const c of displayChanges) process.stdout.write(` ${c.rel}${selfChangeDisplay && c === selfChangeDisplay ? " (moved file, intra-file imports)" : ""}\n`);
|
|
453
496
|
}
|
|
454
497
|
if (verify && r.regressions.length) {
|
|
455
498
|
process.stdout.write(`regressions: ${r.regressions.length}\n`);
|
|
@@ -463,8 +506,10 @@ const renameFileCmd = defineCommand({
|
|
|
463
506
|
}
|
|
464
507
|
if (!apply) {
|
|
465
508
|
process.stdout.write(`rename ${args.old} -> ${args.new}\n`);
|
|
466
|
-
|
|
467
|
-
|
|
509
|
+
const consumerCount = r.changes.length;
|
|
510
|
+
const selfSuffix = selfChangeDisplay ? ` (+ moved file's own imports)` : "";
|
|
511
|
+
process.stdout.write(`${consumerCount} consumer file${consumerCount === 1 ? "" : "s"}${selfSuffix}, +${s.linesAdded} -${s.linesRemoved} lines\n\n`);
|
|
512
|
+
printDiffs(displayChanges);
|
|
468
513
|
}
|
|
469
514
|
if (verify && r.regressions.length) {
|
|
470
515
|
process.stderr.write(`\n${formatRegressions(r.regressions, process.cwd())}\n`);
|
|
@@ -475,6 +520,7 @@ const renameFileCmd = defineCommand({
|
|
|
475
520
|
}
|
|
476
521
|
if (wrote) {
|
|
477
522
|
for (const c of r.changes) process.stdout.write(`wrote ${c.rel}\n`);
|
|
523
|
+
if (selfChangeDisplay) process.stdout.write(`wrote ${selfChangeDisplay.rel} (moved file, intra-file imports)\n`);
|
|
478
524
|
process.stdout.write(`renamed ${args.old} -> ${args.new}\n`);
|
|
479
525
|
}
|
|
480
526
|
const suffix = apply ? "" : " (dry run, pass --apply to write)";
|
|
@@ -626,6 +672,15 @@ function resolveCssClassFileScanSort(raw) {
|
|
|
626
672
|
}
|
|
627
673
|
return raw;
|
|
628
674
|
}
|
|
675
|
+
const scopeArg = {
|
|
676
|
+
type: "string",
|
|
677
|
+
description: "Restrict to a single .vue file (skips glob/rg)."
|
|
678
|
+
};
|
|
679
|
+
const rootOnlyArg = {
|
|
680
|
+
type: "boolean",
|
|
681
|
+
default: false,
|
|
682
|
+
description: "Match only template-root elements (direct children of <template>); ignores nested matches."
|
|
683
|
+
};
|
|
629
684
|
runMain(defineCommand({
|
|
630
685
|
meta: {
|
|
631
686
|
name: "ripast",
|
|
@@ -641,7 +696,61 @@ runMain(defineCommand({
|
|
|
641
696
|
"move": moveCmd,
|
|
642
697
|
"delete": deleteCmd,
|
|
643
698
|
"css-class-rename": cssClassRenameCmd,
|
|
644
|
-
"css-class-scan": cssClassScanCmd
|
|
699
|
+
"css-class-scan": cssClassScanCmd,
|
|
700
|
+
"vue-template-wrap": defineCommand({
|
|
701
|
+
meta: {
|
|
702
|
+
name: "vue-template-wrap",
|
|
703
|
+
description: "Wrap every matching element in a Vue <template> with a parent component. Selector: \"Tag\" or \"Tag[attr]\" / \"Tag[attr=value]\". Wrapper: tag name with optional inline attributes (e.g. \"ProPageStates name=\\\"lh\\\"\")."
|
|
704
|
+
},
|
|
705
|
+
args: {
|
|
706
|
+
selector: {
|
|
707
|
+
type: "positional",
|
|
708
|
+
required: true
|
|
709
|
+
},
|
|
710
|
+
wrapper: {
|
|
711
|
+
type: "positional",
|
|
712
|
+
required: true
|
|
713
|
+
},
|
|
714
|
+
glob: globArg,
|
|
715
|
+
scope: scopeArg,
|
|
716
|
+
rootOnly: rootOnlyArg,
|
|
717
|
+
apply: applyArg,
|
|
718
|
+
profile: profileArg,
|
|
719
|
+
json: jsonArg
|
|
720
|
+
},
|
|
721
|
+
async run({ args }) {
|
|
722
|
+
emitResult(await runVueTemplateWrap(args.selector, args.wrapper, {
|
|
723
|
+
glob: args.glob ? args.glob.split(",") : void 0,
|
|
724
|
+
scope: args.scope,
|
|
725
|
+
rootOnly: args.rootOnly
|
|
726
|
+
}), !!args.apply, false, !!args.json, resolveProfile(args.profile).agentProfile);
|
|
727
|
+
}
|
|
728
|
+
}),
|
|
729
|
+
"vue-template-unwrap": defineCommand({
|
|
730
|
+
meta: {
|
|
731
|
+
name: "vue-template-unwrap",
|
|
732
|
+
description: "Remove every matching element in a Vue <template>, hoisting its children up one level. Inverse of vue-template-wrap."
|
|
733
|
+
},
|
|
734
|
+
args: {
|
|
735
|
+
selector: {
|
|
736
|
+
type: "positional",
|
|
737
|
+
required: true
|
|
738
|
+
},
|
|
739
|
+
glob: globArg,
|
|
740
|
+
scope: scopeArg,
|
|
741
|
+
rootOnly: rootOnlyArg,
|
|
742
|
+
apply: applyArg,
|
|
743
|
+
profile: profileArg,
|
|
744
|
+
json: jsonArg
|
|
745
|
+
},
|
|
746
|
+
async run({ args }) {
|
|
747
|
+
emitResult(await runVueTemplateUnwrap(args.selector, {
|
|
748
|
+
glob: args.glob ? args.glob.split(",") : void 0,
|
|
749
|
+
scope: args.scope,
|
|
750
|
+
rootOnly: args.rootOnly
|
|
751
|
+
}), !!args.apply, false, !!args.json, resolveProfile(args.profile).agentProfile);
|
|
752
|
+
}
|
|
753
|
+
})
|
|
645
754
|
}
|
|
646
755
|
}));
|
|
647
756
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ripast/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"description": "CLI for ripast. Deterministic AST refactors (rename, move, find-usages, tailwind/CSS class migration) for TypeScript and frontend frameworks. Auto-installs framework adapters as needed.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"citty": "^0.2.2",
|
|
52
52
|
"std-env": "^4.1.0",
|
|
53
|
-
"@ripast/core": "0.
|
|
53
|
+
"@ripast/core": "0.2.2"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "obuild",
|