@ripast/cli 0.0.0 → 0.0.1

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/bin/ripast.mjs CHANGED
@@ -45,7 +45,9 @@ function ensureAdapters(needed) {
45
45
  const require = createRequire(import.meta.url)
46
46
  const missing = []
47
47
  for (const name of needed) {
48
- try { require.resolve(`@ripast/${name}`) }
48
+ try {
49
+ require.resolve(`@ripast/${name}`)
50
+ }
49
51
  catch { missing.push(`@ripast/${name}`) }
50
52
  }
51
53
  if (!missing.length)
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { mkdirSync, readFileSync, renameSync } from "node:fs";
2
2
  import { dirname, resolve } from "node:path";
3
3
  import process from "node:process";
4
- import { buildDeclarationTree, buildScanGraph, formatAgentDeclarationTree, formatAgentHits, formatAgentScanHits, formatDeclarationTree, formatHits, formatRegressions, formatScanGraph, formatScanHits, printDiffs, resolveVerifyMode, runCssClassRename, runCssClassScan, runMove, runRename, runRenameFile, 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, 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 = {
@@ -69,7 +69,7 @@ function resolveCliVerifyMode(verify, verifyMode) {
69
69
  }
70
70
  function resolveExportFilter(raw) {
71
71
  if (raw !== "all" && raw !== "exported" && raw !== "local") {
72
- process.stderr.write(`ripast tree: --exports must be "all", "exported", or "local".\n`);
72
+ process.stderr.write(`ripast: --exports must be "all", "exported", or "local".\n`);
73
73
  process.exit(2);
74
74
  }
75
75
  return raw;
@@ -162,6 +162,42 @@ const renameCmd = defineCommand({
162
162
  }), !!args.apply, verifyMode !== "none", !!args.json, resolveProfile(args.profile).agentProfile);
163
163
  }
164
164
  });
165
+ const replaceCmd = defineCommand({
166
+ meta: {
167
+ name: "replace",
168
+ description: "Replace an imported symbol with another project export; updates imports and call sites."
169
+ },
170
+ args: {
171
+ "from": {
172
+ type: "positional",
173
+ required: true
174
+ },
175
+ "to": {
176
+ type: "positional",
177
+ required: true
178
+ },
179
+ "tsconfig": { type: "string" },
180
+ "glob": globArg,
181
+ "target-scope": {
182
+ type: "string",
183
+ description: "Restrict target symbol resolution to a single file when multiple files export the same name."
184
+ },
185
+ "apply": applyArg,
186
+ "verify": verifyArg,
187
+ "verifyMode": verifyModeArg,
188
+ "profile": profileArg,
189
+ "json": jsonArg
190
+ },
191
+ async run({ args }) {
192
+ const verifyMode = resolveCliVerifyMode(args.verify, args.verifyMode);
193
+ emitResult(await runReplace(args.from, args.to, {
194
+ tsconfig: args.tsconfig,
195
+ glob: args.glob ? args.glob.split(",") : void 0,
196
+ verify: verifyMode,
197
+ targetScope: args["target-scope"]
198
+ }), !!args.apply, verifyMode !== "none", !!args.json, resolveProfile(args.profile).agentProfile);
199
+ }
200
+ });
165
201
  const treeCmd = defineCommand({
166
202
  meta: {
167
203
  name: "tree",
@@ -191,6 +227,30 @@ const treeCmd = defineCommand({
191
227
  process.stdout.write(`${formatDeclarationTree(tree, !!args.json)}\n`);
192
228
  }
193
229
  });
230
+ const unusedCmd = defineCommand({
231
+ meta: {
232
+ name: "unused",
233
+ description: "Find unreferenced top-level declarations."
234
+ },
235
+ args: {
236
+ glob: globArg,
237
+ exports: {
238
+ type: "string",
239
+ description: "Declaration filter: all, exported, or local. Defaults to local."
240
+ },
241
+ tsconfig: { type: "string" },
242
+ json: jsonArg
243
+ },
244
+ run({ args }) {
245
+ const exportFilter = args.exports == null ? "local" : resolveExportFilter(args.exports);
246
+ const unused = buildUnusedDeclarations({
247
+ glob: args.glob ? args.glob.split(",") : void 0,
248
+ exports: exportFilter,
249
+ tsconfig: args.tsconfig
250
+ });
251
+ process.stdout.write(`${formatUnusedDeclarations(unused, !!args.json)}\n`);
252
+ }
253
+ });
194
254
  const moveCmd = defineCommand({
195
255
  meta: {
196
256
  name: "move",
@@ -228,6 +288,36 @@ const moveCmd = defineCommand({
228
288
  }), !!args.apply, verifyMode !== "none", !!args.json, resolveProfile(args.profile).agentProfile);
229
289
  }
230
290
  });
291
+ const deleteCmd = defineCommand({
292
+ meta: {
293
+ name: "delete",
294
+ description: "Delete an unused top-level declaration from a file; refuses if references remain."
295
+ },
296
+ args: {
297
+ symbol: {
298
+ type: "positional",
299
+ required: true
300
+ },
301
+ from: {
302
+ type: "string",
303
+ required: true,
304
+ description: "Source file path."
305
+ },
306
+ tsconfig: { type: "string" },
307
+ apply: applyArg,
308
+ verify: verifyArg,
309
+ verifyMode: verifyModeArg,
310
+ profile: profileArg,
311
+ json: jsonArg
312
+ },
313
+ async run({ args }) {
314
+ const verifyMode = resolveCliVerifyMode(args.verify, args.verifyMode);
315
+ emitResult(await runDelete(args.symbol, args.from, {
316
+ tsconfig: args.tsconfig,
317
+ verify: verifyMode
318
+ }), !!args.apply, verifyMode !== "none", !!args.json, resolveProfile(args.profile).agentProfile);
319
+ }
320
+ });
231
321
  function emitResult(r, apply, verify = false, json = false, agentProfile = false) {
232
322
  const s = summarize(r.changes);
233
323
  if (json) {
@@ -458,6 +548,82 @@ function buildRenameMap(from, to, mapPath) {
458
548
  }
459
549
  return new Map(entries);
460
550
  }
551
+ const cssClassScanCmd = defineCommand({
552
+ meta: {
553
+ name: "css-class-scan",
554
+ description: "Tokenize every class site (strings, Vue class attrs, @apply) and emit sortable token or file frequency lists. Use --sort count-asc for rare tokens or --by file for files introducing the most unique classes."
555
+ },
556
+ args: {
557
+ pattern: {
558
+ type: "string",
559
+ description: "Comma-separated globs matched against the bare token (e.g. \"bg-*,text-*\"). Default: all tokens."
560
+ },
561
+ glob: globArg,
562
+ by: {
563
+ type: "string",
564
+ description: "Group by token or file. Default: token."
565
+ },
566
+ sort: {
567
+ type: "string",
568
+ description: "Sort order. Token: count-desc, count-asc, token. File: unique-desc, unique-asc, count-desc, count-asc, file."
569
+ },
570
+ profile: profileArg,
571
+ json: jsonArg
572
+ },
573
+ run({ args }) {
574
+ const { agentProfile } = resolveProfile(args.profile);
575
+ const by = resolveCssClassScanGroup(args.by);
576
+ const base = {
577
+ glob: args.glob ? args.glob.split(",") : void 0,
578
+ pattern: args.pattern ? args.pattern.split(",") : void 0
579
+ };
580
+ if (by === "file") {
581
+ const hits = runCssClassFileScan({
582
+ ...base,
583
+ sort: resolveCssClassFileScanSort(args.sort)
584
+ });
585
+ if (agentProfile && !args.json) {
586
+ process.stdout.write(`${profileHeader()}\n${formatAgentFileScanHits(hits)}\n`);
587
+ return;
588
+ }
589
+ process.stdout.write(`${formatFileScanHits(hits, !!args.json)}\n`);
590
+ return;
591
+ }
592
+ const hits = runCssClassScan({
593
+ ...base,
594
+ sort: resolveCssClassScanSort(args.sort)
595
+ });
596
+ if (agentProfile && !args.json) {
597
+ process.stdout.write(`${profileHeader()}\n${formatAgentScanHits(hits)}\n`);
598
+ return;
599
+ }
600
+ process.stdout.write(`${formatScanHits(hits, !!args.json)}\n`);
601
+ }
602
+ });
603
+ function resolveCssClassScanGroup(raw) {
604
+ if (raw == null) return "token";
605
+ if (raw !== "token" && raw !== "file") {
606
+ process.stderr.write(`ripast css-class-scan: --by must be "token" or "file".\n`);
607
+ process.exit(2);
608
+ }
609
+ return raw;
610
+ }
611
+ function resolveCssClassScanSort(raw) {
612
+ if (raw == null) return "count-desc";
613
+ if (raw !== "count-desc" && raw !== "count-asc" && raw !== "token") {
614
+ process.stderr.write(`ripast css-class-scan: --sort must be "count-desc", "count-asc", or "token".\n`);
615
+ process.exit(2);
616
+ }
617
+ return raw;
618
+ }
619
+ function resolveCssClassFileScanSort(raw) {
620
+ if (raw == null) return "unique-desc";
621
+ if (raw !== "unique-desc" && raw !== "unique-asc" && raw !== "count-desc" && raw !== "count-asc" && raw !== "file") {
622
+ process.stderr.write(`ripast css-class-scan: --sort with --by file must be "unique-desc", "unique-asc", "count-desc", "count-asc", or "file".\n`);
623
+ process.exit(2);
624
+ }
625
+ return raw;
626
+ }
461
627
  runMain(defineCommand({
462
628
  meta: {
463
629
  name: "ripast",
@@ -466,37 +632,14 @@ runMain(defineCommand({
466
632
  subCommands: {
467
633
  "scan": scanCmd,
468
634
  "tree": treeCmd,
635
+ "unused": unusedCmd,
469
636
  "rename": renameCmd,
637
+ "replace": replaceCmd,
470
638
  "rename-file": renameFileCmd,
471
639
  "move": moveCmd,
640
+ "delete": deleteCmd,
472
641
  "css-class-rename": cssClassRenameCmd,
473
- "css-class-scan": defineCommand({
474
- meta: {
475
- name: "css-class-scan",
476
- description: "Tokenize every class site (strings, Vue class attrs, @apply) and emit a frequency-sorted list. Feeds --map for css-class-rename."
477
- },
478
- args: {
479
- pattern: {
480
- type: "string",
481
- description: "Comma-separated globs matched against the bare token (e.g. \"bg-*,text-*\"). Default: all tokens."
482
- },
483
- glob: globArg,
484
- profile: profileArg,
485
- json: jsonArg
486
- },
487
- run({ args }) {
488
- const { agentProfile } = resolveProfile(args.profile);
489
- const hits = runCssClassScan({
490
- glob: args.glob ? args.glob.split(",") : void 0,
491
- pattern: args.pattern ? args.pattern.split(",") : void 0
492
- });
493
- if (agentProfile && !args.json) {
494
- process.stdout.write(`${profileHeader()}\n${formatAgentScanHits(hits)}\n`);
495
- return;
496
- }
497
- process.stdout.write(`${formatScanHits(hits, !!args.json)}\n`);
498
- }
499
- })
642
+ "css-class-scan": cssClassScanCmd
500
643
  }
501
644
  }));
502
645
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ripast/cli",
3
3
  "type": "module",
4
- "version": "0.0.0",
4
+ "version": "0.0.1",
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.0.0"
53
+ "@ripast/core": "0.0.1"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "obuild",