11import {
22 type ConstrainedChoiceInfo ,
3+ type FieldSlicing ,
34 isChoiceDeclarationField ,
45 isNotChoiceDeclarationField ,
56 isPrimitiveIdentifier ,
7+ isTypeDiscriminated ,
68 type RegularField ,
79 type SnapshotProfileTypeSchema ,
810 type TypeIdentifier ,
@@ -49,10 +51,11 @@ export const collectTypesFromSlices = (
4951 addType : ( typeId : TypeIdentifier ) => void ,
5052) => {
5153 const pkgName = snapshot . identifier . package ;
52- for ( const field of Object . values ( snapshot . fields ) ) {
53- if ( ! isNotChoiceDeclarationField ( field ) || ! field . slicing ?. slices || ! field . type ) continue ;
54- const isTypeDisc = field . slicing . discriminator ?. some ( ( d ) => d . type === "type" ) ?? false ;
55- for ( const slice of Object . values ( field . slicing . slices ) ) {
54+ for ( const [ fieldName , fieldSlicing ] of Object . entries ( snapshot . slicing ?? { } ) ) {
55+ const field = snapshot . fields [ fieldName ] ;
56+ if ( ! isNotChoiceDeclarationField ( field ) || ! fieldSlicing . slices || ! field . type ) continue ;
57+ const isTypeDisc = isTypeDiscriminated ( fieldSlicing ) ;
58+ for ( const slice of Object . values ( fieldSlicing . slices ) ) {
5659 if ( Object . keys ( slice . match ?? { } ) . length > 0 ) {
5760 addType ( field . type ) ;
5861 const cc = slice . elements ? tsIndex . constrainedChoice ( pkgName , field . type , slice . elements ) : undefined ;
@@ -79,11 +82,13 @@ export const collectTypesFromSlices = (
7982 * - The field uses a type discriminator (e.g. Bundle entry.resource) — the stub only sets
8083 * resourceType, the user must provide the actual typed resource
8184 */
82- export const collectRequiredSliceNames = ( field : RegularField ) : string [ ] | undefined => {
83- if ( ! field . array || ! field . slicing ?. slices ) return undefined ;
84- const isTypeDisc = field . slicing . discriminator ?. some ( ( d ) => d . type === "type" ) ?? false ;
85- if ( isTypeDisc ) return undefined ;
86- const names = Object . entries ( field . slicing . slices )
85+ export const collectRequiredSliceNames = (
86+ field : RegularField ,
87+ fieldSlicing : FieldSlicing | undefined ,
88+ ) : string [ ] | undefined => {
89+ if ( ! field . array || ! fieldSlicing ?. slices ) return undefined ;
90+ if ( isTypeDiscriminated ( fieldSlicing ) ) return undefined ;
91+ const names = Object . entries ( fieldSlicing . slices )
8792 . filter ( ( [ _ , s ] ) => {
8893 if ( s . min === undefined || s . min < 1 || ! s . match || Object . keys ( s . match ) . length === 0 ) return false ;
8994 const matchKeys = new Set ( Object . keys ( s . match ) ) ;
@@ -115,44 +120,41 @@ export type SliceDef = {
115120} ;
116121
117122export const collectSliceDefs = ( tsIndex : TypeSchemaIndex , snapshot : SnapshotProfileTypeSchema ) : SliceDef [ ] =>
118- Object . entries ( snapshot . fields )
119- . filter ( ( [ _ , field ] ) => isNotChoiceDeclarationField ( field ) && field . slicing ?. slices )
120- . flatMap ( ( [ fieldName , field ] ) => {
121- if ( ! isNotChoiceDeclarationField ( field ) || ! field . slicing ?. slices || ! field . type ) return [ ] ;
122- const baseType = tsTypeFromIdentifier ( field . type ) ;
123- const pkgName = snapshot . identifier . package ;
124- const choiceBaseNames = collectChoiceBaseNames ( tsIndex , field . type ) ;
125- const isTypeDisc = field . slicing . discriminator ?. some ( ( d ) => d . type === "type" ) ?? false ;
126- return Object . entries ( field . slicing . slices )
127- . filter ( ( [ _ , slice ] ) => Object . keys ( slice . match ?? { } ) . length > 0 )
128- . map ( ( [ sliceName , slice ] ) => {
129- const matchFields = Object . keys ( slice . match ?? { } ) ;
130- const required = ( slice . required ?? [ ] ) . filter (
131- ( name ) => ! matchFields . includes ( name ) && ! choiceBaseNames . has ( name ) ,
132- ) ;
133- const cc = slice . elements
134- ? tsIndex . constrainedChoice ( pkgName , field . type , slice . elements )
135- : undefined ;
136- // Skip flattening for primitive types — can't intersect object with boolean/string/etc.
137- const constrainedChoice = cc && ! isPrimitiveIdentifier ( cc . variantType ) ? cc : undefined ;
138- const resourceType = isTypeDisc ? extractResourceTypeFromMatch ( slice . match ?? { } ) : undefined ;
139- const typedBaseType = resourceType ? `${ baseType } <${ resourceType } >` : baseType ;
140- return {
141- fieldName,
142- baseType,
143- typedBaseType,
144- sliceName,
145- baseName : slice . nameCandidates . recommended ,
146- match : slice . match ?? { } ,
147- required,
148- excluded : slice . excluded ?? [ ] ,
149- array : Boolean ( field . array ) ,
150- constrainedChoice,
151- typeDiscriminator : isTypeDisc ,
152- max : slice . max ?? 0 ,
153- } ;
154- } ) ;
155- } ) ;
123+ Object . entries ( snapshot . slicing ?? { } ) . flatMap ( ( [ fieldName , fieldSlicing ] ) => {
124+ const field = snapshot . fields [ fieldName ] ;
125+ if ( ! isNotChoiceDeclarationField ( field ) || ! fieldSlicing . slices || ! field . type ) return [ ] ;
126+ const baseType = tsTypeFromIdentifier ( field . type ) ;
127+ const pkgName = snapshot . identifier . package ;
128+ const choiceBaseNames = collectChoiceBaseNames ( tsIndex , field . type ) ;
129+ const isTypeDisc = isTypeDiscriminated ( fieldSlicing ) ;
130+ return Object . entries ( fieldSlicing . slices )
131+ . filter ( ( [ _ , slice ] ) => Object . keys ( slice . match ?? { } ) . length > 0 )
132+ . map ( ( [ sliceName , slice ] ) => {
133+ const matchFields = Object . keys ( slice . match ?? { } ) ;
134+ const required = ( slice . required ?? [ ] ) . filter (
135+ ( name ) => ! matchFields . includes ( name ) && ! choiceBaseNames . has ( name ) ,
136+ ) ;
137+ const cc = slice . elements ? tsIndex . constrainedChoice ( pkgName , field . type , slice . elements ) : undefined ;
138+ // Skip flattening for primitive types — can't intersect object with boolean/string/etc.
139+ const constrainedChoice = cc && ! isPrimitiveIdentifier ( cc . variantType ) ? cc : undefined ;
140+ const resourceType = isTypeDisc ? extractResourceTypeFromMatch ( slice . match ?? { } ) : undefined ;
141+ const typedBaseType = resourceType ? `${ baseType } <${ resourceType } >` : baseType ;
142+ return {
143+ fieldName,
144+ baseType,
145+ typedBaseType,
146+ sliceName,
147+ baseName : slice . nameCandidates . recommended ,
148+ match : slice . match ?? { } ,
149+ required,
150+ excluded : slice . excluded ?? [ ] ,
151+ array : Boolean ( field . array ) ,
152+ constrainedChoice,
153+ typeDiscriminator : isTypeDisc ,
154+ max : slice . max ?? 0 ,
155+ } ;
156+ } ) ;
157+ } ) ;
156158
157159export const generateSliceSetters = ( w : TypeScript , sliceDefs : SliceDef [ ] , snapshot : SnapshotProfileTypeSchema ) => {
158160 const profileClassName = tsProfileClassName ( snapshot ) ;
0 commit comments