Skip to content

Commit 508fcac

Browse files
feat: add rsdoctor-analysis skill (#5)
Co-authored-by: Timeless0911 <1604889533@qq.com>
1 parent 07be4a6 commit 508fcac

File tree

27 files changed

+6303
-0
lines changed

27 files changed

+6303
-0
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ npx skills add rstackjs/agent-skills --skill rsbuild-v2-upgrade
3434

3535
Migrate Rsbuild projects from v1 to v2. Use when a user asks to upgrade Rsbuild, follow the v1-to-v2 guide, update configs/plugins, or validate the upgrade.
3636

37+
## Rsdoctor Skills
38+
39+
### rsdoctor-analysis
40+
41+
```bash
42+
npx skills add rstackjs/agent-skills --skill rsdoctor-analytics
43+
```
44+
45+
Analyze Rspack/Webpack bundles from local Rsdoctor build data. Zero-dependency JS CLI for chunk/module/package/loader insights. Provides evidence-based conclusions and actionable optimization recommendations.
46+
47+
Use when you need to analyze bundle composition, identify duplicate packages, detect similar packages, find large chunks, analyze side effects modules, or get comprehensive bundle optimization recommendations.
48+
3749
## License
3850

3951
MIT licensed.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "rsdoctor-analysis",
3+
"version": "1.0.0",
4+
"type": "module",
5+
"scripts": {
6+
"build": "rslib build",
7+
"dev": "rslib build --watch"
8+
},
9+
"devDependencies": {
10+
"@rslib/core": "^0.19.4",
11+
"@types/node": "^24.10.9",
12+
"commander": "^12.1.0",
13+
"typescript": "^5.9.3"
14+
}
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { basename, join } from 'node:path';
2+
import { defineConfig } from '@rslib/core';
3+
import { baseConfig } from '@rstackjs/config/rslib.config.ts';
4+
5+
const pkgName = basename(import.meta.dirname);
6+
7+
export default defineConfig({
8+
lib: [
9+
{
10+
...baseConfig,
11+
source: {
12+
entry: {
13+
rsdoctor: './src/index.ts',
14+
},
15+
},
16+
banner: {
17+
js: '#!/usr/bin/env node',
18+
},
19+
output: {
20+
distPath: join(import.meta.dirname, `../../skills/${pkgName}/scripts`),
21+
legalComments: 'none',
22+
cleanDistPath: true,
23+
},
24+
},
25+
],
26+
});
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Command } from 'commander';
2+
import { registerAssetCommands } from './commands/assets';
3+
import { registerBuildCommands } from './commands/build';
4+
import { registerChunkCommands } from './commands/chunks';
5+
import { registerErrorCommands } from './commands/errors';
6+
import { registerLoaderCommands } from './commands/loaders';
7+
import { registerModuleCommands } from './commands/modules';
8+
import { registerPackageCommands } from './commands/packages';
9+
import { registerRuleCommands } from './commands/rules';
10+
import { registerServerCommands } from './commands/server';
11+
import { closeAllSockets } from './socket';
12+
import { printResult } from './utils/cli-utils';
13+
14+
export const program = new Command();
15+
program
16+
.name('rsdoctor-skill')
17+
.description('Rsdoctor skill CLI')
18+
.option('--data-file <path>', 'Path to rsdoctor-data.json file (required)')
19+
.option('--compact', 'Compact JSON output')
20+
.showHelpAfterError()
21+
.showSuggestionAfterError();
22+
23+
export const execute = async (
24+
handler: () => Promise<unknown>,
25+
): Promise<void> => {
26+
// Parse compact option once at the beginning
27+
const opts = program.opts<{ compact?: boolean | string }>();
28+
const compact = opts.compact === true || opts.compact === 'true';
29+
const spacing = compact ? 0 : 2;
30+
31+
try {
32+
const result = await handler();
33+
// Format result similar to old format
34+
if (result && typeof result === 'object' && 'ok' in result) {
35+
console.log(JSON.stringify(result, null, spacing));
36+
if (!(result as { ok: boolean }).ok) {
37+
process.exit(1);
38+
}
39+
} else {
40+
printResult(result, compact);
41+
}
42+
} catch (error) {
43+
const message = error instanceof Error ? error.message : String(error);
44+
console.log(
45+
JSON.stringify(
46+
{
47+
ok: false,
48+
error: message,
49+
},
50+
null,
51+
spacing,
52+
),
53+
);
54+
process.exit(1);
55+
}
56+
};
57+
58+
// Register all command groups
59+
registerChunkCommands(program, execute);
60+
registerModuleCommands(program, execute);
61+
registerPackageCommands(program, execute);
62+
registerRuleCommands(program, execute);
63+
registerAssetCommands(program, execute);
64+
registerLoaderCommands(program, execute);
65+
registerBuildCommands(program, execute);
66+
registerErrorCommands(program, execute);
67+
registerServerCommands(program, execute);
68+
69+
export async function run(): Promise<void> {
70+
if (process.argv.length <= 2) {
71+
program.help({ error: true });
72+
}
73+
await program.parseAsync(process.argv);
74+
75+
// Cleanup
76+
closeAllSockets();
77+
}

0 commit comments

Comments
 (0)