@@ -8,8 +8,8 @@ import {z, type ZodRawShape} from 'zod';
88import { componentAnalyzer , generateTypeSuggestions , resolveComponent , type TypeSuggestion } from './analyzer.js' ;
99import { generateDecoratorCode , type AttributeContext , type MetadataContext } from './templates/decorator-generator.js' ;
1010import { pageDesignerDecoratorRules } from './rules.js' ;
11- import type { McpTool } from '../../utils/index.js' ;
12- import type { Services } from '../../services.js' ;
11+ import type { McpTool } from '../../../ utils/index.js' ;
12+ import type { Services } from '../../../ services.js' ;
1313
1414// ============================================================================
1515// SCHEMA DEFINITION
@@ -366,13 +366,64 @@ function handleConfigureRegionsStep(args: PageDesignerDecoratorInput, workspaceR
366366 } ;
367367}
368368
369+ function hasNonEmptyConfig ( config : Record < string , unknown > | undefined ) : config is Record < string , unknown > {
370+ return config !== null && config !== undefined && Object . keys ( config ) . length > 0 ;
371+ }
372+
373+ function buildAttributesFromProps (
374+ selectedProps : string [ ] ,
375+ props : { name : string ; type : string ; optional : boolean } [ ] ,
376+ attributeConfig : Record < string , Record < string , unknown > > ,
377+ ) : AttributeContext [ ] {
378+ return selectedProps . flatMap ( ( propName ) => {
379+ const prop = props . find ( ( p ) => p . name === propName ) ;
380+ if ( ! prop ) return [ ] ;
381+ const config = attributeConfig [ propName ] ;
382+ return [
383+ {
384+ name : propName ,
385+ tsType : prop . type ,
386+ optional : prop . optional ,
387+ hasConfig : hasNonEmptyConfig ( config ) ,
388+ config,
389+ } ,
390+ ] ;
391+ } ) ;
392+ }
393+
394+ function buildAttributesFromNewAttrs (
395+ newAttributes : { name : string ; required ?: boolean } [ ] ,
396+ attributeConfig : Record < string , Record < string , unknown > > ,
397+ ) : AttributeContext [ ] {
398+ return newAttributes . map ( ( attr ) => {
399+ const config = attributeConfig [ attr . name ] ;
400+ return {
401+ name : attr . name ,
402+ tsType : 'string' ,
403+ optional : ! attr . required ,
404+ hasConfig : hasNonEmptyConfig ( config ) ,
405+ config,
406+ } ;
407+ } ) ;
408+ }
409+
410+ function resolveRegions ( conversationContext : PageDesignerDecoratorInput [ 'conversationContext' ] ) {
411+ const regionConfig = conversationContext ?. regionConfig ;
412+ const enabled = Boolean ( regionConfig ?. enabled && regionConfig . regions ?. length ) ;
413+ return {
414+ hasRegions : enabled ,
415+ regions : enabled ? regionConfig ! . regions ! : [ ] ,
416+ regionCount : enabled ? regionConfig ! . regions ! . length : 0 ,
417+ } ;
418+ }
419+
369420function handleConfirmGenerationStep ( args : PageDesignerDecoratorInput , workspaceRoot : string ) {
370421 const {
371422 componentMetadata,
372423 selectedProps = [ ] ,
373424 newAttributes = [ ] ,
374425 attributeConfig = { } ,
375- } = args . conversationContext || { } ;
426+ } = args . conversationContext ?? { } ;
376427
377428 if ( ! componentMetadata ) {
378429 return {
@@ -389,51 +440,25 @@ function handleConfirmGenerationStep(args: PageDesignerDecoratorInput, workspace
389440 const fullPath = resolveComponent ( args . component , workspaceRoot , args . searchPaths ) ;
390441 const componentInfo = componentAnalyzer . analyzeComponent ( fullPath ) ;
391442
392- const attributes : AttributeContext [ ] = [ ] ;
393-
394- for ( const propName of selectedProps ) {
395- const prop = componentInfo . props . find ( ( p ) => p . name === propName ) ;
396- if ( ! prop ) continue ;
397-
398- const config = attributeConfig [ propName ] ;
399- const hasConfig = config && Object . keys ( config ) . length > 0 ;
400-
401- attributes . push ( {
402- name : propName ,
403- tsType : prop . type ,
404- optional : prop . optional ,
405- hasConfig,
406- config,
407- } ) ;
408- }
409-
410- for ( const attr of newAttributes ) {
411- const config = attributeConfig [ attr . name ] ;
412- const hasConfig = config && Object . keys ( config ) . length > 0 ;
413-
414- attributes . push ( {
415- name : attr . name ,
416- tsType : 'string' ,
417- optional : ! attr . required ,
418- hasConfig,
419- config,
420- } ) ;
421- }
443+ const attributes = [
444+ ...buildAttributesFromProps ( selectedProps , componentInfo . props , attributeConfig ) ,
445+ ...buildAttributesFromNewAttrs ( newAttributes , attributeConfig ) ,
446+ ] ;
422447
423- const regionConfig = args . conversationContext ?. regionConfig ;
424- const hasRegions = regionConfig ?. enabled && regionConfig . regions && regionConfig . regions . length > 0 ;
448+ const { hasRegions , regions , regionCount } = resolveRegions ( args . conversationContext ) ;
449+ const componentGroup = componentMetadata . group ?? 'odyssey_base' ;
425450
426451 const context : MetadataContext = {
427452 needsImports : true ,
428453 componentId : componentMetadata . id ,
429454 componentName : componentMetadata . name ,
430455 componentDescription : componentMetadata . description ,
431- componentGroup : componentMetadata . group || 'odyssey_base' ,
456+ componentGroup,
432457 metadataClassName : `${ componentInfo . componentName } Metadata` ,
433458 hasAttributes : attributes . length > 0 ,
434- hasRegions : hasRegions || false ,
459+ hasRegions,
435460 hasLoader : false ,
436- regions : hasRegions ? regionConfig . regions || [ ] : [ ] ,
461+ regions,
437462 attributes,
438463 } ;
439464
@@ -443,11 +468,11 @@ function handleConfirmGenerationStep(args: PageDesignerDecoratorInput, workspace
443468 decoratorCode,
444469 componentName : componentInfo . componentName ,
445470 componentId : componentMetadata . id ,
446- componentGroup : componentMetadata . group || 'odyssey_base' ,
471+ componentGroup,
447472 file : args . component ,
448473 attributeCount : attributes . length ,
449- hasRegions : hasRegions || false ,
450- regionCount : hasRegions && regionConfig . regions ? regionConfig . regions . length : 0 ,
474+ hasRegions,
475+ regionCount,
451476 } ) ;
452477
453478 return {
0 commit comments