@@ -93,6 +93,13 @@ export default function (userOptions: TSGenOptions) {
9393 const skippedBlocks : Array < { uid : string ; path : string ; reason : string } > =
9494 [ ] ;
9595
96+ // Collect numeric identifier errors instead of throwing immediately
97+ const numericIdentifierErrors : Array < {
98+ uid : string ;
99+ referenceTo ?: string ;
100+ type : "content_type" | "global_field" ;
101+ } > = [ ] ;
102+
96103 const typeMap : TypeMap = {
97104 text : { func : type_text , track : true , flag : TypeFlags . BuiltinJS } ,
98105 number : { func : type_number , track : true , flag : TypeFlags . BuiltinJS } ,
@@ -153,13 +160,8 @@ export default function (userOptions: TSGenOptions) {
153160 function name_type ( uid : string ) {
154161 // Check if the UID starts with a number, which would create invalid TypeScript
155162 if ( isNumericIdentifier ( uid ) ) {
156- throwUIDValidationError ( {
157- uid,
158- errorCode : "INVALID_INTERFACE_NAME" ,
159- reason : NUMERIC_IDENTIFIER_EXCLUSION_REASON ,
160- suggestion : `Since UIDs cannot be changed, use the --prefix flag to add a valid prefix to all interface names (e.g., --prefix "ContentType")` ,
161- context : "generateTSFromContentTypes" ,
162- } ) ;
163+ // Return a fallback name to continue processing
164+ return `InvalidInterface_${ uid } ` ;
163165 }
164166
165167 return [ options ?. naming ?. prefix , _ . upperFirst ( _ . camelCase ( uid ) ) ]
@@ -175,22 +177,35 @@ export default function (userOptions: TSGenOptions) {
175177 let interfaceName : string ;
176178
177179 const isGlobalField = contentType . data_type === "global_field" ;
178- const identifier = isGlobalField
179- ? ( contentType . reference_to as string )
180- : contentType . uid ;
181- if ( isNumericIdentifier ( identifier ) ) {
182- throwUIDValidationError ( {
180+
181+ // Check if the content type's own UID starts with a number
182+ if ( isNumericIdentifier ( contentType . uid ) ) {
183+ numericIdentifierErrors . push ( {
183184 uid : contentType . uid ,
184- errorCode : isGlobalField
185- ? "INVALID_GLOBAL_FIELD_REFERENCE"
186- : "INVALID_CONTENT_TYPE_UID" ,
187- reason : NUMERIC_IDENTIFIER_EXCLUSION_REASON ,
188- suggestion : `Since UIDs cannot be changed, use the --prefix flag to add a valid prefix to all interface names (e.g., --prefix "ContentType")` ,
189- context : "generateTSFromContentTypes" ,
190- ...( isGlobalField && { referenceTo : identifier } ) ,
185+ type : "content_type" ,
191186 } ) ;
187+ // Return a fallback interface declaration to continue processing
188+ interfaceName = `InvalidInterface_${ contentType . uid } ` ;
189+ } else if (
190+ isGlobalField &&
191+ contentType . reference_to &&
192+ isNumericIdentifier ( contentType . reference_to as string )
193+ ) {
194+ // For global fields, check if the referenced content type has a numeric identifier
195+ // This is a global field error because it references an invalid content type
196+ numericIdentifierErrors . push ( {
197+ uid : contentType . uid , // The global field's UID
198+ type : "global_field" ,
199+ referenceTo : contentType . reference_to as string , // The referenced content type's UID
200+ } ) ;
201+ // Return a fallback interface declaration to continue processing
202+ interfaceName = `InvalidInterface_${ contentType . reference_to } ` ;
203+ } else {
204+ // No numeric identifier issues, generate normal interface name
205+ interfaceName = name_type (
206+ isGlobalField ? ( contentType . reference_to as string ) : contentType . uid
207+ ) ;
192208 }
193- interfaceName = name_type ( identifier ) ;
194209
195210 const interface_declaration = [ "export interface" , interfaceName ] ;
196211 if ( systemFields && contentType . schema_type !== "global_field" ) {
@@ -585,6 +600,56 @@ export default function (userOptions: TSGenOptions) {
585600
586601 const definition = visit_content_type ( contentType ) ;
587602
603+ // Check for numeric identifier errors and throw them immediately
604+ if ( numericIdentifierErrors . length > 0 ) {
605+ // Group errors by type for better organization
606+ const contentTypeErrors = numericIdentifierErrors . filter (
607+ ( err ) => err . type === "content_type"
608+ ) ;
609+ const globalFieldErrors = numericIdentifierErrors . filter (
610+ ( err ) => err . type === "global_field"
611+ ) ;
612+
613+ // Build the detailed error message
614+ let errorDetails = "" ;
615+ errorDetails += `Type generation failed: Found ${ numericIdentifierErrors . length } items with numeric identifiers that create invalid TypeScript interface names. Please use the --prefix flag to resolve this issue.\n\n` ;
616+
617+ if ( contentTypeErrors . length > 0 ) {
618+ errorDetails += "Content Types & Global Fields with Numeric UIDs:\n" ;
619+ errorDetails +=
620+ "Note: Global Fields are Content Types, so they appear in this section if their own UID starts with a number.\n\n" ;
621+
622+ contentTypeErrors . forEach ( ( error , index ) => {
623+ errorDetails += `${ index + 1 } . UID: "${ error . uid } "\n` ;
624+ errorDetails += ` Reason: ${ NUMERIC_IDENTIFIER_EXCLUSION_REASON } \n` ;
625+ errorDetails += ` Suggestion: Since UIDs cannot be changed, use the --prefix flag to add a valid prefix to all interface names (e.g., --prefix "ContentType")\n\n` ;
626+ } ) ;
627+ }
628+
629+ if ( globalFieldErrors . length > 0 ) {
630+ errorDetails += "Global Fields Referencing Invalid Content Types:\n\n" ;
631+
632+ globalFieldErrors . forEach ( ( error , index ) => {
633+ errorDetails += `${ index + 1 } . Global Field: "${ error . uid } "\n` ;
634+ errorDetails += ` References: "${ error . referenceTo || "Unknown" } "\n` ;
635+ errorDetails += ` Reason: ${ NUMERIC_IDENTIFIER_EXCLUSION_REASON } \n` ;
636+ errorDetails += ` Suggestion: Since UIDs cannot be changed, use the --prefix flag to add a valid prefix to all interface names (e.g., --prefix "ContentType")\n\n` ;
637+ } ) ;
638+ }
639+
640+ errorDetails += "To resolve these issues:\n" ;
641+ errorDetails +=
642+ " • Use the --prefix flag to add a valid prefix to all interface names\n" ;
643+ errorDetails += " • Example: --prefix 'ContentType'\n" ;
644+
645+ // Throw a comprehensive error with all the details
646+ throw {
647+ type : "validation" ,
648+ error_code : "VALIDATION_ERROR" ,
649+ error_message : errorDetails ,
650+ } ;
651+ }
652+
588653 // Log summary table of skipped fields and blocks
589654 if ( skippedFields . length > 0 || skippedBlocks . length > 0 ) {
590655 cliux . print ( "" ) ;
0 commit comments