@@ -309,53 +309,69 @@ export default function FakerTool() {
309309 ) ;
310310
311311 function fieldToSchema ( f : FieldConfig ) : any {
312- if ( f . type === "object" ) {
312+ // Helper to build the non-array schema for a field
313+ function buildInner ( field : FieldConfig ) : any {
314+ if ( field . type === "object" ) {
315+ return {
316+ type : "object" ,
317+ properties : ( field . children || [ ] ) . reduce < Record < string , any > > ( ( acc , c ) => {
318+ acc [ c . name ] = fieldToSchema ( c ) ;
319+ return acc ;
320+ } , { } ) ,
321+ } ;
322+ }
323+ const map : Record < string , any > = {
324+ string : { type : "string" } ,
325+ number : { type : "number" } ,
326+ boolean : { type : "boolean" } ,
327+ uuid : { type : "string" } ,
328+ date : { type : "string" , format : "date-time" } ,
329+ email : { type : "string" } ,
330+ firstName : { type : "string" } ,
331+ lastName : { type : "string" } ,
332+ fullName : { type : "string" } ,
333+ jobTitle : { type : "string" } ,
334+ phone : { type : "string" } ,
335+ streetAddress : { type : "string" } ,
336+ city : { type : "string" } ,
337+ country : { type : "string" } ,
338+ countryCode : { type : "string" } ,
339+ latitude : { type : "number" } ,
340+ longitude : { type : "number" } ,
341+ ip : { type : "string" } ,
342+ url : { type : "string" } ,
343+ domain : { type : "string" } ,
344+ username : { type : "string" } ,
345+ password : { type : "string" } ,
346+ company : { type : "string" } ,
347+ avatar : { type : "string" } ,
348+ color : { type : "string" } ,
349+ currencyCode : { type : "string" } ,
350+ iban : { type : "string" } ,
351+ bitcoinAddress : { type : "string" } ,
352+ sentence : { type : "string" } ,
353+ paragraph : { type : "string" } ,
354+ imageUrl : { type : "string" } ,
355+ } ;
356+ const base = map [ field . type ] || { type : "string" } ;
357+ const fakerPath = typeToFaker [ field . type ] ;
358+ if ( fakerPath ) ( base as any ) . faker = fakerPath ;
359+ return base ;
360+ }
361+
362+ if ( f . array ) {
363+ const innerSchema = buildInner ( { ...f , array : false } ) ;
364+ // Preserve fixed length with both standard keywords and custom extension
365+ const len = f . arrayLength || 3 ;
313366 return {
314- type : "object " ,
315- properties : ( f . children || [ ] ) . reduce < Record < string , any > > ( ( acc , c ) => {
316- acc [ c . name ] = fieldToSchema ( c ) ;
317- return acc ;
318- } , { } ) ,
367+ type : "array " ,
368+ items : innerSchema ,
369+ minItems : len ,
370+ maxItems : len ,
371+ "x-arrayLength" : len ,
319372 } ;
320373 }
321- const map : Record < string , any > = {
322- string : { type : "string" } ,
323- number : { type : "number" } ,
324- boolean : { type : "boolean" } ,
325- uuid : { type : "string" } ,
326- date : { type : "string" , format : "date-time" } ,
327- email : { type : "string" } ,
328- firstName : { type : "string" } ,
329- lastName : { type : "string" } ,
330- fullName : { type : "string" } ,
331- jobTitle : { type : "string" } ,
332- phone : { type : "string" } ,
333- streetAddress : { type : "string" } ,
334- city : { type : "string" } ,
335- country : { type : "string" } ,
336- countryCode : { type : "string" } ,
337- latitude : { type : "number" } ,
338- longitude : { type : "number" } ,
339- ip : { type : "string" } ,
340- url : { type : "string" } ,
341- domain : { type : "string" } ,
342- username : { type : "string" } ,
343- password : { type : "string" } ,
344- company : { type : "string" } ,
345- avatar : { type : "string" } ,
346- color : { type : "string" } ,
347- currencyCode : { type : "string" } ,
348- iban : { type : "string" } ,
349- bitcoinAddress : { type : "string" } ,
350- sentence : { type : "string" } ,
351- paragraph : { type : "string" } ,
352- imageUrl : { type : "string" } ,
353- } ;
354- const base = map [ f . type ] || { type : "string" } ;
355- const fakerPath = typeToFaker [ f . type ] ;
356- if ( fakerPath ) ( base as any ) . faker = fakerPath ;
357- if ( f . array ) return { type : "array" , items : base } ;
358- return base ;
374+ return buildInner ( f ) ;
359375 }
360376 function fieldsToSchema ( list : FieldConfig [ ] ) {
361377 return {
@@ -379,7 +395,19 @@ export default function FakerTool() {
379395 }
380396 if ( node . type === "array" ) {
381397 const inner = schemaNodeToField ( name , node . items || { type : "string" } ) ;
382- return { ...inner , array : true , arrayLength : 3 } ;
398+ const inferredLength = ( ( ) : number => {
399+ if (
400+ typeof node . minItems === "number" &&
401+ typeof node . maxItems === "number" &&
402+ node . minItems === node . maxItems
403+ )
404+ return node . minItems ;
405+ if ( typeof node [ "x-arrayLength" ] === "number" ) return node [ "x-arrayLength" ] ;
406+ if ( typeof node . minItems === "number" ) return node . minItems ;
407+ if ( typeof node . maxItems === "number" ) return node . maxItems ;
408+ return 3 ;
409+ } ) ( ) ;
410+ return { ...inner , array : true , arrayLength : inferredLength } ;
383411 }
384412 return { id : faker . string . uuid ( ) , name, type : guessFieldType ( node ) } ;
385413 }
@@ -913,10 +941,10 @@ export default function FakerTool() {
913941 } }
914942 title = {
915943 < span >
916- < b > Tip:</ b > Drag top-level items to reorder only.
944+ < b > Tip:</ b > Drag top-level items to reorder only. Use Add Object then + Child
945+ buttons to manage nesting;
917946 < br />
918- Use Add Object then + Child buttons to manage nesting; dragging into nested
919- levels is disabled.
947+ All the changes are saved automatically, you can come back later and edit them.
920948 </ span >
921949 }
922950 />
0 commit comments