@@ -1131,6 +1131,11 @@ export interface ExpandedViewItem {
11311131 isDefault ?: boolean ;
11321132 order : number ;
11331133 scope : 'package' ;
1134+ /** Non-blocking expansion diagnostics (MetadataValidationResult wire shape).
1135+ * Present only when the item's name had to be rewritten to avoid a
1136+ * collision — loaders surface `warnings` in their boot/HMR logs and
1137+ * Studio can badge the view. */
1138+ _diagnostics ?: { valid : boolean ; warnings : Array < { path : string ; message : string } > } ;
11341139}
11351140
11361141/** True when a raw view artifact still uses the aggregated container shape
@@ -1162,6 +1167,29 @@ function uniqueViewName(base: string, used: Set<string>): string {
11621167 return name ;
11631168}
11641169
1170+ /** Stamp a rename warning on an expanded item whose `<object>.<key>` name was
1171+ * already taken (e.g. `formViews.default` vs the implicit default `list`).
1172+ * The rename itself is kept for backward compatibility — this makes it LOUD:
1173+ * loaders log the warning and Studio can render it, so authors discover that
1174+ * references to the requested name (form action `target`s, navigation
1175+ * `viewName`s) resolve to a DIFFERENT view. */
1176+ function stampRenameWarning ( item : ExpandedViewItem , requestedName : string ) : void {
1177+ if ( item . name === requestedName ) return ;
1178+ item . _diagnostics = {
1179+ valid : true ,
1180+ warnings : [ {
1181+ path : 'name' ,
1182+ message :
1183+ `View key collision: '${ requestedName } ' is already registered by another view in this `
1184+ + `defineView container (list and form views share one '<object>.<key>' namespace, and the `
1185+ + `default 'list' implicitly claims '<object>.default'). This ${ item . viewKind } view was `
1186+ + `renamed to '${ item . name } '. References targeting '${ requestedName } ' — form action `
1187+ + `targets, navigation viewNames — will resolve to the OTHER view. Rename the view key `
1188+ + `to something unique to remove this warning.` ,
1189+ } ] ,
1190+ } ;
1191+ }
1192+
11651193function cloneViewConfig ( v : any ) : any {
11661194 try {
11671195 return structuredClone ( v ) ;
@@ -1191,9 +1219,12 @@ export function expandViewContainer(object: string, container: any): ExpandedVie
11911219 container . listViews && typeof container . listViews === 'object' ? container . listViews : { } ;
11921220 for ( const [ k , v ] of Object . entries < any > ( listViews ) ) {
11931221 if ( ! v || typeof v !== 'object' ) continue ;
1194- const name = uniqueViewName ( `${ object } .${ k } ` , used ) ;
1222+ const requested = `${ object } .${ k } ` ;
1223+ const name = uniqueViewName ( requested , used ) ;
11951224 listSigToName . set ( viewSignature ( v ) , name ) ;
1196- out . push ( { name, object, viewKind : 'list' , label : v . label , config : cloneViewConfig ( v ) , order : order ++ , scope : 'package' } ) ;
1225+ const item : ExpandedViewItem = { name, object, viewKind : 'list' , label : v . label , config : cloneViewConfig ( v ) , order : order ++ , scope : 'package' } ;
1226+ stampRenameWarning ( item , requested ) ;
1227+ out . push ( item ) ;
11971228 }
11981229 const defaultList = container . list ;
11991230 let defaultListName : string | undefined ;
@@ -1203,8 +1234,11 @@ export function expandViewContainer(object: string, container: any): ExpandedVie
12031234 defaultListName = dup ; // already represented by a named listViews entry
12041235 } else {
12051236 const key = typeof defaultList . name === 'string' && defaultList . name ? defaultList . name : 'default' ;
1206- const name = uniqueViewName ( `${ object } .${ key } ` , used ) ;
1207- out . push ( { name, object, viewKind : 'list' , label : defaultList . label , config : cloneViewConfig ( defaultList ) , order : order ++ , scope : 'package' } ) ;
1237+ const requested = `${ object } .${ key } ` ;
1238+ const name = uniqueViewName ( requested , used ) ;
1239+ const item : ExpandedViewItem = { name, object, viewKind : 'list' , label : defaultList . label , config : cloneViewConfig ( defaultList ) , order : order ++ , scope : 'package' } ;
1240+ stampRenameWarning ( item , requested ) ;
1241+ out . push ( item ) ;
12081242 defaultListName = name ;
12091243 }
12101244 }
@@ -1220,16 +1254,22 @@ export function expandViewContainer(object: string, container: any): ExpandedVie
12201254 container . formViews && typeof container . formViews === 'object' ? container . formViews : { } ;
12211255 for ( const [ k , v ] of Object . entries < any > ( formViews ) ) {
12221256 if ( ! v || typeof v !== 'object' ) continue ;
1223- const name = uniqueViewName ( `${ object } .${ k } ` , used ) ;
1257+ const requested = `${ object } .${ k } ` ;
1258+ const name = uniqueViewName ( requested , used ) ;
12241259 formSigSeen . add ( viewSignature ( v ) ) ;
1225- out . push ( { name, object, viewKind : 'form' , label : v . label , config : cloneViewConfig ( v ) , order : order ++ , scope : 'package' } ) ;
1260+ const item : ExpandedViewItem = { name, object, viewKind : 'form' , label : v . label , config : cloneViewConfig ( v ) , order : order ++ , scope : 'package' } ;
1261+ stampRenameWarning ( item , requested ) ;
1262+ out . push ( item ) ;
12261263 }
12271264 const defaultForm = container . form ;
12281265 let defaultFormName : string | undefined ;
12291266 if ( defaultForm && typeof defaultForm === 'object' && ! formSigSeen . has ( viewSignature ( defaultForm ) ) ) {
12301267 const key = typeof defaultForm . name === 'string' && defaultForm . name ? defaultForm . name : 'form' ;
1231- const name = uniqueViewName ( `${ object } .${ key } ` , used ) ;
1232- out . push ( { name, object, viewKind : 'form' , label : defaultForm . label , config : cloneViewConfig ( defaultForm ) , order : order ++ , scope : 'package' } ) ;
1268+ const requested = `${ object } .${ key } ` ;
1269+ const name = uniqueViewName ( requested , used ) ;
1270+ const item : ExpandedViewItem = { name, object, viewKind : 'form' , label : defaultForm . label , config : cloneViewConfig ( defaultForm ) , order : order ++ , scope : 'package' } ;
1271+ stampRenameWarning ( item , requested ) ;
1272+ out . push ( item ) ;
12331273 defaultFormName = name ;
12341274 }
12351275 if ( ! defaultFormName && out . length > formStart ) defaultFormName = out [ formStart ] . name ;
0 commit comments