diff --git a/packages/rsdoctor-analysis/src/commands/build.ts b/packages/rsdoctor-analysis/src/commands/build.ts index 22e7ff4..5329450 100644 --- a/packages/rsdoctor-analysis/src/commands/build.ts +++ b/packages/rsdoctor-analysis/src/commands/build.ts @@ -256,34 +256,14 @@ export async function optimizeBundle( }; } -export function registerBuildCommands( - program: Command, +/** + * Helper function to register the optimize command for a command group + */ +function registerOptimizeCommand( + commandGroup: Command, execute: CommandExecutor, ): void { - const buildProgram = program.command('build').description('Build operations'); - - buildProgram - .command('summary') - .description('Get build summary with costs (build time analysis).') - .action(function (this: Command) { - return execute(() => getSummary()); - }); - - buildProgram - .command('entrypoints') - .description('List all entrypoints in the bundle.') - .action(function (this: Command) { - return execute(() => listEntrypoints()); - }); - - buildProgram - .command('config') - .description('Get build configuration (rspack/webpack config).') - .action(function (this: Command) { - return execute(() => getConfig()); - }); - - buildProgram + commandGroup .command('optimize') .description( 'Combined bundle optimization inputs: duplicate packages, similar packages, media assets, large chunks, and side effects modules. Supports step-by-step execution for better performance.', @@ -315,3 +295,40 @@ export function registerBuildCommands( ); }); } + +export function registerBuildCommands( + program: Command, + execute: CommandExecutor, +): void { + const buildProgram = program.command('build').description('Build operations'); + + buildProgram + .command('summary') + .description('Get build summary with costs (build time analysis).') + .action(function (this: Command) { + return execute(() => getSummary()); + }); + + buildProgram + .command('entrypoints') + .description('List all entrypoints in the bundle.') + .action(function (this: Command) { + return execute(() => listEntrypoints()); + }); + + buildProgram + .command('config') + .description('Get build configuration (rspack/webpack config).') + .action(function (this: Command) { + return execute(() => getConfig()); + }); + + registerOptimizeCommand(buildProgram, execute); + + // Register bundle command group as an alias for bundle optimization + const bundleProgram = program + .command('bundle') + .description('Bundle operations'); + + registerOptimizeCommand(bundleProgram, execute); +} diff --git a/packages/rsdoctor-analysis/src/commands/packages.ts b/packages/rsdoctor-analysis/src/commands/packages.ts index e89f436..8284803 100644 --- a/packages/rsdoctor-analysis/src/commands/packages.ts +++ b/packages/rsdoctor-analysis/src/commands/packages.ts @@ -18,15 +18,35 @@ interface Package { name: string; } -export async function listPackages(): Promise<{ +export async function listPackages( + pageNumberInput?: string, + pageSizeInput?: string, +): Promise<{ ok: boolean; data: unknown; description: string; }> { - const packages = await getPackageInfoFiltered(); + const pageNumber = + parsePositiveInt(pageNumberInput, 'pageNumber', { min: 1 }) ?? 1; + const pageSize = + parsePositiveInt(pageSizeInput, 'pageSize', { min: 1, max: 1000 }) ?? 100; + + const allPackages = (await getPackageInfoFiltered()) as Array; + const total = allPackages.length; + const totalPages = Math.ceil(total / pageSize); + const startIndex = (pageNumber - 1) * pageSize; + const endIndex = startIndex + pageSize; + const items = allPackages.slice(startIndex, endIndex); + return { ok: true, - data: packages, + data: { + total, + pageNumber, + pageSize, + totalPages, + items, + }, description: 'List packages with size/duplication info.', }; } @@ -133,8 +153,11 @@ export function registerPackageCommands( packageProgram .command('list') .description('List packages with size/duplication info.') + .option('--page-number ', 'Page number (default: 1)') + .option('--page-size ', 'Page size (default: 100, max: 1000)') .action(function (this: Command) { - return execute(() => listPackages()); + const options = this.opts<{ pageNumber?: string; pageSize?: string }>(); + return execute(() => listPackages(options.pageNumber, options.pageSize)); }); packageProgram diff --git a/skills/rsdoctor-analysis/scripts/rsdoctor.js b/skills/rsdoctor-analysis/scripts/rsdoctor.js index d01a61f..995dc75 100755 --- a/skills/rsdoctor-analysis/scripts/rsdoctor.js +++ b/skills/rsdoctor-analysis/scripts/rsdoctor.js @@ -2441,6 +2441,12 @@ async function optimizeBundle(stepInput, sideEffectsPageNumberInput, sideEffects description: 'Combined bundle optimization inputs: duplicate packages, similar packages, media assets, large chunks, and side effects modules, add give the advice to optimize the bundle.' }; } +function registerOptimizeCommand(commandGroup, execute) { + commandGroup.command('optimize').description('Combined bundle optimization inputs: duplicate packages, similar packages, media assets, large chunks, and side effects modules. Supports step-by-step execution for better performance.').option('--step ', 'Execution step: 1 (basic analysis) or 2 (side effects). If not specified, executes both steps.').option('--side-effects-page-number ', 'Page number for side effects (default: 1, only used in step 2)').option('--side-effects-page-size ', 'Page size for side effects (default: 100, max: 1000, only used in step 2)').action(function() { + const options = this.opts(); + return execute(()=>optimizeBundle(options.step, options.sideEffectsPageNumber, options.sideEffectsPageSize)); + }); +} function registerBuildCommands(program, execute) { const buildProgram = program.command('build').description('Build operations'); buildProgram.command('summary').description('Get build summary with costs (build time analysis).').action(function() { @@ -2452,10 +2458,9 @@ function registerBuildCommands(program, execute) { buildProgram.command('config').description('Get build configuration (rspack/webpack config).').action(function() { return execute(()=>getConfig()); }); - buildProgram.command('optimize').description('Combined bundle optimization inputs: duplicate packages, similar packages, media assets, large chunks, and side effects modules. Supports step-by-step execution for better performance.').option('--step ', 'Execution step: 1 (basic analysis) or 2 (side effects). If not specified, executes both steps.').option('--side-effects-page-number ', 'Page number for side effects (default: 1, only used in step 2)').option('--side-effects-page-size ', 'Page size for side effects (default: 100, max: 1000, only used in step 2)').action(function() { - const options = this.opts(); - return execute(()=>optimizeBundle(options.step, options.sideEffectsPageNumber, options.sideEffectsPageSize)); - }); + registerOptimizeCommand(buildProgram, execute); + const bundleProgram = program.command('bundle').description('Bundle operations'); + registerOptimizeCommand(bundleProgram, execute); } async function listChunks(pageNumberInput, pageSizeInput) { const pageNumber = parsePositiveInt(pageNumberInput, 'pageNumber', { @@ -2731,11 +2736,29 @@ function registerModuleCommands(program, execute) { return execute(()=>modules_getSideEffects(options.pageNumber, options.pageSize)); }); } -async function listPackages() { - const packages = await getPackageInfoFiltered(); +async function listPackages(pageNumberInput, pageSizeInput) { + const pageNumber = parsePositiveInt(pageNumberInput, 'pageNumber', { + min: 1 + }) ?? 1; + const pageSize = parsePositiveInt(pageSizeInput, 'pageSize', { + min: 1, + max: 1000 + }) ?? 100; + const allPackages = await getPackageInfoFiltered(); + const total = allPackages.length; + const totalPages = Math.ceil(total / pageSize); + const startIndex = (pageNumber - 1) * pageSize; + const endIndex = startIndex + pageSize; + const items = allPackages.slice(startIndex, endIndex); return { ok: true, - data: packages, + data: { + total, + pageNumber, + pageSize, + totalPages, + items + }, description: 'List packages with size/duplication info.' }; } @@ -2834,8 +2857,9 @@ async function detectSimilarPackages() { } function registerPackageCommands(program, execute) { const packageProgram = program.command('packages').description('Package operations'); - packageProgram.command('list').description('List packages with size/duplication info.').action(function() { - return execute(()=>listPackages()); + packageProgram.command('list').description('List packages with size/duplication info.').option('--page-number ', 'Page number (default: 1)').option('--page-size ', 'Page size (default: 100, max: 1000)').action(function() { + const options = this.opts(); + return execute(()=>listPackages(options.pageNumber, options.pageSize)); }); packageProgram.command('by-name').description('Get package entries by name.').requiredOption('--name ', 'Package name').action(function() { const options = this.opts();