7878 */
7979
8080import { expandViewContainerWithDiagnostics , isAggregatedViewContainer } from '@objectstack/spec' ;
81- import { listNames , suggestName } from './object-graph.js' ;
81+ import { listNames , recordsOf , suggestName } from './object-graph.js' ;
8282
8383export interface ViewRefFinding {
8484 where : string ;
@@ -90,14 +90,6 @@ export interface ViewRefFinding {
9090
9191type AnyRec = Record < string , any > ;
9292
93- /** Normalise a record-or-map metadata slot into an array, injecting `name` from
94- * the map key (mirrors the helper in the sibling authoring lints). */
95- function asArray ( v : unknown ) : AnyRec [ ] {
96- if ( Array . isArray ( v ) ) return v as AnyRec [ ] ;
97- if ( v && typeof v === 'object' ) return Object . entries ( v as AnyRec ) . map ( ( [ name , def ] ) => ( { name, ...( def as AnyRec ) } ) ) ;
98- return [ ] ;
99- }
100-
10193export const VIEW_KEY_COLLISION = 'view-key-collision' ;
10294export const VIEW_REF_FORM_TARGET_MISSING = 'view-ref-form-target-missing' ;
10395export const VIEW_REF_FORM_TARGET_KIND = 'view-ref-form-target-kind' ;
@@ -185,7 +177,7 @@ export function lintViewRefs(stack: AnyRec): ViewRefFinding[] {
185177
186178 // 1) Gather every aggregated container: top-level `views` + object-nested.
187179 const containers : Array < { object : string ; container : AnyRec } > = [ ] ;
188- for ( const v of asArray ( stack . views ) ) {
180+ for ( const v of recordsOf ( stack . views ) ) {
189181 if ( v . viewKind ) {
190182 // Already an independent, expanded ViewItem — index it directly.
191183 const kind = v . viewKind === 'form' ? 'form' : 'list' ;
@@ -200,7 +192,7 @@ export function lintViewRefs(stack: AnyRec): ViewRefFinding[] {
200192 const object = viewContainerObjectName ( v ) ;
201193 if ( object ) containers . push ( { object, container : v } ) ;
202194 }
203- for ( const obj of asArray ( stack . objects ) ) {
195+ for ( const obj of recordsOf ( stack . objects ) ) {
204196 const object = typeof obj . name === 'string' ? obj . name : undefined ;
205197 if ( ! object ) continue ;
206198 if ( obj . list || obj . form || obj . listViews || obj . formViews ) {
@@ -281,11 +273,11 @@ export function lintViewRefs(stack: AnyRec): ViewRefFinding[] {
281273 } ;
282274
283275 // Object-nested first so the retained (deduped) finding keeps object context.
284- for ( const obj of asArray ( stack . objects ) ) {
276+ for ( const obj of recordsOf ( stack . objects ) ) {
285277 const object = typeof obj . name === 'string' ? obj . name : undefined ;
286- for ( const action of asArray ( obj . actions ) ) checkAction ( action , object ) ;
278+ for ( const action of recordsOf ( obj . actions ) ) checkAction ( action , object ) ;
287279 }
288- for ( const action of asArray ( stack . actions ) ) checkAction ( action ) ;
280+ for ( const action of recordsOf ( stack . actions ) ) checkAction ( action ) ;
289281
290282 // 4) Validate every app-navigation `viewName` against its object's list views.
291283 // The second door into the same `listViews` namespace as (3) — see the
@@ -366,12 +358,12 @@ export function lintViewRefs(stack: AnyRec): ViewRefFinding[] {
366358 }
367359 } ;
368360
369- for ( const [ ai , app ] of asArray ( stack . apps ) . entries ( ) ) {
361+ for ( const [ ai , app ] of recordsOf ( stack . apps ) . entries ( ) ) {
370362 const appName = typeof app . name === 'string' && app . name ? app . name : `#${ ai } ` ;
371363 walkNav ( app . navigation , appName ) ;
372364 // `areas[]` is the other nav container; it was once skipped wholesale in
373365 // `stack.zod.ts`, so an areas-based app got no nav validation at all.
374- for ( const area of asArray ( app . areas ) ) {
366+ for ( const area of recordsOf ( app . areas ) ) {
375367 walkNav ( area . items , appName ) ;
376368 walkNav ( area . navigation , appName ) ;
377369 }
0 commit comments