@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.
Files changed (2) hide show
  1. package/dist/cli.mjs +122 -13
  2. 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 r = await runRenameFile(args.old, args.new, {
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: args.verify
443
+ verify: verifyMode
411
444
  });
412
445
  const apply = !!args.apply;
413
- const verify = !!args.verify;
446
+ const verify = verifyMode !== "none";
414
447
  const json = !!args.json;
415
448
  const { agentProfile } = resolveProfile(args.profile);
416
- const s = summarize(r.changes);
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: ${args.old} -> ${args.new}\n`);
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 (r.changes.length) {
493
+ if (displayChanges.length) {
451
494
  process.stdout.write(`files:\n`);
452
- for (const c of r.changes) process.stdout.write(` ${c.rel}\n`);
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
- process.stdout.write(`${s.files} consumer file${s.files === 1 ? "" : "s"}, +${s.linesAdded} -${s.linesRemoved} lines\n\n`);
467
- printDiffs(r.changes);
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.1.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.1.0"
53
+ "@ripast/core": "0.2.2"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "obuild",