@@ -12,9 +12,11 @@ import {
1212 type Identifier ,
1313 isChoiceDeclarationField ,
1414 isChoiceInstanceField ,
15+ isComplexTypeIdentifier ,
1516 isComplexTypeTypeSchema ,
1617 isLogicalTypeSchema ,
1718 isProfileTypeSchema ,
19+ isResourceIdentifier ,
1820 isResourceTypeSchema ,
1921 isSpecializationTypeSchema ,
2022 type PkgName ,
@@ -103,74 +105,48 @@ export const sortAsDeclarationSequence = (schemas: RegularTypeSchema[]): Regular
103105} ;
104106
105107///////////////////////////////////////////////////////////
106- // Type Schema Relations
107-
108- interface TypeRelation {
109- parent : Identifier ;
110- child : Identifier ;
111- }
112-
113- const resourceRelatives = ( schemas : TypeSchema [ ] ) : TypeRelation [ ] => {
114- const regularSchemas = schemas . filter (
115- ( e ) => isResourceTypeSchema ( e ) || isLogicalTypeSchema ( e ) || isComplexTypeTypeSchema ( e ) ,
116- ) ;
117-
118- const directPairs : TypeRelation [ ] = [ ] ;
119- const childrenByParent = new Map < string , Identifier [ ] > ( ) ;
120-
121- for ( const schema of regularSchemas ) {
122- if ( schema . base ) {
123- directPairs . push ( { parent : schema . base , child : schema . identifier } ) ;
124- const parentName = schema . base . name ;
125- let children = childrenByParent . get ( parentName ) ;
126- if ( ! children ) {
127- children = [ ] ;
128- childrenByParent . set ( parentName , children ) ;
129- }
130- children . push ( schema . identifier ) ;
131- }
132- }
108+ // Type Family
133109
134- const transitiveCache = new Map < string , Identifier [ ] > ( ) ;
135- const getTransitiveChildren = ( parentName : string ) : Identifier [ ] => {
136- const cached = transitiveCache . get ( parentName ) ;
137- if ( cached ) return cached ;
110+ /** Populate `typeFamily` on specialization schemas with transitive children grouped by kind. */
111+ const populateTypeFamily = ( schemas : TypeSchema [ ] ) : void => {
112+ const directChildrenByParent : Record < string , Identifier [ ] > = { } ;
113+ for ( const schema of schemas ) {
114+ if ( ! isSpecializationTypeSchema ( schema ) || ! schema . base ) continue ;
115+ const parentUrl = schema . base . url ;
116+ if ( ! directChildrenByParent [ parentUrl ] ) directChildrenByParent [ parentUrl ] = [ ] ;
117+ directChildrenByParent [ parentUrl ] . push ( schema . identifier ) ;
118+ }
138119
139- const directChildren = childrenByParent . get ( parentName ) ?? [ ] ;
140- const result : Identifier [ ] = [ ...directChildren ] ;
141- for ( const child of directChildren ) {
142- result . push ( ...getTransitiveChildren ( child . name ) ) ;
120+ const transitiveCache : Record < string , Identifier [ ] > = { } ;
121+ const getTransitiveChildren = ( parentUrl : string ) : Identifier [ ] => {
122+ if ( transitiveCache [ parentUrl ] ) return transitiveCache [ parentUrl ] ;
123+ const direct = directChildrenByParent [ parentUrl ] ?? [ ] ;
124+ const result : Identifier [ ] = [ ...direct ] ;
125+ for ( const child of direct ) {
126+ result . push ( ...getTransitiveChildren ( child . url ) ) ;
143127 }
144- transitiveCache . set ( parentName , result ) ;
128+ transitiveCache [ parentUrl ] = result ;
145129 return result ;
146130 } ;
147131
148- const seen = new Set < string > ( ) ;
149- const allPairs : TypeRelation [ ] = [ ] ;
150-
151- for ( const pair of directPairs ) {
152- const key = `${ pair . parent . name } |${ pair . child . name } ` ;
153- seen . add ( key ) ;
154- allPairs . push ( pair ) ;
155-
156- for ( const transitiveChild of getTransitiveChildren ( pair . child . name ) ) {
157- const transitiveKey = `${ pair . parent . name } |${ transitiveChild . name } ` ;
158- if ( ! seen . has ( transitiveKey ) ) {
159- seen . add ( transitiveKey ) ;
160- allPairs . push ( { parent : pair . parent , child : transitiveChild } ) ;
161- }
162- }
132+ for ( const schema of schemas ) {
133+ if ( ! isSpecializationTypeSchema ( schema ) ) continue ;
134+ const allChildren = getTransitiveChildren ( schema . identifier . url ) ;
135+ if ( allChildren . length === 0 ) continue ;
136+ const resources = allChildren . filter ( isResourceIdentifier ) ;
137+ const complexTypes = allChildren . filter ( isComplexTypeIdentifier ) ;
138+ const family : NonNullable < RegularTypeSchema [ "typeFamily" ] > = { } ;
139+ if ( resources . length > 0 ) family . resources = resources ;
140+ if ( complexTypes . length > 0 ) family . complexTypes = complexTypes ;
141+ if ( Object . keys ( family ) . length > 0 ) schema . typeFamily = family ;
163142 }
164-
165- return allPairs ;
166143} ;
167144
168145///////////////////////////////////////////////////////////
169146// Type Schema Index
170147
171148export type TypeSchemaIndex = {
172149 _schemaIndex : Record < CanonicalUrl , Record < PkgName , TypeSchema > > ;
173- _relations : TypeRelation [ ] ;
174150 schemas : TypeSchema [ ] ;
175151 schemasByPackage : Record < PkgName , TypeSchema [ ] > ;
176152 register ?: Register ;
@@ -180,7 +156,6 @@ export type TypeSchemaIndex = {
180156 collectProfiles : ( ) => ProfileTypeSchema [ ] ;
181157 resolve : ( id : Identifier ) => TypeSchema | undefined ;
182158 resolveByUrl : ( pkgName : PkgName , url : CanonicalUrl ) => TypeSchema | undefined ;
183- resourceChildren : ( id : Identifier ) => Identifier [ ] ;
184159 tryHierarchy : ( schema : TypeSchema ) => TypeSchema [ ] | undefined ;
185160 hierarchy : ( schema : TypeSchema ) => TypeSchema [ ] ;
186161 findLastSpecialization : ( schema : TypeSchema ) => TypeSchema ;
@@ -241,7 +216,7 @@ export const mkTypeSchemaIndex = (
241216 for ( const schema of schemas ) {
242217 append ( schema ) ;
243218 }
244- const relations = resourceRelatives ( schemas ) ;
219+ populateTypeFamily ( schemas ) ;
245220
246221 const resolve = ( id : Identifier ) => {
247222 if ( id . kind === "nested" ) return nestedIndex [ id . url ] ?. [ id . package ] ;
@@ -269,10 +244,6 @@ export const mkTypeSchemaIndex = (
269244 return undefined ;
270245 } ;
271246
272- const resourceChildren = ( id : Identifier ) : Identifier [ ] => {
273- return relations . filter ( ( relative ) => relative . parent . name === id . name ) . map ( ( relative ) => relative . child ) ;
274- } ;
275-
276247 const tryHierarchy = ( schema : TypeSchema ) : TypeSchema [ ] | undefined => {
277248 const res : TypeSchema [ ] = [ ] ;
278249 let cur : TypeSchema | undefined = schema ;
@@ -476,7 +447,6 @@ export const mkTypeSchemaIndex = (
476447
477448 return {
478449 _schemaIndex : index ,
479- _relations : relations ,
480450 schemas,
481451 schemasByPackage : groupByPackages ( schemas ) ,
482452 register,
@@ -486,7 +456,6 @@ export const mkTypeSchemaIndex = (
486456 collectProfiles : ( ) => schemas . filter ( isProfileTypeSchema ) ,
487457 resolve,
488458 resolveByUrl,
489- resourceChildren,
490459 tryHierarchy,
491460 hierarchy,
492461 findLastSpecialization,
0 commit comments