@@ -48,6 +48,96 @@ export async function getConfig(): Promise<{ ok: boolean; data: unknown; descrip
4848 } ;
4949}
5050
51+ /**
52+ * Helper function to execute step 1 logic: basic optimization analysis
53+ * Returns the step 1 data structure without the wrapper
54+ */
55+ async function executeStep1 ( ) : Promise < {
56+ duplicatePackages : { ok : boolean ; data : unknown } ;
57+ similarPackages : { ok : boolean ; data : unknown } ;
58+ mediaAssets : { ok : boolean ; data : unknown } ;
59+ largeChunks : { ok : boolean ; data : unknown } ;
60+ } > {
61+ const [ rules , packages , chunksResult ] = await Promise . all ( [
62+ getRuleInfo ( ) ,
63+ getPackageInfo ( ) ,
64+ getAllChunks ( 1 , Number . MAX_SAFE_INTEGER ) ,
65+ ] ) ;
66+
67+ // Extract chunks from paginated result if needed
68+ const chunksResultTyped = chunksResult as { items ?: Chunk [ ] } | Chunk [ ] ;
69+ const chunks = Array . isArray ( chunksResultTyped )
70+ ? chunksResultTyped
71+ : ( chunksResultTyped . items || [ ] ) ;
72+
73+ // Detect duplicates
74+ const rulesArray = rules as Rule [ ] ;
75+ const duplicateRule = rulesArray ?. find ( ( rule ) => rule . description ?. includes ( 'E1001' ) ) ;
76+
77+ // Detect similar packages
78+ const packagesArray = packages as Package [ ] ;
79+ const similarRules = [
80+ [ 'lodash' , 'lodash-es' , 'string_decode' ] ,
81+ [ 'dayjs' , 'moment' , 'date-fns' , 'js-joda' ] ,
82+ [ 'antd' , 'material-ui' , 'semantic-ui-react' , 'arco-design' ] ,
83+ [ 'axios' , 'node-fetch' ] ,
84+ [ 'redux' , 'mobx' , 'zustand' , 'recoil' , 'jotai' ] ,
85+ [ 'chalk' , 'colors' , 'picocolors' , 'kleur' ] ,
86+ [ 'fs-extra' , 'graceful-fs' ] ,
87+ ] ;
88+
89+ const similarMatches = similarRules
90+ . map ( ( group ) => {
91+ const found = group . filter ( ( pkg ) =>
92+ packagesArray . some ( ( p ) => p . name . toLowerCase ( ) === pkg . toLowerCase ( ) ) ,
93+ ) ;
94+ return found . length > 1 ? found : null ;
95+ } )
96+ . filter ( ( match ) : match is string [ ] => match !== null ) ;
97+
98+ // Get media assets
99+ const mediaAssets = { guidance : 'Media asset optimization guidance.' , chunks } ;
100+
101+ // Find large chunks (>30% over median size and >= 1MB)
102+ const chunksArray = chunks as Chunk [ ] ;
103+ const median = chunksArray . length ? getMedianChunkSize ( chunksArray ) : 0 ;
104+ const operator = 1.3 ;
105+ const minSizeMB = 1 ;
106+ const minSizeBytes = minSizeMB * 1024 * 1024 ; // 1MB in bytes
107+ const oversized = chunksArray . filter ( ( chunk ) => chunk . size > median * operator && chunk . size >= minSizeBytes ) ;
108+
109+ return {
110+ duplicatePackages : {
111+ ok : true ,
112+ data : {
113+ rule : duplicateRule ?? null ,
114+ totalRules : rulesArray ?. length ?? 0 ,
115+ note : duplicateRule
116+ ? undefined
117+ : 'No E1001 duplicate package rule found in current analysis.' ,
118+ } ,
119+ } ,
120+ similarPackages : {
121+ ok : true ,
122+ data : {
123+ similarPackages : similarMatches ,
124+ totalPackages : packagesArray . length ,
125+ note : similarMatches . length
126+ ? undefined
127+ : 'No similar package groups detected in current analysis.' ,
128+ } ,
129+ } ,
130+ mediaAssets : {
131+ ok : true ,
132+ data : mediaAssets ,
133+ } ,
134+ largeChunks : {
135+ ok : true ,
136+ data : { median, operator, minSizeMB, oversized } ,
137+ } ,
138+ } ;
139+ }
140+
51141export async function optimizeBundle (
52142 stepInput ?: string ,
53143 sideEffectsPageNumberInput ?: string ,
@@ -57,86 +147,12 @@ export async function optimizeBundle(
57147
58148 // Step 1: Get basic optimization data (rules, packages, chunks)
59149 if ( step === 1 ) {
60- const [ rules , packages , chunksResult ] = await Promise . all ( [
61- getRuleInfo ( ) ,
62- getPackageInfo ( ) ,
63- getAllChunks ( 1 , Number . MAX_SAFE_INTEGER ) ,
64- ] ) ;
65-
66- // Extract chunks from paginated result if needed
67- const chunksResultTyped = chunksResult as { items ?: Chunk [ ] } | Chunk [ ] ;
68- const chunks = Array . isArray ( chunksResultTyped )
69- ? chunksResultTyped
70- : ( chunksResultTyped . items || [ ] ) ;
71-
72- // Detect duplicates
73- const rulesArray = rules as Rule [ ] ;
74- const duplicateRule = rulesArray ?. find ( ( rule ) => rule . description ?. includes ( 'E1001' ) ) ;
75-
76- // Detect similar packages
77- const packagesArray = packages as Package [ ] ;
78- const similarRules = [
79- [ 'lodash' , 'lodash-es' , 'string_decode' ] ,
80- [ 'dayjs' , 'moment' , 'date-fns' , 'js-joda' ] ,
81- [ 'antd' , 'material-ui' , 'semantic-ui-react' , 'arco-design' ] ,
82- [ 'axios' , 'node-fetch' ] ,
83- [ 'redux' , 'mobx' , 'zustand' , 'recoil' , 'jotai' ] ,
84- [ 'chalk' , 'colors' , 'picocolors' , 'kleur' ] ,
85- [ 'fs-extra' , 'graceful-fs' ] ,
86- ] ;
87-
88- const similarMatches = similarRules
89- . map ( ( group ) => {
90- const found = group . filter ( ( pkg ) =>
91- packagesArray . some ( ( p ) => p . name . toLowerCase ( ) === pkg . toLowerCase ( ) ) ,
92- ) ;
93- return found . length > 1 ? found : null ;
94- } )
95- . filter ( ( match ) : match is string [ ] => match !== null ) ;
96-
97- // Get media assets
98- const mediaAssets = { guidance : 'Media asset optimization guidance.' , chunks } ;
99-
100- // Find large chunks (>30% over median size and >= 1MB)
101- const chunksArray = chunks as Chunk [ ] ;
102- const median = chunksArray . length ? getMedianChunkSize ( chunksArray ) : 0 ;
103- const operator = 1.3 ;
104- const minSizeMB = 1 ;
105- const minSizeBytes = minSizeMB * 1024 * 1024 ; // 1MB in bytes
106- const oversized = chunksArray . filter ( ( chunk ) => chunk . size > median * operator && chunk . size >= minSizeBytes ) ;
107-
150+ const step1Data = await executeStep1 ( ) ;
108151 return {
109152 ok : true ,
110153 data : {
111154 step : 1 ,
112- duplicatePackages : {
113- ok : true ,
114- data : {
115- rule : duplicateRule ?? null ,
116- totalRules : rulesArray ?. length ?? 0 ,
117- note : duplicateRule
118- ? undefined
119- : 'No E1001 duplicate package rule found in current analysis.' ,
120- } ,
121- } ,
122- similarPackages : {
123- ok : true ,
124- data : {
125- similarPackages : similarMatches ,
126- totalPackages : packagesArray . length ,
127- note : similarMatches . length
128- ? undefined
129- : 'No similar package groups detected in current analysis.' ,
130- } ,
131- } ,
132- mediaAssets : {
133- ok : true ,
134- data : mediaAssets ,
135- } ,
136- largeChunks : {
137- ok : true ,
138- data : { median, operator, minSizeMB, oversized } ,
139- } ,
155+ ...step1Data ,
140156 note : 'Step 1 completed. Use --step 2 to get side effects modules.' ,
141157 } ,
142158 description :
@@ -175,86 +191,15 @@ export async function optimizeBundle(
175191 const defaultPageNumber = parsePositiveInt ( sideEffectsPageNumberInput , 'sideEffectsPageNumber' , { min : 1 } ) ?? 1 ;
176192 const defaultPageSize = parsePositiveInt ( sideEffectsPageSizeInput , 'sideEffectsPageSize' , { min : 1 , max : 1000 } ) ?? 100 ;
177193
178- const [ rules , packages , chunksResult , sideEffectsData ] = await Promise . all ( [
179- getRuleInfo ( ) ,
180- getPackageInfo ( ) ,
181- getAllChunks ( 1 , Number . MAX_SAFE_INTEGER ) ,
194+ const [ step1Data , sideEffectsData ] = await Promise . all ( [
195+ executeStep1 ( ) ,
182196 sendRequest ( API . GetSideEffects , { pageNumber : defaultPageNumber , pageSize : defaultPageSize } ) ,
183197 ] ) ;
184-
185- // Extract chunks from paginated result if needed
186- const chunksResultTyped = chunksResult as { items ?: Chunk [ ] } | Chunk [ ] ;
187- const chunks = Array . isArray ( chunksResultTyped )
188- ? chunksResultTyped
189- : ( chunksResultTyped . items || [ ] ) ;
190-
191- // Detect duplicates
192- const rulesArray = rules as Rule [ ] ;
193- const duplicateRule = rulesArray ?. find ( ( rule ) => rule . description ?. includes ( 'E1001' ) ) ;
194-
195- // Detect similar packages
196- const packagesArray = packages as Package [ ] ;
197- const similarRules = [
198- [ 'lodash' , 'lodash-es' , 'string_decode' ] ,
199- [ 'dayjs' , 'moment' , 'date-fns' , 'js-joda' ] ,
200- [ 'antd' , 'material-ui' , 'semantic-ui-react' , 'arco-design' ] ,
201- [ 'axios' , 'node-fetch' ] ,
202- [ 'redux' , 'mobx' , 'zustand' , 'recoil' , 'jotai' ] ,
203- [ 'chalk' , 'colors' , 'picocolors' , 'kleur' ] ,
204- [ 'fs-extra' , 'graceful-fs' ] ,
205- ] ;
206-
207- const similarMatches = similarRules
208- . map ( ( group ) => {
209- const found = group . filter ( ( pkg ) =>
210- packagesArray . some ( ( p ) => p . name . toLowerCase ( ) === pkg . toLowerCase ( ) ) ,
211- ) ;
212- return found . length > 1 ? found : null ;
213- } )
214- . filter ( ( match ) : match is string [ ] => match !== null ) ;
215-
216- // Get media assets
217- const mediaAssets = { guidance : 'Media asset optimization guidance.' , chunks } ;
218-
219- // Find large chunks (>30% over median size and >= 1MB)
220- const chunksArray = chunks as Chunk [ ] ;
221- const median = chunksArray . length ? getMedianChunkSize ( chunksArray ) : 0 ;
222- const operator = 1.3 ;
223- const minSizeMB = 1 ;
224- const minSizeBytes = minSizeMB * 1024 * 1024 ; // 1MB in bytes
225- const oversized = chunksArray . filter ( ( chunk ) => chunk . size > median * operator && chunk . size >= minSizeBytes ) ;
226198
227199 return {
228200 ok : true ,
229201 data : {
230- duplicatePackages : {
231- ok : true ,
232- data : {
233- rule : duplicateRule ?? null ,
234- totalRules : rulesArray ?. length ?? 0 ,
235- note : duplicateRule
236- ? undefined
237- : 'No E1001 duplicate package rule found in current analysis.' ,
238- } ,
239- } ,
240- similarPackages : {
241- ok : true ,
242- data : {
243- similarPackages : similarMatches ,
244- totalPackages : packagesArray . length ,
245- note : similarMatches . length
246- ? undefined
247- : 'No similar package groups detected in current analysis.' ,
248- } ,
249- } ,
250- mediaAssets : {
251- ok : true ,
252- data : mediaAssets ,
253- } ,
254- largeChunks : {
255- ok : true ,
256- data : { median, operator, minSizeMB, oversized } ,
257- } ,
202+ ...step1Data ,
258203 sideEffectsModules : {
259204 ok : true ,
260205 data : sideEffectsData ,
0 commit comments