@ripast/cli 0.0.0 → 0.1.0
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 +3 -1
- package/dist/cli.mjs +175 -30
- package/package.json +2 -2
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 {
|
|
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
|
|
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) {
|
|
@@ -345,11 +435,13 @@ const renameFileCmd = defineCommand({
|
|
|
345
435
|
before: c.before,
|
|
346
436
|
after: c.after
|
|
347
437
|
})),
|
|
348
|
-
regressions: r.regressions
|
|
438
|
+
regressions: r.regressions,
|
|
439
|
+
warnings: r.warnings
|
|
349
440
|
})}\n`);
|
|
350
441
|
if (blockedByRegression) process.exit(1);
|
|
351
442
|
return;
|
|
352
443
|
}
|
|
444
|
+
for (const w of r.warnings) process.stderr.write(`warning: ${w}\n`);
|
|
353
445
|
if (agentProfile) {
|
|
354
446
|
process.stdout.write(`${profileHeader()}\n`);
|
|
355
447
|
process.stdout.write(`rename-file: ${args.old} -> ${args.new}\n`);
|
|
@@ -458,6 +550,82 @@ function buildRenameMap(from, to, mapPath) {
|
|
|
458
550
|
}
|
|
459
551
|
return new Map(entries);
|
|
460
552
|
}
|
|
553
|
+
const cssClassScanCmd = defineCommand({
|
|
554
|
+
meta: {
|
|
555
|
+
name: "css-class-scan",
|
|
556
|
+
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."
|
|
557
|
+
},
|
|
558
|
+
args: {
|
|
559
|
+
pattern: {
|
|
560
|
+
type: "string",
|
|
561
|
+
description: "Comma-separated globs matched against the bare token (e.g. \"bg-*,text-*\"). Default: all tokens."
|
|
562
|
+
},
|
|
563
|
+
glob: globArg,
|
|
564
|
+
by: {
|
|
565
|
+
type: "string",
|
|
566
|
+
description: "Group by token or file. Default: token."
|
|
567
|
+
},
|
|
568
|
+
sort: {
|
|
569
|
+
type: "string",
|
|
570
|
+
description: "Sort order. Token: count-desc, count-asc, token. File: unique-desc, unique-asc, count-desc, count-asc, file."
|
|
571
|
+
},
|
|
572
|
+
profile: profileArg,
|
|
573
|
+
json: jsonArg
|
|
574
|
+
},
|
|
575
|
+
run({ args }) {
|
|
576
|
+
const { agentProfile } = resolveProfile(args.profile);
|
|
577
|
+
const by = resolveCssClassScanGroup(args.by);
|
|
578
|
+
const base = {
|
|
579
|
+
glob: args.glob ? args.glob.split(",") : void 0,
|
|
580
|
+
pattern: args.pattern ? args.pattern.split(",") : void 0
|
|
581
|
+
};
|
|
582
|
+
if (by === "file") {
|
|
583
|
+
const hits = runCssClassFileScan({
|
|
584
|
+
...base,
|
|
585
|
+
sort: resolveCssClassFileScanSort(args.sort)
|
|
586
|
+
});
|
|
587
|
+
if (agentProfile && !args.json) {
|
|
588
|
+
process.stdout.write(`${profileHeader()}\n${formatAgentFileScanHits(hits)}\n`);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
process.stdout.write(`${formatFileScanHits(hits, !!args.json)}\n`);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
const hits = runCssClassScan({
|
|
595
|
+
...base,
|
|
596
|
+
sort: resolveCssClassScanSort(args.sort)
|
|
597
|
+
});
|
|
598
|
+
if (agentProfile && !args.json) {
|
|
599
|
+
process.stdout.write(`${profileHeader()}\n${formatAgentScanHits(hits)}\n`);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
process.stdout.write(`${formatScanHits(hits, !!args.json)}\n`);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
function resolveCssClassScanGroup(raw) {
|
|
606
|
+
if (raw == null) return "token";
|
|
607
|
+
if (raw !== "token" && raw !== "file") {
|
|
608
|
+
process.stderr.write(`ripast css-class-scan: --by must be "token" or "file".\n`);
|
|
609
|
+
process.exit(2);
|
|
610
|
+
}
|
|
611
|
+
return raw;
|
|
612
|
+
}
|
|
613
|
+
function resolveCssClassScanSort(raw) {
|
|
614
|
+
if (raw == null) return "count-desc";
|
|
615
|
+
if (raw !== "count-desc" && raw !== "count-asc" && raw !== "token") {
|
|
616
|
+
process.stderr.write(`ripast css-class-scan: --sort must be "count-desc", "count-asc", or "token".\n`);
|
|
617
|
+
process.exit(2);
|
|
618
|
+
}
|
|
619
|
+
return raw;
|
|
620
|
+
}
|
|
621
|
+
function resolveCssClassFileScanSort(raw) {
|
|
622
|
+
if (raw == null) return "unique-desc";
|
|
623
|
+
if (raw !== "unique-desc" && raw !== "unique-asc" && raw !== "count-desc" && raw !== "count-asc" && raw !== "file") {
|
|
624
|
+
process.stderr.write(`ripast css-class-scan: --sort with --by file must be "unique-desc", "unique-asc", "count-desc", "count-asc", or "file".\n`);
|
|
625
|
+
process.exit(2);
|
|
626
|
+
}
|
|
627
|
+
return raw;
|
|
628
|
+
}
|
|
461
629
|
runMain(defineCommand({
|
|
462
630
|
meta: {
|
|
463
631
|
name: "ripast",
|
|
@@ -466,37 +634,14 @@ runMain(defineCommand({
|
|
|
466
634
|
subCommands: {
|
|
467
635
|
"scan": scanCmd,
|
|
468
636
|
"tree": treeCmd,
|
|
637
|
+
"unused": unusedCmd,
|
|
469
638
|
"rename": renameCmd,
|
|
639
|
+
"replace": replaceCmd,
|
|
470
640
|
"rename-file": renameFileCmd,
|
|
471
641
|
"move": moveCmd,
|
|
642
|
+
"delete": deleteCmd,
|
|
472
643
|
"css-class-rename": cssClassRenameCmd,
|
|
473
|
-
"css-class-scan":
|
|
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
|
-
})
|
|
644
|
+
"css-class-scan": cssClassScanCmd
|
|
500
645
|
}
|
|
501
646
|
}));
|
|
502
647
|
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.1.0",
|
|
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.1.0"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "obuild",
|